CCIP on Canton — Overview

The following outlines the end-to-end data journey between a remote chain (e.g. EVM) and Canton addresses, including execution responsibilities and the components involved at each step.

EVM → Canton

When Canton is the destination (receiving) chain.

Figure 1. Execute flow, on Canton, when Canton is the destination (receiving) chain.

1. On the source chain (e.g. EVM)

Using the CCIP SDK/CLI, the sending user or dApp calls the Router on the source chain, which forwards the message to the chain's OnRamp. The OnRamp:

  • Validates the message structure and contents.
  • Forwards the message to all specified CommitteeVerifiers for additional validation if required.
  • For token transfers: forwards the message to the token pool, which locks or burns tokens to be sent.
  • Calculates the message fee and collects payment.
  • Emits a CCIPMessageSent event containing the message payload.

CommitteeVerifier operators (for the default verifier, Chainlink NOPs) observe the event, validate it, generate proofs, sign with their signer keys, and aggregate proofs to the indexer.

Once all requested CommitteeVerifiers have submitted proofs, the message is written to the destination chain OffRamp by a custom executor operated by the receiver on Canton.

2. On Canton

Using the CCIP API, the status of messages destined for Canton can be retrieved. When a message is ready to execute, the receiver uses the CCIP CLI to manually execute it. Preparation includes:

  • Fetching proofs from the indexer for the target message ID or transaction.
  • Querying the CCIP EDS for explicit disclosures of CCIP contracts.
  • Looking up the PerPartyRouter (or creating one via PerPartyRouterFactory on first use).
  • For custom CommitteeVerifiers: querying the verifier's EDS for disclosures.
  • For token transfers: querying the asset's Token Standard Registry and token pool operator's EDS.

To execute, the user interacts with the CCIPReceiver contract:

  1. Deploy and configure a CCIPReceiver. Set receiverFinalityConfig according to how the receiver handles finality. The sender chooses requested finality in the message; the receiver config must allow it (FTF = faster than finality, FCR = safe confirmation, or default finality tag).
  2. Call the receiver with the message and message proof.
  3. The receiver calls each CommitteeVerifier; each verifies its proof and returns validation.
  4. The receiver calls PerPartyRouter_Execute with CommitteeVerifier validations:
    • PerPartyRouter forwards to the OffRamp, which verifies all required CommitteeVerifiers have validated.
    • On success, the OffRamp/TokenPool consumes tickets and, for token transfers, issues a TokenReceiveTicket.
    • PerPartyRouter marks the message executed to prevent double execution.

If the message contained a token transfer, the receiver uses the TokenReceiveTicket to call the token pool:

  1. The token pool verifies the ticket was issued by the CCIP owner and creates an outgoing TransferInstruction to the token receiver party.
  2. The receiver party accepts the TransferInstruction to gain access to the transferred tokens.

Canton → EVM

When Canton is the source (sending) chain.

Figure 2. Execute flow, on Canton, when Canton is the source (sending) chain.

1. On Canton

Before sending, fetch explicit disclosures and prerequisites using the CCIP CLI:

  • Query the CCIP EDS for disclosures of CCIP contracts.
  • For custom CommitteeVerifiers: query the verifier's EDS.
  • For token transfers: query the token pool operator's EDS and the asset registry API to create a TransferInstruction to the token pool owner party.
  • Retrieve or create the current PerPartyRouter via PerPartyRouterFactory.

Using the CCIP CLI, create a CCIPSender contract and send a message:

  • Call each CommitteeVerifier's CommitteeVerifier_ForwardToVerifier, returning a CCVTicket. Each verifier includes observer parties on the CCIPMessageSent event.
  • For token transfers: call the token pool to lock/burn tokens; the pool issues a TokenPoolTicket.
  • Call PerPartyRouter_CCIPSend with CCVTicket(s) and TokenPoolTicket(s). PerPartyRouter forwards to the OnRamp, which validates tickets and emits CCIPMessageSent.
  • CommitteeVerifier operators observe, validate, generate proofs, and submit to the indexer.
  • Once proofs are aggregated, the indexer marks the message ready for destination execution.

The message is written to the destination chain (e.g. EVM) OffRamp by a custom executor or automatically by Chainlink NOPs (default executor).

2. On the destination chain (e.g. EVM)

The OffRamp calls the receiving contract's ccipReceive. The OffRamp:

  • Validates message structure and contents.
  • Forwards to CommitteeVerifiers for signature validation.
  • For token transfers: forwards to the token pool to unlock or mint received tokens.

Key tools

ToolRole
CCIP CLI / SDKAssemble disclosures, build messages, send and execute on Canton
Global CCIP EDSDisclosures for Chainlink-hosted CCIP contracts
CCIP ExplorerTrack message status
Token pool operator EDSDisclosures for issuer token pools during send/execute

What's next

Get the latest Chainlink content straight to your inbox.