Exercise 2: Build Your First Cross-Chain NFT

Coding Time 🎉

CCIP Config Details

Arbitrum Sepolia
Ethereum Sepolia

Chain Selector

CCIP Router Address

0x2a9c5afb0d0e4bab2bcdae109ec4b0c4be15a165

0x0bf3de8c5d3e8a2b34d2beeb17abfcebaf363a59

LINK Token Address

0xb1D4538B4571d411F07960EF2838Ce337FE1E80E

0x779877A7B0D9E8603169DdbD7836e478b4624789

Getting started

You can use Chainlink CCIP with any blockchain development framework. For this Masterclass, we prepared the steps for Hardhat, Foundry, and Remix IDE.

Let's create a new project

Make sure you have Node.js and NPM installed. To check, run the following command:

node -v
npm -v

Create a new folder and name it ccip-masterclass-3

mkdir ccip-masterclass-3

Navigate to it

cd ccip-masterclass-3

Create a hew Hardhat project by running:

npx hardhat init

And then select "Create a TypeScript project".

Alternatively, you can clone:

To use Chainlink CCIP, you need to interact with Chainlink CCIP-specific contracts from the @chainlink/contracts-ccip NPM package.

To install it, follow steps specific to the development environment you will use for this Masterclass.

We will need a standard @chainlink/contracts NPM package for this Module as well, so let's install it too while we are here by running the following command:

Finally, for this exercise we will need to install and the @openzeppelin/contracts NPM package, as well. To do so, run:

Faucet

To pay for CCIP Fees you can use either LINK token or native/wrapped native asset on a given blockchain. For this exercise we will need at least 1 LINK or Arbitrum Sepolia testnet. To get it, navigate to the https://faucets.chain.link/arbitrum-sepolia

Chainlink Faucets

Develop xNFT smart contract

Create a new file inside the contracts folder and name it XNFT.sol

Compile your contract by running:

Prepare for deployment

Follow the steps to add the necessary environment variables for deploying these contracts and sending your first CCIP Message.

This contract expects at least 0.8.20 Solidity version. It is very important to understand that with Solc version 0.8.20, the default EVM version is set to "Shanghai". A new opcode, PUSH0, was added to the Ethereum Virtual Machine in the Shanghai 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.

To understand more, we highly encourage you to check this StackOverflow answer:

Setting solc EVM version in different environments

We are going to use the @chainlink/env-enc package for extra security. It encrypts sensitive data instead of storing them as plain text in the .env file by creating a new .env.enc file. Although it's not recommended to push this file online, if that accidentally happens, your secrets will still be encrypted.

Install the package by running the following command:

Set a password for encrypting and decrypting the environment variable file. You can change it later by typing the same command.

Now set the following environment variables: PRIVATE_KEY, Source Blockchain RPC URL, Destination Blockchain RPC URL. For this example, we are going to use Arbitrum Sepolia and Ethereum Sepolia.

To set these variables, type the following command and follow the instructions in the terminal:

After you are done, the .env.enc file will be automatically generated. If you want to validate your inputs, you can always run the next command:

Finally, expand the hardhat.config to support these two networks:

Step 1) Deploy XNFT.sol to Ethereum Sepolia

Prepare Chain Selector and CCIP Router & LINK token addresses on Ethereum Sepolia. You can get them if you scroll to the beginning of this page, at CCIP Config Details

Navigate to the scripts folder and create new file named deployXNFT.ts

Run the deployment script:

Step 2) Deploy XNFT.sol to Arbitrum Sepolia

Prepare Chain Selector and CCIP Router & LINK token addresses on Arbitrum Sepolia. You can get them if you scroll to beginning of this page, at CCIP Config Details

Navigate to the scripts folder and create new file named deployXNFTArbitrum.ts

Run the deployment script:

Step 3) On Ethereum Sepolia, call enableChain function

Prepare:

  • The address of the address of the XNFT.sol smart contract you previously deployed to Ethereum Sepolia;

  • The address of the address of the XNFT.sol smart contract you previously deployed to Arbitrum Sepolia;

  • 3478487238524512106, which is the CCIP Chain Selector for the Arbitrum Sepolia network, as the chainSelector parameter;

  • 0x97a657c90000000000000000000000000000000000000000000000000000000000030d40, which is the bytes version of CCIP extraArgs' default value with 200_000 gas set for gasLimit, as ccipExtraArgs parameter.

If you would like to calculate this value by yourself, you can reuse the following helper smart contract:

Create a new TypeScript file under the scripts folder and name it enableChain.ts

Call the function by running the following command:

Step 4) On Arbitrum Sepolia, call enableChain function

Prepare:

  • The address of the XNFT.sol smart contract you previously deployed to Arbitrum Sepolia;

  • The address of the address of the XNFT.sol smart contract you previously deployed to Ethereum Sepolia, as xNftAddress parameter;

  • 16015286601757825753, which is the CCIP Chain Selector for the Ethereum Sepolia network, as the chainSelector parameter;

  • 0x97a657c90000000000000000000000000000000000000000000000000000000000030d40, which is the bytes version of CCIP extraArgs' default value with 200_000 gas set for gasLimit, as ccipExtraArgs parameter.

If you would like to calculate this value by yourself, you can reuse the following helper smart contract:

Create a new TypeScript file under the scripts folder and name it enableChainArbitrum.ts

Call the function by running the following command:

To cover for CCIP fees, fund XNFT.sol with some amount of LINK, 3 should be more than enough for this demo. Obviously, for the sake of full functionality, you should fund XNFT.sol smart contract on other blockchains as well, so you can perform cross-chain transfers between all of them.

Fund your xNFT with LINK

Step 6) On Arbitrum Sepolia, mint new xNFT

Create a new TypeScript file under the scripts folder and name it mint.ts

Call the function by running the following command:

Step 7) On Arbitrum Sepolia, crossTransferFrom xNFT

Prepare:

  • Your EOA address, as the from parameter;

  • The address of an EOA on other chain where you want to cross-transfer your NFT, can be your EOA address, as to parameter;

  • The ID of a xNFT you want to cross-transfer, as tokenId parameter;

  • 16015286601757825753 which is the CCIP Chain Selector of Ethereum Sepolia blockchain, as the destinationChainSelector parameter;

  • 1 which stands that we are paying for CCIP fees in LINK, as the payFeesIn parameter.

Create a new TypeScript file under the scripts folder and name it crossChainTransferFrom.ts

Call the function by running the following command:

You can now monitor this cross-chain transfer on CCIP Explorer page.

CCIP Explorer

Once cross-chain NFT arrives to Ethereum Sepolia, you can manually display it inside your Metamask wallet. Navigate to the "NFT" tab and hit the "Import NFT" button.

Import NFT

Then, fill in XNFT.sol smart contract address on Ethereum Sepolia and token ID you received (0).

Fill in NFT details

Finally, your NFT will appear inside Metamask wallet.

See your newly minted NFT

Last updated