ics20

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2025 License: Apache-2.0 Imports: 21 Imported by: 10

README

ICS20 Precompile

The ICS20 precompile provides an EVM interface to the Inter-Blockchain Communication (IBC) transfer module, enabling smart contracts to perform cross-chain token transfers using the ICS-20 standard.

Address

The precompile is available at the fixed address: 0x0000000000000000000000000000000000000802

Interface

Data Structures
// Denomination information for IBC tokens
struct Denom {
    string base;      // Base denomination of the relayed fungible token
    Hop[] trace;      // List of hops for multi-hop transfers
}

// Port and channel pair for multi-hop transfers
struct Hop {
    string portId;
    string channelId;
}

// Height information for timeout
struct Height {
    uint64 revisionNumber;
    uint64 revisionHeight;
}
Transaction Methods
// Perform an IBC transfer
function transfer(
    string memory sourcePort,
    string memory sourceChannel,
    string memory denom,
    uint256 amount,
    address sender,
    string memory receiver,
    Height memory timeoutHeight,
    uint64 timeoutTimestamp,
    string memory memo
) external returns (uint64 nextSequence);
Query Methods
// Get all denominations with pagination
function denoms(
    PageRequest memory pageRequest
) external view returns (
    Denom[] memory denoms,
    PageResponse memory pageResponse
);

// Get a specific denomination by hash
function denom(
    string memory hash
) external view returns (Denom memory denom);

// Get the hash of a denomination trace
function denomHash(
    string memory trace
) external view returns (string memory hash);

Gas Costs

Gas costs are calculated dynamically based on:

  • Base gas for the method
  • Additional gas for IBC operations
  • Key-value storage operations

The precompile uses standard gas configuration for storage operations.

Implementation Details

Transfer Mechanism
  1. Channel Validation:

    • For v1 packets: Validates that the channel exists and is in OPEN state
    • For v2 packets: Validates the client ID format
    • Checks that the underlying connection is OPEN
  2. Sender Verification: The transaction sender must match the specified sender address

  3. Token Transfer: Uses the IBC transfer keeper to execute the cross-chain transfer

  4. Sequence Tracking: Returns the sequence number of the IBC packet sent

Denomination Handling
  • Denom Traces: Tracks the path of tokens through multiple IBC hops
  • Denom Hashes: Provides unique identifiers for IBC denominations
  • Base Denominations: Identifies the original token denomination
Timeout Configuration
  • Height-based timeout: Specify a block height for timeout
  • Timestamp-based timeout: Specify an absolute timestamp in nanoseconds
  • Setting either to 0 disables that timeout mechanism

Events

event IBCTransfer(
    address indexed sender,
    string indexed receiver,
    string sourcePort,
    string sourceChannel,
    string denom,
    uint256 amount,
    string memo
);

Security Considerations

  1. Channel State Validation: Ensures transfers only occur through active channels
  2. Sender Authentication: Verifies the message sender matches the transfer sender
  3. Balance Handling: Uses the balance handler for proper native token management
  4. Timeout Protection: Prevents indefinite locking of tokens with timeout mechanisms

Usage Example

ICS20I ics20 = ICS20I(ICS20_PRECOMPILE_ADDRESS);

// Prepare transfer parameters
string memory sourcePort = "transfer";
string memory sourceChannel = "channel-0";
string memory denom = "uatom";
uint256 amount = 1000000; // 1 ATOM (6 decimals)
string memory receiver = "cosmos1..."; // Bech32 address on destination chain

// Set timeout (e.g., 1 hour from now)
Height memory timeoutHeight = Height({
    revisionNumber: 0,
    revisionHeight: 0  // Disabled
});
uint64 timeoutTimestamp = uint64(block.timestamp + 3600) * 1e9; // Convert to nanoseconds

// Execute IBC transfer
uint64 sequence = ics20.transfer(
    sourcePort,
    sourceChannel,
    denom,
    amount,
    msg.sender,
    receiver,
    timeoutHeight,
    timeoutTimestamp,
    "Transfer from EVM"
);

// Query denomination information
Denom memory denomInfo = ics20.denom("ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2");

