Build
Connected Blockchains
ZetaChain

To make a call from a universal app to a contract on a connected chain or to withdraw tokens, use the ZetaChain gateway.

ZetaChain gateway supports:

  • withdrawing ZRC-20 tokens as native gas or ERC-20 tokens to connected chains
  • withdrawing ZETA tokens to connected chains withdrawing tokens to and making a contract call on connected chains
  • calling contracts on connected chains

To withdraw ZRC-20 tokens to an EOA or a contract on a connected chain, call the withdraw function of the gateway contract.

withdraw(bytes memory receiver, uint256 amount, address zrc20, RevertOptions calldata revertOptions) external;

The receiver is either an externally-owned account (EOA) or a contract on a connected chain. Even if the receiver is a smart contract with the standard receive function, the withdraw function will not trigger a contract call. If you want to withdraw and call a contract on a connected chain, please, use the withdrawAndCall function, instead.

The receiver is of type bytes, because the receiver may be on a chain that uses a different address type, for example, bech32 on Bitcoin. bytes allow the receiver address to be chain agnostic. When withdrawing to a receiver on an EVM chain make sure that you convert address to bytes.

The amount is the amount and zrc20 is the ZRC-20 address of the token that is being withdrawn.

You don't need to specify which chain to withdraw to, because each ZRC-20 has an associated chain from which it was deposited. A ZRC-20 token can be withdrawn only to the chain from which it was originally deposited. This means that if you want to withdraw ZRC-20 USDC.ETH to the BNB chain, you first have to swap it to ZRC-20 USDC.BNB.

The withdraw function can also be used to withdraw ZETA tokens to a connected chain.

withdraw(bytes memory receiver, uint256 amount, uint256 chainId, RevertOptions calldata revertOptions) external;

To withdraw ZRC-20 tokens and make a call from a universal app to a contract on a connected chain use the withdrawAndCall function of the gateway contract.

function withdrawAndCall(bytes memory receiver, uint256 amount, address zrc20, bytes calldata message, uint256 gasLimit, RevertOptions calldata revertOptions) external;

The tokens are withdrawn and a call is made to a contract on the connected chain identified by the zrc20 address. For example, if ZRC-20 ETH is being withdrawn, then the call is made to a contract on Ethereum.

The withdrawAndCall function can also be used to withdraw ZETA tokens and make a call from a universal app to a contract on a connected chain.

withdrawAndCall(bytes memory receiver, uint256 amount, uint256 chainId, bytes calldata message, RevertOptions calldata revertOptions) external;

To call a contract on a connected chain (without withdrawing tokens), use the call function.

function call(bytes memory receiver, address zrc20, bytes calldata message, uint256 gasLimit, RevertOptions calldata revertOptions) external;

zrc20 represents the ZRC-20 token address of the gas token of the destination chain. In the context of this function zrc20 address acts as an identifier for the chain to which the call is made. For example, to make a call to Ethereum, use ZRC-20 ETH token address.

The withdrawAndCall and call functions have a bytes calldata message parameter. This parameter contains the function selector and the encoded arguments necessary to call a specific function in the target contract.

The message parameter should contain:

  • Function selector: the first 8 bytes represent the function selector, which is the first 4 bytes of the Keccak-256 hash of the function signature.
  • Arguments: the remaining bytes in the message correspond to the arguments passed to the function, encoded according to Ethereum's ABI encoding rules. These arguments can vary in length depending on the data types.

For example, consider the following message:

0xa777d0dc00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005616c696365000000000000000000000000000000000000000000000000000000
  • Function Selector: 0xa777d0dc. This corresponds to the function hello(string).
  • Arguments: The remaining data (0000000000000000000000000000000000000000000000000000000000000020...) is the ABI-encoded argument passed to the hello(string) function. Specifically: 616c696365 represents the string alice in hexadecimal.

The RevertOptions struct defines how assets should be handled in the event of a cross-chain transaction (CCTX) reverting:

struct RevertOptions {
    address revertAddress;
    bool callOnRevert;
    address abortAddress;
    bytes revertMessage;
    uint256 onRevertGasLimit;
}

revertAddress: the address that should get assets back if the CCTX reverts. For example, if a smart contract using ZetaChain wants to send assets back to the sender upon a revert, revertAddress should be set to msg.sender.

callOnRevert: a boolean flag indicating whether the onRevert function should be called on the revertAddress. For example, a smart contract may want to execute custom logic when a revert occurs, such as unlocking tokens. In this case, the contract would set callOnRevert to true and assign revertAddress to address(this).

abortAddress: the address that will receive the funds on ZetaChain if the CCTX aborts. This feature is not currently used.

revertMessage: message sent back to the onRevert function. This allows additional context to be provided for handling the revert.

onRevertGasLimit: the gas limit to be used when executing the onRevert function.

Contracts that implement the onRevert functionality are referred to as Revertable contracts. These contracts should conform to the following interface:

struct RevertContext {
    address asset;
    uint64 amount;
    bytes revertMessage;
}
 
interface Revertable {
    function onRevert(RevertContext calldata revertContext) external;
}

This interface allows the contract to handle reverts in a customized way, based on the context provided through the RevertContext struct.