Cross-Chain ERC-20
In this tutorial you will learn how to create a contract capable of minting ERC-20 tokens and sending them to a contract on a different chain using cross-chain messaging.
Set up your environment
git clone https://github.com/zeta-chain/template
cd template
yarn
Create the Contract
To create a new cross-chain messaging contract you will use the messaging
Hardhat task available by default in the template.
npx hardhat messaging CrossChainERC20 to:address value:uint256
to
: address of the recipient on the destination chainvalue
: the amount of ERC-20 tokens transferred
Cross-Chain Messaging Contract
Let's review and make changes to the contract:
By default the generated contract is a standard cross-chain messaging contract with functions to send a message, message handler and revert handler.
Let's modify the contract to make it ERC-20 compatible.
To enable ERC-20 token features, import the necessary OpenZeppelin contracts:
ERC20
for standard token functionality and ERC20Burnable
to enable burning
tokens.
In the contract's constructor, initialize the ERC-20 token by setting a name and
a symbol using the ERC20
constructor. Then, pre-mint an initial supply of
tokens to the deploying address by calling the _mint
function.
In the sendMessage
function, ensure the sender has sufficient tokens to send
by checking their balance. If they have enough, burn the required amount from
their balance using _burn
. Add msg.sender
to the message by passing it as a
third argument to abi.decode
. This is necessary in case the transaction is
reverted, so the sender can be reimbursed.
To handle the cross-chain message, decode the incoming message in
onZetaMessage
and mint tokens to the intended recipient using the _mint
function.
In the event of a message revert, decode the original message in onZetaRevert
to identify the sender and the amount. Reimburse the sender by minting the
tokens back to their account with _mint
. Use the from
address, as this is
the original sender who should receive the reimbursement.
Deploy the Contract
Clear the cache and artifacts, then compile the contract:
npx hardhat compile --force
Run the following command to deploy the contract to two networks:
npx hardhat deploy --networks sepolia_testnet,bsc_testnet
🚀 Successfully deployed contract on sepolia_testnet
📜 Contract address: 0x18B6f0aB98429F00eDD44D5900090D71e3747e10
🚀 Successfully deployed contract on bsc_testnet
📜 Contract address: 0x7eA3054e5086FeE43D745975d171d3a850A94304
🔗 Setting interactors for a contract on sepolia_testnet
✅ Interactor address for 97 (bsc_testnet) is set to 0x7ea3054e5086fee43d745975d171d3a850a94304
🔗 Setting interactors for a contract on bsc_testnet
✅ Interactor address for 11155111 (sepolia_testnet) is set to 0x18b6f0ab98429f00edd44d5900090d71e3747e10
Send an ERC-20 Token
Use the interact task to call the sendMessage
method of the contract and send
ERC-20 tokens from Sepolia to BSC Testnet
npx hardhat interact --to 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 --value 1000000000 --contract 0x18B6f0aB98429F00eDD44D5900090D71e3747e10 --network sepolia_testnet --amount 0.01 --destination bsc_testnet
🔑 Using account: 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32
✅ The transaction has been broadcasted to sepolia_testnet
📝 Transaction hash: 0x25cfda972e255480e15b47472ae6c8d8842201855776fedaa446f75cab7a0e86
You can check the broadcasted transaction on Sepolia's Etherscan:
Next, you can track the progress of the cross-chain transaction:
npx hardhat cctx 0x25cfda972e255480e15b47472ae6c8d8842201855776fedaa446f75cab7a0e86
✓ CCTXs on ZetaChain found.
✓ 0x258d3ad9adf92ac5b7d59354435adfadac0af6430737f388ebf2664c22c71158: 11155111 → 97: OutboundMined
Source Code
You can find the source code for the example in this tutorial here:
https://github.com/zeta-chain/example-contracts/tree/main/messaging/erc20 (opens in a new tab)