Integration Notes

  • The precompile integrates directly with the IBC transfer module
  • Supports both IBC v1 (channel-based) and v2 (client-based) transfers
  • Memo field can be used for additional transfer metadata or routing information
  • Receiver addresses must be valid Bech32 addresses on the destination chain
  • For v2 packets: Leave sourcePort empty and set sourceChannel to the client ID

Documentation

Index

Constants

View Source
const (
	// ErrInvalidSourcePort is raised when the source port is invalid.
	ErrInvalidSourcePort = "invalid source port"
	// ErrInvalidSourceChannel is raised when the source channel is invalid.
	ErrInvalidSourceChannel = "invalid source port"
	// ErrInvalidSender is raised when the sender is invalid.
	ErrInvalidSender = "invalid sender: %s"
	// ErrInvalidReceiver is raised when the receiver is invalid.
	ErrInvalidReceiver = "invalid receiver: %s"
	// ErrInvalidTimeoutTimestamp is raised when the timeout timestamp is invalid.
	ErrInvalidTimeoutTimestamp = "invalid timeout timestamp: %d"
	// ErrInvalidMemo is raised when the memo is invalid.
	ErrInvalidMemo = "invalid memo: %s"
	// ErrInvalidHash is raised when the hash is invalid.
	ErrInvalidHash = "invalid hash: %s"
	// ErrNoMatchingAllocation is raised when no matching allocation is found.
	ErrNoMatchingAllocation = "no matching allocation found for source port: %s, source channel: %s, and denom: %s"
	// ErrDifferentOriginFromSender is raised when the origin address is not the same as the sender address.
	ErrDifferentOriginFromSender = "origin address %s is not the same as sender address %s"
	// ErrDenomNotFound is raised when the denom for the specified request does not exist.
	ErrDenomNotFound = "denomination not found"
)
View Source
const (
	// DenomMethod defines the ABI method name for the ICS20 Denom
	// query.
	DenomMethod = "denom"
	// DenomsMethod defines the ABI method name for the ICS20 Denoms
	// query.
	DenomsMethod = "denoms"
	// DenomHashMethod defines the ABI method name for the ICS20 DenomHash
	// query.
	DenomHashMethod = "denomHash"
)
View Source
const (
	// DefaultRevisionNumber is the default value used to not set a timeout revision number
	DefaultRevisionNumber = 0

	// DefaultRevisionHeight is the default value used to not set a timeout revision height
	DefaultRevisionHeight = 0

	// DefaultTimeoutMinutes is the default value in minutes used to set a timeout timestamp
	DefaultTimeoutMinutes = 10
)
View Source
const (
	// EventTypeIBCTransfer defines the event type for the ICS20 Transfer transaction.
	EventTypeIBCTransfer = "IBCTransfer"
)
View Source
const PrecompileAddress = "0x0000000000000000000000000000000000000802"

PrecompileAddress of the ICS-20 EVM extension in hex format.

View Source
const (
	// TransferMethod defines the ABI method name for the ICS20 Transfer
	// transaction.
	TransferMethod = "transfer"
)

Variables

View Source
var (
	ABI abi.ABI
)

DefaultTimeoutHeight is the default value used to set a timeout height

Functions

func CheckOriginAndSender

func CheckOriginAndSender(contract *vm.Contract, origin common.Address, sender common.Address) (common.Address, error)

CheckOriginAndSender ensures the correct sender is being used.

func CreateAndValidateMsgTransfer

func CreateAndValidateMsgTransfer(
	sourcePort, sourceChannel string,
	coin sdk.Coin, senderAddress, receiverAddress string,
	timeoutHeight clienttypes.Height,
	timeoutTimestamp uint64,
	memo string,
) (*transfertypes.MsgTransfer, error)

CreateAndValidateMsgTransfer creates a new MsgTransfer message and run validate basic.

func EmitIBCTransferEvent

func EmitIBCTransferEvent(
	ctx sdk.Context,
	stateDB vm.StateDB,
	event abi.Event,
	precompileAddr, senderAddr common.Address,
	receiver string,
	sourcePort, sourceChannel string,
	token sdk.Coin,
	memo string,
) error

