Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

transfer source realm

Readme View source

IBC Transfer App

ICS-20 Fungible Token Transfer implementation for IBC v2 on Gno. Enables cross-chain token transfers between Gno and any IBC v2 compatible chain.

Transfer

Transfer is the single entry point for sending any token to another chain. The token type is detected automatically from the denom argument:

Token type Denom format Example Mechanism
Native coin plain string ugnot Escrowed via banker.OriginSend (direct user-call only)
IBC voucher ibc/{hash} ibc/CAEF9C... Burned from sender
GRC20 token grc20reg key gno.land/r/demo/foo.FOO Escrowed via TransferFrom

Signature:

func Transfer(
    cur realm,
    clientID string,           // IBC client on this chain (e.g. "07-tendermint-1")
    receiver string,           // recipient address on destination chain
    denom string,              // token denomination (see table above)
    amount int64,              // amount to transfer
    timeoutTimestamp uint64,   // unix seconds after which the packet times out
    memo string,               // arbitrary memo included in the IBC packet
) (packet types.MsgSendPacket, sequence uint64)

Native coin

The coin must be attached to the transaction via the -send flag and must match denom and amount. Only direct user calls (gnokey maketx call) are accepted: Transfer reads banker.OriginSend() guarded by runtime.PreviousRealm().IsUserCall() to ensure the coins actually landed at this realm. Calls from intermediate code realms or maketx run ephemeral realms are rejected.

gnokey maketx call -pkgpath gno.land/r/aib/ibc/apps/transfer -func Transfer \
    -send 100ugnot \
    -args "07-tendermint-1" -args "atone1abc..." -args "ugnot" -args "100" \
    -args "1719878400" -args "" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS

IBC voucher

IBC vouchers are GRC20 tokens minted when receiving tokens from another chain. They are burned on transfer back to the source chain.

gnokey maketx call -pkgpath gno.land/r/aib/ibc/apps/transfer -func Transfer \
    -args "07-tendermint-1" -args "atone1abc..." \
    -args "ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8" \
    -args "100" -args "1719878400" -args "memo" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS

GRC20 token

The caller must first approve the transfer app realm to spend the tokens.

From Gno code (e.g. in a MsgRun script):

transferAddr := chain.PackageAddress("gno.land/r/aib/ibc/apps/transfer")
mytoken.Approve(cross, caller, transferAddr, amount)

Or via gnokey directly, where g1tp3gk4quumurav4858hjfdy6hxtyffwmnxyr00 is the transfer app realm address:

gnokey maketx call -pkgpath gno.land/r/demo/foo -func Approve \
    -args "g1caller..." -args "g1tp3gk4quumurav4858hjfdy6hxtyffwmnxyr00" -args "100" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS

Then call Transfer with the grc20reg key as denom:

gnokey maketx call -pkgpath gno.land/r/aib/ibc/apps/transfer -func Transfer \
    -args "07-tendermint-1" -args "atone1abc..." \
    -args "gno.land/r/demo/foo.FOO" -args "100" \
    -args "1719878400" -args "" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS
Info

GRC20 denoms are encoded into slash-free aliases for IBC packets by replacing / with : (e.g. gno.land/r/demo/foo.FOO becomes gno.land:r:demo:foo.FOO). The counterparty chain sees the aliased form, not the original grc20reg key.

Query endpoints

All endpoints return JSON and are accessible via gnoweb or gnokey query vm/qrender.

Path Description
denoms List all registered IBC denominations
denoms/ibc/{hash} Details for a specific IBC denom (base, path, denom)
total_escrow/{denom} Total escrowed amount for a native denom
vouchers List all voucher tokens (paginated, includes grc20reg_key)
voucher/ibc/{hash} Voucher token metadata (denom, grc20reg_key, name, symbol, decimals, total supply)
voucher/ibc/{hash}/balance/{addr} Voucher balance for an address

Example:

gnokey query vm/qrender -data "gno.land/r/aib/ibc/apps/transfer:total_escrow/ugnot"
1{"denom":"ugnot","amount":100}

Helper functions

VoucherBalanceOf

Query the balance of a voucher token for a given address. Returns 0 if the voucher does not exist.

balance := transfer.VoucherBalanceOf("ibc/CAEF9C...", addr)

VoucherSend

Send an IBC voucher token to another Gno address:

transfer.VoucherSend(cross, "ibc/CAEF9C...", recipient, 100)
gnokey maketx call -pkgpath gno.land/r/aib/ibc/apps/transfer -func VoucherSend \
    -args "ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8" \
    -args "g1recipient..." -args "100" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS

VoucherApprove

Set a spender allowance for an IBC voucher token:

