arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 29

CCIP Bootcamp Aug 2024

Loading...

Day 1

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Day 2

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Day 3

Loading...

Loading...

Loading...

Loading...

Tokenizated RWA Bootcamp

Chainlink’s tokenization bootcamp offers an exciting journey for Web3 developers, elevating your skills in bringing real-world assets onchain using Chainlink's cutting-edge tokenization infrastructure.

Secure Your Spot Before Anyone Else. September 30 - October 2, 2024

👉 REGISTER NOWarrow-up-right

Join us for a three-day tokenization adventure, where you’ll tokenize a house onchain. You’ll learn to enhance it with diverse data points, securely transfer it across chains, and unlock its potential beyond the capabilities of traditional systems.

What You’ll Learn:

  • Steps to create and enrich tokenized assets

  • Key stages of onchain development for tokenized assets

  • Strategies to maximize the potential of tokenized assets

  • Powering a Unified Golden Record for tokenized assets

hashtag

Welcome to CCIP Bootcamp!

Warmest welcome to the first-ever CCIP Bootcamp! Designed for established Web3 developer, the CCIP Bootcamp is meant to elevate your cross-chain development skills to the next level.

Onchain Certificate of Completion will be issued to all qualifying participants - please make sure to complete your homework for each day!

Certificate of Completion

hashtag
Curriculum

hashtag
Day 1

hashtag
Theory

hashtag
Exercises

hashtag
Homework

👉

hashtag

hashtag
Day 2

hashtag
Theory

hashtag
Exercises

hashtag
Homework

👉

hashtag

hashtag
Day 3

hashtag
Homework

👉

hashtag