EmitIBCTransferEvent creates a new IBC transfer event emitted on a Transfer transaction.

func NewDenomHashRequest

func NewDenomHashRequest(args []interface{}) (*transfertypes.QueryDenomHashRequest, error)

NewDenomHashRequest returns a new denom hash request from the given arguments.

func NewDenomRequest added in v0.2.0

func NewDenomRequest(args []interface{}) (*transfertypes.QueryDenomRequest, error)

NewDenomRequest returns a new denom request from the given arguments.

func NewDenomsRequest added in v0.2.0

func NewDenomsRequest(method *abi.Method, args []interface{}) (*transfertypes.QueryDenomsRequest, error)

NewDenomsRequest returns a new denoms request from the given arguments.

func NewMsgTransfer

func NewMsgTransfer(method *abi.Method, args []interface{}) (*transfertypes.MsgTransfer, common.Address, error)

NewMsgTransfer returns a new transfer message from the given arguments.

Types

type DenomResponse added in v0.2.0

type DenomResponse struct {
	Denom transfertypes.Denom
}

DenomResponse defines the data for the denom response.

type DenomsResponse added in v0.2.0

type DenomsResponse struct {
	Denoms       []transfertypes.Denom
	PageResponse query.PageResponse
}

DenomsResponse defines the data for the denoms response.

type EventIBCTransfer

type EventIBCTransfer struct {
	Sender        common.Address
	Receiver      common.Hash
	SourcePort    string
	SourceChannel string
	Denom         string
	Amount        *big.Int
	Memo          string
}

EventIBCTransfer is the event type emitted when a transfer is executed.

type EventTransferAuthorization

type EventTransferAuthorization struct {
	Grantee     common.Address
	Granter     common.Address
	Allocations []cmn.ICS20Allocation
}

EventTransferAuthorization is the event type emitted when a transfer authorization is created.

type PageRequest

type PageRequest struct {
	PageRequest query.PageRequest
}

PageRequest defines the data for the page request.

type Precompile

type Precompile struct {
	cmn.Precompile

	abi.ABI
	// contains filtered or unexported fields
}

func NewPrecompile

func NewPrecompile(
	bankKeeper cmn.BankKeeper,
	stakingKeeper cmn.StakingKeeper,
	transferKeeper cmn.TransferKeeper,
	channelKeeper cmn.ChannelKeeper,
) *Precompile

NewPrecompile creates a new ICS-20 Precompile instance as a PrecompiledContract interface.

func (Precompile) Denom added in v0.2.0

func (p Precompile) Denom(
	ctx sdk.Context,
	_ *vm.Contract,
	method *abi.Method,
	args []interface{},
) ([]byte, error)

Denom returns the requested denomination information.

func (Precompile) DenomHash

func (p Precompile) DenomHash(
	ctx sdk.Context,
	_ *vm.Contract,
	method *abi.Method,
	args []interface{},
) ([]byte, error)

DenomHash returns the denom hash (in hex format) of the denomination information.

func (Precompile) Denoms added in v0.2.0

func (p Precompile) Denoms(
	ctx sdk.Context,
	_ *vm.Contract,
	method *abi.Method,
	args []interface{},
) ([]byte, error)

Denoms returns the requested denomination information.

func (Precompile) Execute added in v0.5.0

func (p Precompile) Execute(ctx sdk.Context, stateDB vm.StateDB, contract *vm.Contract, readOnly bool) ([]byte, error)

func (Precompile) IsTransaction

func (Precompile) IsTransaction(method *abi.Method) bool

IsTransaction checks if the given method name corresponds to a transaction or query.

Available ics20 transactions are:

  • Transfer

func (Precompile) RequiredGas

func (p Precompile) RequiredGas(input []byte) uint64

RequiredGas calculates the precompiled contract's base gas rate.

func (Precompile) Run

func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error)

func (*Precompile) Transfer

func (p *Precompile) Transfer(
	ctx sdk.Context,
	contract *vm.Contract,
	stateDB vm.StateDB,
	method *abi.Method,
	args []interface{},
) ([]byte, error)

Transfer implements the ICS20 transfer transactions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL