Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 49 additions & 47 deletions chains/evm/.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@ BurnToAddressMintTokenPool_lockOrBurn:test_LockOrBurn() (gas: 241476)
BurnWithFromMintTokenPool_lockOrBurn:test_constructor() (gas: 23892)
BurnWithFromMintTokenPool_lockOrBurn:test_lockOrBurn() (gas: 246012)
CCIPClientExampleWithCCVs_applyCCVConfigUpdates:test_applyCCVConfigUpdates() (gas: 166808)
CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2116446)
CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2124124)
CCTPMessageTransmitterProxy_configureAllowedCallers:test_configureAllowedCallers() (gas: 66306)
CCTPMessageTransmitterProxy_getAllowedCallers:test_configureAllowedCallers() (gas: 75959)
CCTPMessageTransmitterProxy_getCCTPTransmitter:test_getCCTPTransmitter() (gas: 10899)
CCTPMessageTransmitterProxy_receiveMessage:test_receiveMessage() (gas: 32098)
CCVConfigValidation_validateDefaultAndMandatedCCVs:test_validateDefaultAndMandatedCCVs_OnlyDefaultProvided() (gas: 7802)
CCVConfigValidation_validateDefaultAndMandatedCCVs:test_validateDefaultAndMandatedCCVs_OnlyMandatedProvided() (gas: 7620)
CommitteeVerifier_applyAllowlistUpdates:test_applyAllowlistUpdates_AsAllowlistAdmin() (gas: 93093)
CommitteeVerifier_applyAllowlistUpdates:test_applyAllowlistUpdates_AsOwner() (gas: 94653)
CommitteeVerifier_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 47083)
CommitteeVerifier_constructor:test_constructor() (gas: 2053135)
CommitteeVerifier_forwardToVerifier:test_forwardToVerifier() (gas: 29460)
CommitteeVerifier_setDynamicConfig:test_setDynamicConfig() (gas: 30125)
CommitteeVerifier_updateStorageLocation:test_updateStorageLocation() (gas: 23029)
CommitteeVerifier_verifyMessage:test_verifyMessage_ExtractsSignatureLengthCorrectly() (gas: 31823)
CommitteeVerifier_verifyMessage:test_verifyMessage_ForwardCompatibilityWithExtraData() (gas: 32187)
CommitteeVerifier_withdrawFeeTokens:test_withdrawFeeTokens() (gas: 216273)
CommitteeVerifier_withdrawFeeTokens:test_withdrawFeeTokens_MultipleTokens() (gas: 1494933)
CommitteeVerifier_applyAllowlistUpdates:test_applyAllowlistUpdates_AsAllowlistAdmin() (gas: 93115)
CommitteeVerifier_applyAllowlistUpdates:test_applyAllowlistUpdates_AsOwner() (gas: 94697)
CommitteeVerifier_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 47127)
CommitteeVerifier_constructor:test_constructor() (gas: 2067210)
CommitteeVerifier_forwardToVerifier:test_forwardToVerifier() (gas: 29658)
CommitteeVerifier_setDynamicConfig:test_setDynamicConfig() (gas: 30169)
CommitteeVerifier_updateStorageLocation:test_updateStorageLocation() (gas: 23051)
CommitteeVerifier_verifyMessage:test_verifyMessage_ExtractsSignatureLengthCorrectly() (gas: 31845)
CommitteeVerifier_verifyMessage:test_verifyMessage_ForwardCompatibilityWithExtraData() (gas: 32209)
CommitteeVerifier_withdrawFeeTokens:test_withdrawFeeTokens() (gas: 216291)
CommitteeVerifier_withdrawFeeTokens:test_withdrawFeeTokens_MultipleTokens() (gas: 1494955)
DefensiveExampleTest:test_HappyPath() (gas: 204086)
DefensiveExampleTest:test_Recovery() (gas: 429422)
ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10673)
Expand Down Expand Up @@ -220,40 +220,40 @@ MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue() (gas: 127926)
MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens() (gas: 44327)
OffRamp_applySourceChainConfigUpdates:test_applySourceChainConfigUpdates_multipleChains() (gas: 464460)
OffRamp_applySourceChainConfigUpdates:test_applySourceChainConfigUpdates_updateExistingChain() (gas: 155371)
OffRamp_constructor:test_constructor() (gas: 4454945)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_AllCCVsFound() (gas: 84824)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_OptionalIsAlsoRequired() (gas: 58188)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_Success_OptionalCCVsFound() (gas: 55471)
OffRamp_execute:test_execute() (gas: 111477)
OffRamp_constructor:test_constructor() (gas: 4486233)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_AllCCVsFound() (gas: 84524)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_OptionalIsAlsoRequired() (gas: 58038)
OffRamp_ensureCCVQuorumIsReached:test_ensureCCVQuorumIsReached_Success_OptionalCCVsFound() (gas: 55321)
OffRamp_execute:test_execute() (gas: 112412)
OffRamp_execute:test_execute_InsufficientGasToCompleteTx_setsToFailure() (gas: 92073)
OffRamp_execute:test_execute_ReentrancyGuardReentrantCall_Fails() (gas: 1033367)
OffRamp_execute:test_execute_RunsOutOfGasAndSetsStateToFailure() (gas: 109908)
OffRamp_execute:test_execute_WithReceiver() (gas: 442664)
OffRamp_execute:test_execute_ReentrancyGuardReentrantCall_Fails() (gas: 1075260)
OffRamp_execute:test_execute_RunsOutOfGasAndSetsStateToFailure() (gas: 106553)
OffRamp_execute:test_execute_WithReceiver() (gas: 443299)
OffRamp_getAllSourceChainConfigs:test_getAllSourceChainConfigs_ReturnsMultipleChains() (gas: 225835)
OffRamp_getAllSourceChainConfigs:test_getAllSourceChainConfigs_ReturnsSingleChain() (gas: 38266)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsDefaultCCVs_WhenPoolDoesNotSupportV2() (gas: 286649)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsDefaultCCVs_WhenPoolReturnsEmptyArray() (gas: 221969)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsPoolCCVs_WhenPoolSupportsV2() (gas: 286119)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractNoV2_fallsBackToDefaults() (gas: 29158)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractV2_fallsBackToDefaults_WhenEmptyValues() (gas: 224163)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractV2_usesReceiverValues() (gas: 360061)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsDefaultCCVs_WhenPoolDoesNotSupportV2() (gas: 288438)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsDefaultCCVs_WhenPoolReturnsEmptyArray() (gas: 221819)
OffRamp_getCCVsFromPool:test_getCCVsFromPool_ReturnsPoolCCVs_WhenPoolSupportsV2() (gas: 285969)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractNoV2_fallsBackToDefaults() (gas: 29141)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractV2_fallsBackToDefaults_WhenEmptyValues() (gas: 224013)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_contractV2_usesReceiverValues() (gas: 359911)
OffRamp_getCCVsFromReceiver:test_getCCVsFromReceiver_noContract_fallsBackToDefaults() (gas: 30666)
OffRamp_getSourceChainConfig:test_getSourceChainConfig_ReturnsCorrectConfig() (gas: 30153)
OffRamp_getStaticConfig:test_getStaticConfig_MatchesConstructorValues() (gas: 4454213)
OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 236291)
OffRamp_getStaticConfig:test_getStaticConfig_MatchesConstructorValues() (gas: 4485501)
OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 237195)
OnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_AllowsZeroRouterToPause() (gas: 127813)
OnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_SetsConfigAndEmitsEvent() (gas: 204078)
OnRamp_constructor:test_constructor() (gas: 3850333)
OnRamp_forwardFromRouter:test_forwardFromRouter_SequenceNumberPersistsAndIncrements() (gas: 208089)
OnRamp_forwardFromRouter:test_forwardFromRouter_oldExtraArgs() (gas: 114849)
OnRamp_constructor:test_constructor() (gas: 3897059)
OnRamp_forwardFromRouter:test_forwardFromRouter_SequenceNumberPersistsAndIncrements() (gas: 213737)
OnRamp_forwardFromRouter:test_forwardFromRouter_oldExtraArgs() (gas: 117673)
OnRamp_getCCVsForPool:test_getCCVsForPool_PassesThroughAddressZeroSentinel() (gas: 297517)
OnRamp_getCCVsForPool:test_getCCVsForPool_ReturnsDefaultCCVs_WhenPoolDoesNotSupportV2() (gas: 263643)
OnRamp_getCCVsForPool:test_getCCVsForPool_ReturnsDefaultCCVs_WhenPoolReturnsEmptyArray() (gas: 221105)
OnRamp_getCCVsForPool:test_getCCVsForPool_ReturnsPoolCCVs_WhenPoolSupportsV2() (gas: 290360)
OnRamp_getFee:test_getFee_WithCustomExecutorAndCCVs() (gas: 50516)
OnRamp_getFee:test_getFee_WithLaneMandatedCCVs() (gas: 119678)
OnRamp_getFee:test_getFee_WithV3ExtraArgs_CustomCCV_SkipsDefaults() (gas: 49821)
OnRamp_getFee:test_getFee_WithV3ExtraArgs_EmptyCCVs_UsesDefaults() (gas: 47503)
OnRamp_getFee:test_getFee_WithCustomExecutorAndCCVs() (gas: 52460)
OnRamp_getFee:test_getFee_WithLaneMandatedCCVs() (gas: 122126)
OnRamp_getFee:test_getFee_WithV3ExtraArgs_CustomCCV_SkipsDefaults() (gas: 51762)
OnRamp_getFee:test_getFee_WithV3ExtraArgs_EmptyCCVs_UsesDefaults() (gas: 48011)
OnRamp_mergeCCVLists:test_mergeCCVLists_DedupUserAndMandatoryCCVs() (gas: 41789)
OnRamp_mergeCCVLists:test_mergeCCVLists_DedupUserAndPoolCCVs() (gas: 23677)
OnRamp_mergeCCVLists:test_mergeCCVLists_NoChangesWhenPoolCCVAlreadyInRequired() (gas: 23474)
Expand All @@ -269,11 +269,11 @@ OnRamp_setDynamicConfig:test_SetDynamicConfig() (gas: 35513)
OnRamp_setDynamicConfig:test_SetDynamicConfig_MultipleUpdates() (gas: 41788)
OnRamp_withdrawFeeTokens:test_withdrawFeeTokens() (gas: 216614)
OnRamp_withdrawFeeTokens:test_withdrawFeeTokens_MultipleTokens() (gas: 1494944)
PingPong_ccipReceive:test_CcipReceive() (gas: 146874)
PingPong_ccipReceive:test_CcipReceive() (gas: 148793)
PingPong_setOutOfOrderExecution:test_OutOfOrderExecution() (gas: 20879)
PingPong_setPaused:test_Pausing() (gas: 18247)
PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 153662)
PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 148616)
PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 155581)
PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 150535)
Proxy_fallback:test_fallback() (gas: 17349)
Proxy_setTarget:test_setTarget() (gas: 19905)
RMNProxy_constructor:test_Constructor() (gas: 294118)
Expand All @@ -299,17 +299,17 @@ RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetC
RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 128616)
Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10941199)
Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 58667)
Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 122302)
Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 238417)
Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 124221)
Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 240337)
Router_ccipSend:test_InvalidMsgValue() (gas: 28520)
Router_ccipSend:test_NativeFeeToken() (gas: 149211)
Router_ccipSend:test_NativeFeeToken() (gas: 151130)
Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 34636)
Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 150695)
Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 152614)
Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 26738)
Router_ccipSend:test_NonLinkFeeToken() (gas: 223578)
Router_ccipSend:test_WrappedNativeFeeToken() (gas: 152087)
Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 128224)
Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 244361)
Router_ccipSend:test_NonLinkFeeToken() (gas: 225497)
Router_ccipSend:test_WrappedNativeFeeToken() (gas: 154006)
Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 130143)
Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 246281)
Router_constructor:test_Constructor() (gas: 13301)
Router_getArmProxy:test_getArmProxy() (gas: 10647)
Router_getFee:test_GetFeeSupportedChain() (gas: 20949)
Expand Down Expand Up @@ -453,4 +453,6 @@ USDCTokenPool_lockOrBurn:test_LockOrBurn_LegacySourcePoolDataFormat() (gas: 1445
USDCTokenPool_lockOrBurn:test_LockOrBurn_MintRecipientOverride() (gas: 160102)
USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx() (gas: 265877)
USDCTokenPool_supportsInterface:test_SupportsInterface() (gas: 10210)
e2e:test_e2e() (gas: 449485)
VersionedVerifierResolver_applyInboundImplementationUpdates:test_applyInboundImplementationUpdates() (gas: 73392)
VersionedVerifierResolver_applyOutboundImplementationUpdates:test_applyOutboundImplementationUpdates() (gas: 62475)
e2e:test_e2e() (gas: 463771)
13 changes: 11 additions & 2 deletions chains/evm/contracts/ccvs/CommitteeVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.24;

import {ICrossChainVerifierV1} from "../interfaces/ICrossChainVerifierV1.sol";
import {IVersionedVerifier} from "../interfaces/IVersionedVerifier.sol";

import {MessageV1Codec} from "../libraries/MessageV1Codec.sol";
import {BaseVerifier} from "./components/BaseVerifier.sol";
Expand All @@ -11,7 +12,13 @@ import {Ownable2StepMsgSender} from "@chainlink/contracts/src/v0.8/shared/access

/// @notice The CommitteeVerifier is a contract that handles lane-specific fee logic and message verification.
/// @dev Source and destination responsibilities are combined to enable a single proxy address for a CCV on each chain.
contract CommitteeVerifier is Ownable2StepMsgSender, ICrossChainVerifierV1, SignatureQuorumValidator, BaseVerifier {
contract CommitteeVerifier is
Ownable2StepMsgSender,
ICrossChainVerifierV1,
SignatureQuorumValidator,
BaseVerifier,
IVersionedVerifier
{
error InvalidConfig();
error InvalidCCVData();
error OnlyCallableByOwnerOrAllowlistAdmin();
Expand All @@ -26,6 +33,8 @@ contract CommitteeVerifier is Ownable2StepMsgSender, ICrossChainVerifierV1, Sign

// STATIC CONFIG
string public constant override typeAndVersion = "CommitteeVerifier 1.7.0-dev";
/// @dev The preimage is bytes4(keccak256("CommitteeVerifier 1.7.0"))
bytes4 public constant VERSION_TAG = 0x49ff34ed;
/// @dev The number of bytes allocated to encoding the signature length within the ccvData.
uint256 internal constant SIGNATURE_LENGTH_BYTES = 2;

Expand All @@ -49,7 +58,7 @@ contract CommitteeVerifier is Ownable2StepMsgSender, ICrossChainVerifierV1, Sign
_assertSenderIsAllowed(message.destChainSelector, senderAddress);

// TODO: Process msg & return verifier data
return "";
return abi.encodePacked(VERSION_TAG);
}

/// @inheritdoc ICrossChainVerifierV1
Expand Down
107 changes: 107 additions & 0 deletions chains/evm/contracts/ccvs/VersionedVerifierResolver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import {ICrossChainVerifierResolver} from "../interfaces/ICrossChainVerifierResolver.sol";
import {IVersionedVerifier} from "../interfaces/IVersionedVerifier.sol";

import {Ownable2StepMsgSender} from "@chainlink/contracts/src/v0.8/shared/access/Ownable2StepMsgSender.sol";

/// @notice Resolves and returns the appropriate verifier contract for the given outbound / inbound traffic.
/// @dev On source, the destChainSelector of a message is used to determine the verifier implementation to apply.
/// On destination, we must use the verifier version was applied on source, parsing this version from the ccvData.
contract VersionedVerifierResolver is ICrossChainVerifierResolver, Ownable2StepMsgSender {
error InvalidCCVDataLength();
error InvalidDestChainSelector(uint64 destChainSelector);
error VersionMismatch(address verifier, bytes4 expected, bytes4 got);

event InboundImplementationRemoved(bytes4 version);
event OutboundImplementationRemoved(uint64 destChainSelector);
event InboundImplementationUpdated(bytes4 version, address prevImpl, address newImpl);
event OutboundImplementationUpdated(uint64 destChainSelector, address prevImpl, address newImpl);

struct InboundImplementationArgs {
bytes4 version; // ────╮ Verifier version.
address verifier; // ──╯ Address of the verifier contract.
}

struct OutboundImplementationArgs {
uint64 destChainSelector; // ──╮ Destination chain selector.
address verifier; // ──────────╯ Address of the verifier contract.
}

/// @notice maps verifier versions to their implementation addresses, applied to inbound traffic.
mapping(bytes4 version => address verifier) private s_inboundImplementations;
/// @notice maps destination chain selectors to their implementation addresses, applied to outbound traffic.
mapping(uint64 destChainSelector => address version) private s_outboundImplementations;

/// @inheritdoc ICrossChainVerifierResolver
function getInboundImplementation(
bytes calldata ccvData
) external view returns (address) {
if (ccvData.length < 4) {
revert InvalidCCVDataLength();
}
return s_inboundImplementations[bytes4(ccvData[:4])];
}

/// @notice Returns the verifier contract for a given version.
/// @param version The version of the verifier contract.
/// @return verifierAddress The address of the verifier contract.
function getInboundImplementationForVersion(
bytes4 version
) external view returns (address) {
return s_inboundImplementations[version];
}

/// @inheritdoc ICrossChainVerifierResolver
function getOutboundImplementation(
uint64 destChainSelector
) external view returns (address) {
return s_outboundImplementations[destChainSelector];
}

/// @notice Updates inbound implementations.
/// @param implementations Verifier versions and their corresponding contracts.
function applyInboundImplementationUpdates(
InboundImplementationArgs[] calldata implementations
) external onlyOwner {
for (uint256 i = 0; i < implementations.length; ++i) {
InboundImplementationArgs memory implementation = implementations[i];
if (implementation.verifier == address(0)) {
// If the verifier address is zero, we clear the implementation for this version.
delete s_inboundImplementations[implementation.version];
emit InboundImplementationRemoved(implementation.version);
continue;
}
bytes4 expectedVersion = IVersionedVerifier(implementation.verifier).VERSION_TAG();
if (expectedVersion != implementation.version) {
revert VersionMismatch(implementation.verifier, expectedVersion, implementation.version);
}
address previous = s_inboundImplementations[implementation.version];
s_inboundImplementations[implementation.version] = implementation.verifier;
emit InboundImplementationUpdated(implementation.version, previous, implementation.verifier);
}
}

/// @notice Updates outbound implementations.
/// @param implementations Destination chain selectors and their corresponding verifier contracts.
function applyOutboundImplementationUpdates(
OutboundImplementationArgs[] calldata implementations
) external onlyOwner {
for (uint256 i = 0; i < implementations.length; ++i) {
OutboundImplementationArgs memory implementation = implementations[i];
if (implementation.verifier == address(0)) {
// If the verifier address is zero, we clear the implementation for this destination chain.
delete s_outboundImplementations[implementation.destChainSelector];
emit OutboundImplementationRemoved(implementation.destChainSelector);
continue;
}
if (implementation.destChainSelector == 0) {
revert InvalidDestChainSelector(implementation.destChainSelector);
}
address previous = s_outboundImplementations[implementation.destChainSelector];
s_outboundImplementations[implementation.destChainSelector] = implementation.verifier;
emit OutboundImplementationUpdated(implementation.destChainSelector, previous, implementation.verifier);
}
}
}
Loading
Loading