Submessages
Messages serve as a means to interact with both SDK modules and CW smart contracts. It's important to note that messages are executed in a 'set-and-forget' manner, meaning you won't receive immediate feedback about the success or failure of the call.
Nevertheless, obtaining the result of your call can be highly advantageous in the following scenarios:
When you're instantiating a new contract and need to acquire the contract address.
When you're executing an action and need to confirm that the result was successful. For instance, you might want to ensure that a specific token amount has been correctly transferred to your contract.
When you wish to handle an error from your cross-contract call instead of rolling back the transaction.
To retrieve the result of the message sent from your smart contract, you will need to initiate a submessage. For further insights into the semantics of submessages and the order of submessage execution, you can refer to additional documentation located here.
Creating a Submessage
A submessage encapsulates a CosmosMsg within a SubMsg structure:
pub struct SubMsg<T> {
pub id: u64, // reply_id that will be used to handle the reply
pub msg: CosmosMsg<T>, // message to be sent
pub gas_limit: Option<u64>, // gas limit for the submessage
pub reply_on: ReplyOn, // a flag to determine when the reply should be sent
}The source code for the SubMsg struct can be located here.
Now, let's examine an illustration of instantiating a cw20 token using a submessage:
const INSTANTIATE_REPLY_ID = 1u64;
// Creating a message to create a new cw20 token
let instantiate_tx = WasmMsg::Instantiate {
admin: None,
code_id: msg.cw20_code_id,
msg: to_binary(&Cw20InstantiateMsg {
name: "new token".to_string(),
symbol: "nToken".to_string(),
decimals: 6,
initial_balances: vec![],
mint: Some(MinterResponse {
minter: env.contract.address.to_string(),
cap: None,
}),
})?,
funds: vec![],
label: "".to_string(),
};
// Creating a submessage that wraps the message above
let submessage = SubMsg::reply_on_success(instantiate_tx.into(), INSTANTIATE_REPLY_ID);
// Creating a response with the submessage
let response = Response::new().add_submessage(submessage);Reply Strategies
Submessages provide four distinct response options for the recipient contract to offer:
Previously, we generated the submessage using the SubMsg::reply_on_success shortcut. Nevertheless, it's worth noting that we can also create a submessage while explicitly specifying the reply strategy.
Handling a Reply
To process the response from the other contract, the calling contract must incorporate a new entry point. Below, you'll find two examples illustrating how to manage these responses:
Instantiating a new contract:
Handling a reply from a token transfer:
Transmitting Context Between Contracts
In order to prevent reentrancy attacks, CosmWasm prohibits the storage of context within the contract memory. To propagate state between contracts, there are two available methods:
All events produced by the submessage can be accessed from the Reply message.
Temporary state can be stored using cw_storage_plus::Item and subsequently loaded into the reply handler.
Last updated
Was this helpful?