Join our community of builders on

Telegram!Telegram

Chainlink CCV

Symbiotic-secured Cross-Chain Verifier (CCV) for Chainlink CCIP-compatible message verification.

Overview

The CCV provider implements a Symbiotic-backed verifier compatible with Chainlink's CCIP CCV interface. When a message is sent through an OnRamp-compatible contract, a CCIPMessageSent event is emitted. Operators build a CCV payload, collect BLS attestations via Symbiotic relay sidecars, and the relayer submits the proof to OffRamp.execute(...) on the destination chain. The OffRamp calls SymbioticCCV.verifyMessage(...) for each message, and success is confirmed when MessageExecuted(messageId) is emitted.

This template supports the Symbiotic CCV variant only. The Chainlink auxiliary devenv stack (aggregator, indexer, verifier, executor) is not required.

Message Flow

Code Pointers

Contracts

  • contracts/src/ccv/SymbioticCCV.sol -- CCV verifier implementation (verifyMessage, forwardToVerifier)
  • contracts/src/ccv/interfaces/ -- CCV interface definitions (ICrossChainVerifierV1, etc.)
  • contracts/src/ccv/libraries/ -- CCV encoding and helper libraries
  • contracts/src/symbiotic/Settlement.sol -- BLS signature verification and quorum enforcement
  • contracts/src/symbiotic/KeyRegistry.sol -- Operator BLS public key registry
  • contracts/src/symbiotic/Driver.sol -- Epoch and genesis management

Operator (Rust)

  • operator/src/provider/chainlink_ccv.rs -- Decodes CCIPMessageSent events, builds CCV payloads
  • operator/src/provider/mod.rs -- Provider trait and registration

Config Templates

  • config/templates/oz-monitor/monitors/ccip_message_sent.json -- Monitor job for CCIPMessageSent events

Configuration

Select CCV as the active provider:

// config/environments/<env>.json
{
  "activeProvider": "chainlink_ccv"
}

Chain config is shared across providers — chain IDs from chains.source.chainId and chains.destination.chainId are used as CCIP chain selectors at runtime.

Address resolution for CCV scripts:

  1. CCV_* environment variables (highest priority)
  2. deployments/<env>.json

CCV settlement addresses in deployment state:

  • Destination: destination.chainlinkCcv.settlement in deployments/<env>.json

Available CCV_* override variables:

VariableDescription
CCV_SOURCE_ADDRESSSymbioticCCV on source chain
CCV_DEST_ADDRESSSymbioticCCV on destination chain
CCV_SOURCE_ONRAMP_ADDRESSSource OnRamp-compatible contract
CCV_DEST_OFFRAMP_ADDRESSDestination OffRamp submit target

Usage

# Select chainlink_ccv provider in config/environments/local.json
# "activeProvider": "chainlink_ccv"

# Start the stack
make start

# Send a test message
make send MSG="hello"

# Watch until MessageExecuted on destination
make watch

# Or run both
make e2e

make send sends through the source mock OnRamp.sendMessage(...), emitting CCIPMessageSent.

make watch succeeds only when MessageExecuted(messageId) is found on the destination chain (not just relayer submission).

See CLI Reference for full command options.

Deployment Status

EnvironmentStatus
LocalSupported (Symbiotic-only mock path)
TestnetNot yet
MainnetNot yet

Common Issues

  • EpochTooStale revert (0xf5ab0d81) -- Settlement epoch data is stale. Refresh genesis or tune epoch timing. See Troubleshooting.
  • Watch does not reach success -- CCV requires destination MessageExecuted(messageId), not just relayer submission. See Troubleshooting.
  • Submission fails at estimate-gas -- Common causes: stale epoch, incorrect CCV addresses, settlement not initialized. See Troubleshooting.