使用 /v2/fungible/msgs 端点的 post_route_handler 参数,可以定义在路由转账或兑换完成后、于目标链上执行的操作。这些操作会与原始兑换或转账在同一笔交易中执行。 通过这个处理器,开发者可以构建全链与全代币工作流,让用户从 Cosmos 中的任意链或任意代币出发,在单笔交易中完成兑换、流动性质押、存款、购买 NFT 或其他任意操作。 该参数当前支持:
  1. 在目标链上调用 CosmWasm 合约
  2. 支持在 Stride 上进行流动性质押交互的 autopilot

背景信息

所有 post_route 操作都必须满足以下特性:
  • 无需许可: Skip Go 只能支持无需许可的操作,因为底层协议(例如 IBC hooks、IBC callbacks、packet-forward-middleware)会根据转账来源推导出用于调用合约的地址。Skip Go 会根据目标链接入的模块,支持 ibc-hooks 和 ibc-callbacks 两种方式(两者互不兼容),并自动为各自生成合适的消息负载。这意味着,同一个用户如果从两条不同链发起,或以两种不同代币作为起点,最终调用目标合约或模块时使用的地址都会不同。只有在你能确定某个操作 1)始终从同一条链发起,且 2)始终通过同一路径到达目标链时,才可能可靠地为其配置权限。通常情况下,除非你是互操作性专家,否则我们不建议做这种假设。
  • 单代币输入: 底层 IBC 转账协议(ICS-20)不支持在单条转账消息中传输超过 1 种代币 denom,因此我们一次只能向最终合约或模块发送 1 种代币 denom。这意味着 post_route_handler 中的合约或模块不能要求同时接收多种代币 denom。例如,经典的 LP 操作通常要求用户同时提供资金池两侧的代币,这种场景就无法支持。
对于支持后续受限操作的无需许可动作,请使用带本地地址的 authority delegation很多情况下,用户与合约的第一次交互本身是无需许可的,但它会授予终端用户某种需要权限的后续操作能力(例如:质押后可解质押和领取奖励;存款后可提款和获得收益),或发放回执类代币(例如:提供 LP 后获得 LP 回执代币)。作为跨链调用方,你通常应避免使用那些会把这些权限隐式委托给调用者,或把回执代币直接发给调用者的合约,因为调用者地址会依赖用户通过 IBC 所经过的路径。你应优先寻找支持 authority delegation 的合约,也就是能在 calldata 中显式把权限分配给某个地址的合约,该地址可以不同于调用者以及发送代币的地址。此模式的示例包括:
  • Astroport 在 provide_liquidity 消息中的 receiver 参数
  • Mars 在 deposit 消息中的 on_behalf_of 参数
  • Astroport 在 swap 消息中的 to 参数
我们建议将这些 authority delegation 参数设置为用户在目标链上的本地地址,这样他们后续就可以在本地执行相关操作。

CosmWasm

要在目标链上调用 CosmWasm 合约,需要满足以下条件:
  1. 目标链支持 CosmWasm,并且支持 ibc-hooks 或 ibc-callbacks 之一。
  2. 路由中位于目标链之前的那条链支持 IBC memo,并且支持 packet-forward-middleware。
要在目标链上指定一次 CosmWasm 合约调用,请在 /v2/fungible/msgs 请求中将 wasm_msg 作为 post_route_handler 传入,其中包括:
  • contract_address:目标合约地址
  • msg:传递给合约的消息 JSON 字符串
此外,还需要将 address_list 中的目标地址设置为该合约地址。 例如,下面这个请求表示将 USDC 从 Axelar 转账到 Neutron,并通过 post-route handler 在 Neutron 上使用 Astroport 池将 USDC 兑换为 Neutron:
{
  "source_asset_denom": "uusdc",
  "source_asset_chain_id": "axelar-dojo-1",
  "dest_asset_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
  "dest_asset_chain_id": "neutron-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "axelar1x8ad0zyw52mvndh7hlnafrg0gt284ga7u3rez0",
    "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-78",
        "chain_id": "axelar-dojo-1",
        "pfm_enabled": false,
        "dest_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "wasm_msg": {
      "contract_address": "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3",
        "msg": "{\"swap\":{\"offer_asset\":{\"info\":{\"native_token\":{\"denom\":\"ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349\"}},\"amount\":\"10000\"},\"to\":\"neutron1x8ad0zyw52mvndh7hlnafrg0gt284ga7uqunnf\"}}"
    }
  }
}

