Skip to main content
Version: main

Callbacks

The cw-ica-controller contract provides a callback mechanism upon various channel and packet lifecycle events. A callback address is recorded in the contract's state. This address is set during the contract's instantiation or can be updated later by the contract owner using ExecuteMsg::UpdateCallbackAddress.

ReceiveIcaCallback enum variant

The contract whose address is recorded as the callback address must include a callback enum variant in its ExecuteMsg enum. We included a procedural macro to generate this enum variant for you in cw-ica-controller's helpers module. See the following example:

src/msg.rs
use cw_ica_controller::helpers::ica_callback_execute;

#[ica_callback_execute]
#[cw_serde]
pub enum ExecuteMsg {}

This will transform the enum to:

src/msg.rs
#[cw_serde]
pub enum ExecuteMsg {
ReceiveIcaCallback(::cw_ica_controller::types::callbacks::IcaControllerCallbackMsg),
}
note

Other derive macro invocations must occur after this procedural macro as they may depend on the new variant. For example, the following will fail because the Clone derivation occurs before the addition of the field.

use cw_ica_controller::helper::ica_callback_execute;
use cosmwasm_schema::cw_serde;

#[derive(Clone)]
#[ica_callback_execute]
#[allow(dead_code)]
#[cw_serde]
enum Test {
Foo,
Bar(u64),
Baz { foo: u64 },
}

Since this variant is inserted to the ExecuteMsg, the callback contract must handle this enum variant in its execute function:

testing/contracts/callback-counter/src/contract.rs
loading...

The callback contract can then handle the callback message as it sees fit, ideally by performing some kind of validation that the callback comes from an expected legitimate source. The callback contract can also perform some kind of action based on the callback message, such as incrementing a counter or error handling.

warning

If the callback contract returns an error, the cw-ica-controller will not proceed with the channel or packet lifecycle event that triggered the callback.

  1. If the callback contract returns an error in response to a ChannelOpenAck callback, then the cw-ica-controller will not proceed with the channel opening.
  2. If the callback contract returns an error in response to a OnAcknowledgementPacketCallback callback, then the cw-ica-controller will not proceed with the packet acknowledgement.
  3. If the callback contract returns an error in response to a OnTimeoutPacketCallback callback, then the cw-ica-controller will not proceed with the packet timeout.

If the ICA channel is ordered, cases 2 and 3 will result in the halting of the channel until the callback contract returns a successful response.

IcaControllerCallbackMsg

The IcaControllerCallbackMsg enum is the message type that is sent to the callback contract. It contains the following variants:

src/types/callbacks.rs
loading...

OnChannelOpenAckCallback

The OnChannelOpenAckCallback variant is sent to the callback contract when the cw-ica-controller receives a ChannelOpenAck message from the counterparty chain.

Let's go through the fields of this variant:

  • channel: This is the IBC Channel that would be opened if the callback contract returns a successful response. See cosmwasm_std::IbcChannel for more details.

  • ica_address: This is the address (in the counterparty chain) of the interchain account that would be created if the callback contract returns a successful response.

  • tx_encoding: This is the transaction encoding that would be used for the ICS-27 transactions.

OnAcknowledgementPacketCallback

The OnAcknowledgementPacketCallback variant is sent to the callback contract when the cw-ica-controller receives an acknowledgement packet from the counterparty chain for a packet that was sent from the calling cw-ica-controller contract.

Let's go through the fields of this variant:

  • ica_acknowledgement: This is the acknowledgement data that was sent by the counterparty chain.
src/ibc/types/packet.rs
loading...

If the ICA packet was successfully executed on the counterparty chain, then this will be Data::Result(Binary) where Binary is the protobuf encoded result of the ICA packet execution.

If the ICA packet was not successfully executed on the counterparty chain, then this will be Data::Error(String) where String is the error message returned by the counterparty chain.

note

The error message returned by the counterparty chain doesn't include any useful information about the error. It only contains the codespace of the error. This is because in CosmosSDK, tx error messages may be non-deterministic, and thus, they cannot be included in the IBC packet acknowledgement which is a deterministic message. This is a limitation of ibc-go.

  • original_packet: This is the original ICA packet that was sent by the calling cw-ica-controller contract. See cosmwasm_std::IbcPacket

  • relayer: This is the address of the relayer that relayed the packet to the counterparty chain.

  • query_result: This is the result of the queries that were executed on the counterparty chain. This is only present if the packet contained queries. See IcaQueryResult

OnTimeoutPacketCallback

The OnTimeoutPacketCallback variant is sent to the callback contract when the cw-ica-controller receives a timeout packet for a packet that was sent.

Let's go through the fields of this variant:

  • original_packet: This is the original ICA packet that was sent by the calling cw-ica-controller contract. See cosmwasm_std::IbcPacket

  • relayer: This is the address of the relayer that relayed the packet to the counterparty chain.