From 3551d9add7fbd1ba50ac1bd15ff230c952d93680 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 24 May 2021 16:00:56 +0200 Subject: [PATCH 1/6] Update data structures to match implementation, note on JSON encoding --- .../ics-020-fungible-token-transfer/README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index 1aae8b0dd..6fde0ecca 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -34,7 +34,7 @@ The IBC handler interface & IBC routing module interface are as defined in [ICS ### Data Structures -Only one packet data type, `FungibleTokenPacketData`, which specifies the denomination, amount, sending account, receiving account, and whether the sending chain is the source of the asset, is required. +Only one packet data type is required: `FungibleTokenPacketData`, which specifies the denomination, amount, sending account, and receiving account. ```typescript interface FungibleTokenPacketData { @@ -45,15 +45,25 @@ interface FungibleTokenPacketData { } ``` +Whether the sending chain is the original source of funds, whether it is redeeming funds received over this channel, or whether it is relaying funds received from a 3rd chain is encoded in the `denomination` field. If the sending chain is the original source of funds, `denomination` must not contain the character `/`. If it contains `/`, then `denomination` must be of the form `{ics20Port}/{ics20Channel}/{remote_denom}`, where `ics20Port` and `ics20Channel` are the ics20 port and channel on the remote chain where the funds originated. If `ics20Port == packet.sourcePort` and `ics20Channel == packet.sourceChannel`, then the remote blockchain is returning/redeeming funds originally sent from this blockchain over this connection. + The acknowledgement data type describes whether the transfer succeeded or failed, and the reason for failure (if any). ```typescript -interface FungibleTokenPacketAcknowledgement { - success: boolean - error: Maybe +type FungibleTokenPacketAcknowledgement = FungibleTokenPacketSuccess | FungibleTokenPacketError; + +interface FungibleTokenPacketSuccess { + // This is binary 0x01 base64 encoded + success: "AQ==" +} + +interface FungibleTokenPacketSuccess { + error: string } ``` +Note that both the `FungibleTokenPacketData` as well as `FungibleTokenPacketAcknowledgement` must be JSON-encoded (not Protobuf encoded) when they serialized into packet data. + The fungible token transfer bridge module tracks escrow addresses associated with particular channels in state. Fields of the `ModuleState` are assumed to be in scope. ```typescript From e758703651cb1a1bf4e05fd5af7339b8e3cc1865 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 24 May 2021 16:02:17 +0200 Subject: [PATCH 2/6] Fix prefix in pseudocode (port/channel/denom) --- spec/app/ics-020-fungible-token-transfer/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index 6fde0ecca..74c6fc7b4 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -212,7 +212,7 @@ function createOutgoingPacket( sourceChannel: string, timeoutHeight: Height, timeoutTimestamp: uint64) { - prefix = "{sourcePort}/{sourceChannel}" + prefix = "{sourcePort}/{sourceChannel}/" // we are the source if the denomination is not prefixed source = denomination.slice(0, len(prefix)) !== prefix if source { @@ -236,7 +236,7 @@ function onRecvPacket(packet: Packet) { FungibleTokenPacketData data = packet.data // construct default acknowledgement of success FungibleTokenPacketAcknowledgement ack = FungibleTokenPacketAcknowledgement{true, null} - prefix = "{packet.sourcePort}/{packet.sourceChannel}" + prefix = "{packet.sourcePort}/{packet.sourceChannel}/" // we are the source if the packets were prefixed by the sending chain source = data.denomination.slice(0, len(prefix)) === prefix if source { @@ -248,7 +248,7 @@ function onRecvPacket(packet: Packet) { if (err !== nil) ack = FungibleTokenPacketAcknowledgement{false, "transfer coins failed"} } else { - prefix = "{packet.destPort}/{packet.destChannel}" + prefix = "{packet.destPort}/{packet.destChannel}/" prefixedDenomination = prefix + data.denomination // sender was source, mint vouchers to receiver (assumed to fail if balance insufficient) err = bank.MintCoins(data.receiver, prefixedDenomination, data.amount) @@ -285,7 +285,7 @@ function onTimeoutPacket(packet: Packet) { ```typescript function refundTokens(packet: Packet) { FungibleTokenPacketData data = packet.data - prefix = "{packet.sourcePort}/{packet.sourceChannel}" + prefix = "{packet.sourcePort}/{packet.sourceChannel}/" // we are the source if the denomination is not prefixed source = denomination.slice(0, len(prefix)) !== prefix if source { From 35d1f00f32f165ae18559ee342706b6202828431 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 24 May 2021 16:19:25 +0200 Subject: [PATCH 3/6] Specify uint256 is string encoded as JSON --- spec/app/ics-020-fungible-token-transfer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index 74c6fc7b4..b37ebad3e 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -62,7 +62,7 @@ interface FungibleTokenPacketSuccess { } ``` -Note that both the `FungibleTokenPacketData` as well as `FungibleTokenPacketAcknowledgement` must be JSON-encoded (not Protobuf encoded) when they serialized into packet data. +Note that both the `FungibleTokenPacketData` as well as `FungibleTokenPacketAcknowledgement` must be JSON-encoded (not Protobuf encoded) when they serialized into packet data. Also note that `uint256` is string encoded when converted to JSON, but must be a valid decimal number of the form `[0-9]+`. The fungible token transfer bridge module tracks escrow addresses associated with particular channels in state. Fields of the `ModuleState` are assumed to be in scope. From e419e69e33e2a0ecc34e7b1ef8396e95670a3880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Colin=20Axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 25 May 2021 13:06:54 +0200 Subject: [PATCH 4/6] update wording --- spec/app/ics-020-fungible-token-transfer/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index b37ebad3e..a42f6e28d 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -45,7 +45,11 @@ interface FungibleTokenPacketData { } ``` -Whether the sending chain is the original source of funds, whether it is redeeming funds received over this channel, or whether it is relaying funds received from a 3rd chain is encoded in the `denomination` field. If the sending chain is the original source of funds, `denomination` must not contain the character `/`. If it contains `/`, then `denomination` must be of the form `{ics20Port}/{ics20Channel}/{remote_denom}`, where `ics20Port` and `ics20Channel` are the ics20 port and channel on the remote chain where the funds originated. If `ics20Port == packet.sourcePort` and `ics20Channel == packet.sourceChannel`, then the remote blockchain is returning/redeeming funds originally sent from this blockchain over this connection. +As tokens are sent across chains using the ICS 20 protocol, they begin to accrue a record of channels for which they have been transferred across. This information is encoded into the `denomination` field. + +The ics20 token denominations are represented the form `{ics20Port}/{ics20Channel}/{denom}`, where `ics20Port` and `ics20Channel` are an ics20 port and channel on the current chain for which the funds exist. The prefixed port and channel pair indicate which channel the funds were previously sent through. If `{denom}` contains `/`, then it must also be in the ics20 form which indicates that this token has a multi-hop record. + +A sending chain may be acting as a source or sink zone. When a chain is sending tokens across a port and channel which are not equal to the last prefixed port and channel pair, it is acting as a source zone. When tokens are sent from a source zone, the destination port and channel will be prefixed onto the denomination adding another hop to a tokens record. When a chain is sending tokens across a port and channel which are equal to the last prefixed port and channel pair, it is acting as a sink zone. When tokens are sent from a sink zone, the last prefixed port and channel pair on the denomination is removed, undoing the last hop in the tokens record. The acknowledgement data type describes whether the transfer succeeded or failed, and the reason for failure (if any). From 6ea8f4ceab37033dee6d3c99d7943f876031cb77 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 25 May 2021 16:07:25 +0200 Subject: [PATCH 5/6] Addressed PR comments from cwgoes --- spec/app/ics-020-fungible-token-transfer/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index a42f6e28d..fc2193d0a 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -47,7 +47,7 @@ interface FungibleTokenPacketData { As tokens are sent across chains using the ICS 20 protocol, they begin to accrue a record of channels for which they have been transferred across. This information is encoded into the `denomination` field. -The ics20 token denominations are represented the form `{ics20Port}/{ics20Channel}/{denom}`, where `ics20Port` and `ics20Channel` are an ics20 port and channel on the current chain for which the funds exist. The prefixed port and channel pair indicate which channel the funds were previously sent through. If `{denom}` contains `/`, then it must also be in the ics20 form which indicates that this token has a multi-hop record. +The ics20 token denominations are represented the form `{ics20Port}/{ics20Channel}/{denom}`, where `ics20Port` and `ics20Channel` are an ics20 port and channel on the current chain for which the funds exist. The prefixed port and channel pair indicate which channel the funds were previously sent through. If `{denom}` contains `/`, then it must also be in the ics20 form which indicates that this token has a multi-hop record. Note that this requires that the `/` (slash character) is prohibited in non-IBC token denomination names. A sending chain may be acting as a source or sink zone. When a chain is sending tokens across a port and channel which are not equal to the last prefixed port and channel pair, it is acting as a source zone. When tokens are sent from a source zone, the destination port and channel will be prefixed onto the denomination adding another hop to a tokens record. When a chain is sending tokens across a port and channel which are equal to the last prefixed port and channel pair, it is acting as a sink zone. When tokens are sent from a sink zone, the last prefixed port and channel pair on the denomination is removed, undoing the last hop in the tokens record. @@ -61,7 +61,7 @@ interface FungibleTokenPacketSuccess { success: "AQ==" } -interface FungibleTokenPacketSuccess { +interface FungibleTokenPacketError { error: string } ``` From fff202fdc4676df5c0582ca93c67942f1ebd622c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 25 May 2021 16:10:47 +0200 Subject: [PATCH 6/6] Address PR comments by colin-axner --- spec/app/ics-020-fungible-token-transfer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-020-fungible-token-transfer/README.md b/spec/app/ics-020-fungible-token-transfer/README.md index fc2193d0a..939b1c72b 100644 --- a/spec/app/ics-020-fungible-token-transfer/README.md +++ b/spec/app/ics-020-fungible-token-transfer/README.md @@ -49,7 +49,7 @@ As tokens are sent across chains using the ICS 20 protocol, they begin to accrue The ics20 token denominations are represented the form `{ics20Port}/{ics20Channel}/{denom}`, where `ics20Port` and `ics20Channel` are an ics20 port and channel on the current chain for which the funds exist. The prefixed port and channel pair indicate which channel the funds were previously sent through. If `{denom}` contains `/`, then it must also be in the ics20 form which indicates that this token has a multi-hop record. Note that this requires that the `/` (slash character) is prohibited in non-IBC token denomination names. -A sending chain may be acting as a source or sink zone. When a chain is sending tokens across a port and channel which are not equal to the last prefixed port and channel pair, it is acting as a source zone. When tokens are sent from a source zone, the destination port and channel will be prefixed onto the denomination adding another hop to a tokens record. When a chain is sending tokens across a port and channel which are equal to the last prefixed port and channel pair, it is acting as a sink zone. When tokens are sent from a sink zone, the last prefixed port and channel pair on the denomination is removed, undoing the last hop in the tokens record. +A sending chain may be acting as a source or sink zone. When a chain is sending tokens across a port and channel which are not equal to the last prefixed port and channel pair, it is acting as a source zone. When tokens are sent from a source zone, the destination port and channel will be prefixed onto the denomination (once the tokens are received) adding another hop to a tokens record. When a chain is sending tokens across a port and channel which are equal to the last prefixed port and channel pair, it is acting as a sink zone. When tokens are sent from a sink zone, the last prefixed port and channel pair on the denomination is removed (once the tokens are received), undoing the last hop in the tokens record. A more complete explanation is [present in the ibc-go implementation](https://github.com/cosmos/ibc-go/blob/457095517b7832c42ecf13571fee1e550fec02d0/modules/apps/transfer/keeper/relay.go#L18-L49). The acknowledgement data type describes whether the transfer succeeded or failed, and the reason for failure (if any).