transfer.VoucherApprove(cross, "ibc/CAEF9C...", spender, 100)
gnokey maketx call -pkgpath gno.land/r/aib/ibc/apps/transfer -func VoucherApprove \
    -args "ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8" \
    -args "g1spender..." -args "100" \
    -gas-fee 1000000ugnot -gas-wanted 90000000 \
    -broadcast -chainid gnoland-1 ADDRESS

GRC20Alias

Convert a grc20reg key to the slash-free alias used in IBC packets.

alias := transfer.GRC20Alias("gno.land/r/demo/foo.FOO")
// "gno.land:r:demo:foo.FOO"

NewDenom / NewHop

Construct a Denom to compute the expected IBC denom hash:

denom := transfer.NewDenom("uphoton", transfer.NewHop(transfer.PortID, "07-tendermint-1"))
ibcDenom := denom.IBCDenom()
// "ibc/CAEF9CA8CE6C302D73A831A49E34E59149D3A9AD96CCEBDFBF62F6D5710D92D8"

DEX integration for voucher tokens

Voucher tokens minted on RecvPacket are standard GRC20 tokens registered in grc20reg. A DEX (e.g. Gnoswap) can discover and list them like any other GRC20 token.

Discovery

Voucher tokens can be discovered in two ways:

  1. From the transfer app — query the vouchers render endpoint to list all voucher tokens with their metadata. Each entry includes a grc20reg_key field with the token's grc20reg key, ready for direct lookup. Supports pagination.

  2. From grc20reg — voucher tokens are registered with the key gno.land/r/aib/ibc/apps/transfer.{HASH}, where {HASH} is the uppercase hex SHA256 hash from the ibc/{HASH} denom. Enumerate entries with the gno.land/r/aib/ibc/apps/transfer. prefix.

The token name is the base denomination (e.g. uatom) and the symbol is the full IBC denom (e.g. ibc/CAEF9C...). For richer metadata (trace hops, total supply), query the render endpoint voucher/ibc/{HASH}.

Trading

  1. A user receives voucher tokens via an IBC RecvPacket.
  2. The user approves the DEX realm address to spend their voucher tokens (Approve).
  3. The DEX interacts with the voucher via the standard GRC20 teller interface (TransferFrom, BalanceOf, etc.).

Multiple vouchers for the same base denom

The same base denomination (e.g. uatom) arriving from different chains produces distinct voucher tokens with different IBC hashes. A DEX should use the full ibc/{HASH} denom (available as the token symbol) to distinguish them, and query denoms/ibc/{HASH} to resolve the trace path for display purposes.

Events

ibc_transfer

Emitted in OnSendPacket for every outgoing transfer packet.

Attribute Description
sender Sender address on source chain
receiver Receiver address on destination chain
denom Full denom path
amount Transfer amount
memo Memo text

fungible_token_packet

Emitted on OnRecvPacket:

Attribute Description
sender Sender address
receiver Receiver address
denom Full denom path
amount Amount
memo Memo text
success "true" or "false"
error Error message (on failure)

Also emitted on OnAcknowledgementPacket:

Attribute Description
sender Sender address
receiver Receiver address
denom Full denom path
amount Amount
memo Memo text
acknowledgement Acknowledgement bytes

denomination

Emitted when a new voucher denom is created during OnRecvPacket.

Attribute Description
denom_hash Uppercase hex SHA256 hash
denom JSON representation of the Denom

timeout

Emitted on OnTimeoutPacket. Tokens are refunded to the original sender.

Attribute Description
receiver Refund recipient (original sender)
denom Full denom path
amount Refunded amount
memo Original memo

IBC packet lifecycle

  1. Transfer -- Caller invokes Transfer. Tokens are escrowed (native/GRC20) or burned (voucher). An IBC packet is sent via core.SendPacket.

  2. RecvPacket -- The destination chain receives the packet. If the token originated on the destination chain, the escrowed tokens are returned. Otherwise a voucher GRC20 token is minted and registered in grc20reg.

  3. Acknowledgement -- On success, only a fungible_token_packet event is emitted. On failure, the sender is refunded (re-mint vouchers, unescrow native/GRC20).

  4. Timeout -- If the packet is not received before timeoutTimestamp, the sender is refunded using the same mechanism as a failed acknowledgement.

Constants 2

const EventTypeTimeout, EventTypePacket, EventTypeTransfer, EventTypeDenom, AttributeKeySender, AttributeKeyReceiver, AttributeKeyDenom, AttributeKeyDenomHash, AttributeKeyAmount, AttributeKeyRefundReceiver, AttributeKeyRefundTokens, AttributeKeyAckSuccess, AttributeKeyAck, AttributeKeyAckError, AttributeKeyMemo

 1const (
 2	EventTypeTimeout  = "timeout"
 3	EventTypePacket   = "fungible_token_packet"
 4	EventTypeTransfer = "ibc_transfer"
 5	EventTypeDenom    = "denomination"
 6
 7	AttributeKeySender         = "sender"
 8	AttributeKeyReceiver       = "receiver"
 9	AttributeKeyDenom          = "denom"
10	AttributeKeyDenomHash      = "denom_hash"
11	AttributeKeyAmount         = "amount"
12	AttributeKeyRefundReceiver = "refund_receiver"
13	AttributeKeyRefundTokens   = "refund_tokens"
14	AttributeKeyAckSuccess     = "success"
15	AttributeKeyAck            = "acknowledgement"
16	AttributeKeyAckError       = "error"
17	AttributeKeyMemo           = "memo"
18)
source

