Gaia EVM Devnet
- Introduction
- Connect to the Network
- Run a Full Node
- Get Tokens
- Tooling & Resources
Precompiles
ICS20
Cross-chain token transfers via IBC (Inter-Blockchain Communication) protocol
Overview
The ICS20 precompile provides an interface to the Inter-Blockchain Communication (IBC) protocol, allowing smart contracts to perform cross-chain token transfers. It enables sending tokens to other IBC-enabled chains and querying information about IBC denominations.
Precompile Address: 0x0000000000000000000000000000000000000802
Related Module: x/ibc-transfer
Transaction Methods
transfer
Initiates a cross-chain token transfer using the IBC protocol.
Copy
Ask AI
import { ethers } from "ethers";
// ABI definition for the transfer function
const precompileAbi = [
"function transfer(string memory sourcePort, string memory sourceChannel, string memory token, address sender, string memory receiver, uint64 timeoutHeight, uint64 timeoutTimestamp, string memory memo) payable"
];
// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000802";
const signer = new ethers.Wallet("<PRIVATE_KEY>", provider);
const contract = new ethers.Contract(precompileAddress, precompileAbi, signer);
// Transfer parameters
const sourcePort = "transfer";
const sourceChannel = "channel-0";
const token = "uatom"; // or ERC20 token address
const sender = await signer.getAddress();
const receiver = "cosmos1..."; // Destination address on target chain
const timeoutHeight = 0; // 0 for no height timeout
const timeoutTimestamp = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
const memo = "";
async function transferTokens() {
try {
const tx = await contract.transfer(
sourcePort,
sourceChannel,
token,
sender,
receiver,
timeoutHeight,
timeoutTimestamp,
memo,
{ value: ethers.parseEther("1.0") } // Amount to transfer
);
console.log("Transfer initiated:", tx.hash);
await tx.wait();
console.log("Transfer confirmed");
} catch (error) {
console.error("Error initiating transfer:", error);
}
}
// transferTokens();
Query Methods
denom
Queries denomination information for an IBC token by its hash.
Copy
Ask AI
import { ethers } from "ethers";
// ABI definition for the function
const precompileAbi = [
"function denom(string memory hash) view returns (tuple(string base, tuple(string portId, string channelId)[] trace) denom)"
];
// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000802";
const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);
// Input: The hash of the denomination to query
const denomHash = "ibc/..."; // Placeholder for actual denomination hash
async function getDenom() {
try {
const denom = await contract.denom(denomHash);
console.log("Denomination Info:", JSON.stringify(denom, null, 2));
} catch (error) {
console.error("Error fetching denomination:", error);
}
}
getDenom();
denoms
Retrieves a paginated list of all denomination traces registered on the chain.
Copy
Ask AI
import { ethers } from "ethers";
// ABI definition for the function
const precompileAbi = [
"function denoms(tuple(bytes key, uint64 offset, uint64 limit, bool countTotal, bool reverse) pageRequest) view returns (tuple(string base, tuple(string portId, string channelId)[] trace)[] denoms, tuple(bytes nextKey, uint64 total) pageResponse)"
];
// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000802";
const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);
// Input for pagination
const pagination = {
key: "0x",
offset: 0,
limit: 10,
countTotal: true,
reverse: false,
};
async function getDenoms() {
try {
const result = await contract.denoms(pagination);
console.log("Denominations:", JSON.stringify(result.denoms, null, 2));
console.log("Pagination Response:", result.pageResponse);
} catch (error) {
console.error("Error fetching denominations:", error);
}
}
getDenoms();
denomHash
Computes the hash of a denomination trace path.
Copy
Ask AI
import { ethers } from "ethers";
// ABI definition for the function
const precompileAbi = [
"function denomHash(string memory trace) view returns (string memory hash)"
];
// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000802";
const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);
// Input: The trace path to hash
const tracePath = "transfer/channel-0/uatom"; // Placeholder for actual trace path
async function getDenomHash() {
try {
const hash = await contract.denomHash(tracePath);
console.log("Denomination Hash:", hash);
} catch (error) {
console.error("Error computing denomination hash:", error);
}
}
getDenomHash();
Full Solidity Interface & ABI
ICS20 Solidity Interface
Copy
Ask AI
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.18;
import "../common/Types.sol";
/// @dev The ICS20I contract's address.
address constant ICS20_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000802;
/// @dev The ICS20 contract's instance.
ICS20I constant ICS20_CONTRACT = ICS20I(ICS20_PRECOMPILE_ADDRESS);
/// @dev Denom contains the base denomination for ICS20 fungible tokens and the
/// source tracing information path.
struct Denom {
/// base denomination of the relayed fungible token.
string base;
/// trace contains a list of hops for multi-hop transfers.
Hop[] trace;
}
/// @dev Hop defines a port ID, channel ID pair specifying where
/// tokens must be forwarded next in a multi-hop transfer.
struct Hop {
string portId;
string channelId;
}
/// @author Evmos Team
/// @title ICS20 Transfer Precompiled Contract
/// @dev The interface through which solidity contracts will interact with IBC Transfer (ICS20)
/// @custom:address 0x0000000000000000000000000000000000000802
interface ICS20I {
/// @dev Emitted when an ICS-20 transfer is executed.
/// @param sender The address of the sender.
/// @param receiver The address of the receiver.
/// @param sourcePort The source port of the IBC transaction, For v2 packets, leave it empty.
/// @param sourceChannel The source channel of the IBC transaction, For v2 packets, set the client ID.
/// @param denom The denomination of the tokens transferred.
/// @param amount The amount of tokens transferred.
/// @param memo The IBC transaction memo.
event IBCTransfer(
address indexed sender,
string indexed receiver,
string sourcePort,
string sourceChannel,
string denom,
uint256 amount,
string memo
);
/// @dev Transfer defines a method for performing an IBC transfer.
/// @param sourcePort the port on which the packet will be sent
/// @param sourceChannel the channel by which the packet will be sent
/// @param denom the denomination of the Coin to be transferred to the receiver
/// @param amount the amount of the Coin to be transferred to the receiver
/// @param sender the hex address of the sender
/// @param receiver the bech32 address of the receiver
/// @param timeoutHeight the timeout height relative to the current block height.
/// The timeout is disabled when set to 0
/// @param timeoutTimestamp the timeout timestamp in absolute nanoseconds since unix epoch.
/// The timeout is disabled when set to 0
/// @param memo optional memo
/// @return nextSequence sequence number of the transfer packet sent
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);
/// @dev denoms Defines a method for returning all denoms.
/// @param pageRequest Defines the pagination parameters to for the request.
function denoms(
PageRequest memory pageRequest
)
external
view
returns (
Denom[] memory denoms,
PageResponse memory pageResponse
);
/// @dev Denom defines a method for returning a denom.
function denom(
string memory hash
) external view returns (Denom memory denom);
/// @dev DenomHash defines a method for returning a hash of the denomination info.
function denomHash(
string memory trace
) external view returns (string memory hash);
}
ICS20 ABI
Copy
Ask AI
{
"_format": "hh-sol-artifact-1",
"contractName": "ICS20I",
"sourceName": "solidity/precompiles/ics20/ICS20I.sol",
"abi": [
{ "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, { "indexed": true, "internalType": "string", "name": "receiver", "type": "string" }, { "indexed": false, "internalType": "string", "name": "sourcePort", "type": "string" }, { "indexed": false, "internalType": "string", "name": "sourceChannel", "type": "string" }, { "indexed": false, "internalType": "string", "name": "denom", "type": "string" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, { "indexed": false, "internalType": "string", "name": "memo", "type": "string" } ], "name": "IBCTransfer", "type": "event" },
{ "inputs": [ { "internalType": "string", "name": "hash", "type": "string" } ], "name": "denom", "outputs": [ { "components": [ { "internalType": "string", "name": "base", "type": "string" }, { "components": [ { "internalType": "string", "name": "portId", "type": "string" }, { "internalType": "string", "name": "channelId", "type": "string" } ], "internalType": "struct Hop[]", "name": "trace", "type": "tuple[]" } ], "internalType": "struct Denom", "name": "denom", "type": "tuple" } ], "stateMutability": "view", "type": "function" },
{ "inputs": [ { "internalType": "string", "name": "trace", "type": "string" } ], "name": "denomHash", "outputs": [ { "internalType": "string", "name": "hash", "type": "string" } ], "stateMutability": "view", "type": "function" },
{ "inputs": [ { "components": [ { "internalType": "bytes", "name": "key", "type": "bytes" }, { "internalType": "uint64", "name": "offset", "type": "uint64" }, { "internalType": "uint64", "name": "limit", "type": "uint64" }, { "internalType": "bool", "name": "countTotal", "type": "bool" }, { "internalType": "bool", "name": "reverse", "type": "bool" } ], "internalType": "struct PageRequest", "name": "pageRequest", "type": "tuple" } ], "name": "denoms", "outputs": [ { "components": [ { "internalType": "string", "name": "base", "type": "string" }, { "components": [ { "internalType": "string", "name": "portId", "type": "string" }, { "internalType": "string", "name": "channelId", "type": "string" } ], "internalType": "struct Hop[]", "name": "trace", "type": "tuple[]" } ], "internalType": "struct Denom[]", "name": "denoms", "type": "tuple[]" }, { "components": [ { "internalType": "bytes", "name": "nextKey", "type": "bytes" }, { "internalType": "uint64", "name": "total", "type": "uint64" } ], "internalType": "struct PageResponse", "name": "pageResponse", "type": "tuple" } ], "stateMutability": "view", "type": "function" },
{ "inputs": [ { "internalType": "string", "name": "sourcePort", "type": "string" }, { "internalType": "string", "name": "sourceChannel", "type": "string" }, { "internalType": "string", "name": "denom", "type": "string" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "string", "name": "receiver", "type": "string" }, { "components": [ { "internalType": "uint64", "name": "revisionNumber", "type": "uint64" }, { "internalType": "uint64", "name": "revisionHeight", "type": "uint64" } ], "internalType": "struct Height", "name": "timeoutHeight", "type": "tuple" }, { "internalType": "uint64", "name": "timeoutTimestamp", "type": "uint64" }, { "internalType": "string", "name": "memo", "type": "string" } ], "name": "transfer", "outputs": [ { "internalType": "uint64", "name": "nextSequence", "type": "uint64" } ], "stateMutability": "nonpayable", "type": "function" }
]
}
Assistant
Responses are generated using AI and may contain mistakes.