We will now see what the workflow of a CCIP Message looks like in a couple of steps.
The Sender prepares a CCIP Message (EVM2AnyMessage
) for their cross-chain transaction to a destination blockchain (chainSelector
) of choice. A CCIP message includes the following information:
Receiver
Data payload
Tokens and amounts
Fee token
Additional parameters (gasLimit
)
The Sender calls Router.getFee()
to receive the total fees (gas + premium) to pay CCIP and approves the requested fee amount.
The Sender calls Router.ccipSend()
, providing the CCIP Message they want to send along with their desired destination chainSelector
. In the case of token transfers, the amount to be transferred must be approved to the Router.
The Router validates the received Message (e.g., valid and supported destination chainId
and supported tokens at the destination chain).
The Router receives and transfers fees to the OnRamp
.
The Router receives and transfers tokens to its corresponding Token Pool. If the sender has not approved the tokens to the Router, this will fail.
The Router forwards the Message to the correct OnRamp
(based on destination chainSelector
) for processing:
Validate the message (number of tokens, gasLimit
, data length …)
[For token transfers] Ensure that the transferred value does not hit the aggregate rate limit of the lane.
Sequence the message with a sequence number.
For each Token included in the Message: instruct the token pool to lock/burn the tokens. This will also validate the token pool rate limit for this lane.
The OnRamp
emits an event containing the sequenced message. This triggers the DONs to process the message.
A messageId
is generated and returned to the Sender.
Nodes in the Committing DON listen for events of Messages that are ready to be sent
Messages must be finalized to be considered secure against reorg attacks.
Triggered by time or number of messages queued in the OnRamp
, the Committing DON creates a Report with a commitment of all messages ready to be sent, in a batch. This commitment takes the form of a Merkle Root
Upon consensus in the Committing DON, the Report containing the Merkle Root is transmitted to the CommitStore
contract on the destination chain
The Risk Management Network “blesses” the Merkle Root in the CommitStore
, to make sure it is a correct representation of the queued messages at the OnRamp
.
Merkle Root: the root hash of the Merkle Tree. It is a commitment to all the leaves (Messages M1
-M4
) in the tree. Each node in the tree is the hash of the nodes below it.
Merkle Proof: to prove that Message M1 is included in the Merkle Root (commitment), a Prover provides the following elements as proof to a Verifier (who only has the root hash):
M1
H(M2)
H(H(M3),H(M4))
Using this Merkle Proof, a Verifier can easily verify that, indeed, M1
is included in the commitment (root hash) that it possesses.
Nodes in the Executing DON listen for events of Messages that are ready to be sent, similar to the Committing DON
Messages must be finalized to be considered secure against reorg attacks.
In addition to the time or number of messages queued in the OnRamp
, the Executing DON also monitors the CommitStore
to make sure the messages are ready to be executed at the destination chain, i.e., are the messages included in a blessed on-chain commitment?
If conditions are met, the Executing DON creates a Report with all messages ready to be sent, in a batch. It accounts for the gasLimit
of each message in its batching logic. It also calculates a relevant Merkle Proof for each message to prove that the message is included in the Merkle Root submitted by the Committing DON in the CommitStore
. Note that Executing DON batches can be any subset of a Committing DON batch.
Upon consensus, the Report is transmitted to the OffRamp
contract on the destination chain.
For each message in the batch received, the OffRamp
verifies using the provided Merkle Proof whether the transaction is included in the blessed commitment in the CommitStore
.
If tokens are included in the transaction, the OffRamp
validates the aggregate rate limit of the lane and identifies the matching Token Pool(s).
OffRamp
calls the TokenPool
’s unlock
/mint
function. This will validate the token pool rate limit, unlock or mint the token and transfer them to the specified receiver.
If the receiver is not an EOA and has the correct interface implemented, the OffRamp
uses the Router to call the receiver’s ccipReceive()
function
The receiver processes the message and is informed where the message comes from (blockchain + sender), the tokens transferred, and the data payload (with relevant instructions).
Based on the data payload, the receiver might transfer the tokens to the final recipient (end-user)
Now, do you need to know in details how the processing of CCIP Message works? Absolutely not, you just need to send the cross-chain Message by interacting with the Router contract and Chainlink CCIP will deliver it, the same as when sending a package you just drop it at the Post Office, mark to whom you are sending it and pay for fees.
Just as international travel involves various checkpoints and procedures to ensure a safe and verified journey from one country to another, Chainlink CCIP ensures secure and verified communication between different blockchain networks.
Pre-Boarding at JFK Airport: The Committing Phase
Before any plane takes off, a series of rigorous checks are in place—mirroring the initiating phase of CCIP. Here, the Router acts as our check-in desk, where users present their cross-chain requests, akin to passengers confirming their flight details.
Travelers check in their luggage, which is then handled by the airport staff. As with any luggage on a long-haul flight, the cross-chain message undergoes a meticulous security protocol. Similarly, in CCIP, the OnRamp contract checks the validity of the destination blockchain address, message size, gas limits, and sequence numbers, ensuring that the 'luggage' (or data payload) is prepared correctly for its journey.
Passport and Visa verification are much comparable to the Commit Store smart contract, which stores the Merkle root of finalized messages and ensures they are 'blessed' by the Risk Management Network for authenticity and security before being executed on the destination chain.
In-Flight: The Cross-Chain Transit
During the flight, passengers and luggage are in transit, similar to the cross-chain message being propagated across networks. The Executing DON works behind the scenes, analogous to the flight crew, ensuring the smooth passage of the cross-chain interaction.
As we know, the duration of a flight can vary - flying east might chase the sun, shortening our perceived day, while westward travel extends it. Similarly, the delivery time of a cross-chain message depends on the source blockchain finality. We remember from the CCIP Masterclass #1 that finality refers to the state of irreversibility and permanent record of a transaction on the blockchain.
Touchdown at Hong Kong Airport: The Executing Phase
On arrival, the OffRamp contract ensures the message is authentic, verifying the proof against the committed and blessed Merkle root.
Similarly to the final checks by the Risk Management Network, behind the scenes (unseen by the passenger) the suitcase or our cross-chain message undergoes various security checks, ensuring that the message adheres to the rules and regulations of the destination blockchain.
Finally, the Router on the destination chain assumes the role of border control, delivering the message data and/or tokens to the receiver's address, akin to a traveler receiving their stamped passport and entering a new country.
This entire process, while complex, remains largely invisible to the end-user, who simply experiences the seamless transfer of their digital assets from one blockchain to another. From the moment of check-in to the joy of retrieval, the journey of a cross-chain message through CCIP is a marvel of modern cryptography, ensuring that what we entrust to the network is what we receive.