IBC transfer events

Functions 12

func GRC20Alias

Action
1func GRC20Alias(grc20regKey string) string
source

GRC20Alias returns a slash-free alias for a GRC20 denom (grc20reg key) by replacing "/" with ":". This is safe because grc20reg slugs are alphanumeric (enforced by grc20reg.Register), so colons never appear in grc20reg keys, making the replacement reversible. Examples:

Example
1"gno.land/r/demo/foo"      → "gno.land:r:demo:foo"
2"gno.land/r/demo/foo.FOO"  → "gno.land:r:demo:foo.FOO"

func Transfer

crossing Action
1func Transfer(cur realm, clientID, receiver, denom string, amount int64, timeoutTimestamp uint64, memo string) (
2	packet types.MsgSendPacket, sequence uint64,
3)
source

Transfer is the entry point for sending tokens to another chain using the IBC protocol. It supports three token types, detected automatically from the denom argument:

  • IBC voucher (denom starts with "ibc/"): burns the voucher GRC20 token.
  • Non-IBC GRC20 token (registered in grc20reg): escrows via TransferFrom.
  • Native coin (everything else): the coin must be sent with the transaction via the send field, and must match denom and amount.

memo is included in the IBC packet payload.

func VoucherApprove

crossing Action
1func VoucherApprove(cur realm, ibcDenom string, spender address, amount int64)
source

VoucherApprove is a convenience helper to set a spender allowance for an IBC voucher token on behalf of the caller.

func VoucherBalanceOf

Action
1func VoucherBalanceOf(ibcDenom string, addr address) int64
source

VoucherBalanceOf returns the balance of a voucher token for a given address. Returns 0 if the token does not exist.

func VoucherSend

crossing Action
1func VoucherSend(cur realm, ibcDenom string, to address, amount int64)
source

VoucherSend is a convenience helper to send an IBC voucher token from the caller to the provided recipient.

func VoucherSymbol

Action
1func VoucherSymbol(ibcDenom string) string
source

VoucherSymbol returns the grc20 token symbol for an IBC voucher denom: the IBC hash truncated to grc20's MaxSymbolLen. The full voucherDenom ("ibc/<64-hex- hash>") can't be a symbol because v2 grc20 enforces MaxSymbolLen and [A-Za-z0-9_-] only. Since grc20reg keys tokens by rlmpath.symbol, this is also the symbol component of a voucher's registry key, so callers locate a voucher via grc20reg.Get(<this realm's pkgpath> + "." + VoucherSymbol(ibcDenom)).

func NewDenom

Action
1func NewDenom(base string, trace ...Hop) Denom
source

NewDenom creates a new Denom instance given the base denomination and a variable number of hops.

func NewFungibleTokenPacketData

Action
1func NewFungibleTokenPacketData(
2	denom string, amount string,
3	sender, receiver string,
4	memo string,
5) FungibleTokenPacketData
source

NewFungibleTokenPacketData constructs a new FungibleTokenPacketData instance

func NewHop

Action
1func NewHop(portID, clientID string) Hop
source

NewHop creates a Hop with the given port ID and client ID.

func NewToken

Action
1func NewToken(baseDenom, amount string) Token
source

NewToken constructs a Token with the given native base denom and amount (no trace, no prefix hops). Provided so external callers — which cannot construct foreign-stamped composite literals under v2 borrow rule #1 — can still build Token values for tests and packet assembly.

Types 5

type App

struct
1type App struct{}
source

Methods on App

func OnAcknowledgementPacket

crossing method on App
1func (a *App) OnAcknowledgementPacket(
2	cur realm,
3	sourceClient string,
4	destinationClient string,
5	sequence uint64,
6	acknowledgement []byte,
7	payload types.Payload,
8) error
source

OnAcknowledgementPacket responds to the success or failure of a packet acknowledgment written on the receiving chain.

If the acknowledgement was a success then nothing occurs. Otherwise, if the acknowledgement failed, then the sender is refunded their tokens. Implements app.IBCApp

func OnRecvPacket

crossing method on App
1func (a *App) OnRecvPacket(
2	cur realm,
3	sourceClient string,
4	destinationClient string,
5	sequence uint64,
6	payload types.Payload,
7) types.RecvPacketResult
source

