Instantiating a CosmWasm Contract: A Step-by-Step Guide
In this guide, we will walk through the process of instantiating a CosmWasm smart contract. We'll cover the InstantiateMsg
structure passed during contract creation and the instantiate
function executed upon contract deployment.
What is InstantiateMsg?
InstantiateMsg
is the initialization message used when a contract is instantiated. It includes variables provided during the contract creation. Here is a simple example of what InstantiateMsg
looks like:
rust 复制代码 /// Variables for contract instantiation. /// Exclude variables susceptible to replay attacks or secret data. pub struct InstantiateMsg { pub sent_message: String, }
This structure is defined in msg.rs
. It's important to ensure that no sensitive data prone to replay attacks is included in this message.
The Instantiate Function
The instantiate
function is executed when the contract is created. It sets the initial state of the smart contract, performs necessary checks, and can act similarly to an execute message. Below is an example of how this function is defined in contract.rs
:
rust 复制代码 pub fn instantiate( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> Result<Response, ContractError> { // Initialize contract's state.let state = State { global_var: msg.sent_message, }; // Save state to the blockchain. STATE.save(deps.storage, &state)?; Ok(Response::new().add_attribute("instantiated", "true")) }
This function initializes the contract's state with the provided sent_message
and saves this state to the blockchain.
Example: Setting Up the Contract Files
To instantiate a CosmWasm contract, you need to set up several files. Here is an example layout of the files and their content:
- lib.rs
rust 复制代码 pub mod contract; mod error; pub mod helpers; pub mod msg; pub mod state; pub use crate::error::ContractError;
- contract.rs
rust 复制代码 #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, to_binary}; use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state::{State, STATE}; #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> Result<Response, ContractError> { let state = State { global_var: msg.sent_message, }; STATE.save(deps.storage, &state)?; Ok(Response::new().add_attribute("instantiated", "true")) } #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( _deps: DepsMut, _env: Env, _info: MessageInfo, _msg: ExecuteMsg, ) -> Result<Response, ContractError> { unimplemented!() } #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> { match msg { QueryMsg::GetMessage {} => to_binary(&query::message(deps)?), } } pub mod query { use crate::msg::GetMessageResponse; use super::*; pub fn message(deps: Deps) -> StdResult<GetMessageResponse> { let state = STATE.load(deps.storage)?; Ok(GetMessageResponse { message: state.global_var }) } } #[cfg(test)] mod tests { use cosmwasm_std::{testing::{mock_dependencies, mock_env, mock_info}, Addr, from_binary}; use crate::msg::GetMessageResponse; use super::*; #[test]fn instantiate_test() { let mut deps = mock_dependencies(); let env = mock_env(); let msg = InstantiateMsg { sent_message: "Hey!".to_string()}; let info = mock_info("creator", &[]); instantiate(deps.as_mut(), env.clone(), info, msg).unwrap(); let res = query(deps.as_ref(), env, QueryMsg::GetMessage {}).unwrap(); let message: GetMessageResponse = from_binary(&res).unwrap(); assert_eq!("Hey!".to_string(), message.message); } }
- msg.rs
rust 复制代码 use cosmwasm_schema::{cw_serde, QueryResponses}; #[cw_serde] pub struct InstantiateMsg { pub sent_message: String, } #[cw_serde] pub enum ExecuteMsg {} #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { #[returns(GetMessageResponse)] GetMessage {}, } #[cw_serde] pub struct GetMessageResponse { pub message: String, }
- error.rs
rust 复制代码 use cosmwasm_std::StdError; use thiserror::Error; #[derive(Error, Debug)] pub enum ContractError { #[error("{0}")]Std(#[from] StdError), #[error("Unauthorized")] Unauthorized {}, }
- state.rs
rust 复制代码 use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use cw_storage_plus::Item; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct State { pub global_var: String, } pub const STATE: Item<State> = Item::new("state");
- helpers.rs
rust 复制代码 use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg}; use crate::msg::ExecuteMsg; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct CwTemplateContract(pub Addr); impl CwTemplateContract { pub fn addr(&self) -> Addr { self.0.clone() } pub fn call<T: Into<ExecuteMsg>>(&self, msg: T) -> StdResult<CosmosMsg> { let msg = to_binary(&msg.into())?; Ok(WasmMsg::Execute { contract_addr: self.addr().into(), msg, funds: vec![], } .into()) } }
By following these steps and organizing your files as shown, you can successfully instantiate and deploy a CosmWasm smart contract. This setup forms the foundation for more complex contract development and deployment on the blockchain.