Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICS20-1 cleanup #576

Merged
merged 7 commits into from
May 26, 2021
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions spec/app/ics-020-fungible-token-transfer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
ethanfrey marked this conversation as resolved.
Show resolved Hide resolved

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<string>
type FungibleTokenPacketAcknowledgement = FungibleTokenPacketSuccess | FungibleTokenPacketError;

interface FungibleTokenPacketSuccess {
// This is binary 0x01 base64 encoded
success: "AQ=="
}

interface FungibleTokenPacketSuccess {
ethanfrey marked this conversation as resolved.
Show resolved Hide resolved
error: string
}
```

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.

```typescript
Expand Down Expand Up @@ -202,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 {
Expand All @@ -226,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 {
Expand All @@ -238,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)
Expand Down Expand Up @@ -275,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 {
Expand Down