Implements app.IBCApp

func OnSendPacket

crossing method on App
1func (a *App) OnSendPacket(
2	cur realm,
3	sourceClient string,
4	destinationClient string,
5	sequence uint64,
6	payload types.Payload,
7) error
source

Implements app.IBCApp

func OnTimeoutPacket

crossing method on App
1func (a *App) OnTimeoutPacket(
2	cur realm,
3	sourceClient string,
4	destinationClient string,
5	sequence uint64,
6	payload types.Payload,
7) error
source

OnTimeoutPacket processes a transfer packet timeout by refunding the tokens to the sender Implements app.IBCApp

type Denom

struct
1type Denom struct {
2	// the base token denomination
3	Base string
4	// the trace of the token
5	Trace []Hop
6}
source

Denom holds the base denom of a Token and a trace of the chains it was sent through.

Methods on Denom

func HasPrefix

method on Denom
1func (d Denom) HasPrefix(portID, clientID string) bool
source

HasPrefix returns true if the first element of the trace of the denom matches the provided portId and clientId.

func Hash

method on Denom
1func (d Denom) Hash() []byte
source

Hash returns the hex bytes of the SHA256 hash of the Denom fields using the following formula:

hash = sha256(trace + "/" + baseDenom)

func HashHex

method on Denom
1func (d Denom) HashHex() string
source

func IBCDenom

method on Denom
1func (d Denom) IBCDenom() string
source

IBCDenom a coin denomination for an ICS20 fungible token in the format 'ibc/{hash(trace + baseDenom)}'. If the trace is empty, it will return the base denomination.

func IsNative

method on Denom
1func (d Denom) IsNative() bool
source

IsNative returns true if the denomination is native, thus containing no trace history.

func Path

method on Denom
1func (d Denom) Path() string
source

Path returns the full denomination according to the ICS20 specification: trace + "/" + baseDenom If there exists no trace then the base denomination is returned.

func RenderJSON

method on Denom
1func (d Denom) RenderJSON() *json.Node
source

Implements jsonpage.JSONRenderer

func ValidateBasic

method on Denom
1func (d Denom) ValidateBasic() error
source

ValidateBasic performs a basic validation of the Denom fields.

type FungibleTokenPacketData

struct
 1type FungibleTokenPacketData struct {
 2	// the token denomination to be transferred
 3	Denom string
 4	// the token amount to be transferred
 5	Amount string
 6	// the sender address
 7	Sender string
 8	// the recipient address on the destination chain
 9	Receiver string
10	// optional memo
11	Memo string
12}
source

FungibleTokenPacketData defines a struct for the packet payload See FungibleTokenPacketData spec: https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures

Methods on FungibleTokenPacketData

func ProtoMarshal

method on FungibleTokenPacketData
1func (f *FungibleTokenPacketData) ProtoMarshal() (buf []byte)
source

ProtoMarshal returns the protobuf encoding of f.

Example
1message FungibleTokenPacketData {
2	string denom = 1;
3	string amount = 2;
4	string sender = 3;
5	string receiver = 4;
6	string memo = 5;
7}

func ProtoUnmarshal

method on FungibleTokenPacketData
1func (f *FungibleTokenPacketData) ProtoUnmarshal(bz []byte) error
source

ProtoUnmarshal reads the protobuf encoded bz into f.

Example
1message FungibleTokenPacketData {
2	string denom = 1;
3	string amount = 2;
4	string sender = 3;
5	string receiver = 4;
6	string memo = 5;
7}

func ValidateBasic

method on FungibleTokenPacketData
1func (f FungibleTokenPacketData) ValidateBasic() error
source

ValidateBasic is used for validating the token transfer.

type Hop

struct
1type Hop struct {
2	PortId   string
3	ClientId string
4}
source

Hop defines a port ID, client ID pair specifying a unique "hop" in a trace

Methods on Hop

func String

method on Hop
1func (h Hop) String() string
source

String returns the Hop in the format: <portID>/<clientID>

func ValidateBasic

method on Hop
1func (h Hop) ValidateBasic() error
source

ValidateBasic performs a basic validation of the Hop fields.

type Token

struct
1type Token struct {
2	// the token denomination
3	Denom Denom
4	// the token amount to be transferred
5	Amount string
6}
source

Token defines a struct which represents a token to be transferred.

Methods on Token

func AmountInt64

method on Token
1func (t Token) AmountInt64() (int64, error)
source

func ToCoin

method on Token
1func (t Token) ToCoin() (chain.Coin, error)
source

ToCoin converts a Token to an chain.Coin.

The function parses the Token.Amount field and returns a new sdk.Coin with the IBCDenom of the Token's Denom field and the parsed Amount. If the Amount cannot be parsed, an error is returned with a wrapped error message.

Imports 26

Source Files 58