CCIP Programmable Token Transfers in TradFi
  • CCIP Programmable Token Transfers in DeFi

  • How to Use Chainlink CCIP

  • Transporter, powered by CCIP
    Introduction to Interoperability Problem and Chainlink CCIP
    How CCIP Programmable Token Transfers Unlock Cross-Chain Innovation
    Exercise 1: Programmable Token Transfers using the Defensive Example Pattern
    Defensive Example Pattern
    Day 1 Homework
    A talk with the Interport team
    CCIP Architecture and Message Processing
    Building Cross-Chain NFTs
    Exercise 2: Build Your First Cross-Chain NFT
    Exercise 3: Testing Cross-Chain NFTs
    Debugging Tips and Tricks
    Day 2 Homework
    A talk with the Celo team
    5 Levels of Cross-Chain Security with Chainlink CCIP
    Exercise 4: Sending USDC Cross-Chainarrow-up-right
    Day 3 Homework
    Next Steps

    SmartCon

    hashtag
    Where TradFi and DeFi converge

    Chainlink SmartCon is the convergence point for the worlds of blockchain and finance, where digital asset leaders, DeFi pioneers, and onchain builders come together to invent the future of global markets and Web3.

    👉 REGISTER NOWarrow-up-right

    hashtag
    Event Highlights

    hashtag
    Hacker House | October 28-29

    Build alongside onchain innovators developing real-world applications that scale blockchain tech to billions of users worldwide.

    hashtag
    SmartCon Main Event | October 30-31

    Get cutting-edge insights from global financial institutions, premier DeFi protocols, and game-changing startups.

    hashtag
    Past SmartCon Speakers

    Eric Schmidt, former CEO, Google

    Jonathan Ehrenfeld Solé, Strategy Director, SWIFT

    Balaji Srinivasan, Angel Investor and Former CTO, Coinbase

    Laurence Moroney, AI Lead, Google

    Joseph Chan, Under Secretary for Financial Services and The Treasury, Hong Kong SAR

    Oliver Roucloux, Business Analyst & Product Owner, Euroclear

    Rashmi Misra, General Manager AI & Emerging Technologies Business Development, Microsoft

    Setup Instructions

    Please make sure you have completed these steps ahead of Day 1:

    • (required for test tokens, and homework exercises)

    CCIP Programmable Token Transfers in TradFi

    CCIP Programmable Token Transfers are critical to enabling cross-chain . DvP in traditional finance refers to the requirement that the delivery of assets (e.g., securities) and the payment for those assets happen simultaneously (i.e., atomic settlement). DvP is an important feature in reducing the risk that a counterparty won’t deliver on its leg of the transaction despite the other leg being fulfilled.

    demonstrated how CCIP Programmable Token Transfers can enable a cross-border, cross-chain, cross-currency DvP transaction. In a single cross-chain transaction, a stablecoin backed by a local currency (NZ$DC) was converted to another stablecoin in a different national currency (A$DC), transferred from the buyer’s source chain to the seller’s destination chain along with the instruction to purchase a tokenized asset (e.g., reef credits), which was subsequently sent back to the customer’s wallet on the source chain.

    To learn more, check out the case study written in collaboration with ANZ and the between Chainlink Co-Founder Sergey Nazarov and ANZ’s Banking Services Lead Nigel Dobson.

    Avalanche Fuji, Ethereum Sepolia, Arbitrum Sepolia testnets added arrow-up-right
  • Test LINK, AVAX, ETH, ARBarrow-up-right

    • if you have difficulties please use Bootcamp Faucetarrow-up-right

    • password: BigMac777

  • Test USDC on Avalanche Fujiarrow-up-right

  • If you have any questions, please ask them on discord: https://discord.gg/m9vSfK65arrow-up-right

    MetaMaskarrow-up-right
    GitHub profilearrow-up-right
    Delivery vs. Payment (DvP) transactionsarrow-up-right
    The Australia and New Zealand Banking Group Limited (ANZ)arrow-up-right
    Cross-Chain Settlement of Tokenized Assets Using CCIParrow-up-right
    Sibos panel discussionarrow-up-right
    ANZ used CCIP to showcase a cross-currency, cross-chain settlement of tokenized assets using stablecoins.

    Introduction to Interoperability Problem and Chainlink CCIP

    hashtag
    Chainlink CCIP

    General overview of the Chainlink CCIP

    hashtag
    The interoperability problem

    Interoperability is the ability to exchange information between different systems or networks, even if they are incompatible. Shared concepts on different networks ensure that each party understands and trusts the exchanged information. It also considers the concept of finality to establish trust in the exchanged information by validating its accuracy and integrity.

    The Web3 ecosystem has become multi-chain, with the rise of layer-1 blockchains and layer-2 scaling solutions like appchains, subnets, and more, where each network has its own approach to scalability, security, and trust.

    However, blockchains are isolated networks that operate independently and cannot communicate natively. To create a truly interoperable Web3 ecosystem, data and value must move seamlessly between chains. This is where bridges come in.

    Traditional bridges are one of the biggest problems in today's Web3 ecosystem because they are centralized. When you are transferring funds from one chain to another using bridge, you are essentially giving your funds to some centralized entity, and you are trusting them that the funds will appear on the other side. And surprise, surprise, numerous bridge hacks have happened so far.

    hashtag
    The solution - Chainlink CCIP

    The Chainlink Cross-Chain Interoperability Protocol (CCIP) provides a single simple interface through which dApps and web3 entrepreneurs can securely meet all their cross-chain needs, including token transfers and arbitrary messaging.

    Chainlink CCIP connects blockchain networks via lanes. The lane is a unique combination of source blockchain to destination blockchain path, e.g., from blockchain A to blockchain C. To transfer messages in reverse order, from blockchain C to blockchain A using Chianlink CCIP, you will need to use a different lane, the one which is unique to the C -> A path.

    Chainlink CCIP will always support bi-directional lanes for each new chain added in the future. The logical question is how CCIP knows through which lane to transfer a CCIP cross-chain message. It's actually quite simple - each blockchain supported by CCIP has a unique chain selector.

    We said multiple times that by using Chainlink CCIP, you can send cross-chain messages. But what can a cross-chain message consist of? With Chainlink CCIP, one can:

    • Transfer (supported) tokens

    • Send any kind of data

    • Send both tokens and data

    CCIP sender can be:

    • EOA

    • Any smart contract

    CCIP receiver can be:

    • EOA

    • Any smart contract that implements CCIPReceiver.sol

    Note: If you send a message and token(s) to EOA, only tokens will arrive.

    For now, you can consider CCIP as a "black-box" component and be aware of the Router contract only. We will explain the Chainlink CCIP architecture in the following chapters.

    The Router is the primary contract CCIP users interface with. This contract is responsible for initiating cross-chain interactions. One router contact exists per chain. When transferring tokens, callers have to approve the router contract to be able to "spend" (transfer) the caller's tokens. When a message is received on the destination chain, the router is the contract that “delivers” tokens to the user's account or the message to the receiver's smart contract.

    hashtag
    Recap

    The Chainlink Cross-Chain Interoperability Protocol provides a single interface to transfer tokens and data across multiple chains in a secure and decentralized manner.

    New Terms
    Meaning

    CCIP Programmable Token Transfers in DeFi

    hashtag
    Cross-Chain Swaps

    CCIP Programmable Token Transfers enable cross-chain swap use cases, where any token can be effectively bridged over CCIP by connecting to liquidity pools / DEXs on the source and destination chains.

    For example, a cross-chain swap app built on CCIP enables users holding Token A on Arbitrum to be swapped for Token B on Optimism by first swapping Token A on Arbitrum for USDC, bridging the USDC to Optimism along with data about the swap, and then automatically swapping the USDC to Token B and sending it to the user’s wallet. This is why CCIP’s support for native USDCarrow-up-right is so powerful; it doesn’t just support the cross-chain transfer of native USDC via burn and mint, but also the simultaneous transmission of data on what to do with the USDC once it arrives on the destination chain—a unique feature of CCIP Programmable Token Transfers.

    is a cross-chain swaps protocol and participant that uses CCIP for Programmable Token Transfers to enable cross-chain swaps between blockchain networks. USDC is used as the liquidity token for XSwap. Since its launch, XSwap users have initiated over $130M in CCIP Programmable Token Transfers.

    Other users of CCIP Programmable Token Transfers include , , , , and more.

    hashtag
    Cross-Chain Staking and Restaking

    CCIP Programmable Token Transfers unlock innovation for . End-users can stake/restake assets directly from a layer-2 network, where CCIP is used to transfer the native assets back to the layer-1 blockchain chain along with instructions to (re)stake the asset in a specified (re)staking protocol. This reduces gas costs for users and provides them the convenience to (re)stake from any chain.

    For example, to enable its users to deposit ETH directly into their layer-2 contracts in order to receive the corresponding LRT (egETH) without ever having to leave the chain. Once users deposit ETH into the layer-2 contract, CCIP’s Programmable Token Transfers will bridge the tokens to Ethereum with instructions to restake them into Eigenlayer. CCIP is then used to lock the minted egETH on Ethereum and bridge it back to the L2 where it is minted and sent to the end user’s wallet address.

    You can read more about Chainlink’s support for staking and restaking in the blog: . Learn how to implement Chainlink CCIP Programmable Token Transfers in the for a more technical deep dive.

    How CCIP Programmable Token Transfers Unlock Cross-Chain Innovation

    The Chainlink Cross-Chain Interoperability Protocol (CCIP) is far more than a simple token bridging solution. It’s a generalized cross-chain messaging protocol for transferring tokens (value), messages (data), or both tokens and messages simultaneously within a single cross-chain transaction—referred to as Programmable Token Transfers.

    In effect, CCIP Programmable Token Transfers enable smart contracts to transfer tokens cross-chain along with instructions on what the receiving smart contract should do with those tokens once they arrive on the destination chain. This revolutionary concept of wrapping value and instructions together allows tokenized value to interact automatically and dynamically once it arrives at a destination, opening up a world of new possibilities.

    In decentralized finance (DeFi), CCIP Programmable Token Transfers enable the creation of cross-chain native dApps, such as a smart contract that can automatically transfer tokens cross-chain and deposit them into the highest yield lending markets. Within traditional finance (TradFi), CCIP Programmable Token Transfers enable advanced use cases, such as a cross-chain delivery-vs-payment (DvP) transaction where an institution holding stablecoins on its private blockchain can purchase a tokenized asset issued on a different private or public chain.

    Importantly, CCIP Programmable Token Transfers enable institutions to interact with smart contractsarrow-up-right and tokenized assetsarrow-up-right on other blockchain networks without needing to integrate or directly interact with that blockchain. All they need to do is send instructions to CCIP on how to interact with that chain, greatly reducing their overhead and the risks associated with point-to-point integrations with each blockchain network.

    hashtag
    CCIP Supports Any Cross-Chain Transfer Involving Both Data and Value

    Just as TCP/IP is a universal standard that underpins the Internet, Chainlink CCIP serves as a universal standard that underpins the . To support all the various cross-chain use cases that exist within DeFi and TradFi, CCIP allows for a variety of ways to transfer data and/or value across blockchains.

    hashtag
    Arbitrary Messaging

    CCIP’s support for enables developers to transfer any arbitrary data (encoded as bytes) across blockchain networks. Developers utilize CCIP’s Arbitrary Messaging to make their smart contract applications cross-chain native.

    With CCIP, smart contracts on a source chain can call any arbitrary function on any arbitrary smart contract on a destination chain to trigger any arbitrary action (and receive a callback on the source chain if needed). Developers can encode multiple instructions in a single message, empowering them to orchestrate complex, multi-step, multi-chain tasks.

    hashtag
    Token Transfers

    CCIP Token Transfers enable the transfer of tokens between chains via highly audited and security-reviewed token pool contracts. Transactions can be initiated directly by externally owned accounts (EOAs), such as from user wallets via a bridging app like , or directly by a smart contract. Tokens can then be sent to an EOA or to a smart contract.

    In order to ensure the highest level of security and a superior user experience, token issuers can use CCIP directly within their token’s smart contract to make it a native cross-chain token. As a result, any user or developer can use CCIP to transfer the official (canonical) version of that issuer’s token cross-chain. Various layer-1 blockchain and layer-2 rollups such as Wemix and Metis built upon this concept by integrating to power their canonical token bridges. Every token transferred onto those blockchain networks via CCIP is the canonical representation of that token on that chain.

    There are three primary ways developers can integrate CCIP for token transfers:

    • Burn and mint—Tokens are burned on a source chain, and an equivalent amount is minted on a destination chain. This enables the creation of cross-chain native tokens with a dynamic, unified supply across chains. via the burn and mint token transfer method.

    • Lock and mint—Tokens are locked on the chain they were natively issued on, and fully collateralized “wrapped” tokens are minted on destination chains. These wrapped tokens can be transferred across other non-native destination chains via burn and mint or be burned to unlock tokens back on the original issuing source chain. TRUF token utilizes lock and mint for its token transfers on CCIP.

    hashtag
    Programmable Token Transfers

    Programmable Token Transfers combine Token Transfers with Arbitrary Messaging. This enables developers to transfer both tokens (value) and instructions (data) about what to do with those tokens cross-chain within a single transaction. Importantly, Programmable Token Transfers are built natively into CCIP to give users the best possible security, reliability, UX (e.g., composability), and risk management.

    How to Use Chainlink CCIP

    The minimal code needed to send and receive CCIP Messages

    hashtag
    The minimal CCIP architecture

    To recap, with Chainlink CCIP, one can:

    • Transfer (supported) tokens

    • Send any kind of data

    • Send both tokens and data

    CCIP receiver can be:

    • EOA

    • Any smart contract that implements CCIPReceiver.sol

    Note: If you send a message and token(s) to EOA, only tokens will arrive.

    For now, you can consider CCIP as a "black-box" component and be aware of the Router contract only. We will explain the Chainlink CCIP architecture in the following chapters.

    hashtag
    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 and installed. To check, run the following command:

    Create a new folder and name it ccip-masterclass

    Navigate to it

    Create a hew Hardhat project by running:

    And then select either "Create a JavaScript project" or "Create a TypeScript project".

    Make sure you have installed. To check, run the following command:

    Alternatively, you can clone:

    hashtag
    The @chainlink/contracts-ccip NPM package

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

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

    Option 1)

    We cannot use git submodules to install @chainlink/contracts-ccip because the content of this package is not available as a separate GitHub repo. This essentially means that we cannot run a forge install command. Here's the workaround:

    Add the following line to the .gitignore file

    Then run the following command in your Terminal:

    Finally, add the following lines to the foundry.toml

    hashtag
    Basic interface

    Although, as being said, CCIP sender and receiver can be EOA and smart contract, and all combinations are possible, we are going to cover the most complex use-case where both CCIP sender and receiver are smart contracts on different blockchains.

    hashtag
    Source blockchain

    To send CCIP Messages, the smart contract on the source blockchain must call the ccipSend() function, which is defined the IRouterClient.sol interface.

    The CCIP Message which is being sent is a type of EVM2AnyMessage Solidity struct from the Client library.

    Let's now understand what each property of the EVM2AnyMessage struct we are sending represents and how to use it.

    receiver

    Receiver address. It can be a smart contract or an EOA. Use abi.encode(receiver) to encode the address to the bytes Solidity data-type.

    data

    Payload sent within the CCIP message. This is that "any type of data" one can send as a CCIP Message we are referring to from the start. It can be anything from simple text like "Hello, world!" to Solidity structs or function selectors.

    tokenAmounts

    Tokens and their amounts in the source chain representation. Here we are specifying which tokens (out of supported ones) we are sending and how much of it. This is the array of a EVMTokenAmount struct, which consists of two properties only:

    • token - Address of a token we are sending on the local (source) blockchain

    • amount The amount of tokens we are sending. The sender must approve the CCIP router to spend this amount on behalf of the sender, otherwise the call to the ccipSend function will revert.

    Currently, the maximum number of tokens one can send in a single CCIP send transaction is five.

    feeToken

    Address of feeToken. CCIP supports fee payments in LINK and in alternative assets, which currently include native blockchain gas coins and their ERC20 wrapped versions. For developers, this means you can simply pay on the source chain, and CCIP will take care of execution on the destination chain. Set address(0) to pay in native gas coins such as ETH on Ethereum or MATIC on Polygon. Keep in mind that even if you are paying for fees in the native asset, nodes in the Chainlink DON will be rewarded in LINK only.

    extraArgs

    Users fill in the EVMExtraArgsV1 struct and then encode it to bytes using the _argsToBytes function. The struct consists of two properties:

    • gasLimit - The maximum amount of gas CCIP can consume to execute ccipReceive() on the contract located on the destination blockchain. Unspent gas is not refunded. This means that if you are sending tokens to EOA, for example, you should put 0 as a gasLimit value because EOAs can't implement the ccipReceive() (or any other) function. To estimate the accurate gas limit for your destination contract, consider Leveraging Ethereum client RPC by applying eth_estimateGas on receiver.ccipReceive() function, or use the , or conduct .

    If extraArgs are left empty, a.k.a extraArgs: "", a default of 200_000 gasLimit will be set with no strict sequencing. For production deployments, make sure that extraArgs is mutable. This allows you to build it off-chain and pass it in a call to a function or store it in a variable that you can update on demand. This makes extraArgs compatible with future CCIP upgrades.

    hashtag
    Destination blockchain

    To receive CCIP Messages, the smart contract on the destination blockchain must implement the IAny2EVMMessageReceiver interface. The NPM package comes up with the contract which implements it in the right way, called CCIPReceiver.sol, but we are going to talk more about it in the next chapter. For now, let's understand which functions from the IAny2EVMMessageReceiver interface must be implemented in the general-case scenario.

    As you can see, the ccipReceive() function from the IAny2EVMMessageReceiver interface accepts object of the Any2EVMMessage struct from the Client library. This struct is the Solidity representation of the received CCIP Message. Please note that this struct, Any2EVMMessage is different than the one we used to send on the source blockchain - EVM2AnyMessage. They are not the same.

    Let's now understand what each property of the Any2EVMMessage struct we are receiving represents and how to use it.

    • messageId - CCIP Message Id, generated on the source chain.

    • sourceChainSelector - Source chain selector.

    • sender - Sender address. abi.decode(sender, (address))

    To recap, here's the diagram with the minimal architecture needed to send & receive the Chainlink CCIP Message:

    Transporter, powered by CCIP

    hashtag
    Introduction to Transporter

    Transporter is a highly secure interface for bridging tokens across blockchains with total peace of mind. Transporter is built on top of Chainlink CCIParrow-up-right, the industry-leading cross-chain protocol for defense-in-depth security. Transporter is the cross-chain bridging app for transferring digital assets across blockchains and experiencing the best that each chain has to offer. In just a few clicks, you can bridge your tokens and cross chains with confidence knowing that Transporter is underpinned by Chainlink CCIP’s Level-5 Security, offers users real-time transaction tracking, and is available to provide 24/7 support.

    hashtag
    Warm-up Exercise: Let's bridge some testnet tokens

    Video tutorial:

    Navigate to

    Connect your wallet by clicking the "Connect wallet button"

    Select your Source and Destination Network of choice. I am going to send tokens from Avalanche Fuji to Ethereum Sepolia.

    Then select Token you want to send (we can also send Messages). I am going to use USDC.

    If you need tesnet USDC, you can get 10 units from the

    Then select the amount of tokens you want to send. I am going to choose 1 USDC.

    And approve Transporter to transfer that amount of tokens on behalf of you, by clicking the "Approve USDC" button.

    The next step is to select token you would like to use to pay for CCIP fees. By default the native coin of the source blockchain is selected (AVAX), but I am going to use LINK because it is cheaper.

    Finally, initiate the transfer by clicking the "Send" button.

    You can now sit back, relax and monitor your first cross-chain transfer in real time!

    Once your transaction is completed on the source blockchain (Avalanche Fuji in this example) you can monitor it on Chainlink CCIP Block Explorer as well - at .

    Bookmark this URL, because we are going to use it a lot during this bootcamp.

    To navigate to the Chainlink CCIP Block Explorer click the "View transaction" button.

    Once the transaction on the source blockchain is finalized, Chainlink DONs can proceed with the cross-chain transfers. Finality is really important security concept in blockchain technology, so make sure you familiarize yourself with it by the end of this bootcamp.

    Finally, we just need to wait for a destination transaction to be included in the next Ethereum Sepolia block.

    And that's it! Transport is completed, simple as that!

    You can of course always come back to Chainlink CCIP Block Explorer to see more details about the transfer.

    Defensive Example Pattern

    Another best practice that we will implement is so called Defensive Example, the pattern which allows us to reprocess failed messages without forcing the original transaction to fail. Let's explain how it works.

    Receiving and processing messages

    Upon receiving a message on the destination blockchain, the ccipReceive function is called by the CCIP Router. This function serves as the entry point to the contract for processing incoming CCIP messages, enforcing crucial security checks through the onlyRouter, and onlyAllowlisted modifiers.

    Here's the step-by-step breakdown of the process:

    1. Entrance through ccipReceive:

      • The ccipReceive function is invoked with an Any2EVMMessage struct containing the message to be processed.

      • Security checks ensure the call is from the authorized router, an allowlisted source chain, and an allowlisted sender.

    2. Processing Message:

      • ccipReceive calls the processMessage function, which is external to leverage Solidity's try/catch error handling mechanism. Note: The onlySelf modifier ensures that only the contract can call this function.

    3. Message Processing in _ccipReceive:

      • _ccipReceive extracts and stores various information from the message, such as the messageId, decoded sender address, token amounts, and data.

    4. Error Handling:

      • If an error occurs during the processing (or a simulated revert is triggered), the catch block within ccipReceive is executed.

      • The messageId of the failed message is added to s_failedMessages, and the message content is stored in

    Reprocessing of failed messages

    The retryFailedMessage function provides a mechanism to recover assets if a CCIP message processing fails. It's specifically designed to handle scenarios where message data issues prevent entire processing yet allow for token recovery:

    1. Initiation:

      • Only the contract owner can call this function, providing the messageId of the failed message and the tokenReceiver address for token recovery.

    2. Validation:

    This function showcases a graceful asset recovery solution, protecting user values even when message processing encounters issues.

    Inside processMessage, a check is performed for a simulated revert condition using the s_simRevert state variable. This simulation is toggled by the setSimRevert function, callable only by the contract owner.
  • If s_simRevert is false, processMessage calls the _ccipReceive function for further message processing.

  • It then emits a MessageReceived event, signaling the successful processing of the message.
    s_messageContents
    .
  • A MessageFailed event is emitted, which allows for later identification and reprocessing of failed messages.

  • It checks if the message has failed using s_failedMessages.get(messageId). If not, it reverts the transaction.

  • Status Update:

    • The error code for the message is updated to RESOLVED to prevent reentry and multiple retries.

  • Token Recovery:

    • Retrieves the failed message content using s_messageContents[messageId].

    • Transfers the locked tokens associated with the failed message to the specified tokenReceiver as an escape hatch without processing the entire message again.

  • Event Emission:

    • An event MessageRecovered is emitted to signal the successful recovery of the tokens.

  • Source blockchain

    The blockchain the CCIP Message is sent from

    Receiver

    A smart contract or an EOA that receives the CCIP Message

    Destination blockchain

    The blockchain the CCIP Message is sent to

    Interoperability

    The ability to exchange information between different systems or networks, even if they are incompatible

    Chainlink CCIP

    The protocol that allows you to send tokens and arbitrary messages across different blockchains

    Lane

    The unique combination of source blockchain to destination blockchain path

    Chain Selector

    The unique identifier of a blockchain in Chainlink CCIP

    CCIP Message

    The message that you can send across blockchains through CCIP lane which can consist of tokens and arbitrary data

    Sender

    A smart contract (of the User) or an EOA that sends the CCIP Message

    Example of a traditional bridge
    Trust assumptions - Patrick bridging funds
    Example of bi-directional CCIP lanes between two blockchains
    CCIP lanes
    Basic CCIP Architecture
    XSwaparrow-up-right
    BUILDarrow-up-right
    Transporterarrow-up-right
    ChainSwaparrow-up-right
    WEMIX PLAYarrow-up-right
    Amino Rewardsarrow-up-right
    cross-chain staking and restakingarrow-up-right
    EigenPie is integrating Chainlink CCIParrow-up-right
    How The Chainlink Platform Unlocks LST and LRT Adoption in DeFiarrow-up-right
    CCIP Masterclass: Cross-Chain Staking Editionarrow-up-right
    Chainlink CCIP enables Programmable Token Transfers across blockchains involving the USDC stablecoin.
    Lock and unlock
    —Tokens are locked on a source blockchain, and an equivalent amount of tokens are released on the destination blockchain. This enables the support of tokens without a burn/mint function or tokens that would introduce challenges if wrapped, such as native blockchain gas tokens. CCIP supports
    via the lock and unlock token transfer method.
    Internet of Contractsarrow-up-right
    Arbitrary Messagingarrow-up-right
    Transporterarrow-up-right
    CCIP as their official cross-chain infrastructurearrow-up-right
    CCIP supports Circle’s USDCarrow-up-right
    Truflation’sarrow-up-right
    CCIP is purpose-built to support cross-chain token transfers across a wide range of assets and applications.
    Programmable Token Transfers enable tokens and messages to be sent cross-chain as part of a single transaction, improving the developer and user experience.
    native ETH transfersarrow-up-right
    Create a new folder and name it ccip-masterclass

    Navigate to it

    Create a hew Foundry project by running:

    Navigate to https://remix.ethereum.org/arrow-up-right and click the "Create new Workspace" button.

    file:

    Option 2) [October 2023 UPDATE]

    You can run

    And after that set remappings in your foundry.toml or remappings.txt files to

    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 package.

    Compile it. If compiled successfully and new .deps/npm/@chainlink/contracts-ccip folders are generated, that means we imported the @chainlink/contracts-ccip package into the Remix IDE Workspace.

    Remix IDE compile
    strict - Used for strict sequencing. You should set it to false. CCIP will always process messages sent from a specific sender to a specific destination blockchain in the order they were sent. If you set strict: true in the extraArgs part of the message, and if the ccipReceive fails (reverts), it will prevent any following messages from the same sender from being processed until the current message is successfully executed. You should be very careful when using this feature to avoid unintentionally stopping messages from the sender from being processed. The strict sequencing feature is currently experimental, and there is no guarantee of its maintenance or further development in the future.
    if the source chain is an EVM chain.
  • data - Payload sent within the CCIP message. For example, "Hello, world!"

  • tokenAmounts - Received tokens and their amounts in their destination chain representation.

  • Node.jsarrow-up-right
    NPMarrow-up-right
    Foundryarrow-up-right
    CCIP Starter Kit (Hardhat version)arrow-up-right
    CCIP Starter Kit (Foundry version)arrow-up-right
    @chainlink/contracts-cciparrow-up-right
    Hardhat plugin for gas testsarrow-up-right
    Foundry gas testsarrow-up-right
    @chainlink/contracts-cciparrow-up-right
    Basic CCIP Architecture
    Developer Interfaces
    https://www.youtube.com/watch?v=dCDQ-xetzpMarrow-up-right
    https://test.transporter.io/ arrow-up-right
    https://faucet.circle.com/arrow-up-right
    https://ccip.chain.linkarrow-up-right

    Exercise 1: Programmable Token Transfers using the Defensive Example Pattern

    Transfer Tokens With Data - Defensive Example

    This tutorial extends the programmable token transfers examplearrow-up-right. It uses Chainlink CCIP to transfer tokens and arbitrary data between smart contracts on different blockchains, and focuses on defensive coding in the receiver contract. In the event of a specified error during the CCIP message reception, the contract locks the tokens. Locking the tokens allows the owner to recover and redirect them as needed. Defensive coding is crucial as it enables the recovery of locked tokens and ensures the protection of your users' assets.

    Before You Begin

    1. You should understand how to write, compile, deploy, and fund a smart contract. If you need to brush up on the basics, read this tutorialarrow-up-right, which will guide you through using the Solidity programming languagearrow-up-right, interacting with the and working within the .

    2. Your account must have some AVAX and LINK tokens on Avalanche Fuji and ETH tokens on Ethereum Sepolia. Learn how to .

    3. Check the to confirm that the tokens you will transfer are supported for your lane. In this example, you will transfer tokens from Avalanche Fuji to Ethereum Sepolia so check the list of supported tokens .

    4. Learn how to . Following this guide, you should have CCIP-BnM tokens, and CCIP-BnM should appear in the list of your tokens in MetaMask.

    5. Learn how to . This guide shows how to fund your contract in LINK, but you can use the same guide for funding your contract with any ERC20 tokens as long as they appear in the list of tokens in MetaMask.

    6. Follow the previous tutorial: to learn how to make programmable token transfers using CCIP.

    Coding time!

    In this exercise, we'll initiate a transaction from a smart contract on Avalanche Fuji, sending a string text and CCIP-BnM tokens to another smart contract on Ethereum Sepolia using CCIP. However, a deliberate failure in the processing logic will occur upon reaching the receiver contract. This tutorial will demonstrate a graceful error-handling approach, allowing the contract owner to recover the locked tokens.

    CORRECTLY ESTIMATE YOUR GAS LIMIT

    It is crucial to thoroughly test all scenarios to accurately estimate the required gas limit, including for failure scenarios. Be aware that the gas used to execute the error-handling logic for failure scenarios may be higher than that for successful scenarios.

    hashtag
    Deploy Your Contracts

    To use this contract:

    1. .

    2. Compile your contract.

    3. Deploy, fund your sender contract on Avalanche Fuji and enable sending messages to Ethereum Sepolia:

    At this point, you have one sender contract on Avalanche Fuji and one receiver contract on Ethereum Sepolia. As security measures, you enabled the sender contract to send CCIP messages to Ethereum Sepolia and the receiver contract to receive CCIP messages from the sender on Avalanche Fuji. The receiver contract cannot process the message, and therefore, instead of throwing an exception, it will lock the received tokens, enabling the owner to recover them.

    Note: Another security measure enforces that only the router can call the _ccipReceive function. Read the section for more details.

    hashtag
    Recover the locked tokens

    You will transfer 0.001 CCIP-BnM and a text. The CCIP fees for using CCIP will be paid in LINK.

    1. Open MetaMask and connect to Avalanche Fuji. Fund your contract with LINK tokens. You can transfer 0.5 LINK to your contract. In this example, LINK is used to pay the CCIP fees.

    2. Send a string data with tokens from Avalanche Fuji:

      1. Open MetaMask and select the network

    NOTE

    During gas price spikes, your transaction might fail, requiring more than 0.5 LINK to proceed. If your transaction fails, fund your contract with more LINK tokens and try again.

    1. Open the and search your cross-chain transaction using the transaction hash.

    1. The CCIP transaction is completed once the status is marked as "Success". In this example, the CCIP message ID is 0x120367995ef71f83d64a05bd7793862afda9d04049da4cb32851934490d03ae4.

    1. Check the receiver contract on the destination chain:

      1. Open MetaMask and select the network Ethereum Sepolia.

      2. In Remix IDE, under Deploy & Run Transactions, open the list of functions of your smart contract deployed on Ethereum Sepolia.

    Argument
    Description

    1. After confirming the transaction, you can open it in a block explorer. Notice that the locked funds were transferred to the tokenReceiver address.

    2. Call again the getFailedMessages function with an offset of 0 and a limit of 1 to retrieve the first failed message. Notice that the error code is now 0

    Note: These example contracts are designed to work bi-directionally. As an exercise, you can use them to transfer tokens with data from Avalanche Fuji to Ethereum Sepolia and from Ethereum Sepolia back to Avalanche Fuji.

    hashtag
    Explanations

    The smart contract featured in this tutorial is designed to interact with CCIP to transfer and receive tokens and data. The contract code is similar to the tutorial. Hence, you can refer to its . We will only explain the main differences.

    hashtag
    Sending messages

    The sendMessagePayLINK function is similar to the sendMessagePayLINK function in the tutorial. The main difference is the increased gas limit to account for the additional gas required to process the error-handling logic.

    hashtag
    Receiving and processing messages

    Upon receiving a message on the destination blockchain, the ccipReceive function is called by the CCIP router. This function serves as the entry point to the contract for processing incoming CCIP messages, enforcing crucial security checks through the onlyRouter, and onlyAllowlisted modifiers.

    Here's the step-by-step breakdown of the process:

    1. Entrance through ccipReceive:

      • The ccipReceive function is invoked with an Any2EVMMessage containing the message to be processed.

    hashtag
    Reprocessing of failed messages

    The retryFailedMessage function provides a mechanism to recover assets if a CCIP message processing fails. It's specifically designed to handle scenarios where message data issues prevent entire processing yet allow for token recovery:

    1. Initiation:

      • Only the contract owner can call this function, providing the messageId of the failed message and the tokenReceiver address for token recovery.

    2. Validation:

    This function showcases a graceful asset recovery solution, protecting user values even when message processing encounters issues.

    Meet Our Instructors

    hashtag
    Richard Gottleber, Developer Relations Engineer, Chainlink Labs

    X (Twitter): @thergdevarrow-up-right

    Email: richard.gottleber@smartcontract.comenvelope

    hashtag
    Andrej Rakic, Developer Relations Engineer, Chainlink Labs

    X (Twitter):

    Email:

    hashtag
    Darby Martinez, Developer Expert, Chainlink Community

    X (Twitter):

    LinkedIn:

    Day 1 Homework

    Please note, only participants who finish their homework for all three days will be eligible for the Certificate of Completion.

    Please answer these 15 questions by the end of the bootcamp.

    Submit your answers via this formarrow-up-right

    Easy:

    1. What is CCIP Lane?

    2. What is CCIP Chain Selector? How does it differ from Chain ID?

    3. What is gasLimit in CCIP Messages used for?

    4. How can one monitor CCIP Messages in real time?

    5. What are the three main capabilities of Chainlink CCIP? Provide examples of potential use cases leveraging these capabilities.

    Medium:

    1. Detail the security best practices for verifying the integrity of incoming CCIP messages in your smart contracts. What specific checks should be implemented in the ccipReceive function, and why are these verifications crucial for the security of cross-chain dApps

    2. Which token transfer mechanisms are supported by Chainlink CCIP?

    3. Describe the role of the Risk Management Network in Chainlink CCIP and explain the process of "blessing" and "cursing".

    Hard:

    1. Explain the DefensiveExample Pattern and how to handle CCIP message failures gracefully.

    2. List and explain the scenarios that would trigger the need for manual execution using the Chainlink CCIP Explorer.

    3. Explain why it is a best practice to make the extraArgs mutable in Chainlink CCIP and describe how a developer can implement this in their smart contract.

    Day 2 Homework

    Please note, only participants who finish their homework for all three days will be eligible for the Certificate of Completion.

    Submit your public GitHub repo for the exercise below via this formarrow-up-right

    Using chainlink-local write a test for the https://github.com/smartcontractkit/ccip-cross-chain-name-servicearrow-up-right project. You can use https://cll-devrel.gitbook.io/chainlink-local-documentationarrow-up-right for help.

    circle-exclamation

    During the Exercise #3 we used Chainlink Local's Forked Mode with Foundry. For this homework you should use Chainlink Local's Local Mode with Hardhat.

    In the test you must:

    • Create an instance of CCIPLocalSimulator.sol smart contract.

    • Call the configuration() function to get Router contract address.

    • Create instances of CrossChainNameServiceRegister.sol, CrossChainNameServiceReceiver.sol

    triangle-exclamation

    DO NOT PROVIDE PRIVATE KEY OR TESTNET RPC DETAILS, USE HARDHAT NETWORK ONLY! npx hardhat test --network hardhat

    Exercise 3: Testing Cross-Chain contracts using Chainlink Local

    You might noticed so far that building with CCIP directly on test networks is not ideal due to extra points of friction - like setting up a wallet, getting testnet tokens, waiting for cross-chain transactions to complete, etc. This is because test networks are for testing and local environments (like Foundry, Hardhat or Remix IDE) are for building and unit testing.

    hashtag
    Introducing Chainlink Local

    To address this issue, we created , and in this chapter you will learn how to simulate your cross-chain transactions locally and build with Chainlink CCIP 2000x quicker compared to working on test networks!

    A talk with the Interport team

    hashtag
    Vladimir Makarov, co-founder of Interport

    Website:

    X (Twitter):

    CCIP Architecture and Message Processing

    We will now see what the workflow of a CCIP Message looks like in a couple of steps.

    hashtag
    Step 1: Prepare

    1. The Sender prepares a CCIP Message (EVM2AnyMessage

    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 and clicking the "Create new Workspace" button. Select "Blank" template and name the workspace as "CCIP Masterclass 4".

    Alternatively, you can clone:

    A talk with the Celo team

    hashtag
    Sophia Dew, Developer Relations Engineering Lead

    X (Twitter):

    💻

    Github repo:

    Building Cross-Chain NFTs

    How to design a cross-chain NFT smart contract

    hashtag
    What are Cross-Chain NFTs?

    A cross-chain NFT is a smart contract that can exist on any blockchain, abstracting away the need for users to understand which blockchain they’re using.

    Typically, NFT movements from one chain to another are eye-catching events, but this simple fact brings up a larger question of the reliability and security of Web3’s middleware infrastructure. In a seamless cross-chain world, moving digital assets from one chain to another should be as normal as submitting a transaction on the same blockchain.

    When an NFT moves from one blockchain to another, it becomes a cross-chain NFT.

    // SPDX-License-Identifier: MIT
    pragma solidity 0.8.19;
    
    import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
    
    contract Empty {}
    node -v
    npm -v
    mkdir ccip-masterclass
    cd ccip-masterclass
    npx hardhat@2.14.1 init
    forge --version
    npm i @chainlink/contracts-ccip --save-dev
    # Node modules
    node_modules/
    npm i @chainlink/contracts-ccip --save-dev
    // SOURCE BLOCKCHAIN 
    
    interface IRouterClient {
        /// @notice Request a CCIP message to be sent to the destination chain
        /// @param destinationChainSelector The destination chain selector
        /// @param message The cross-chain CCIP message including data and/or tokens
        /// @return messageId The message ID
        function ccipSend(
            uint64 destinationChainSelector,
            Client.EVM2AnyMessage calldata message
        ) external payable returns(bytes32 messageId);
    }
    // SOURCE BLOCKCHAIN
    
    library Client {
        struct EVM2AnyMessage {
            bytes receiver; // abi.encode(receiver address) for dest EVM chains
            bytes data; // data payload
            EVMTokenAmount[] tokenAmounts; // token transfers
            address feeToken; // fee token address; address(0) means you are sending msg.value
            bytes extraArgs; // populate this with _argsToBytes(EVMExtraArgsV1)
        }
        
        struct EVMTokenAmount {
            address token; // token address on local blockchain
            uint256 amount;
        }
        
        struct EVMExtraArgsV1 {
            uint256 gasLimit;
            bool strict;
        }
    }
    // DESTINATION BLOCKCHAIN
    
    /// @notice Application contracts that intend to receive messages from 
    /// the router should implement this interface.
    interface IAny2EVMMessageReceiver {
        /// @notice Router calls this to deliver a message
        /// @param message CCIP Message
        /// @dev Note ensure you check that msg.sender is the Router
        function ccipReceive(Client.Any2EVMMessage calldata message) external;
    }
    // DESTINATION BLOCKCHAIN
    
    library Client {
        struct Any2EVMMessage {
            bytes32 messageId; // MessageId corresponding to ccipSend on source
            uint64 sourceChainSelector; // Source chain selector
            bytes sender; // abi.decode(sender) if coming from an EVM chain
            bytes data; // payload sent in original message
            EVMTokenAmount[] tokenAmounts; // Tokens and their amounts at destination
        }
        
        struct EVMTokenAmount {
            address token; // token address on local blockchain
            uint256 amount;
        }
    }
    mkdir ccip-masterclass
    cd ccip-masterclass
    forge init
    libs = ['node_modules', 'lib']
    remappings = [
        '@chainlink/contracts-ccip/=node_modules/@chainlink/contracts-ccip'
    ]
    forge install smartcontractkit/ccip@ccip-develop
    # foundry.toml
    remappings = [
        '@chainlink/contracts-ccip/=lib/ccip/contracts/'
    ]