This is CCTP V1 version. For the latest version, see CCTP.
This is CCTP V1 version. For the latest version, see CCTP.
This guide demonstrates how to use the viem framework and the CCTP V1 API in a simple script that enables a user to transfer USDC from a wallet address on the Ethereum Sepolia testnet to another wallet address on the Avalanche Fuji testnet.
To get started with CCTP V1, follow the example script provided on GitHub. The example uses web3.js to transfer USDC from a wallet address on Ethereum Sepolia testnet to another wallet address on Avalanche Fuji testnet.
Interactive Tutorial with Developer Services
If you are new to building smart contracts, check out our interactive tutorial where you can transfer USDC using Circle's Developer Services: Contracts and Wallets.
The script has five steps:
const approveTx = await usdcEthContract.methods
.approve(ETH_TOKEN_MESSENGER_CONTRACT_ADDRESS, amount)
.send({ gas: approveTxGas });
depositForBurn
function on the
Ethereum Sepolia TokenMessenger contract deployed on
Sepolia testnet.const burnTx = await ethTokenMessengerContract.methods
.depositForBurn(
amount,
AVAX_DESTINATION_DOMAIN,
destinationAddressInBytes32,
USDC_ETH_CONTRACT_ADDRESS,
)
.send();
messageBytes
emitted by the MessageSent event from
depositForBurn
transaction logs and hashes the retrieved messageBytes
using the 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);
messageHash
from the previous step.Rate Limit
The attestation service rate limit is 35 requests per second. If you exceed 35 requests per second, the service blocks all API requests for the next 5 minutes and returns an HTTP 429 response.
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));
}
receiveMessage
function on the Avalanche Fuji
MessageTransmitter contract to receive USDC at the Avalanche Fuji wallet
address.const receiveTx = await avaxMessageTransmitterContract.receiveMessage(
receivingMessageBytes,
signature,
);
You have successfully transferred USDC between two EVM-compatible chains using CCTP V1 end-to-end!
WHAT'S NEXT