请注意,address_list 中提供的最后一个地址是 Neutron 上的池合约地址,而不是用户地址。 该请求返回的消息会在 Neutron 上使用 ibc-hooks,从而在 IBC 转账的同时原子性地执行 CosmWasm 合约调用。

Autopilot

要在路由后操作中使用 Autopilot,需要满足以下条件:
  1. 目标链支持 autopilot 模块。目前这意味着目标链必须是 stride-1。
  2. 路由中位于目标链之前的那条链支持 IBC memo,并且支持 packet-forward-middleware。
要在目标链上指定一次 Autopilot 操作,请在 /v2/fungible/msgs 请求中将 autopilot_msg 作为 post_route_handler 传入,其中包括:
  • receiver:设置为你要代表其执行该操作的地址
  • action:一个枚举值,用于指定你希望执行的操作
    • 可选值包括 LIQUID_STAKE(用于对资产进行流动性质押)或 CLAIM(用于更新空投领取地址)。
例如,下面这个请求表示将 ATOM 从 Cosmos Hub 转账到 Stride,并通过 post-route handler 在 Stride 上以原子方式对转入的 ATOM 进行流动性质押,并将 stATOM 发送给 Stride 上指定的接收地址:
{
  "source_asset_denom": "uatom",
  "source_asset_chain_id": "cosmoshub-4",
  "dest_asset_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
  "dest_asset_chain_id": "stride-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "cosmos1x8ad0zyw52mvndh7hlnafrg0gt284ga7cl43fw",
    "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-391",
        "chain_id": "cosmoshub-4",
        "pfm_enabled": true,
        "dest_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "autopilot_msg": {
      "receiver": "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz",
      "action": "LIQUID_STAKE"
    }
  }
}
有问题或反馈?欢迎帮助我们做得更好!加入我们的 Discord,并选择 “Skip Go Developer” 角色,与我们分享你的问题和反馈。

Use the post_route_handler parameter of /v2/fungible/msgs endpoint to define actions that will be executed on the destination chain after a route transfer or swap is completed. These actions are executed within the same transaction as the original swap or transfer. This handler allows developers to build omni-chain and omni-token workflows where users can swap, liquid stake, deposit, buy an NFT, or take any other action starting from any chain or any token in Cosmos — all in a single transaction. This parameter currently supports:
  1. CosmWasm contract calls on the destination chain
  2. autopilot support for liquid staking interactions on Stride

Background Info

All post_route actions must have the following characteristics:
  • Permissionless: Skip Go can only support permissionless actions because the underlying protocols (e.g. IBC hooks, IBC callbacks, packet-forward-middleware) derive the addresses they use to call contracts based on the origin of the transfer. Skip Go supports both ibc-hooks and ibc-callbacks depending on which module the destination chain has implemented (they are incompatible approaches), automatically generating the appropriate message payloads for each. This means one user originating on two different chains or starting with two different tokens will eventually call the final contract / module with different addresses. You can only reliably permission actions that you know will 1) always originate on the same chain and 2) always take the same path to the destination chain. In general, we recommend not making this assumption unless you are an interoperability expert
  • Single-token input: The underlying IBC transfer protocol (ICS-20) doesn’t support transfers of more than 1 token denom in a single transfer message, so we can only send 1 token denom to the final contract or module at a time. This means the contract or module in the post_route_handler must not require multiple token denoms sent to it simultaneously. For example, a classic LP action where the user must provide tokens in both sides of the pool simultaneously would not work.
