Quickstart: Cross-chain USDC Transfer

To get started with CCTP follow the example script provided here. The example uses web3.js to transfer USDC from an address on ETH Goerli testnet to another address on AVAX Fuji testnet.

The script has 5 steps:

  1. First step approves ETH TokenMessenger contract to withdraw USDC from provided eth address.
const approveTx = await usdcEthContract.methods.approve(ETH_TOKEN_MESSENGER_CONTRACT_ADDRESS, amount).send({gas: approveTxGas})
  1. Second step executes depositForBurn function on ETH TokenMessenger contract deployed in Goerli testnet.
const burnTx = await ethTokenMessengerContract.methods.depositForBurn(amount, AVAX_DESTINATION_DOMAIN, destinationAddressInBytes32, USDC_ETH_CONTRACT_ADDRESS).send();
  1. Third step extracts messageBytes emitted by MessageSent event from depositForBurn transaction logs and hashes the retrieved messageBytes using keccak256 hashing algorithm.
const transactionReceipt = await web3.eth.getTransactionReceipt(burnTx.transactionHash);
const eventTopic = web3.utils.keccak256('MessageSent(bytes)')
const log = transactionReceipt.logs.find((l) => l.topics[0] === eventTopic)
const messageBytes = web3.eth.abi.decodeParameters(['bytes'], log.data)[0]
const messageHash = web3.utils.keccak256(messageBytes);
  1. Fourth step polls the attestation service to acquire signature using the messageHash from previous step.
let attestationResponse = {status: 'pending'};
while(attestationResponse.status != 'complete') {
    const response = await fetch(`https://iris-api-sandbox.circle.com/attestations/${messageHash}`);
    attestationResponse = await response.json()
    await new Promise(r => setTimeout(r, 2000));
  1. Last step calls the receiveMessage function on AVAX MessageTransmitter contract to receive USDC at AVAX address.

Note: The attestation service is rate-limited, please limit your requests to less than 1 per second.

const receiveTx = await avaxMessageTransmitterContract.receiveMessage(receivingMessageBytes, signature);

What’s Next