diff --git a/CHANGELOG.md b/CHANGELOG.md index ca85931d..495a1761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## v0.6.0 (2024-06-18) + ### Features - Added support for ICA queries. (https://github.com/srdtrk/cw-ica-controller/issues/88) diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 4aaf7dd2..9bb11bb9 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -1,5 +1,5 @@ -import {themes as prismThemes} from 'prism-react-renderer'; -import type {Config} from '@docusaurus/types'; +import { themes as prismThemes } from 'prism-react-renderer'; +import type { Config } from '@docusaurus/types'; import type * as Preset from '@docusaurus/preset-classic'; const config: Config = { @@ -43,13 +43,17 @@ const config: Config = { routeBasePath: "/", sidebarCollapsed: false, // Select the latest version - lastVersion: "v0.5.x", + lastVersion: "v0.6.x", versions: { current: { label: 'main', path: 'main', banner: 'unreleased', }, + "v0.6.x": { + label: 'v0.6.x', + path: 'v0.6', + }, "v0.5.x": { label: 'v0.5.x', path: 'v0.5', @@ -158,10 +162,10 @@ const config: Config = { }, // github codeblock theme configuration codeblock: { - showGithubLink: true, - githubLinkLabel: 'View on GitHub', - showRunmeLink: false, - runmeLinkLabel: 'Checkout via Runme' + showGithubLink: true, + githubLinkLabel: 'View on GitHub', + showRunmeLink: false, + runmeLinkLabel: 'Checkout via Runme' }, } satisfies Preset.ThemeConfig, plugins: [ diff --git a/docs/versioned_docs/version-v0.6.x/00-intro.mdx b/docs/versioned_docs/version-v0.6.x/00-intro.mdx new file mode 100644 index 00000000..e400a8e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/00-intro.mdx @@ -0,0 +1,43 @@ +--- +title: Introduction +sidebar_label: Introduction +sidebar_position: 0 +slug: / +--- + +import HighlightTag from '@site/src/components/HighlightTag'; + +# CosmWasm ICA Controller + + + +Welcome to the documentation for CosmWasm Interchain Accounts Controller. This document will guide you through +understanding the [ICS-27](https://github.com/cosmos/ibc/tree/main/spec/app/ics-027-interchain-accounts) +Interchain Accounts protocol and how to use `cw-ica-controller` to create and manage interchain accounts on +any IBC enabled CosmWasm chain. + +The CosmWasm ICA Controller is a CosmWasm contract that implements the ICS-27 interchain accounts controller in +pure Rust. It is designed to be used by other CosmWasm contracts to create and manage interchain accounts on +the chain where the contract is deployed. + +## High Level Overview + +The following diagram shows how `cw-ica-controller` works at a high level. + +![High Level Overview](/img/cw-ica-controller.svg) + +The `cw-ica-controller` contract code is deployed on a chain that supports IBC CosmWasm. This chain does not need +to support ICS-27 interchain accounts nor does it need to support any custom IBC bindings. Then when an external +account or a contract instantiates a `cw-ica-controller` contract, the contract will initiate the ICS-27 handshake +with a chain that supports ICS-27 interchain accounts based on the options provided by the caller. + +:::note + +The counterparty chain need not be a CosmWasm chain. It can be any chain that uses ibc-go and supports `ICS-27`. +Such as CosmosHub, Osmosis, etc. + +::: + +Then the rest of the ICS-27 handshake is completed by the relayers automatically. Both the hermes relayer and the +go relayer support `ICS-27` interchain accounts. Once the handshake is complete, the `cw-ica-controller` contract +makes a callback to the callback contract if one was provided during instantiation. diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/00-intro.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/00-intro.mdx new file mode 100644 index 00000000..6a3c519c --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/00-intro.mdx @@ -0,0 +1,22 @@ +--- +title: Contract API +sidebar_label: Overview +sidebar_position: 0 +slug: /contract-api/intro +--- + +import HighlightTag from '@site/src/components/HighlightTag'; + +# Contract API + + + +In this section we will cover how to interact with the contract and design decisions that were made. A full integration guide is work in progress. + +In this section, we cover the following topics: + +- ✉️ [`InstantiateMsg`](./01-instantiate-msg.mdx) +- 📨 [`ExecuteMsg`](./02-execute-msg.mdx) +- 🤔 [`QueryMsg`](./03-query-msg.mdx) +- 🤙 [Callbacks](./04-callbacks.mdx) +- 📜 [Events](./05-events.mdx) diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/01-instantiate-msg.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/01-instantiate-msg.mdx new file mode 100644 index 00000000..c1f6b7bf --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/01-instantiate-msg.mdx @@ -0,0 +1,58 @@ +--- +title: InstantiateMsg +sidebar_label: InstantiateMsg +sidebar_position: 1 +slug: /contract-api/instantiate-msg +--- + +# `InstantiateMsg` + +The `InstantiateMsg` is the message that is used to instantiate the `cw-ica-controller` contract. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/msg.rs#L8-L21 +``` + +## Fields + +### `owner` + +This contract has an owner who is allowed to call the `ExecuteMsg` methods. +The owner management is handled by the amazing [cw-ownable](https://crates.io/crates/cw-ownable) crate. +If left empty, the owner is set to the sender of the `InstantiateMsg`. + +### `channel_open_init_options` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/6843b80b29af97b9c4561ad487420e2f54857553/src/types/msg.rs#L95-L107 +``` + +These are the options required for the contract to initiate an ICS-27 channel open handshake. +This contract requires there to be an IBC connection between the two chains before it can open a channel. + +#### `connection_id` + +The identifier of the IBC connection end on the deployed (source) chain. (The underlying IBC light client must +be live.) If this field is set to a non-existent connection, the execution of the `InstantiateMsg` will fail. + +#### `counterparty_connection_id` + +The identifier of the IBC connection end on the counterparty (destination) chain. (The underlying IBC light +client must be live.) If this field is set to a non-existent connection or a different connection's end, +then the execution of the `InstantiateMsg` will not fail. This is because the source chain does not know +about the counterparty chain's connections. Instead, the channel open handshake will fail to complete. + +If the contract was instantiated with a `counterparty_connection_id` that does not match the connection +end on the counterparty chain, then the owner must call [`ExecuteMsg::CreateChannel`](./02-execute-msg.mdx#createchannel) with the correct parameters to start a new channel open handshake. + +#### `counterparty_port_id` + +This is a required parameter for the ICS-27 channel version metadata. I've added it here for consistency. +Currently, the only supported value is `icahost`. If left empty, it is set to `icahost`. +**So you should ignore this field.** + +### `send_callbacks_to` + +This is the address of the contract that will receive the callbacks from the `cw-ica-controller` contract. +This may be the same address as the `owner` or a different address. If left empty, no callbacks will be sent. +Learn more about callbacks [here](./04-callbacks.mdx). diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/02-execute-msg.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/02-execute-msg.mdx new file mode 100644 index 00000000..d05dd6eb --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/02-execute-msg.mdx @@ -0,0 +1,151 @@ +--- +title: ExecuteMsg +sidebar_label: ExecuteMsg +sidebar_position: 2 +slug: /contract-api/execute-msg +--- + +# `ExecuteMsg` + +The `ExecuteMsg` is the message that is used to interact with the `cw-ica-controller` contract. +**All execute messages are only callable by the owner of the contract.** + +## `CreateChannel` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/7773fbd8d4e227b6c942f0c88575f9800809b4bf/src/types/msg.rs#L29-L39 +``` + +This message is used to initiate an ICS-27 channel open handshake. It is only callable by the owner. +This message only takes one optional parameter: `channel_open_init_options`. + +If this parameter is left empty, then the contract will use the `channel_open_init_options` that were last +passed to the `InstantiateMsg` or `CreateChannel` messages. + +If this parameter is set, then the contract will use the `channel_open_init_options` that are passed to this +message and save them for future `CreateChannel` messages. + +## `CloseChannel` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/7773fbd8d4e227b6c942f0c88575f9800809b4bf/src/types/msg.rs#L40-L41 +``` + +This message is used to close the ICS-27 channel. It is only callable by the owner. +The channel can then be reopened with parameters (e.g. channel ordering and version) that are different from the +original channel open handshake. + +## `SendCosmosMsgs` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/7773fbd8d4e227b6c942f0c88575f9800809b4bf/src/types/msg.rs#L42-L64 +``` + +Once an ICS-27 channel open handshake is complete, the owner can control the interchain account on the counterparty +chain. To give the owner a familiar interface, this message allows the owner to take actions with the interchain +account using `CosmosMsg`s. This is the recommended way to use the interchain account. We will go over the fields of +this message in detail. + +### `messages` + +This is a list of `CosmosMsg`s that the contract will execute on the counterparty chain using the interchain account. +This execution is atomic. If any of the `CosmosMsg`s fail, then the entire execution will fail. + +:::note + +All applicable `CosmosMsg`s are supported if the channel was opened with `tx_encoding` set to `proto3`. +The `proto3json` encoding is not supported by this contract anymore. + +| **CosmosMsg** | `proto3` | +|:------------------------------------------:|:--------:| +| `Stargate` | ✅ | +| `BankMsg::Send` | ✅ | +| `BankMsg::Burn` | ❌ | +| `IbcMsg::Transfer` | ✅ | +| `IbcMsg::SendPacket` | N/A | +| `IbcMsg::CloseChannel` | N/A | +| `WasmMsg::*` | ✅ | +| `GovMsg::*` | ✅ | +| `StakingMsg::Delegate` | ✅ | +| `StakingMsg::*` | 🟢 | +| `DistributionMsg::WithdrawDelegatorReward` | 🟢 | +| `DistributionMsg::*` | ✅ | + +Note that `🟢` means that the `CosmosMsg` is supported but not tested in the contract's test suite. +These will be tested in the future. + +::: + +### `queries` + +This is a list of `QueryRequest`s that the contract will execute on the counterparty chain using the interchain account. + +:::warning + +This feature only works if the host (counterparty) chain is on ibc-go v7.5+. If the host chain is on an older version, then the packet will return an error acknowledgement. + +::: + +:::info + +If both `messages` and `queries` are provided, then the `messages` will be executed first. If the `messages` are successful, then the `queries` will be executed. If any of the `queries` fail, then the entire execution will fail. + +::: + +:::note + +In CosmosSDK, query execution is not generally deterministic. This is the main reason why not all query requests are supported. The supported query requests are: + +| **QueryRequest** | `proto3` | +|:-------------------:|:--------:| +| `BankQuery` | ✅ | +| `Stargate` | ✅ | +| `StakingQuery` | ✅ | +| `IbcQuery` | ❌ | +| `DistributionQuery` | ❌ | +| `WasmQuery` | ❌ | + +Note that not all Stargate queries are supported. Only queries which are marked with [`module_query_safe`](https://github.com/cosmos/cosmos-sdk/blob/27a231ae4816fd8c3ee39a1cc02eccf977fb1b79/proto/cosmos/query/v1/query.proto#L36) tag are supported. You can find a list of supported queries in the [ibc-go documentation](https://ibc.cosmos.network/main/apps/interchain-accounts/messages/#queries) for different versions of ibc-go. + +Note that `WasmQuery` support will be added once [this issue](https://github.com/CosmWasm/wasmd/issues/1903) is resolved. Moreover, governance queries (as stargate queries) and `DistributionQuery` will be supported in the next version of the SDK. + +::: + +### `packet_memo` + +This is the IBC packet memo that will be included in the ICS-27 packet. It is optional and defaults to `""`. +Additionally, the memo field is used by some IBC middleware to execute custom logic on the counterparty chain. +But most of these middlewares do not yet support ICS-27 channels. + +### `timeout_seconds` + +This is the timeout in seconds that will be used for the ICS-27 packet. It is optional and defaults to [`DEFAULT_TIMEOUT_SECONDS`](https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/ibc/types/packet.rs#L15-L16). + +## `UpdateCallbackAddress` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/msg.rs#L92-L97 +``` + +This message is used to update the contract address that this contract will send callbacks to. +This is useful if the owner wants to change the contract that receives the callbacks. +If set to `None`, then no callbacks will be sent. + +## `UpdateOwnership` + +```rust reference +https://github.com/larry0x/cw-plus-plus/blob/ownable-v0.5.0/packages/ownable/derive/src/lib.rs#L86-L90 +``` + +This message type is provided by the [cw-ownable](https://crates.io/crates/cw-ownable) crate. It wraps a +`cw_ownable::Action` enum. + +```rust reference +https://github.com/larry0x/cw-plus-plus/blob/ownable-v0.5.0/packages/ownable/src/lib.rs#L31-L57 +``` + +The owner can propose to transfer the ownership of the contract to a new address using `Action::TransferOwnership` and +set and expiry time for the proposal. If the proposal is accepted before the expiry time through +`Action::AcceptOwnership`, then the ownership of the contract is transferred to the new address. + +You can learn more about `cw-ownable` in its crate documentation. diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/03-query-msg.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/03-query-msg.mdx new file mode 100644 index 00000000..bd70c163 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/03-query-msg.mdx @@ -0,0 +1,64 @@ +--- +title: QueryMsg +sidebar_label: QueryMsg +sidebar_position: 3 +slug: /contract-api/query-msg +--- + +# `QueryMsg` + +The `QueryMsg` is the message that allows you to see the state of the contract. Therefore, it is important to +understand the state of the contract. + +## `GetChannel` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/msg.rs#L105-L107 +``` + +This message is used to query the state of the ICS-27 channel as tracked by the contract. It returns + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/state.rs#L158-L166 +``` + +## `GetContractState` + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.0/src/types/msg.rs#L108-L110 +``` + +This message is used to query the state of the contract. It returns + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/state.rs#L39-L50 +``` + +Lets look at the fields of the `ContractState`: + +### `ica_info` + +This field will be empty if the channel handshake has not been completed. Otherwise, it will contain the +following information: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/state.rs#L90-L96 +``` + +### `callback_address` + +This is the contract address that the `cw-ica-controller` contract will send callbacks to. If this field is empty, +then the contract will not send callbacks. + +## `Ownership` + +```rust reference +https://github.com/larry0x/cw-plus-plus/blob/ownable-v0.5.0/packages/ownable/derive/src/lib.rs#L142-L144 +``` + +This message type is provided by the [cw-ownable](https://crates.io/crates/cw-ownable) crate. It allows to query +the ownership of the contract. It returns `Ownership`: + +```rust reference +https://github.com/larry0x/cw-plus-plus/blob/ownable-v0.5.0/packages/ownable/src/lib.rs#L14-L29 +``` diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/04-callbacks.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/04-callbacks.mdx new file mode 100644 index 00000000..f503d925 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/04-callbacks.mdx @@ -0,0 +1,138 @@ +--- +title: Callbacks +sidebar_label: Callbacks +sidebar_position: 4 +slug: /contract-api/callbacks +--- + +# 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`](./02-execute-msg.mdx#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: + +```rust title="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: + +```rust title="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. + +```rust +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: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.1/testing/contracts/callback-counter/src/contract.rs#L28-L40 +``` + +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: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/7773fbd8d4e227b6c942f0c88575f9800809b4bf/src/types/callbacks.rs#L15-L59 +``` + +### 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`](https://github.com/CosmWasm/cosmwasm/blob/v1.5.2/packages/std/src/ibc.rs#L115-L128) 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. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.1/src/ibc/types/packet.rs#L169-L177 +``` + +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`](https://github.com/CosmWasm/cosmwasm/blob/v1.5.2/packages/std/src/ibc.rs#L195-L207) + +- **`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`](https://github.com/srdtrk/cw-ica-controller/blob/7773fbd8d4e227b6c942f0c88575f9800809b4bf/src/types/query_msg.rs#L93-L106) + +### 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`](https://github.com/CosmWasm/cosmwasm/blob/v1.5.2/packages/std/src/ibc.rs#L195-L207) + +- **`relayer`**: This is the address of the relayer that relayed the packet to the counterparty chain. diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/05-events.mdx b/docs/versioned_docs/version-v0.6.x/contract-api/05-events.mdx new file mode 100644 index 00000000..db248684 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/05-events.mdx @@ -0,0 +1,40 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 5 +slug: /contract-api/events +--- + +# Events + +The `cw-ica-controller` contract emits events upon various channel and packet lifecycle events. +I haven't really thought about what events should be emitted, so this is a work in progress and feel free to open +an issue if you have any suggestions. Changes in events will not be considered breaking changes as they are not +stored on the blockchain, thus, can be included in patch releases. + +Core IBC already emits events for channel and packet lifecycle events, so we keep the events to a minimum. + +The only events emitted by the contract are when an acknowledgement packet is received, so that an external +indexer can index the result of the packet execution. + +## Attributes + +Whether or not the result of the packet execution was successful, the following attributes are emitted: + +| **Attribute Key** | **Attribute Value** | +|:--------------------:|:-------------------:| +| `packet_sequence` | String | +| `packet_src_port` | String | +| `packet_src_channel` | String | + +If the packet execution was successful, then the following attributes are also emitted: + +| **Attribute Key** | **Attribute Value** | +|:-------------------:|:-------------------:| +| `packet_ack_base64` | Base64 (String) | + +If the packet execution was unsuccessful, then the following attributes are also emitted: + +| **Attribute Key** | **Attribute Value** | +|:-----------------:|:-------------------:| +| `error` | String | diff --git a/docs/versioned_docs/version-v0.6.x/contract-api/_category_.json b/docs/versioned_docs/version-v0.6.x/contract-api/_category_.json new file mode 100644 index 00000000..efb2a00e --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/contract-api/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Contract API", + "position": 1, + "link": { "type": "doc", "id": "intro" } +} diff --git a/docs/versioned_docs/version-v0.6.x/how-it-works/01-introduction.mdx b/docs/versioned_docs/version-v0.6.x/how-it-works/01-introduction.mdx new file mode 100644 index 00000000..4026ce3a --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/how-it-works/01-introduction.mdx @@ -0,0 +1,38 @@ +--- +title: Introduction +sidebar_label: Introduction +sidebar_position: 1 +slug: /how-it-works/introduction +--- + +# How it works? + +:::info + +[ICS-27](https://github.com/cosmos/ibc/tree/main/spec/app/ics-027-interchain-accounts) is an interchain standard +that specifies packet data structure, state machine handling logic, and encoding details for the account management +system over an IBC channel between separate chains. + +::: + +CosmWasm provides native entry points for IBC channel and packet semantics (known as [ICS-4](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics)). +This allows CosmWasm contracts to implement interchain specifications for IBC applications. Some notable examples are: + +- [`cw20-ics20`](https://github.com/CosmWasm/cw-plus/tree/main/contracts/cw20-ics20) contract which implements the [ICS-20](https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer) fungible token transfer standard. +- [`cw-ics721`](https://github.com/public-awesome/cw-ics721) contract which implements the [ICS-721](https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer) non-fungible token transfer standard. + +CosmWasm ICA Controller is a contract that implements the [ICS-27](https://github.com/cosmos/ibc/tree/main/spec/app/ics-027-interchain-accounts) interchain accounts standard. It allows this contract to manage accounts an another chain. +This means that this contract doesn't rely on the golang implementation of the ICS-27, but rather implements it in Rust and provides a CosmWasm native API for managing accounts on another chain. + +It is important to note that this contract is not a full implementation of the ICS-27 standard. It only implements the +controller contract, which is responsible for creating and managing accounts on another chain. The contract does not +implement the ICA host module, which is responsible for executing the ICA transactions sent by the controller contract. + +Most IBC enabled chains do have the golang implementation of the ICS-27 standard, so you can use the CosmWasm ICA +Controller contract to manage accounts on those chains, the Cosmos Hub, Osmosis, etc. + +In this section, we will go over the following topics: + +- ⚔️ [Golang ICA Controller vs CosmWasm ICA Controller](./02-go-vs-cosmwasm.mdx) +- 🤝 [Channel Opening Handshake](./03-channel-handshake.mdx) +- ✉️ [Packet Data Structure](./04-packet-data.mdx) diff --git a/docs/versioned_docs/version-v0.6.x/how-it-works/02-go-vs-cosmwasm.mdx b/docs/versioned_docs/version-v0.6.x/how-it-works/02-go-vs-cosmwasm.mdx new file mode 100644 index 00000000..844bf7a7 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/how-it-works/02-go-vs-cosmwasm.mdx @@ -0,0 +1,48 @@ +--- +title: Go vs CosmWasm +sidebar_label: Go vs CosmWasm +sidebar_position: 2 +slug: /how-it-works/go-vs-cosmwasm +--- + +# Golang ICA Controller vs CosmWasm ICA Controller + +The golang implementation of the ICS-27 controller standard is also widely deployed on IBC enabled chains, with some +notable exceptions being the Cosmos Hub and Osmosis. + +A contract developer could use the golang implementation of the ICA controller by submitting `CosmosMsg::Stargate` +messages which would be handled by the golang implementation of the ICA controller. + +:::warning + +Using the golang implementation comes with a great disadvantage, which is that the golang implementation does not +make callbacks to the contract that submitted the `CosmosMsg::Stargate` message! This means that the contract that +submitted the `CosmosMsg::Stargate` message will not be able to know the result of the ICA transaction, nor the +address of the newly created account on the other chain without intervention. + +::: + +:::tip + +Currently, Neutron and Nolus have custom bindings for the golang implementation of the ICA controller standard, which +make callbacks to the contract that submitted the `CosmosMsg::Stargate` message. This means that you can use the +golang implementation of the ICA controller standard on Neutron and Nolus without any problems. However, any +applications that are built on these chains will not be able to be ported to other chains. + +::: + +`cw-ica-controller` solves this problem by making callbacks to a contract that the developer specifies. +This means that the users of `cw-ica-controller` can use the same contract on any chain that supports CosmWasm. + +But there is more! `cw-ica-controller` is also able to do some things that the golang API limits you from doing. + +| **Feature** | `cw-ica-controller` | golang `ica-controller` | neutron bindings | **Description** | +|:-------------------------------------------:|:-------------------:|:-----------------------:|:----------------:|:-------------------------------------------------------------------------------------------------------------------------:| +| Callbacks | ✅ | ❌ | ✅ | Golang implementation does not make callbacks | +| Submit `cosmwasm_std::CosmosMsg`s | ✅ | ❌ | ❌ | Golang implementation requires ICA transactions to be submitted in protobuf or `proto3json` format. | +| Reopen an ICA channel with different params | ✅ | ❌ | ❌ | In golang implementation, if the channel closes due to timeout the channel can only be reopened with the same parameters. | +| Change owner | ✅ | ❌ | ✅ | `cw-ica-controller` uses [`cw-ownable`][1] for owner management | +| Live upgrades | ✅ | ❌ | ❌ | In golang implementation, new features require coordinated chain upgrades which could get blocked on upgrading CosmosSDK. | +| Permanent channel closure | ✅ | ❌ | ❌ | Golang implementation allows any relayer to always reopen any ICA channel (with the same parameters). | + +[1]: https://github.com/larry0x/cw-plus-plus/tree/main/packages/ownable diff --git a/docs/versioned_docs/version-v0.6.x/how-it-works/03-channel-handshake.mdx b/docs/versioned_docs/version-v0.6.x/how-it-works/03-channel-handshake.mdx new file mode 100644 index 00000000..36dd4e5f --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/how-it-works/03-channel-handshake.mdx @@ -0,0 +1,94 @@ +--- +title: Channel Opening Handshake +sidebar_label: Channel Opening Handshake +sidebar_position: 3 +slug: /how-it-works/channel-handshake +--- + +import HighlightTag from '@site/src/components/HighlightTag'; + +# Channel Opening Handshake + + + +The channel opening handshake is a 4-step process (see [ICS-004](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics#opening-handshake) to learn more): + +1. **Channel Open Init** (source chain) +2. **Channel Open Try** (destination chain) +3. **Channel Open Ack** (source chain) +4. **Channel Open Confirm** (destination chain) + +Naturally, this contract only implements the first and third steps of the channel opening handshake, as the second and +fourth steps are handled by the counterparty ICA host module. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/ibc/handshake.rs#L15-L46 +``` + +## Channel Open Init + +### Authorization + +A channel open init message can be sent to any IBC module by any user, and it is up to the module to decide +whether to accept the request or not. + +In the case of `cw-ica-controller`, only the contract itself can send a channel open init message. Since the sender of +`MsgChannelOpenInit` is not passed to the contract (or any other IBC module), we enforce this by having a [state +variable](https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/types/state.rs#L41) that keeps track of whether +or not to accept channel open init messages. This variable is only set to true by the contract itself right before +it is about to send a channel open init message in [`InstantiateMsg`](../contract-api/01-instantiate-msg.mdx) or +[`ExecuteMsg::CreateChannel`](../contract-api/02-execute-msg.mdx#createchannel). + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/contract.rs#L130-L133 +``` + +### Version Metadata and Ordering + +Whenever a new channel is created, the submitter of `MsgChannelOpenInit` must propose a version string and ordering. + +In IBC, the version string is used to determine whether or not the two modules on either side of the channel are +compatible. The two modules are compatible if and only if they both support and agree on the same version string. +Moreover, the version string may carry arbitrary metadata encoded in JSON format. This metadata can be used to +carry key information about the channel, such as the encoding format, the application version, etc. + +The format of the version string for ICS-27 is specified [here](https://github.com/cosmos/ibc/tree/main/spec/app/ics-027-interchain-accounts#metadata-negotiation-summary). +The following rust code shows the version metadata struct used to encode the version string: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/ibc/types/metadata.rs#L19-L50 +``` + +Since it is the contract itself that submits the `MsgChannelOpenInit`, the contract constructs the version string +based on the `channel_open_init_options` that are passed to it in [`InstantiateMsg`](../contract-api/01-instantiate-msg.mdx) or [`ExecuteMsg::CreateChannel`](../contract-api/02-execute-msg.mdx#createchannel). + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/main/src/ibc/types/stargate.rs#L25-L57 +``` + +The actual entry point for the `MsgChannelOpenInit` only does validation checks on channel parameters. For example, +it checks that the channel is not already open. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/ibc/handshake.rs#L71-L126 +``` + +## Channel Open Ack + +Unlike the `MsgChannelOpenInit`, the `MsgChannelOpenAck` is submitted by a relayer, and we do not need to worry about +authorization. This step comes after the `MsgChannelOpenTry` is submitted by the counterparty ICA host module. In the +`Try` step, the counterparty ICA host module may propose a different version string. Therefore, the contract must +validate the version string and channel parameters once again in the `MsgChannelOpenAck`. + +:::note + +The interchain account address is passed to the contract in this step through the version string. In `Init` step, +`cw-ica-controller` leaves the interchain account address empty, and the counterparty ICA host module fills it in. + +::: + +After validating the version string, the contract then stores the channel parameters in its state. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.4.2/src/ibc/handshake.rs#L128-L188 +``` diff --git a/docs/versioned_docs/version-v0.6.x/how-it-works/04-packet-data.mdx b/docs/versioned_docs/version-v0.6.x/how-it-works/04-packet-data.mdx new file mode 100644 index 00000000..cdba47ed --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/how-it-works/04-packet-data.mdx @@ -0,0 +1,49 @@ +--- +title: Packet Data +sidebar_label: Packet Data +sidebar_position: 4 +slug: /how-it-works/packet-data +--- + +import HighlightTag from '@site/src/components/HighlightTag'; + +# Packet Data Structure + + + +The data that is sent over an IBC channel is called a packet. The packet data is defined by the IBC application module +that is sending the packet. In the case of `cw-ica-controller`, the packet data is defined by the ICS-27 specification. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/ibc/types/packet.rs#L18-L44 +``` + +The data field is encoded as protobuf bytes using the following function: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/6843b80b29af97b9c4561ad487420e2f54857553/src/ibc/types/packet.rs#L90-L96 +``` + +## From CosmosMsg to Packet Data + +Since this contract also provides an execute message to send `CosmosMsg`s as ICA packets, we have a helper function +that converts a `CosmosMsg` to a packet data: + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/6843b80b29af97b9c4561ad487420e2f54857553/src/ibc/types/packet.rs#L98-L133 +``` + +The specific conversion of each `CosmosMsg` variant into a protobuf any can be found in +[`cosmos_msg.rs`](https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/types/cosmos_msg.rs). + +## Acknowledgement Data + +For each packet that is sent, the receiving module must respond with an acknowledgement packet. The acknowledgement +packet is used to signal whether or not the ICA packet was successfully executed. The acknowledgement data is defined by the ICS-27 specification. + +```rust reference +https://github.com/srdtrk/cw-ica-controller/blob/v0.5.0/src/ibc/types/packet.rs#L169-L177 +``` + +`cw-ica-controller` includes the acknowledgement packet in the [callbacks](../contract-api/04-callbacks.mdx) that +it makes to the external contract. diff --git a/docs/versioned_docs/version-v0.6.x/how-it-works/_category_.json b/docs/versioned_docs/version-v0.6.x/how-it-works/_category_.json new file mode 100644 index 00000000..b36fa485 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.x/how-it-works/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "How it works?", + "position": 2, + "link": null +} diff --git a/docs/versioned_sidebars/version-v0.6.x-sidebars.json b/docs/versioned_sidebars/version-v0.6.x-sidebars.json new file mode 100644 index 00000000..39332bfe --- /dev/null +++ b/docs/versioned_sidebars/version-v0.6.x-sidebars.json @@ -0,0 +1,8 @@ +{ + "docsSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index 6a78cf57..6e389a6e 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,4 +1,5 @@ [ + "v0.6.x", "v0.5.x", "v0.4.x" ]