Skip to content

Commit

Permalink
docs: update transfer docs with support for path forwarding (#6813)
Browse files Browse the repository at this point in the history
* docs: path forwarding

* create ICS20 v1 folder for pre-v9 transfer docs

* clean up

* clarification

* nil forwarding hops

* fix link

* lint + added info about v2 channels

* lint: new line

* Apply suggestions from code review

Co-authored-by: DimitrisJim <[email protected]>

* update images

---------

Co-authored-by: DimitrisJim <[email protected]>
  • Loading branch information
crodriguezvega and DimitrisJim authored Jul 16, 2024
1 parent 45ecd69 commit 69b4cba
Show file tree
Hide file tree
Showing 18 changed files with 747 additions and 38 deletions.
1 change: 0 additions & 1 deletion docs/docs/01-ibc/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ sidebar_position: 1
slug: /ibc/overview
---


# Overview

:::note Synopsis
Expand Down
43 changes: 43 additions & 0 deletions docs/docs/02-apps/01-transfer/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,49 @@ chain #1 -> ... -> chain #(n-1) -> final chain`). These services could provide m
The only viable alternative for clients (at the time of writing) to tokens with multiple connection hops, is to connect to all chains directly and perform relevant queries to each of them in the sequence.
:::

## Forwarding

:::info
Token forwarding and unwinding is supported only on ICS20 v2 transfer channels.
:::

Forwarding allows tokens to be routed to a final destination through multiple (up to 8) intermediary
chains. With forwarding, it's also possible to unwind IBC vouchers to their native chain, and forward
them afterwards to another destination, all with just a single transfer transaction on the sending chain.

### Forward tokens

Native tokens or IBC vouchers on any chain can be forwarded through intermediary chains to reach their
final destination. For example, given the topology below, with 3 chains and a transfer channel between
chains A and B and between chains B and C:

![Light Mode Forwarding](./images/forwarding-3-chains-light.png#gh-light-mode-only)![Dark Mode Forwarding](./images/forwarding-3-chains-dark.png#gh-dark-mode-only)

Native tokens on chain `A` can be sent to chain `C` through chain `B`. The routing is specified by the
source port ID and channel ID of choice on every intermediary chain. In this example, there is only one
forwarding hop on chain `B` and the port ID, channel ID pair is `transfer`, `channelBToC`. Forwarding of
a multi-denom collections of tokens is also allowed (i.e. forwarding of tokens of different denominations).

### Unwind tokens

Taking again as an example the topology from the previous section, we assume that native tokens on chain `A`
have been transfered to chain `C`. The IBC vouchers on chain `C` have the denomination trace
`transfer/channelCtoB/transfer/channelBtoA`, and with forwarding it is possible to submit a transfer message
on chain `C` and automatically unwind the vouchers through chain `B` to chain `A`, so that the tokens recovered
on the origin chain regain their native denomination. In order to execute automatic unwinding, the transfer
module does not require extra user input: the unwind route is encoded in the denomination trace with the
pairs of destination port ID, channel ID that are added on every chain where the tokens are received.

Please note that unwinding of vouchers is only allowed when vouchers of a single IBC denomination are
transferred (i.e. it is not possible to unwind vouchers of two different IBC denominations, since they
come from different source chains).

### Unwind tokens and then forward

Unwinding and forwarding can be used in combination, so that vouchers are first unwound to their origin chain
and then forwarded to a final destination. The same restriction as in the unwinding case applies: only vouchers
of a single IBC denomination can be used.

## Locked funds

In some [exceptional cases](/architecture/adr-026-ibc-client-recovery-mechanisms#exceptional-cases), a client state associated with a given channel cannot be updated. This causes that funds from fungible tokens in that channel will be permanently locked and thus can no longer be transferred.
Expand Down
24 changes: 23 additions & 1 deletion docs/docs/02-apps/01-transfer/04-messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,25 @@ type MsgTransfer struct {
TimeoutTimestamp uint64
Memo string
Tokens []sdk.Coin
Forwarding *Forwarding
}

type Forwarding struct {
Unwind bool
Hops []Hop
}

type Hop struct {
PortId string
ChannelId string
}
```

This message is expected to fail if:
:::info
Multi-denom token transfers and token forwarding are features supported only on ICS20 v2 transfer channels.
:::

If `Forwarding` is `nil`, this message is expected to fail if:

- `SourcePort` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators).
- `SourceChannel` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)).
Expand All @@ -39,6 +54,11 @@ This message is expected to fail if:
- `Memo` contains more than 32768 bytes.
- `TimeoutHeight` and `TimeoutTimestamp` are both zero.

If `Forwarding` is not `nil`, then to use forwarding you must either set `Unwind` to true or provide a non-empty list of `Hops`. Setting both `Unwind` to true and providing a non-empty list of `Hops` is allowed, but the total number of hops that is formed as a combination of the hops needed to unwind the tokens and the hops to forward them afterwards to the final destination must not exceed 8. When using forwarding, timeout must be specified using only `TimeoutTimestamp` (i.e. `TimeoutHeight` must be zero). Please note that the timeout timestamp must take into account the time that it may take tokens to be forwarded through the intermediary chains. Additionally, please note that the `MsgTransfer` will fail if:

- `Hops` is not empty, and the number of elements of `Hops` is greater than 8, or either the `PortId` or `ChannelId` of any of the `Hops` is not a valid identifier.
- `Unwind` is true, and either the number of elements in `Tokens` is greater than 1, or `SourcePort` and `SourceChannel` are not empty strings (they must be empty because they are set by the transfer module, since it has access to the denomination trace information and is thus able to know the source port ID, channel ID to use in order to unwind the tokens). If `Unwind` is true, the transfer module expects the tokens in `MsgTransfer` to not be native to the sending chain (i.e. they must be IBC vouchers).

Please note that the `Token` field is deprecated and users should now use `Tokens` instead. If `Token` is used then `Tokens` must be empty. Similarly, if `Tokens` is used then `Token` should be left empty.
This message will send a fungible token to the counterparty chain represented by the counterparty Channel End connected to the Channel End with the identifiers `SourcePort` and `SourceChannel`.

Expand All @@ -61,3 +81,5 @@ For example, the following memo field is used by the [callbacks middleware](../.
```

You can find more information about other applications that use the memo field in the [chain registry](https://github.com/cosmos/chain-registry/blob/master/_memo_keys/ICS20_memo_keys.json).

Please note that the memo field is always meant to be consumed only on the final destination chain. This means that the transfer module will guarantee that the memo field in the intermediary chains is empty.
70 changes: 37 additions & 33 deletions docs/docs/02-apps/01-transfer/05-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,49 @@ slug: /apps/transfer/events

## `MsgTransfer`

| Type | Attribute Key | Attribute Value |
|--------------|---------------|-----------------|
| ibc_transfer | sender | \{sender\} |
| ibc_transfer | receiver | \{receiver\} |
| ibc_transfer | tokens | \{jsonTokens\} |
| ibc_transfer | memo | \{memo\} |
| message | module | transfer |
| Type | Attribute Key | Attribute Value |
|--------------|-----------------|------------------------|
| ibc_transfer | sender | \{sender\} |
| ibc_transfer | receiver | \{receiver\} |
| ibc_transfer | tokens | \{jsonTokens\} |
| ibc_transfer | memo | \{memo\} |
| ibc_transfer | forwarding_hops | \{jsonForwardingHops\} |
| message | module | transfer |

## `OnRecvPacket` callback

| Type | Attribute Key | Attribute Value |
|-----------------------|---------------|------------------|
| fungible_token_packet | sender | \{sender\} |
| fungible_token_packet | receiver | \{receiver\} |
| fungible_token_packet | tokens | \{jsonTokens\} |
| fungible_token_packet | memo | \{memo\} |
| fungible_token_packet | success | \{ackSuccess\} |
| fungible_token_packet | error | \{ackError\} |
| denomination | trace_hash | \{hex_hash\} |
| denomination | denom | \{jsonDenom\} |
| message | module | transfer |
| Type | Attribute Key | Attribute Value |
|-----------------------|-----------------|------------------------|
| fungible_token_packet | sender | \{sender\} |
| fungible_token_packet | receiver | \{receiver\} |
| fungible_token_packet | tokens | \{jsonTokens\} |
| fungible_token_packet | memo | \{memo\} |
| fungible_token_packet | forwarding_hops | \{jsonForwardingHops\} |
| fungible_token_packet | success | \{ackSuccess\} |
| fungible_token_packet | error | \{ackError\} |
| denomination | trace_hash | \{hex_hash\} |
| denomination | denom | \{jsonDenom\} |
| message | module | transfer |

## `OnAcknowledgePacket` callback

| Type | Attribute Key | Attribute Value |
|-----------------------|-----------------|------------------|
| fungible_token_packet | sender | \{sender\} |
| fungible_token_packet | receiver | \{receiver\} |
| fungible_token_packet | tokens | \{jsonTokens\} |
| fungible_token_packet | memo | \{memo\} |
| fungible_token_packet | acknowledgement | \{ack.String()\} |
| fungible_token_packet | success / error | \{ack.Response\} |
| message | module | transfer |
| Type | Attribute Key | Attribute Value |
|-----------------------|-----------------|------------------------|
| fungible_token_packet | sender | \{sender\} |
| fungible_token_packet | receiver | \{receiver\} |
| fungible_token_packet | tokens | \{jsonTokens\} |
| fungible_token_packet | memo | \{memo\} |
| fungible_token_packet | forwarding_hops | \{jsonForwardingHops\} |
| fungible_token_packet | acknowledgement | \{ack.String()\} |
| fungible_token_packet | success / error | \{ack.Response\} |
| message | module | transfer |

## `OnTimeoutPacket` callback

| Type | Attribute Key | Attribute Value |
|---------|-----------------|-----------------|
| timeout | refund_receiver | \{receiver\} |
| timeout | refund_tokens | \{jsonTokens\} |
| timeout | memo | \{memo\} |
| message | module | transfer |
| Type | Attribute Key | Attribute Value |
|---------|-----------------|------------------------|
| timeout | refund_receiver | \{receiver\} |
| timeout | refund_tokens | \{jsonTokens\} |
| timeout | memo | \{memo\} |
| timeout | forwarding_hops | \{jsonForwardingHops\} |
| message | module | transfer |
14 changes: 11 additions & 3 deletions docs/docs/02-apps/01-transfer/08-authorizations.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sidebar_label: Authorizations
sidebar_position: 8
slug: /apps/transfer/authorizations
---

# `TransferAuthorization`

`TransferAuthorization` implements the `Authorization` interface for `ibc.applications.transfer.v1.MsgTransfer`. It allows a granter to grant a grantee the privilege to submit `MsgTransfer` on its behalf. Please see the [Cosmos SDK docs](https://docs.cosmos.network/v0.47/modules/authz) for more details on granting privileges via the `x/authz` module.
Expand All @@ -17,12 +18,10 @@ The granter may be able to specify the list of addresses that they allow to rece
It takes:

- a `SourcePort` and a `SourceChannel` which together comprise the unique transfer channel identifier over which authorized funds can be transferred.

- a `SpendLimit` that specifies the maximum amount of tokens the grantee can transfer. The `SpendLimit` is updated as the tokens are transferred, unless the sentinel value of the maximum value for a 256-bit unsigned integer (i.e. 2^256 - 1) is used for the amount, in which case the `SpendLimit` will not be updated (please be aware that using this sentinel value will grant the grantee the privilege to transfer **all** the tokens of a given denomination available at the granter's account). The helper function `UnboundedSpendLimit` in the `types` package of the `transfer` module provides the sentinel value that can be used. This `SpendLimit` may also be updated to increase or decrease the limit as the granter wishes.

- an `AllowList` list that specifies the list of addresses that are allowed to receive funds. If this list is empty, then all addresses are allowed to receive funds from the `TransferAuthorization`.

- an `AllowedPacketData` list that specifies the list of memo strings that are allowed to be included in the memo field of the packet. If this list is empty, then only an empty memo is allowed (a `memo` field with non-empty content will be denied). If this list includes a single element equal to `"*"`, then any content in `memo` field will be allowed.
- an `AllowedForwarding` list that specifies the combinations of source port ID/channel ID pairs through which the tokens are allowed to be forwarded until final destination. Please note that granters are expected to specify the unwinding route of IBC vouchers if they wish to allow grantees to unwind the vouchers to their native chain (i.e. grantees cannot make use of the `Unwind` flag and must also set the source port ID, channel ID pairs required to unwind the vouchers in the forwarding `Hops` field).

Setting a `TransferAuthorization` is expected to fail if:

Expand All @@ -32,6 +31,7 @@ Setting a `TransferAuthorization` is expected to fail if:
- the source channel ID is invalid
- there are duplicate entries in the `AllowList`
- the `memo` field is not allowed by `AllowedPacketData`
- the forwarding hops do not match any of the combinations specified in `AllowedForwarding`

Below is the `TransferAuthorization` message:

Expand All @@ -54,5 +54,13 @@ type Allocation struct {
// allow list of memo strings, an empty list prohibits all memo strings;
// a list only with "*" permits any memo string
AllowedPacketData []string
// Optional list of allowed combinations of source port ID/channel ID pairs
// through which the tokens are allowed to be forwarded until final
// destination
AllowedForwarding []AllowedForwarding
}

type AllowedForwarding struct {
Hops []Hop
}
```
28 changes: 28 additions & 0 deletions docs/docs/02-apps/01-transfer/09-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,34 @@ The `query` commands allow users to query `transfer` state.
simd query ibc-transfer --help
```

#### Transactions

The `tx` commands allow users to interact with the controller submodule.

```shell
simd tx ibc-transfer --help
```

#### `transfer`

The `transfer` command allows users to execute cross-chain token transfers from the source port ID and channel ID on the sending chain.

```shell
simd tx ibc-transfer transfer [src-port] [src-channel] [receiver] [coins] [flags]
```

Multiple tokens can be transferred on the same transaction by specifying a comma-separated list
of amount and denomination (e.g. `100uatom,100uosmo`) in the `coins` option.

The additional flags that can be used with the command are:

- `--packet-timeout-height` to specify the timeout block height in the format `{revision}-{height}`. The default value is `0-0`, which effectively disables the timeout. Timeout height can only be absolute, therefore this option must be used in combination with `--absolute-timeouts` set to true.
- `--packet-timeout-timestamp` to specify the timeout timestamp in nanoseconds. The timeout can be either relative (fromthe current UTC time) or absolute. The default value is 10 minutes (and thus relative). The timeout is disabled when set to 0.
- `--absolute-timeouts` to interpret the timeout timestamp as an aboslute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time).
- `--memo` to specify the memo string to be sent along with the transfer packet. If forwarding is used, then the memo string will be carried through the intermediary chains to the final destination.
- `--forwarding` to specify forwarding information in the form of a comma separated list of source port ID/channel ID pairs at each intermediary chain (e.g. `transfer/channel-0,transfer/channel-1`).
- `--unwind` to specify if the tokens must be automatically unwound to there origin chain. This option can be used in combination with `--forwarding` to forward the tokens to the final destination after unwinding. When this flag is true, the `coins` option must specify a single coin.

#### `total-escrow`

The `total-escrow` command allows users to query the total amount in escrow for a particular coin denomination regardless of the transfer channel from where the coins were sent out.
Expand Down
Loading

0 comments on commit 69b4cba

Please sign in to comment.