CCIP v2.0.0 LombardVerifier API Reference
Summary
LombardVerifier is a Cross-Chain Verifier (CCV) that integrates Lombard BridgeV3 for token-transfer verification.
It:
- Deposits tokens on the source chain via
BridgeV3.deposit - Embeds
(versionTag || messageId)intooptionalMessage - Verifies delivery on the destination chain via
Mailbox.deliverAndHandle - Validates the delivered message matches
(versionTag || messageId) - Integrates RMN curse checks and router-based ramp gating via
[BaseVerifier](/ccip/evm/api-reference/v2.0.0/base-verifier)
Contract
chains/evm/contracts/ccvs/LombardVerifier.sol
Import
import {LombardVerifier} from "chainlink-ccip/chains/evm/contracts/ccvs/LombardVerifier.sol";
Inheritance
BaseVerifierOwnable2StepMsgSender
Implements:
ICrossChainVerifierV1ITypeAndVersion
typeAndVersion
string public constant override typeAndVersion =
"LombardVerifier 2.0.0-dev";
State
Constants
bytes4 internal constant VERSION_TAG_V1_7_0 =
bytes4(keccak256("LombardVerifier 1.7.0"));
uint8 internal constant SUPPORTED_BRIDGE_MSG_VERSION = 1;
uint256 internal constant VERSION_TAG_SIZE = 4;
uint256 internal constant BYTES32_SIZE = 32;
uint256 internal constant BRIDGED_MESSAGE_SIZE = 36;
uint256 internal constant RAW_PAYLOAD_LENGTH_SIZE = 2;
uint256 internal constant PAYLOAD_START_INDEX =
VERSION_TAG_SIZE + RAW_PAYLOAD_LENGTH_SIZE;
Immutables
IBridgeV3 internal immutable i_bridge;
Storage
DynamicConfig private s_dynamicConfig;
EnumerableMap.AddressToAddressMap private s_supportedTokens;
EnumerableSet.UintSet private s_supportedChains;
mapping(uint64 => Path) private s_chainSelectorToPath;
Constructor
constructor(
DynamicConfig memory dynamicConfig,
IBridgeV3 bridge,
string[] memory storageLocation,
address rmn
)
BaseVerifier(storageLocation, rmn)
Validations:
bridge != address(0)→ elseZeroBridge()bridge.MSG_VERSION() == SUPPORTED_BRIDGE_MSG_VERSION
Initializes:
i_bridges_dynamicConfig
Emits:
event DynamicConfigSet(DynamicConfig dynamicConfig);
External API
forwardToVerifier
function forwardToVerifier(
MessageV1Codec.MessageV1 calldata message,
bytes32 messageId,
address,
uint256,
bytes calldata
) external returns (bytes memory verifierData)
Source-chain behavior:
_assertNotCursedByRMN(message.destChainSelector)- Require
message.tokenTransfer.length > 0 - Enforce allowlist via
_assertSenderIsAllowed - Call
_callDepositOnBridge - Return raw
payloadHashbytes
verifyMessage
function verifyMessage(
MessageV1Codec.MessageV1 calldata message,
bytes32 messageId,
bytes calldata ccvData
) external
Destination-chain behavior:
_assertNotCursedByRMN(message.sourceChainSelector)_onlyOffRamp(message.sourceChainSelector)- Parse and validate version prefix
- Parse
rawPayloadandproof - Call:
IMailbox(i_bridge.mailbox())
.deliverAndHandle(rawPayload, proof);
- Require
executed == true - Validate bridged message equals
(VERSION_TAG_V1_7_0 || messageId)
versionTag
function versionTag()
public
pure
override
returns (bytes4)
Returns VERSION_TAG_V1_7_0.
withdrawFeeTokens
function withdrawFeeTokens(address[] calldata feeTokens)
external
Transfers balances to s_dynamicConfig.feeAggregator.
Token Administration
updateSupportedTokens
Owner-only.
function updateSupportedTokens(
address[] calldata tokensToRemove,
SupportedTokenArgs[] calldata tokensToSet
) external onlyOwner
Manages supported tokens and optional adapters.
getSupportedTokens
function getSupportedTokens()
external
view
returns (address[] memory)
isSupportedToken
function isSupportedToken(address token)
external
view
returns (bool)
Path Administration
setPath
function setPath(
uint64 remoteChainSelector,
bytes32 lChainId,
bytes32 allowedCaller
) external onlyOwner
removePaths
function removePaths(uint64[] calldata remoteChainSelectors)
external
onlyOwner
getPath
function getPath(uint64 remoteChainSelector)
external
view
returns (Path memory)
getSupportedChains
function getSupportedChains()
external
view
returns (uint64[] memory)
Remote Chain Config
Owner-only passthrough to BaseVerifier:
function applyRemoteChainConfigUpdates(
RemoteChainConfigArgs[] calldata remoteChainConfigArgs
) external onlyOwner
Events
event PathSet(
uint64 remoteChainSelector,
bytes32 lChainId,
bytes32 allowedCaller
);
event PathRemoved(
uint64 remoteChainSelector,
bytes32 lChainId,
bytes32 allowedCaller
);
event SupportedTokenSet(
address localToken,
address localAdapter
);
event SupportedTokenRemoved(address token);
event DynamicConfigSet(DynamicConfig dynamicConfig);
Inherited events from BaseVerifier.
Errors
error ZeroBridge();
error InvalidMessageVersion(uint8 expected, uint8 actual);
error ZeroLombardChainId();
error PathNotExist(uint64 remoteChainSelector);
error TokenNotSupported(address token);
error MustTransferTokens();
error InvalidReceiver(bytes receiver);
error InvalidVerifierResults();
error InvalidCCVVersion(bytes4 expected, bytes4 actual);
error InvalidMessageLength(uint256 expected, uint256 actual);
error InvalidMessageId(bytes32 expected, bytes32 actual);
error ExecutionError();
Inherited errors from BaseVerifier.
Structs
struct DynamicConfig {
address feeAggregator;
}
struct Path {
bytes32 allowedCaller;
bytes32 lChainId;
}
struct SupportedTokenArgs {
address localToken;
address localAdapter;
}
Internal Functions
_callDepositOnBridge
Internal deposit wrapper:
function _callDepositOnBridge(
MessageV1Codec.TokenTransferV1 calldata tokenTransfer,
uint64 destChainSelector,
bytes calldata sender,
bytes32 messageId
) internal returns (bytes memory)
Calls i_bridge.deposit with:
optionalMessage =
bytes.concat(VERSION_TAG_V1_7_0, messageId);
Returns raw payloadHash.
Security model
- RMN curse gating blocks both source and destination flows.
- Router-based ramp gating enforced via
BaseVerifier. - Token support explicitly allowlisted.
- Path must exist for destination chain.
- Receiver limited to ≤ 32 bytes.
- Message binding enforced via
(versionTag || messageId). - Bridge proof verification delegated to Lombard Mailbox.
- No signature quorum used (BridgeV3 handles proof verification).