Use authority-delegation with local address for permissionless actions that enable permissioned follow-upsCommonly, the first interaction with a contract is permissionless, but it awards the end-user some kind of permissioned authority to perform follow-on actions (e.g. staking enables unstaking + collecting rewards; depositing enables withdrawing and earning yield) or receipt tokens (e.g. LPing produces LP receipt tokens).As a cross-chain caller, you should generally avoid contracts that implicitly delegate these authorities or give receipt tokens to the caller because the caller will depend on the path the user has taken over IBC. You should look for contracts to imply authority delegation — i.e. contracts that explicitly assign permissions to an address in the calldata that may be different than the caller and address sending the tokens. Examples of this pattern are:
  • Astroport’s receiver parameter in the provide_liquidity message
  • Mars’ on_behalf_of parameter in the deposit message
  • Astroport’s to parameter in the swap message
We recommend setting these authority delegation parameters to the user’s local address on the destination chain, so they can perform future actions locally.

CosmWasm

To call a CosmWasm contract on the destination chain, the following requirements must be satisfied:
  1. The destination chain supports CosmWasm & either ibc-hooks or ibc-callbacks.
  2. The chain in the route immediately before the destination chain supports IBC memos as well as packet-forward-middleware.
To specify a CosmWasm contract call on the destination chain, pass a wasm_msg as the post_route_handler in the /v2/fungible/msgs call with:
  • contract_address: The target contract address
  • msg: JSON string of the message to pass to the contract
In addition, set the destination address in the address_list to the address of the contract. For example, this is a request for a transfer of USDC from Axelar to Neutron, with a post-route handler that swaps the USDC to Neutron using an Astroport pool on Neutron:
{
  "source_asset_denom": "uusdc",
  "source_asset_chain_id": "axelar-dojo-1",
  "dest_asset_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
  "dest_asset_chain_id": "neutron-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "axelar1x8ad0zyw52mvndh7hlnafrg0gt284ga7u3rez0",
    "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-78",
        "chain_id": "axelar-dojo-1",
        "pfm_enabled": false,
        "dest_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "wasm_msg": {
      "contract_address": "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3",
        "msg": "{\"swap\":{\"offer_asset\":{\"info\":{\"native_token\":{\"denom\":\"ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349\"}},\"amount\":\"10000\"},\"to\":\"neutron1x8ad0zyw52mvndh7hlnafrg0gt284ga7uqunnf\"}}"
    }
  }
}

Note that the last address provided in the address_list is the address of the pool contract on Neutron, rather than a user address. The message returned from this request uses ibc-hooks on Neutron to perform the CosmWasm contract call atomically with the IBC transfer.

Autopilot

To use Autopilot after route actions, the following requirements must be satisfied:
  1. The destination chain supports the autopilot module. Currently, this means the destination chain must be stride-1.
  2. The chain in the route immediately before the destination chain supports IBC memos as well as packet-forward-middleware.
To specify an Autopilot action on the destination chain, pass a autopilot_msg as the post_route_handler in the /v2/fungible/msgs call with:
  • receiver: Set to the address on behalf of which you’re performing the action
  • action: An enum giving the action that you wish to execute
    • This may be one of LIQUID_STAKE (for liquid staking an asset) or CLAIM for updating airdrop claim addresses.
For example, this is a request for a transfer of ATOM from Cosmos Hub to Stride, with a post-route handler that atomically liquid stakes the transferred ATOM on Stride, sending stATOM to the specific receiver on Stride:
{
  "source_asset_denom": "uatom",
  "source_asset_chain_id": "cosmoshub-4",
  "dest_asset_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
  "dest_asset_chain_id": "stride-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "cosmos1x8ad0zyw52mvndh7hlnafrg0gt284ga7cl43fw",
    "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-391",
        "chain_id": "cosmoshub-4",
        "pfm_enabled": true,
        "dest_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "autopilot_msg": {
      "receiver": "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz",
      "action": "LIQUID_STAKE"
    }
  }
}
Have questions or feedback? Help us get better!Join our Discord and select the “Skip Go Developer” role to share your questions and feedback.