Exercise 4: Sending USDC Cross-Chain
Getting started
You can use Chainlink CCIP with any blockchain development framework. For this Masterclass, we will use Remix IDE.
Let's create a new project by navigating to https://remix.ethereum.org/ and clicking the "Create new Workspace" button. Select "Blank" template and name the workspace as "CCIP Masterclass 4".
Alternatively, you can clone:
The @chainlink/contracts-ccip NPM package
To use Chainlink CCIP, you need to interact with Chainlink CCIP-specific contracts from the @chainlink/contracts-ccip NPM package.
To install it, create a new Solidity file, and paste the following content. It is an empty contract that just imports one of the contracts from the @chainlink/contracts-ccip
and @openzeppelin/contracts
packages that we will use throughout this Masterclass as well.
This contract expects at least 0.8.20
version of a Solidity compiler. It is very important to understand that with the latest Remix IDE release, the default EVM version is set to "Cancun". A new opcode, PUSH0, was added to the Ethereum Virtual Machine in the Shanghai upgrade, which happened prior to the current, Cancun upgrade.
However, besides Ethereum, the majority of blockchains haven't included PUSH0 opcode.
That means the PUSH0 opcode can now be part of the contract's bytecode and if the chain you are working on does not support it, it will error with the "Invalid opcode" error.
What we want is to downgrade Ethereum Virtual Machine version to "Paris" instead.
To understand more, we highly encourage you to check this StackOverflow answer:
To set EVM version to "Paris", navigate to the "Solidity compiler" tab and then:
Set "COMPILER" version to
0.8.20+commit.a1b79de6
Toggle the "Advanced Configurations" dropdown
Toggle the "EVM VERSION" dropdown menu and select
paris
instead ofdefault
Now compile the smart contract by clicking the "Compile Empty.sol" button. If compiled successfully, go back to "File explorer" tab and if new .deps/npm/@chainlink/contracts-ccip
and .deps/npm/@openzeppelin/contracts
folders are generated, that means we imported all of the necessary packages into the Remix IDE Workspace successfully.
Faucet
During this Masterclass, we will transfer USDC from Avalanche Fuji testnet to Ethereum Sepolia testnet. To get some amount of testnet USDC on Avalanche Fuji testnet, navigate to the https://faucet.circle.com/
To pay for CCIP Fees you can use either LINK token or native/wrapped native asset on a given blockchain. For this Masterclass we will need at least 3 LINK or Avalanche Fuji testnet. To get it, navigate to the https://faucets.chain.link/fuji
Develop TransferUSDC smart contract
Create a new Solidity file by clicking on the "Create new file" button, name it TransferUSDC.sol
, and paste the following Solidity code.
Prepare for deployment
Navigate to the "Deploy & run transactions" tab and select the "Injected Provider - Metamask" option from the "Environment" dropdown menu.
If you are using Metamask wallet, make sure you have added Avalanche Fuji C-Chain and Ethereum Sepolia (should already be added by default) networks.
Go to Chainlist.org and search for "avalanche fuji". Once you see the network with Chain ID 43113, click the "Add to Metamask" button.
Ethereum Sepolia should already be added by default to your Metamask wallet. However, if you need to manually add it, you can always repeat the same step we did for Avalanche Fuji C-Chain. Navigate to Chainlist.org and search for "sepolia". Once you see the network with Chain ID 11155111, click the "Add to Metamask" button.
Step 1) Deploy TransferUSDC.sol to Avalanche Fuji
Open your Metamask wallet and switch to the Avalanche Fuji network.
Open the TransferUSDC.sol
file.
Navigate to the "Solidity Compiler" tab and click the "Compile TransferUSDC.sol" button.
Navigate to the "Deploy & run transactions" tab and select the "Injected Provider - Metamask" option from the "Environment" dropdown menu. Make sure that chainId
is switched to 43113 (if not, you may need to refresh the Remix IDE page in your browser).
Under the "Contract" dropdown menu, make sure that the "TransferUSDC - TransferUSDC.sol" is selected.
Locate the orange "Deploy" button. Provide:
0xF694E193200268f9a4868e4Aa017A0118C9a8177
as theccipRouter
,0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846
as thelinkToken
and0x5425890298aed601595a70AB815c96711a31Bc65
as theusdcToken
.
Click the orange "Deploy"/"Transact" button.
Metamask notification will pop up. Sign the transaction.
Step 2) On AvalancheFuji, call allowlistDestinationChain function
Under the "Deployed Contracts" section, you should find the TransferUSDC.sol
contract you previously deployed to Avalanche Fuji. Find the allowlistDestinationChain
function and provide:
16015286601757825753, which is the CCIP Chain Selector for the Ethereum Sepolia test network, as the
_destinationChainSelector
parameter,true
as_allowed
parameter
Hit the "Transact" orange button.
Step 3) On AvalancheFuji, fund TransferUSDC.sol with 3 LINK
To cover for CCIP fees, fund TransferUSDC.sol
with some amount of LINK, 3 should be enough for this demo.
Step 4) On Avalanche Fuji, call approve function on USDC.sol
Go to the Avalanche Fuji Snowtrace Explorer and search for USDC token. Locate the "Contract" tab, then click the "Write as Proxy" tab. Connect your wallet to the blockchain explorer. And finally find the "approve" function.
We want to approve 1 USDC to be spent by the TransferUSDC.sol
on our behalf. To do so we must provide:
The address of the
TransferUSDC.sol
smart contract we previously deployed, asspender
parameter1000000, as
value
parameter.
Because USDC token has 6 decimals, 1000000 means that we will approve 1 USDC to be spent on our behalf.
Click the "Write" button. Metamask popup will show up. Sign the transaction.
Step 5) On AvalancheFuji, call transferUsdc function
Under the "Deployed Contracts" section, you should find the TransferUSDC.sol
contract you previously deployed to Avalanche Fuji. Find the transferUsdc
function and provide:
16015286601757825753, which is the CCIP Chain Selector for the Ethereum Sepolia test network, as the
_destinationChainSelector
parameter,Your wallet address, as the
_receiver
parameter,1000000, as the
_amount
parameter0, as the
_gasLimit
parameter
0 is set as the _gasLimit
parameter because we are sending tokens to an EOA so there is no cost for executing the ccipReceive
function on the destination side.
Hit the "Transact" orange button.
You can now monitor the live status of your cross-chain message by copying the transaction hash into the search bar of a Chainlink CCIP Explorer.
Last updated