diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 4af4b21269..d70f3da3f0 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -34,6 +34,56 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28789) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55208) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243659) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) +CCIPCapabilityConfigurationSetup:test_getCapabilityConfiguration_Success() (gas: 9561) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70645) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 350565) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 471510) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 440232) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) +CCIPCapabilityConfiguration_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 9028) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 303038) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49619) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32253) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 367516) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120877) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 156973) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 367292) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157040) +CCIPCapabilityConfiguration_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9648) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1044432) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23118) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1992348) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2595930) +CCIPCapabilityConfiguration__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1834017) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1055344) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1055375) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilityRegistryCanCall_Reverts() (gas: 9576) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 182909) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 342472) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 19116) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 266071) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14807) +CCIPCapabilityConfiguration_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9604) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 285383) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 282501) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 283422) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 283588) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 287815) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1068544) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 282309) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 284277) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_Success() (gas: 289222) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 285518) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1120660) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1119000) +CCIPCapabilityConfiguration_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9540) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2133850) CommitStore_constructor:test_Constructor_Success() (gas: 3091440) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 75331) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 2c209d69d6..661de2b842 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -75,6 +75,7 @@ compileContract ccip/RMN.sol compileContract ccip/ARMProxy.sol compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +compileContract ccip/capability/CCIPCapabilityConfiguration.sol # Test helpers compileContract ccip/test/helpers/BurnMintERC677Helper.sol diff --git a/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol b/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol new file mode 100644 index 0000000000..45ffe3da78 --- /dev/null +++ b/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ICapabilityRegistry} from "./interfaces/ICapabilityRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice CCIPCapabilityConfiguration stores the configuration for the CCIP capability. +/// We have two classes of configuration: chain configuration and DON (in the CapabilityRegistry sense) configuration. +/// Each chain will have a single configuration which includes information like the router address. +/// Each CR DON will have up to four configurations: for each of (commit, exec), one blue and one green configuration. +/// This is done in order to achieve "blue-green" deployments. +contract CCIPCapabilityConfiguration is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator { + using EnumerableSet for EnumerableSet.UintSet; + + /// @notice Emitted when a chain's configuration is set. + /// @param chainSelector The chain selector. + /// @param chainConfig The chain configuration. + event ChainConfigSet(uint64 chainSelector, ChainConfig chainConfig); + + /// @notice Emitted when a chain's configuration is removed. + /// @param chainSelector The chain selector. + event ChainConfigRemoved(uint64 chainSelector); + + error ChainConfigNotSetForChain(uint64 chainSelector); + error NodeNotInRegistry(bytes32 p2pId); + error OnlyCapabilityRegistryCanCall(); + error ChainSelectorNotFound(uint64 chainSelector); + error ChainSelectorNotSet(); + error TooManyOCR3Configs(); + error TooManySigners(); + error TooManyTransmitters(); + error TooManyBootstrapP2PIds(); + error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); + error NotEnoughTransmitters(uint256 got, uint256 minimum); + error FMustBePositive(); + error FChainMustBePositive(); + error FTooHigh(); + error InvalidPluginType(); + error OfframpAddressCannotBeZero(); + error InvalidConfigLength(uint256 length); + error InvalidConfigStateTransition(ConfigState currentState, ConfigState proposedState); + error NonExistentConfigTransition(); + error WrongConfigCount(uint64 got, uint64 expected); + error WrongConfigDigest(bytes32 got, bytes32 expected); + error WrongConfigDigestBlueGreen(bytes32 got, bytes32 expected); + + /// @notice PluginType indicates the type of plugin that the configuration is for. + /// @param Commit The configuration is for the commit plugin. + /// @param Execution The configuration is for the execution plugin. + enum PluginType { + Commit, + Execution + } + + /// @notice ConfigState indicates the state of the configuration. + /// A DON's configuration always starts out in the "Init" state - this is the starting state. + /// The only valid transition from "Init" is to the "Running" state - this is the first ever configuration. + /// The only valid transition from "Running" is to the "Staging" state - this is a blue/green proposal. + /// The only valid transition from "Staging" is back to the "Running" state - this is a promotion. + /// TODO: explain rollbacks? + enum ConfigState { + Init, + Running, + Staging + } + + /// @notice Chain configuration. + /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. + struct ChainConfig { + bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capability registry. + uint8 fChain; // The fault tolerance parameter of the chain. + bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. + } + + /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. + struct ChainConfigInfo { + uint64 chainSelector; + ChainConfig chainConfig; + } + + /// @notice OCR3 configuration. + struct OCR3Config { + PluginType pluginType; // ────────╮ The plugin that the configuration is for. + uint64 chainSelector; // | The (remote) chain that the configuration is for. + uint8 F; // | The "big F" parameter for the role DON. + uint64 offchainConfigVersion; // ─╯ The version of the offchain configuration. + bytes offrampAddress; // The remote chain offramp address. + bytes32[] bootstrapP2PIds; // The bootstrap P2P IDs of the oracles that are part of the role DON. + // len(p2pIds) == len(signers) == len(transmitters) == 3 * F + 1 + // NOTE: indexes matter here! The p2p ID at index i corresponds to the signer at index i and the transmitter at index i. + // This is crucial in order to build the oracle ID <-> peer ID mapping offchain. + bytes32[] p2pIds; // The P2P IDs of the oracles that are part of the role DON. + bytes[] signers; // The onchain signing keys of nodes in the don. + bytes[] transmitters; // The onchain transmitter keys of nodes in the don. + bytes offchainConfig; // The offchain configuration for the OCR3 protocol. Protobuf encoded. + } + + /// @notice OCR3 configuration with metadata, specifically the config count and the config digest. + struct OCR3ConfigWithMeta { + OCR3Config config; // The OCR3 configuration. + uint64 configCount; // The config count used to compute the config digest. + bytes32 configDigest; // The config digest of the OCR3 configuration. + } + + /// @notice Type and version override. + string public constant override typeAndVersion = "CCIPCapabilityConfiguration 1.6.0-dev"; + + /// @notice The canonical capability registry address. + address internal immutable i_capabilityRegistry; + + /// @notice chain configuration for each chain that CCIP is deployed on. + mapping(uint64 chainSelector => ChainConfig chainConfig) internal s_chainConfigurations; + + /// @notice All chains that are configured. + EnumerableSet.UintSet internal s_remoteChainSelectors; + + /// @notice OCR3 configurations for each DON. + /// Each CR DON will have a commit and execution configuration. + /// This means that a DON can have up to 4 configurations, since we are implementing blue/green deployments. + mapping(uint32 donId => mapping(PluginType pluginType => OCR3ConfigWithMeta[] ocr3Configs)) internal s_ocr3Configs; + + /// @notice The DONs that have been configured. + EnumerableSet.UintSet internal s_donIds; + + uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; + uint8 internal constant MAX_OCR3_CONFIGS_PER_DON = 4; + uint8 internal constant MAX_NUM_ORACLES = 31; + + /// @param capabilityRegistry the canonical capability registry address. + constructor(address capabilityRegistry) { + i_capabilityRegistry = capabilityRegistry; + } + + // ================================================================ + // │ Config Getters │ + // ================================================================ + + /// @notice Returns all the chain configurations. + /// @return The chain configurations. + // TODO: will this eventually hit the RPC max response size limit? + function getAllChainConfigs() external view returns (ChainConfigInfo[] memory) { + uint256[] memory chainSelectors = s_remoteChainSelectors.values(); + ChainConfigInfo[] memory chainConfigs = new ChainConfigInfo[](s_remoteChainSelectors.length()); + for (uint256 i = 0; i < chainSelectors.length; ++i) { + uint64 chainSelector = uint64(chainSelectors[i]); + chainConfigs[i] = + ChainConfigInfo({chainSelector: chainSelector, chainConfig: s_chainConfigurations[chainSelector]}); + } + return chainConfigs; + } + + /// @notice Returns the OCR configuration for the given don ID and plugin type. + /// @param donId The DON ID. + /// @param pluginType The plugin type. + /// @return The OCR3 configurations, up to 2 (blue and green). + function getOCRConfig(uint32 donId, PluginType pluginType) external view returns (OCR3ConfigWithMeta[] memory) { + return s_ocr3Configs[donId][pluginType]; + } + + // ================================================================ + // │ Capability Configuration │ + // ================================================================ + + /// @inheritdoc ICapabilityConfiguration + /// @dev The CCIP capability will fetch the configuration needed directly from this contract. + /// The offchain syncer will call this function, however, so its important that it doesn't revert. + function getCapabilityConfiguration(uint32 /* donId */ ) external pure override returns (bytes memory configuration) { + return bytes(""); + } + + /// @notice Called by the registry prior to the config being set for a particular DON. + function beforeCapabilityConfigSet( + bytes32[] calldata, /* nodes */ + bytes calldata config, + uint64, /* configCount */ + uint32 donId + ) external override { + if (msg.sender != i_capabilityRegistry) { + revert OnlyCapabilityRegistryCanCall(); + } + + OCR3Config[] memory ocr3Configs = abi.decode(config, (OCR3Config[])); + (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) = _groupByPluginType(ocr3Configs); + if (commitConfigs.length > 0) { + _updatePluginConfig(donId, PluginType.Commit, commitConfigs); + } + if (execConfigs.length > 0) { + _updatePluginConfig(donId, PluginType.Execution, execConfigs); + } + } + + function _updatePluginConfig(uint32 donId, PluginType pluginType, OCR3Config[] memory newConfig) internal { + OCR3ConfigWithMeta[] memory currentConfig = s_ocr3Configs[donId][pluginType]; + + // Validate the state transition being proposed, which is implicitly defined by the combination + // of lengths of the current and new configurations. + ConfigState currentState = _stateFromConfigLength(currentConfig.length); + ConfigState proposedState = _stateFromConfigLength(newConfig.length); + _validateConfigStateTransition(currentState, proposedState); + + // Build the new configuration with metadata and validate that the transition is valid. + OCR3ConfigWithMeta[] memory newConfigWithMeta = + _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, proposedState); + _validateConfigTransition(currentConfig, newConfigWithMeta); + + // Update contract state with new configuration if its valid. + // We won't run out of gas from this delete since the array is at most 2 elements long. + delete s_ocr3Configs[donId][pluginType]; + for (uint256 i = 0; i < newConfigWithMeta.length; ++i) { + s_ocr3Configs[donId][pluginType].push(newConfigWithMeta[i]); + } + } + + // ================================================================ + // │ Config State Machine │ + // ================================================================ + + /// @notice Determine the config state of the configuration from the length of the config. + /// @param configLen The length of the configuration. + /// @return The config state. + function _stateFromConfigLength(uint256 configLen) internal pure returns (ConfigState) { + if (configLen > 2) { + revert InvalidConfigLength(configLen); + } + return ConfigState(configLen); + } + + // the only valid state transitions are the following: + // init -> running (first ever config) + // running -> staging (blue/green proposal) + // staging -> running (promotion) + // everything else is invalid and should revert. + function _validateConfigStateTransition(ConfigState currentState, ConfigState newState) internal pure { + // TODO: may be able to save gas if we put this in the if condition. + bool initToRunning = currentState == ConfigState.Init && newState == ConfigState.Running; + bool runningToStaging = currentState == ConfigState.Running && newState == ConfigState.Staging; + bool stagingToRunning = currentState == ConfigState.Staging && newState == ConfigState.Running; + if (initToRunning || runningToStaging || stagingToRunning) { + return; + } + revert InvalidConfigStateTransition(currentState, newState); + } + + function _validateConfigTransition( + OCR3ConfigWithMeta[] memory currentConfig, + OCR3ConfigWithMeta[] memory newConfigWithMeta + ) internal pure { + uint256 currentConfigLen = currentConfig.length; + uint256 newConfigLen = newConfigWithMeta.length; + if (currentConfigLen == 0 && newConfigLen == 1) { + // Config counts always must start at 1 for the first ever config. + if (newConfigWithMeta[0].configCount != 1) { + revert WrongConfigCount(newConfigWithMeta[0].configCount, 1); + } + return; + } + + if (currentConfigLen == 1 && newConfigLen == 2) { + // On a blue/green proposal: + // * the config digest of the blue config must remain unchanged. + // * the green config count must be the blue config count + 1. + if (newConfigWithMeta[0].configDigest != currentConfig[0].configDigest) { + revert WrongConfigDigestBlueGreen(newConfigWithMeta[0].configDigest, currentConfig[0].configDigest); + } + if (newConfigWithMeta[1].configCount != currentConfig[0].configCount + 1) { + revert WrongConfigCount(newConfigWithMeta[1].configCount, currentConfig[0].configCount + 1); + } + return; + } + + if (currentConfigLen == 2 && newConfigLen == 1) { + // On a promotion, the green config digest must become the blue config digest. + if (newConfigWithMeta[0].configDigest != currentConfig[1].configDigest) { + revert WrongConfigDigest(newConfigWithMeta[0].configDigest, currentConfig[1].configDigest); + } + return; + } + + revert NonExistentConfigTransition(); + } + + /// @notice Computes a new configuration with metadata based on the current configuration and the new configuration. + /// @param donId The DON ID. + /// @param currentConfig The current configuration, including metadata. + /// @param newConfig The new configuration, without metadata. + /// @param currentState The current state of the configuration. + /// @param newState The new state of the configuration. + /// @return The new configuration with metadata. + function _computeNewConfigWithMeta( + uint32 donId, + OCR3ConfigWithMeta[] memory currentConfig, + OCR3Config[] memory newConfig, + ConfigState currentState, + ConfigState newState + ) internal view returns (OCR3ConfigWithMeta[] memory) { + uint64[] memory configCounts = new uint64[](newConfig.length); + + // Set config counts based on the only valid state transitions. + // Init -> Running (first ever config) + // Running -> Staging (blue/green proposal) + // Staging -> Running (promotion) + if (currentState == ConfigState.Init && newState == ConfigState.Running) { + // First ever config starts with config count == 1. + configCounts[0] = 1; + } else if (currentState == ConfigState.Running && newState == ConfigState.Staging) { + // On a blue/green proposal, the config count of the green config is the blue config count + 1. + configCounts[0] = currentConfig[0].configCount; + configCounts[1] = currentConfig[0].configCount + 1; + } else if (currentState == ConfigState.Staging && newState == ConfigState.Running) { + // On a promotion, the config count of the green config becomes the blue config count. + configCounts[0] = currentConfig[1].configCount; + } else { + revert InvalidConfigStateTransition(currentState, newState); + } + + OCR3ConfigWithMeta[] memory newConfigWithMeta = new OCR3ConfigWithMeta[](newConfig.length); + for (uint256 i = 0; i < configCounts.length; ++i) { + _validateConfig(newConfig[i]); + newConfigWithMeta[i] = OCR3ConfigWithMeta({ + config: newConfig[i], + configCount: configCounts[i], + configDigest: _computeConfigDigest(donId, configCounts[i], newConfig[i]) + }); + } + + return newConfigWithMeta; + } + + /// @notice Group the OCR3 configurations by plugin type for further processing. + /// @param ocr3Configs The OCR3 configurations to group. + function _groupByPluginType(OCR3Config[] memory ocr3Configs) + internal + pure + returns (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) + { + if (ocr3Configs.length > MAX_OCR3_CONFIGS_PER_DON) { + revert TooManyOCR3Configs(); + } + + // Declare with size 2 since we have a maximum of two configs per plugin type (blue, green). + // If we have less we will adjust the length later using mstore. + // If the caller provides more than 2 configs per plugin type, we will revert due to out of bounds + // access in the for loop below. + commitConfigs = new OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); + execConfigs = new OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); + uint256 commitCount; + uint256 execCount; + for (uint256 i = 0; i < ocr3Configs.length; ++i) { + if (ocr3Configs[i].pluginType == PluginType.Commit) { + commitConfigs[commitCount] = ocr3Configs[i]; + ++commitCount; + } else { + execConfigs[execCount] = ocr3Configs[i]; + ++execCount; + } + } + + // Adjust the length of the arrays to the actual number of configs. + assembly { + mstore(commitConfigs, commitCount) + mstore(execConfigs, execCount) + } + + return (commitConfigs, execConfigs); + } + + function _validateConfig(OCR3Config memory cfg) internal view { + if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); + if (cfg.pluginType != PluginType.Commit && cfg.pluginType != PluginType.Execution) revert InvalidPluginType(); + // TODO: can we do more sophisticated validation than this? + if (cfg.offrampAddress.length == 0) revert OfframpAddressCannotBeZero(); + if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); + + // Some of these checks below are done in OCR2/3Base config validation, so we do them again here. + // Role DON OCR configs will have all the Role DON signers but only a subset of transmitters. + if (cfg.signers.length > MAX_NUM_ORACLES) revert TooManySigners(); + if (cfg.transmitters.length > MAX_NUM_ORACLES) revert TooManyTransmitters(); + + // We check for chain config presence above, so fChain here must be non-zero. + uint256 minTransmittersLength = 3 * s_chainConfigurations[cfg.chainSelector].fChain + 1; + if (cfg.transmitters.length < minTransmittersLength) { + revert NotEnoughTransmitters(cfg.transmitters.length, minTransmittersLength); + } + if (cfg.F == 0) revert FMustBePositive(); + if (cfg.signers.length <= 3 * cfg.F) revert FTooHigh(); + + if (cfg.p2pIds.length != cfg.signers.length || cfg.p2pIds.length != cfg.transmitters.length) { + revert P2PIdsLengthNotMatching(cfg.p2pIds.length, cfg.signers.length, cfg.transmitters.length); + } + if (cfg.bootstrapP2PIds.length > cfg.p2pIds.length) revert TooManyBootstrapP2PIds(); + + // Check that the readers are in the capability registry. + // TODO: check for duplicate signers, duplicate p2p ids, etc. + // TODO: check that p2p ids in cfg.bootstrapP2PIds are included in cfg.p2pIds. + for (uint256 i = 0; i < cfg.signers.length; ++i) { + _ensureInRegistry(cfg.p2pIds[i]); + } + } + + /// @notice Computes the digest of the provided configuration. + /// @dev In traditional OCR config digest computation, block.chainid and address(this) are used + /// in order to further domain separate the digest. We can't do that here since the digest will + /// be used on remote chains; so we use the chain selector instead of block.chainid. The don ID + /// replaces the address(this) in the traditional computation. + /// @param donId The DON ID. + /// @param configCount The configuration count. + /// @param ocr3Config The OCR3 configuration. + /// @return The computed digest. + function _computeConfigDigest( + uint32 donId, + uint64 configCount, + OCR3Config memory ocr3Config + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + ocr3Config.chainSelector, + donId, + ocr3Config.pluginType, + ocr3Config.offrampAddress, + configCount, + ocr3Config.bootstrapP2PIds, + ocr3Config.p2pIds, + ocr3Config.signers, + ocr3Config.transmitters, + ocr3Config.F, + ocr3Config.offchainConfigVersion, + ocr3Config.offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x000a << (256 - 16); // 0x000a00..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + // ================================================================ + // │ Chain Configuration │ + // ================================================================ + + /// @notice Sets and/or removes chain configurations. + /// @param chainSelectorRemoves The chain configurations to remove. + /// @param chainConfigAdds The chain configurations to add. + function applyChainConfigUpdates( + uint64[] calldata chainSelectorRemoves, + ChainConfigInfo[] calldata chainConfigAdds + ) external onlyOwner { + // Process removals first. + for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { + // check if the chain selector is in s_remoteChainSelectors first. + if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { + revert ChainSelectorNotFound(chainSelectorRemoves[i]); + } + + delete s_chainConfigurations[chainSelectorRemoves[i]]; + s_remoteChainSelectors.remove(chainSelectorRemoves[i]); + + emit ChainConfigRemoved(chainSelectorRemoves[i]); + } + + // Process additions next. + for (uint256 i = 0; i < chainConfigAdds.length; ++i) { + ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; + bytes32[] memory readers = chainConfig.readers; + uint64 chainSelector = chainConfigAdds[i].chainSelector; + + // Verify that the provided readers are present in the capability registry. + for (uint256 j = 0; j < readers.length; j++) { + _ensureInRegistry(readers[j]); + } + + // Verify that fChain is positive. + if (chainConfig.fChain == 0) { + revert FChainMustBePositive(); + } + + s_chainConfigurations[chainSelector] = chainConfig; + s_remoteChainSelectors.add(chainSelector); + + emit ChainConfigSet(chainSelector, chainConfig); + } + } + + /// @notice Helper function to ensure that a node is in the capability registry. + /// @param p2pId The P2P ID of the node to check. + function _ensureInRegistry(bytes32 p2pId) internal view { + (ICapabilityRegistry.NodeInfo memory node,) = ICapabilityRegistry(i_capabilityRegistry).getNode(p2pId); + if (node.p2pId == bytes32("")) { + revert NodeNotInRegistry(p2pId); + } + } +} diff --git a/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol b/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol new file mode 100644 index 0000000000..85a98843c6 --- /dev/null +++ b/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface ICapabilityRegistry { + struct NodeInfo { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. + /// This key is guaranteed to be unique in the CapabilityRegistry. It is + /// used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + } + + /// @notice Gets a node's data + /// @param p2pId The P2P ID of the node to query for + /// @return NodeInfo The node data + /// @return configCount The number of times the node has been configured + function getNode(bytes32 p2pId) external view returns (NodeInfo memory, uint32 configCount); +} diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol new file mode 100644 index 0000000000..25e6d79c88 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol @@ -0,0 +1,1572 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Test} from "forge-std/Test.sol"; + +import {CCIPCapabilityConfiguration} from "../../capability/CCIPCapabilityConfiguration.sol"; +import {ICapabilityRegistry} from "../../capability/interfaces/ICapabilityRegistry.sol"; +import {CCIPCapabilityConfigurationHelper} from "../helpers/CCIPCapabilityConfigurationHelper.sol"; + +contract CCIPCapabilityConfigurationSetup is Test { + address public constant OWNER = 0x82ae2B4F57CA5C1CBF8f744ADbD3697aD1a35AFe; + address public constant CAPABILITY_REGISTRY = 0x272aF4BF7FBFc4944Ed59F914Cd864DfD912D55e; + + CCIPCapabilityConfigurationHelper public s_ccipCC; + + function setUp() public { + changePrank(OWNER); + s_ccipCC = new CCIPCapabilityConfigurationHelper(CAPABILITY_REGISTRY); + } + + function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { + arr = new bytes32[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = keccak256(abi.encode(i, 1, seed)); + } + return arr; + } + + function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { + arr = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = abi.encodePacked(keccak256(abi.encode(i, 1, seed))); + } + return arr; + } + + function _subset(bytes32[] memory arr, uint256 start, uint256 end) internal pure returns (bytes32[] memory) { + bytes32[] memory subset = new bytes32[](end - start); + for (uint256 i = start; i < end; i++) { + subset[i - start] = arr[i]; + } + return subset; + } + + function _addChainConfig(uint256 numNodes) + internal + returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) + { + p2pIds = _makeBytes32Array(numNodes, 0); + signers = _makeBytesArray(numNodes, 10); + transmitters = _makeBytesArray(numNodes, 20); + for (uint256 i = 0; i < numNodes; i++) { + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, p2pIds[i]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(signers[i]), + p2pId: p2pIds[i], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + } + // Add chain selector for chain 1. + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](1); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: p2pIds, fChain: 1, config: bytes("config1")}) + }); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + return (p2pIds, signers, transmitters); + } + + function test_getCapabilityConfiguration_Success() public { + bytes memory capConfig = s_ccipCC.getCapabilityConfiguration(42 /* doesn't matter, not used */ ); + assertEq(capConfig.length, 0, "capability config length must be 0"); + } +} + +contract CCIPCapabilityConfiguration_chainConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test_applyChainConfigUpdates_addChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(2, adds[1].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPCapabilityConfiguration.ChainConfigInfo[] memory configs = s_ccipCC.getAllChainConfigs(); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + } + + function test_applyChainConfigUpdates_removeChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(2, adds[1].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigRemoved(1); + s_ccipCC.applyChainConfigUpdates(removes, new CCIPCapabilityConfiguration.ChainConfigInfo[](0)); + } + + // Reverts. + + function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.ChainSelectorNotFound.selector, 1)); + s_ccipCC.applyChainConfigUpdates(removes, new CCIPCapabilityConfiguration.ChainConfigInfo[](0)); + } + + function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](1); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NodeNotInRegistry.selector, chainReaders[0])); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + } + + function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectRevert(CCIPCapabilityConfiguration.FChainMustBePositive.selector); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + } +} + +contract CCIPCapabilityConfiguration_validateConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test__validateConfig_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + s_ccipCC.validateConfig(config); + } + + // Reverts. + + function test__validateConfig_ChainSelectorNotSet_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 0, // invalid + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.ChainSelectorNotSet.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: bytes(""), // invalid + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.OfframpAddressCannotBeZero.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_ChainSelectorNotFound_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 2, // not set + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.ChainSelectorNotFound.selector, 2)); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManySigners_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManySigners.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManyTransmitters_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); + + // truncate signers but keep transmitters > 31 + assembly { + mstore(signers, 30) + } + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManyTransmitters.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmitters_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(31); + + // truncate transmitters to < 3 * fChain + 1 + // since fChain is 1 in this case, we need to truncate to 3 transmitters. + assembly { + mstore(transmitters, 3) + } + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NotEnoughTransmitters.selector, 3, 4)); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_FMustBePositive_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 0, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.FMustBePositive.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_FTooHigh_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 2, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.FTooHigh.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_P2PIdsLengthNotMatching_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // truncate the p2pIds length + assembly { + mstore(p2pIds, 3) + } + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.P2PIdsLengthNotMatching.selector, uint256(3), uint256(4), uint256(4) + ) + ); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManyBootstrapP2PIds_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _makeBytes32Array(5, 0), // too many bootstrap p2pIds, 5 > 4 + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManyBootstrapP2PIds.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_NodeNotInRegistry_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + bytes32 nonExistentP2PId = keccak256("notInRegistry"); + p2pIds[0] = nonExistentP2PId; + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, nonExistentP2PId), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NodeNotInRegistry.selector, nonExistentP2PId)); + s_ccipCC.validateConfig(config); + } +} + +contract CCIPCapabilityConfiguration_ConfigStateMachine is CCIPCapabilityConfigurationSetup { + // Successful cases. + + function test__stateFromConfigLength_Success() public { + uint256 configLen = 0; + CCIPCapabilityConfiguration.ConfigState state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Init)); + + configLen = 1; + state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Running)); + + configLen = 2; + state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Staging)); + } + + function test__validateConfigStateTransition_Success() public { + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Init, CCIPCapabilityConfiguration.ConfigState.Running + ); + + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Running, CCIPCapabilityConfiguration.ConfigState.Staging + ); + + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Staging, CCIPCapabilityConfiguration.ConfigState.Running + ); + } + + function test__computeConfigDigest_Success() public { + // config digest must change upon: + // - ocr config change (e.g plugin type, chain selector, etc.) + // - don id change + // - config count change + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(2, 10); + bytes[] memory transmitters = _makeBytesArray(2, 20); + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + uint32 donId = 1; + uint32 configCount = 1; + + bytes32 configDigest1 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + donId = 2; + bytes32 configDigest2 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + donId = 1; + configCount = 2; + bytes32 configDigest3 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + configCount = 1; + config.pluginType = CCIPCapabilityConfiguration.PluginType.Execution; + bytes32 configDigest4 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + assertNotEq(configDigest1, configDigest2, "config digests 1 and 2 must not match"); + assertNotEq(configDigest1, configDigest3, "config digests 1 and 3 must not match"); + assertNotEq(configDigest1, configDigest4, "config digests 1 and 4 must not match"); + + assertNotEq(configDigest2, configDigest3, "config digests 2 and 3 must not match"); + assertNotEq(configDigest2, configDigest4, "config digests 2 and 4 must not match"); + } + + function test_Fuzz__groupByPluginType_Success(uint256 numCommitCfgs, uint256 numExecCfgs) public { + vm.assume(numCommitCfgs >= 0 && numCommitCfgs < 3); + vm.assume(numExecCfgs >= 0 && numExecCfgs < 3); + + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = + new CCIPCapabilityConfiguration.OCR3Config[](numCommitCfgs + numExecCfgs); + for (uint256 i = 0; i < numCommitCfgs; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("commit", i) + }); + } + for (uint256 i = 0; i < numExecCfgs; i++) { + cfgs[numCommitCfgs + i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("exec", numCommitCfgs + i) + }); + } + ( + CCIPCapabilityConfiguration.OCR3Config[] memory commitCfgs, + CCIPCapabilityConfiguration.OCR3Config[] memory execCfgs + ) = s_ccipCC.groupByPluginType(cfgs); + + assertEq(commitCfgs.length, numCommitCfgs, "commitCfgs length must match"); + assertEq(execCfgs.length, numExecCfgs, "execCfgs length must match"); + for (uint256 i = 0; i < commitCfgs.length; i++) { + assertEq( + uint8(commitCfgs[i].pluginType), + uint8(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + assertEq(commitCfgs[i].offchainConfig, abi.encode("commit", i), "offchain config must match"); + } + for (uint256 i = 0; i < execCfgs.length; i++) { + assertEq( + uint8(execCfgs[i].pluginType), + uint8(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + assertEq(execCfgs[i].offchainConfig, abi.encode("exec", numCommitCfgs + i), "offchain config must match"); + } + } + + function test__computeNewConfigWithMeta_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Init; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Running; + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); + assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count must be 1"); + assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(newConfig[0].pluginType), "plugin type must match"); + assertEq(newConfigWithMeta[0].config.offchainConfig, newConfig[0].offchainConfig, "offchain config must match"); + assertEq( + newConfigWithMeta[0].configDigest, + s_ccipCC.computeConfigDigest(donId, 1, newConfig[0]), + "config digest must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__computeNewConfigWithMeta_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](2); + // existing blue config first. + newConfig[0] = blueConfig; + // green config next. + newConfig[1] = greenConfig; + + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Running; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Staging; + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + assertEq(newConfigWithMeta.length, 2, "new config with meta length must be 2"); + + assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count of blue must be 1"); + assertEq( + uint8(newConfigWithMeta[0].config.pluginType), uint8(blueConfig.pluginType), "plugin type of blue must match" + ); + assertEq( + newConfigWithMeta[0].config.offchainConfig, blueConfig.offchainConfig, "offchain config of blue must match" + ); + assertEq( + newConfigWithMeta[0].configDigest, + s_ccipCC.computeConfigDigest(donId, 1, blueConfig), + "config digest of blue must match" + ); + + assertEq(newConfigWithMeta[1].configCount, uint64(2), "config count of green must be 2"); + assertEq( + uint8(newConfigWithMeta[1].config.pluginType), uint8(greenConfig.pluginType), "plugin type of green must match" + ); + assertEq( + newConfigWithMeta[1].config.offchainConfig, greenConfig.offchainConfig, "offchain config of green must match" + ); + assertEq( + newConfigWithMeta[1].configDigest, + s_ccipCC.computeConfigDigest(donId, 2, greenConfig), + "config digest of green must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__computeNewConfigWithMeta_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](1); + newConfig[0] = greenConfig; + + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Staging; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Running; + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + + assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); + assertEq(newConfigWithMeta[0].configCount, uint64(2), "config count must be 2"); + assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(greenConfig.pluginType), "plugin type must match"); + assertEq(newConfigWithMeta[0].config.offchainConfig, greenConfig.offchainConfig, "offchain config must match"); + assertEq( + newConfigWithMeta[0].configDigest, s_ccipCC.computeConfigDigest(donId, 2, greenConfig), "config digest must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__validateConfigTransition_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + // Reverts. + + function test_Fuzz__stateFromConfigLength_Reverts(uint256 configLen) public { + vm.assume(configLen > 2); + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigLength.selector, configLen)); + s_ccipCC.stateFromConfigLength(configLen); + } + + function test__groupByPluginType_threeCommitConfigs_Reverts() public { + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](3); + for (uint256 i = 0; i < 3; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("commit", i) + }); + } + vm.expectRevert(); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__groupByPluginType_threeExecutionConfigs_Reverts() public { + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](3); + for (uint256 i = 0; i < 3; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("exec", i) + }); + } + vm.expectRevert(); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__groupByPluginType_TooManyOCR3Configs_Reverts() public { + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](5); + vm.expectRevert(CCIPCapabilityConfiguration.TooManyOCR3Configs.selector); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 0, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.WrongConfigCount.selector, 0, 1)); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, blueConfig) // wrong config digest (due to diff config count) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.WrongConfigDigestBlueGreen.selector, + s_ccipCC.computeConfigDigest(donId, 3, blueConfig), + s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + ) + ); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 3, // wrong config count + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.WrongConfigCount.selector, 3, 2)); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) // wrong config digest + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.WrongConfigDigest.selector, + s_ccipCC.computeConfigDigest(donId, 3, greenConfig), + s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + ) + ); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_NonExistentConfigTransition_Reverts() public { + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](3); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + vm.expectRevert(CCIPCapabilityConfiguration.NonExistentConfigTransition.selector); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } +} + +contract CCIPCapabilityConfiguration__updatePluginConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test__updatePluginConfig_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, configs); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 1, "don config length must be 1"); + assertEq(storedConfig[0].configCount, uint64(1), "config count must be 1"); + assertEq(uint256(storedConfig[0].config.pluginType), uint256(blueConfig.pluginType), "plugin type must match"); + } + + function test__updatePluginConfig_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // add blue config. + uint32 donId = 1; + CCIPCapabilityConfiguration.PluginType pluginType = CCIPCapabilityConfiguration.PluginType.Commit; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory startConfigs = new CCIPCapabilityConfiguration.OCR3Config[](1); + startConfigs[0] = blueConfig; + + // add blue AND green config to indicate an update. + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, startConfigs); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory blueAndGreen = new CCIPCapabilityConfiguration.OCR3Config[](2); + blueAndGreen[0] = blueConfig; + blueAndGreen[1] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, blueAndGreen); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 2, "don config length must be 2"); + // 0 index is blue config, 1 index is green config. + assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq( + uint256(storedConfig[1].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); + assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + } + + function test__updatePluginConfig_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // add blue config. + uint32 donId = 1; + CCIPCapabilityConfiguration.PluginType pluginType = CCIPCapabilityConfiguration.PluginType.Commit; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory startConfigs = new CCIPCapabilityConfiguration.OCR3Config[](1); + startConfigs[0] = blueConfig; + + // add blue AND green config to indicate an update. + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, startConfigs); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory blueAndGreen = new CCIPCapabilityConfiguration.OCR3Config[](2); + blueAndGreen[0] = blueConfig; + blueAndGreen[1] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, blueAndGreen); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 2, "don config length must be 2"); + // 0 index is blue config, 1 index is green config. + assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq( + uint256(storedConfig[1].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); + assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + + // promote green to blue. + CCIPCapabilityConfiguration.OCR3Config[] memory promote = new CCIPCapabilityConfiguration.OCR3Config[](1); + promote[0] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, promote); + + // should see the updated config in the contract state. + storedConfig = s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 1, "don config length must be 1"); + assertEq(storedConfig[0].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + } + + // Reverts. + function test__updatePluginConfig_InvalidConfigLength_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](3); + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigLength.selector, uint256(3))); + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, newConfig); + } + + function test__updatePluginConfig_InvalidConfigStateTransition_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](2); + // 0 -> 2 is an invalid state transition. + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigStateTransition.selector, 0, 2)); + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, newConfig); + } +} + +contract CCIPCapabilityConfiguration_beforeCapabilityConfigSet is CCIPCapabilityConfigurationSetup { + // Successes. + function test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() public { + changePrank(CAPABILITY_REGISTRY); + + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](0); + bytes memory encodedConfigs = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encodedConfigs, 1, 1); + } + + function test_beforeCapabilityConfigSet_CommitConfigOnly_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfigs.length, 1, "config length must be 1"); + assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + } + + function test_beforeCapabilityConfigSet_ExecConfigOnly_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("exec") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Execution); + assertEq(storedConfigs.length, 1, "config length must be 1"); + assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + } + + function test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueCommitConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory blueExecConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("exec") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](2); + configs[0] = blueExecConfig; + configs[1] = blueCommitConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedExecConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Execution); + assertEq(storedExecConfigs.length, 1, "config length must be 1"); + assertEq(storedExecConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedExecConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedCommitConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedCommitConfigs.length, 1, "config length must be 1"); + assertEq(storedCommitConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedCommitConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + } + + // Reverts. + + function test_beforeCapabilityConfigSet_OnlyCapabilityRegistryCanCall_Reverts() public { + bytes32[] memory nodes = new bytes32[](0); + bytes memory config = bytes(""); + uint64 configCount = 1; + uint32 donId = 1; + vm.expectRevert(CCIPCapabilityConfiguration.OnlyCapabilityRegistryCanCall.selector); + s_ccipCC.beforeCapabilityConfigSet(nodes, config, configCount, donId); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol new file mode 100644 index 0000000000..7acc65f9bd --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {CCIPCapabilityConfiguration} from "../../capability/CCIPCapabilityConfiguration.sol"; + +contract CCIPCapabilityConfigurationHelper is CCIPCapabilityConfiguration { + constructor(address capabilityRegistry) CCIPCapabilityConfiguration(capabilityRegistry) {} + + function stateFromConfigLength(uint256 configLength) public pure returns (ConfigState) { + return _stateFromConfigLength(configLength); + } + + function validateConfigStateTransition(ConfigState currentState, ConfigState newState) public pure { + _validateConfigStateTransition(currentState, newState); + } + + function validateConfigTransition( + OCR3ConfigWithMeta[] memory currentConfig, + OCR3ConfigWithMeta[] memory newConfigWithMeta + ) public pure { + _validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function computeNewConfigWithMeta( + uint32 donId, + OCR3ConfigWithMeta[] memory currentConfig, + OCR3Config[] memory newConfig, + ConfigState currentState, + ConfigState newState + ) public view returns (OCR3ConfigWithMeta[] memory) { + return _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + } + + function groupByPluginType(OCR3Config[] memory ocr3Configs) + public + pure + returns (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) + { + return _groupByPluginType(ocr3Configs); + } + + function computeConfigDigest( + uint32 donId, + uint64 configCount, + OCR3Config memory ocr3Config + ) public pure returns (bytes32) { + return _computeConfigDigest(donId, configCount, ocr3Config); + } + + function validateConfig(OCR3Config memory cfg) public view { + _validateConfig(cfg); + } + + function updatePluginConfig(uint32 donId, PluginType pluginType, OCR3Config[] memory newConfig) public { + _updatePluginConfig(donId, pluginType, newConfig); + } +} diff --git a/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go b/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go new file mode 100644 index 0000000000..88e100fd7b --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go @@ -0,0 +1,1079 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_capability_configuration + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type CCIPCapabilityConfigurationChainConfig struct { + Readers [][32]byte + FChain uint8 + Config []byte +} + +type CCIPCapabilityConfigurationChainConfigInfo struct { + ChainSelector uint64 + ChainConfig CCIPCapabilityConfigurationChainConfig +} + +type CCIPCapabilityConfigurationOCR3Config struct { + PluginType uint8 + ChainSelector uint64 + F uint8 + OffchainConfigVersion uint64 + OfframpAddress []byte + BootstrapP2PIds [][32]byte + P2pIds [][32]byte + Signers [][]byte + Transmitters [][]byte + OffchainConfig []byte +} + +type CCIPCapabilityConfigurationOCR3ConfigWithMeta struct { + Config CCIPCapabilityConfigurationOCR3Config + ConfigCount uint64 + ConfigDigest [32]byte +} + +var CCIPCapabilityConfigurationMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilityRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigNotSetForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPCapabilityConfiguration.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPCapabilityConfiguration.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilityRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyTransmitters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumCCIPCapabilityConfiguration.PluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumCCIPCapabilityConfiguration.PluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPCapabilityConfiguration.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620040563803806200405683398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b608051613e83620001d360003960008181610d640152610ff90152613e836000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80638da5cb5b11610076578063f2fde38b1161005b578063f2fde38b1461014e578063f442c89a14610161578063fba64a7c1461017457600080fd5b80638da5cb5b14610111578063ddc042a81461013957600080fd5b8063181f5a77146100a85780634bd0473f146100c657806379ba5097146100e65780638318ed5d146100f0575b600080fd5b6100b0610187565b6040516100bd9190612d12565b60405180910390f35b6100d96100d4366004612d56565b6101a3565b6040516100bd9190612e82565b6100ee610674565b005b6100b06100fe36600461305f565b5060408051602081019091526000815290565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bd565b610141610776565b6040516100bd91906130c0565b6100ee61015c366004613150565b610968565b6100ee61016f3660046131d2565b61097c565b6100ee610182366004613256565b610d4c565b604051806060016040528060258152602001613e526025913981565b63ffffffff821660009081526005602052604081206060918360018111156101cd576101cd612d8b565b60018111156101de576101de612d8b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561066757600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561025157610251612d8b565b600181111561026257610262612d8b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916102ba90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546102e690613313565b80156103335780601f1061030857610100808354040283529160200191610333565b820191906000526020600020905b81548152906001019060200180831161031657829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561038b57602002820191906000526020600020905b815481526020019060010190808311610377575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156103e357602002820191906000526020600020905b8154815260200190600101908083116103cf575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156104bd57838290600052602060002001805461043090613313565b80601f016020809104026020016040519081016040528092919081815260200182805461045c90613313565b80156104a95780601f1061047e576101008083540402835291602001916104a9565b820191906000526020600020905b81548152906001019060200180831161048c57829003601f168201915b505050505081526020019060010190610411565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b8282101561059657838290600052602060002001805461050990613313565b80601f016020809104026020016040519081016040528092919081815260200182805461053590613313565b80156105825780601f1061055757610100808354040283529160200191610582565b820191906000526020600020905b81548152906001019060200180831161056557829003601f168201915b5050505050815260200190600101906104ea565b5050505081526020016006820180546105ae90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546105da90613313565b80156106275780601f106105fc57610100808354040283529160200191610627565b820191906000526020600020905b81548152906001019060200180831161060a57829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161020c565b5050505090505b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006107846003610e0d565b905060006107926003610e21565b67ffffffffffffffff8111156107aa576107aa613366565b6040519080825280602002602001820160405280156107e357816020015b6107d0612a3f565b8152602001906001900390816107c85790505b50905060005b825181101561096157600083828151811061080657610806613395565b60209081029190910181015160408051808201825267ffffffffffffffff83168082526000908152600285528290208251815460808188028301810190955260608201818152959750929586019490939192849284919084018282801561088c57602002820191906000526020600020905b815481526020019060010190808311610878575b5050509183525050600182015460ff1660208201526002820180546040909201916108b690613313565b80601f01602080910402602001604051908101604052809291908181526020018280546108e290613313565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b50505050508152505081525083838151811061094d5761094d613395565b6020908102919091010152506001016107e9565b5092915050565b610970610e2b565b61097981610eae565b50565b610984610e2b565b60005b83811015610b6a576109cb8585838181106109a4576109a4613395565b90506020020160208101906109b991906133c4565b60039067ffffffffffffffff16610fa3565b610a35578484828181106109e1576109e1613395565b90506020020160208101906109f691906133c4565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f1565b60026000868684818110610a4b57610a4b613395565b9050602002016020810190610a6091906133c4565b67ffffffffffffffff1681526020810191909152604001600090812090610a878282612a87565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610abf600283016000612aa5565b5050610afd858583818110610ad657610ad6613395565b9050602002016020810190610aeb91906133c4565b60039067ffffffffffffffff16610fbb565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610b3157610b31613395565b9050602002016020810190610b4691906133c4565b60405167ffffffffffffffff909116815260200160405180910390a1600101610987565b5060005b81811015610d45576000838383818110610b8a57610b8a613395565b9050602002810190610b9c91906133df565b610baa90602081019061341d565b610bb39061361f565b80519091506000858585818110610bcc57610bcc613395565b9050602002810190610bde91906133df565b610bec9060208101906133c4565b905060005b8251811015610c2457610c1c838281518110610c0f57610c0f613395565b6020026020010151610fc7565b600101610bf1565b50826020015160ff16600003610c66576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120845180518693610c96928492910190612adf565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610ce39082613706565b50610cfd91506003905067ffffffffffffffff83166110e1565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08184604051610d2f929190613820565b60405180910390a1505050806001019050610b6e565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610dbb576040517f7b2485a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610dc9848601866138cb565b9050600080610dd7836110ed565b8151919350915015610def57610def84600084611346565b805115610e0257610e0284600183611346565b505050505050505050565b60606000610e1a83611b27565b9392505050565b600061066e825490565b60005473ffffffffffffffffffffffffffffffffffffffff163314610eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f1565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610f2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f1565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610e1a565b6000610e1a8383611b83565b6040517f50c946fe000000000000000000000000000000000000000000000000000000008152600481018290526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906350c946fe90602401600060405180830381865afa158015611055573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261109b9190810190613add565b5060408101519091506110dd576040517f8907a4fa000000000000000000000000000000000000000000000000000000008152600481018390526024016106f1565b5050565b6000610e1a8383611c76565b606080600460ff168351111561112f576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b6111b36040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161114557505060408051600280825260608201909252919350602082015b61124b6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816111dd57905050905060008060005b855181101561133957600086828151811061128357611283613395565b60200260200101516000015160018111156112a0576112a0612d8b565b036112ed578581815181106112b7576112b7613395565b60200260200101518584815181106112d1576112d1613395565b6020026020010181905250826112e690613c0b565b9250611331565b8581815181106112ff576112ff613395565b602002602001015184838151811061131957611319613395565b60200260200101819052508161132e90613c0b565b91505b600101611266565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561136e5761136e612d8b565b600181111561137f5761137f612d8b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561180857600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156113f2576113f2612d8b565b600181111561140357611403612d8b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a010000000000000000000090910416606082015260018201805460809092019161145b90613313565b80601f016020809104026020016040519081016040528092919081815260200182805461148790613313565b80156114d45780601f106114a9576101008083540402835291602001916114d4565b820191906000526020600020905b8154815290600101906020018083116114b757829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561152c57602002820191906000526020600020905b815481526020019060010190808311611518575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561158457602002820191906000526020600020905b815481526020019060010190808311611570575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561165e5783829060005260206000200180546115d190613313565b80601f01602080910402602001604051908101604052809291908181526020018280546115fd90613313565b801561164a5780601f1061161f5761010080835404028352916020019161164a565b820191906000526020600020905b81548152906001019060200180831161162d57829003601f168201915b5050505050815260200190600101906115b2565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156117375783829060005260206000200180546116aa90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546116d690613313565b80156117235780601f106116f857610100808354040283529160200191611723565b820191906000526020600020905b81548152906001019060200180831161170657829003601f168201915b50505050508152602001906001019061168b565b50505050815260200160068201805461174f90613313565b80601f016020809104026020016040519081016040528092919081815260200182805461177b90613313565b80156117c85780601f1061179d576101008083540402835291602001916117c8565b820191906000526020600020905b8154815290600101906020018083116117ab57829003601f168201915b505050919092525050508152600782015467ffffffffffffffff1660208083019190915260089092015460409091015290825260019290920191016113ad565b505050509050600061181a8251611cc5565b905060006118288451611cc5565b90506118348282611d17565b60006118438785878686611e0b565b905061184f84826121f7565b63ffffffff871660009081526005602052604081209087600181111561187757611877612d8b565b600181111561188857611888612d8b565b815260200190815260200160002060006118a29190612b2a565b60005b8151811015611b1d5763ffffffff88166000908152600560205260408120908860018111156118d6576118d6612d8b565b60018111156118e7576118e7612d8b565b815260200190815260200160002082828151811061190757611907613395565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690838181111561197157611971612d8b565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611a409082613706565b5060a08201518051611a5c916002840191602090910190612adf565b5060c08201518051611a78916003840191602090910190612adf565b5060e08201518051611a94916004840191602090910190612b4b565b506101008201518051611ab1916005840191602090910190612b4b565b506101208201516006820190611ac79082613706565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516008909101556001016118a5565b5050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7757602002820191906000526020600020905b815481526020019060010190808311611b63575b50505050509050919050565b60008181526001830160205260408120548015611c6c576000611ba7600183613c43565b8554909150600090611bbb90600190613c43565b9050818114611c20576000866000018281548110611bdb57611bdb613395565b9060005260206000200154905080876000018481548110611bfe57611bfe613395565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c3157611c31613c56565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061066e565b600091505061066e565b6000818152600183016020526040812054611cbd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561066e565b50600061066e565b60006002821115611d05576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016106f1565b81600281111561066e5761066e612d8b565b600080836002811115611d2c57611d2c612d8b565b148015611d4a57506001826002811115611d4857611d48612d8b565b145b905060006001846002811115611d6257611d62612d8b565b148015611d8057506002836002811115611d7e57611d7e612d8b565b145b905060006002856002811115611d9857611d98612d8b565b148015611db657506001846002811115611db457611db4612d8b565b145b90508280611dc15750815b80611dc95750805b15611dd5575050505050565b84846040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016106f1929190613c95565b60606000845167ffffffffffffffff811115611e2957611e29613366565b604051908082528060200260200182016040528015611e52578160200160208202803683370190505b5090506000846002811115611e6957611e69612d8b565b148015611e8757506001836002811115611e8557611e85612d8b565b145b15611ec857600181600081518110611ea157611ea1613395565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612030565b6001846002811115611edc57611edc612d8b565b148015611efa57506002836002811115611ef857611ef8612d8b565b145b15611f915785600081518110611f1257611f12613395565b60200260200101516020015181600081518110611f3157611f31613395565b602002602001019067ffffffffffffffff16908167ffffffffffffffff168152505085600081518110611f6657611f66613395565b6020026020010151602001516001611f7e9190613cb0565b81600181518110611ea157611ea1613395565b6002846002811115611fa557611fa5612d8b565b148015611fc357506001836002811115611fc157611fc1612d8b565b145b15611ffa5785600181518110611fdb57611fdb613395565b60200260200101516020015181600081518110611ea157611ea1613395565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016106f1929190613c95565b6000855167ffffffffffffffff81111561204c5761204c613366565b60405190808252806020026020018201604052801561210257816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161206a5790505b50905060005b82518110156121eb5761213387828151811061212657612126613395565b6020026020010151612576565b604051806060016040528088838151811061215057612150613395565b6020026020010151815260200184838151811061216f5761216f613395565b602002602001015167ffffffffffffffff1681526020016121c38b86858151811061219c5761219c613395565b60200260200101518b86815181106121b6576121b6613395565b602002602001015161296a565b8152508282815181106121d8576121d8613395565b6020908102919091010152600101612108565b50979650505050505050565b81518151811580156122095750806001145b156122ab578260008151811061222157612221613395565b60200260200101516020015167ffffffffffffffff166001146122a5578260008151811061225157612251613395565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016106f1565b50505050565b8160011480156122bb5750806002145b1561247157836000815181106122d3576122d3613395565b602002602001015160400151836000815181106122f2576122f2613395565b6020026020010151604001511461237e578260008151811061231657612316613395565b6020026020010151604001518460008151811061233557612335613395565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016106f1929190918252602082015260400190565b8360008151811061239157612391613395565b60200260200101516020015160016123a99190613cb0565b67ffffffffffffffff16836001815181106123c6576123c6613395565b60200260200101516020015167ffffffffffffffff16146122a557826001815181106123f4576123f4613395565b6020026020010151602001518460008151811061241357612413613395565b602002602001015160200151600161242b9190613cb0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016106f1565b8160021480156124815750806001145b15612544578360018151811061249957612499613395565b602002602001015160400151836000815181106124b8576124b8613395565b602002602001015160400151146122a557826000815181106124dc576124dc613395565b602002602001015160400151846001815181106124fb576124fb613395565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016106f1929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff166000036125be576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156125d3576125d3612d8b565b141580156125f457506001815160018111156125f1576125f1612d8b565b14155b1561262b576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80608001515160000361266a576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516126859060039067ffffffffffffffff16610fa3565b6126cd5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f1565b60e081015151601f101561270d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f101561274e576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff1660009081526002909152604081206001015461277e9060ff166003613cd1565b612789906001613ced565b60ff169050808261010001515110156127e057610100820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f1565b816040015160ff16600003612821576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040820151612831906003613cd1565b60ff168260e001515111612871576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c00151511415806128955750816101000151518260c001515114155b156128f05760c08201515160e083015151610100840151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016106f1565b8160c00151518260a00151511115612934576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8260e00151518110156129655761295d8360c001518281518110610c0f57610c0f613395565b600101612937565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d61012001516040516020016129be9c9b9a99989796959493929190613d71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a82604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b50805460008255906000526020600020908101906109799190612b9d565b508054612ab190613313565b6000825580601f10612ac1575050565b601f0160209004906000526020600020908101906109799190612b9d565b828054828255906000526020600020908101928215612b1a579160200282015b82811115612b1a578251825591602001919060010190612aff565b50612b26929150612b9d565b5090565b50805460008255600902906000526020600020908101906109799190612bb2565b828054828255906000526020600020908101928215612b91579160200282015b82811115612b915782518290612b819082613706565b5091602001919060010190612b6b565b50612b26929150612c73565b5b80821115612b265760008155600101612b9e565b80821115612b265780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612bf16001830182612aa5565b612bff600283016000612a87565b612c0d600383016000612a87565b612c1b600483016000612c90565b612c29600583016000612c90565b612c37600683016000612aa5565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612bb2565b80821115612b26576000612c878282612aa5565b50600101612c73565b50805460008255906000526020600020908101906109799190612c73565b6000815180845260005b81811015612cd457602081850181015186830182015201612cb8565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610e1a6020830184612cae565b63ffffffff8116811461097957600080fd5b8035612d4281612d25565b919050565b803560028110612d4257600080fd5b60008060408385031215612d6957600080fd5b8235612d7481612d25565b9150612d8260208401612d47565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612dca57612dca612d8b565b9052565b60008151808452602080850194506020840160005b83811015612dff57815187529582019590820190600101612de3565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015612e75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612e63838351612cae565b98840198925090830190600101612e29565b5090979650505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613051577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612ef08287018251612dba565b898101516080612f0b8189018367ffffffffffffffff169052565b8a830151915060a0612f21818a018460ff169052565b938301519360c09250612f3f8984018667ffffffffffffffff169052565b818401519450610140915060e082818b0152612f5f6101a08b0187612cae565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612f9e8885612dce565b97508587015195506101209350818c890301848d0152612fbe8887612dce565b9750828701519550818c890301858d0152612fd98887612e0a565b975080870151955050808b8803016101608c0152612ff78786612e0a565b9650828601519550808b8803016101808c015250505050506130198282612cae565b915050888201516130358a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eab565b509098975050505050505050565b60006020828403121561307157600080fd5b8135610e1a81612d25565b60008151606084526130916060850182612dce565b905060ff6020840151166020850152604083015184820360408601526130b78282612cae565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613051578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261313d8785018261307c565b95880195935050908601906001016130e9565b60006020828403121561316257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e1a57600080fd5b60008083601f84011261319857600080fd5b50813567ffffffffffffffff8111156131b057600080fd5b6020830191508360208260051b85010111156131cb57600080fd5b9250929050565b600080600080604085870312156131e857600080fd5b843567ffffffffffffffff8082111561320057600080fd5b61320c88838901613186565b9096509450602087013591508082111561322557600080fd5b5061323287828801613186565b95989497509550505050565b803567ffffffffffffffff81168114612d4257600080fd5b6000806000806000806080878903121561326f57600080fd5b863567ffffffffffffffff8082111561328757600080fd5b6132938a838b01613186565b909850965060208901359150808211156132ac57600080fd5b818901915089601f8301126132c057600080fd5b8135818111156132cf57600080fd5b8a60208285010111156132e157600080fd5b6020830196508095505050506132f96040880161323e565b915061330760608801612d37565b90509295509295509295565b600181811c9082168061332757607f821691505b602082108103613360577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156133d657600080fd5b610e1a8261323e565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261341357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261341357600080fd5b604051610140810167ffffffffffffffff8111828210171561347557613475613366565b60405290565b6040516080810167ffffffffffffffff8111828210171561347557613475613366565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156134e5576134e5613366565b604052919050565b600067ffffffffffffffff82111561350757613507613366565b5060051b60200190565b600082601f83011261352257600080fd5b81356020613537613532836134ed565b61349e565b8083825260208201915060208460051b87010193508684111561355957600080fd5b602086015b84811015613575578035835291830191830161355e565b509695505050505050565b803560ff81168114612d4257600080fd5b600082601f8301126135a257600080fd5b813567ffffffffffffffff8111156135bc576135bc613366565b6135ed60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161349e565b81815284602083860101111561360257600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561363157600080fd5b6040516060810167ffffffffffffffff828210818311171561365557613655613366565b81604052843591508082111561366a57600080fd5b61367636838701613511565b835261368460208601613580565b6020840152604085013591508082111561369d57600080fd5b506136aa36828601613591565b60408301525092915050565b601f821115612965576000816000526020600020601f850160051c810160208610156136df5750805b601f850160051c820191505b818110156136fe578281556001016136eb565b505050505050565b815167ffffffffffffffff81111561372057613720613366565b6137348161372e8454613313565b846136b6565b602080601f83116001811461378757600084156137515750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556136fe565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156137d4578886015182559484019460019091019084016137b5565b508582101561381057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613843604083018461307c565b949350505050565b600082601f83011261385c57600080fd5b8135602061386c613532836134ed565b82815260059290921b8401810191818101908684111561388b57600080fd5b8286015b8481101561357557803567ffffffffffffffff8111156138af5760008081fd5b6138bd8986838b0101613591565b84525091830191830161388f565b600060208083850312156138de57600080fd5b823567ffffffffffffffff808211156138f657600080fd5b818501915085601f83011261390a57600080fd5b8135613918613532826134ed565b81815260059190911b8301840190848101908883111561393757600080fd5b8585015b83811015613ac55780358581111561395257600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561398757600080fd5b61398f613451565b61399a898301612d47565b81526139a86040830161323e565b898201526139b860608301613580565b60408201526139c96080830161323e565b606082015260a0820135878111156139e057600080fd5b6139ee8d8b83860101613591565b60808301525060c082013587811115613a0657600080fd5b613a148d8b83860101613511565b60a08301525060e082013587811115613a2c57600080fd5b613a3a8d8b83860101613511565b60c0830152506101008083013588811115613a5457600080fd5b613a628e8c8387010161384b565b60e0840152506101208084013589811115613a7c57600080fd5b613a8a8f8d8388010161384b565b8385015250610140840135915088821115613aa457600080fd5b613ab28e8c84870101613591565b908301525084525091860191860161393b565b5098975050505050505050565b8051612d4281612d25565b60008060408385031215613af057600080fd5b825167ffffffffffffffff80821115613b0857600080fd5b9084019060808287031215613b1c57600080fd5b613b2461347b565b8251613b2f81612d25565b81526020838101518183015260408085015190830152606084015183811115613b5757600080fd5b80850194505087601f850112613b6c57600080fd5b83519250613b7c613532846134ed565b83815260059390931b84018101928181019089851115613b9b57600080fd5b948201945b84861015613bb957855182529482019490820190613ba0565b8060608501525050819550613bcf818801613ad2565b9450505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613c3c57613c3c613bdc565b5060010190565b8181038181111561066e5761066e613bdc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60038110612dca57612dca612d8b565b60408101613ca38285613c85565b610e1a6020830184613c85565b67ffffffffffffffff81811683821601908082111561096157610961613bdc565b60ff818116838216029081169081811461096157610961613bdc565b60ff818116838216019081111561066e5761066e613bdc565b60008282518085526020808601955060208260051b8401016020860160005b84811015612e75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952613d5f838351612cae565b98840198925090830190600101613d25565b67ffffffffffffffff8d16815263ffffffff8c166020820152613d97604082018c612dba565b61018060608201526000613daf61018083018c612cae565b67ffffffffffffffff8b16608084015282810360a0840152613dd1818b612dce565b905082810360c0840152613de5818a612dce565b905082810360e0840152613df98189613d06565b9050828103610100840152613e0e8188613d06565b60ff8716610120850152905067ffffffffffffffff8516610140840152828103610160840152613e3e8185612cae565b9f9e50505050505050505050505050505056fe434349504361706162696c697479436f6e66696775726174696f6e20312e362e302d646576a164736f6c6343000818000a", +} + +var CCIPCapabilityConfigurationABI = CCIPCapabilityConfigurationMetaData.ABI + +var CCIPCapabilityConfigurationBin = CCIPCapabilityConfigurationMetaData.Bin + +func DeployCCIPCapabilityConfiguration(auth *bind.TransactOpts, backend bind.ContractBackend, capabilityRegistry common.Address) (common.Address, *types.Transaction, *CCIPCapabilityConfiguration, error) { + parsed, err := CCIPCapabilityConfigurationMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CCIPCapabilityConfigurationBin), backend, capabilityRegistry) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CCIPCapabilityConfiguration{address: address, abi: *parsed, CCIPCapabilityConfigurationCaller: CCIPCapabilityConfigurationCaller{contract: contract}, CCIPCapabilityConfigurationTransactor: CCIPCapabilityConfigurationTransactor{contract: contract}, CCIPCapabilityConfigurationFilterer: CCIPCapabilityConfigurationFilterer{contract: contract}}, nil +} + +type CCIPCapabilityConfiguration struct { + address common.Address + abi abi.ABI + CCIPCapabilityConfigurationCaller + CCIPCapabilityConfigurationTransactor + CCIPCapabilityConfigurationFilterer +} + +type CCIPCapabilityConfigurationCaller struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationTransactor struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationFilterer struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationSession struct { + Contract *CCIPCapabilityConfiguration + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CCIPCapabilityConfigurationCallerSession struct { + Contract *CCIPCapabilityConfigurationCaller + CallOpts bind.CallOpts +} + +type CCIPCapabilityConfigurationTransactorSession struct { + Contract *CCIPCapabilityConfigurationTransactor + TransactOpts bind.TransactOpts +} + +type CCIPCapabilityConfigurationRaw struct { + Contract *CCIPCapabilityConfiguration +} + +type CCIPCapabilityConfigurationCallerRaw struct { + Contract *CCIPCapabilityConfigurationCaller +} + +type CCIPCapabilityConfigurationTransactorRaw struct { + Contract *CCIPCapabilityConfigurationTransactor +} + +func NewCCIPCapabilityConfiguration(address common.Address, backend bind.ContractBackend) (*CCIPCapabilityConfiguration, error) { + abi, err := abi.JSON(strings.NewReader(CCIPCapabilityConfigurationABI)) + if err != nil { + return nil, err + } + contract, err := bindCCIPCapabilityConfiguration(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfiguration{address: address, abi: abi, CCIPCapabilityConfigurationCaller: CCIPCapabilityConfigurationCaller{contract: contract}, CCIPCapabilityConfigurationTransactor: CCIPCapabilityConfigurationTransactor{contract: contract}, CCIPCapabilityConfigurationFilterer: CCIPCapabilityConfigurationFilterer{contract: contract}}, nil +} + +func NewCCIPCapabilityConfigurationCaller(address common.Address, caller bind.ContractCaller) (*CCIPCapabilityConfigurationCaller, error) { + contract, err := bindCCIPCapabilityConfiguration(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationCaller{contract: contract}, nil +} + +func NewCCIPCapabilityConfigurationTransactor(address common.Address, transactor bind.ContractTransactor) (*CCIPCapabilityConfigurationTransactor, error) { + contract, err := bindCCIPCapabilityConfiguration(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationTransactor{contract: contract}, nil +} + +func NewCCIPCapabilityConfigurationFilterer(address common.Address, filterer bind.ContractFilterer) (*CCIPCapabilityConfigurationFilterer, error) { + contract, err := bindCCIPCapabilityConfiguration(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationFilterer{contract: contract}, nil +} + +func bindCCIPCapabilityConfiguration(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CCIPCapabilityConfigurationMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationCaller.contract.Call(opts, result, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationTransactor.contract.Transfer(opts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationTransactor.contract.Transact(opts, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPCapabilityConfiguration.Contract.contract.Call(opts, result, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.contract.Transfer(opts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.contract.Transact(opts, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getAllChainConfigs") + + if err != nil { + return *new([]CCIPCapabilityConfigurationChainConfigInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPCapabilityConfigurationChainConfigInfo)).(*[]CCIPCapabilityConfigurationChainConfigInfo) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetAllChainConfigs() ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + return _CCIPCapabilityConfiguration.Contract.GetAllChainConfigs(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetAllChainConfigs() ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + return _CCIPCapabilityConfiguration.Contract.GetAllChainConfigs(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getCapabilityConfiguration", arg0) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPCapabilityConfiguration.Contract.GetCapabilityConfiguration(&_CCIPCapabilityConfiguration.CallOpts, arg0) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPCapabilityConfiguration.Contract.GetCapabilityConfiguration(&_CCIPCapabilityConfiguration.CallOpts, arg0) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getOCRConfig", donId, pluginType) + + if err != nil { + return *new([]CCIPCapabilityConfigurationOCR3ConfigWithMeta), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPCapabilityConfigurationOCR3ConfigWithMeta)).(*[]CCIPCapabilityConfigurationOCR3ConfigWithMeta) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + return _CCIPCapabilityConfiguration.Contract.GetOCRConfig(&_CCIPCapabilityConfiguration.CallOpts, donId, pluginType) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + return _CCIPCapabilityConfiguration.Contract.GetOCRConfig(&_CCIPCapabilityConfiguration.CallOpts, donId, pluginType) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) Owner() (common.Address, error) { + return _CCIPCapabilityConfiguration.Contract.Owner(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) Owner() (common.Address, error) { + return _CCIPCapabilityConfiguration.Contract.Owner(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) TypeAndVersion() (string, error) { + return _CCIPCapabilityConfiguration.Contract.TypeAndVersion(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) TypeAndVersion() (string, error) { + return _CCIPCapabilityConfiguration.Contract.TypeAndVersion(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "acceptOwnership") +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.AcceptOwnership(&_CCIPCapabilityConfiguration.TransactOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.AcceptOwnership(&_CCIPCapabilityConfiguration.TransactOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "applyChainConfigUpdates", chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.ApplyChainConfigUpdates(&_CCIPCapabilityConfiguration.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.ApplyChainConfigUpdates(&_CCIPCapabilityConfiguration.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "beforeCapabilityConfigSet", arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.BeforeCapabilityConfigSet(&_CCIPCapabilityConfiguration.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.BeforeCapabilityConfigSet(&_CCIPCapabilityConfiguration.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "transferOwnership", to) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.TransferOwnership(&_CCIPCapabilityConfiguration.TransactOpts, to) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.TransferOwnership(&_CCIPCapabilityConfiguration.TransactOpts, to) +} + +type CCIPCapabilityConfigurationCapabilityConfigurationSetIterator struct { + Event *CCIPCapabilityConfigurationCapabilityConfigurationSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationCapabilityConfigurationSet struct { + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationCapabilityConfigurationSetIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationCapabilityConfigurationSetIterator{contract: _CCIPCapabilityConfiguration.contract, event: "CapabilityConfigurationSet", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationCapabilityConfigurationSet) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseCapabilityConfigurationSet(log types.Log) (*CCIPCapabilityConfigurationCapabilityConfigurationSet, error) { + event := new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationChainConfigRemovedIterator struct { + Event *CCIPCapabilityConfigurationChainConfigRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationChainConfigRemoved struct { + ChainSelector uint64 + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigRemovedIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationChainConfigRemovedIterator{contract: _CCIPCapabilityConfiguration.contract, event: "ChainConfigRemoved", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigRemoved) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseChainConfigRemoved(log types.Log) (*CCIPCapabilityConfigurationChainConfigRemoved, error) { + event := new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationChainConfigSetIterator struct { + Event *CCIPCapabilityConfigurationChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationChainConfigSet struct { + ChainSelector uint64 + ChainConfig CCIPCapabilityConfigurationChainConfig + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigSetIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationChainConfigSetIterator{contract: _CCIPCapabilityConfiguration.contract, event: "ChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigSet) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationChainConfigSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseChainConfigSet(log types.Log) (*CCIPCapabilityConfigurationChainConfigSet, error) { + event := new(CCIPCapabilityConfigurationChainConfigSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationOwnershipTransferRequestedIterator struct { + Event *CCIPCapabilityConfigurationOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationOwnershipTransferRequestedIterator{contract: _CCIPCapabilityConfiguration.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseOwnershipTransferRequested(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferRequested, error) { + event := new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationOwnershipTransferredIterator struct { + Event *CCIPCapabilityConfigurationOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationOwnershipTransferredIterator{contract: _CCIPCapabilityConfiguration.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseOwnershipTransferred(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferred, error) { + event := new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfiguration) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CCIPCapabilityConfiguration.abi.Events["CapabilityConfigurationSet"].ID: + return _CCIPCapabilityConfiguration.ParseCapabilityConfigurationSet(log) + case _CCIPCapabilityConfiguration.abi.Events["ChainConfigRemoved"].ID: + return _CCIPCapabilityConfiguration.ParseChainConfigRemoved(log) + case _CCIPCapabilityConfiguration.abi.Events["ChainConfigSet"].ID: + return _CCIPCapabilityConfiguration.ParseChainConfigSet(log) + case _CCIPCapabilityConfiguration.abi.Events["OwnershipTransferRequested"].ID: + return _CCIPCapabilityConfiguration.ParseOwnershipTransferRequested(log) + case _CCIPCapabilityConfiguration.abi.Events["OwnershipTransferred"].ID: + return _CCIPCapabilityConfiguration.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CCIPCapabilityConfigurationCapabilityConfigurationSet) Topic() common.Hash { + return common.HexToHash("0x84ad7751b744c9e2ee77da1d902b428aec7f0a343d67a24bbe2142e6f58a8d0f") +} + +func (CCIPCapabilityConfigurationChainConfigRemoved) Topic() common.Hash { + return common.HexToHash("0x2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0") +} + +func (CCIPCapabilityConfigurationChainConfigSet) Topic() common.Hash { + return common.HexToHash("0x05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0") +} + +func (CCIPCapabilityConfigurationOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CCIPCapabilityConfigurationOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfiguration) Address() common.Address { + return _CCIPCapabilityConfiguration.address +} + +type CCIPCapabilityConfigurationInterface interface { + GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPCapabilityConfigurationChainConfigInfo, error) + + GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) + + GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) + + BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationCapabilityConfigurationSetIterator, error) + + WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationCapabilityConfigurationSet) (event.Subscription, error) + + ParseCapabilityConfigurationSet(log types.Log) (*CCIPCapabilityConfigurationCapabilityConfigurationSet, error) + + FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigRemovedIterator, error) + + WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigRemoved) (event.Subscription, error) + + ParseChainConfigRemoved(log types.Log) (*CCIPCapabilityConfigurationChainConfigRemoved, error) + + FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigSetIterator, error) + + WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigSet) (event.Subscription, error) + + ParseChainConfigSet(log types.Log) (*CCIPCapabilityConfigurationChainConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index de649f27e2..13aab261a8 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,9 +5,9 @@ burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin fee3f82935ce7a26c65e12f19a472a4fccdae62755abdb42d8b0a01f0f06981a burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin c7efa00d2be62a97a814730c8e13aa70794ebfdd38a9f3b3c11554a5dfd70478 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin a0728e186af74968101135a58a483320ced9ab79b22b1b24ac6994254ee79097 +ccip_capability_configuration: ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.abi ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.bin 75d617a77f82e09a8a4453689fa730a1f369dcf906de750126a3c782b3f885e9 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 -custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 4c7bdddea3decee12887c5bd89648ed3b423bd31eefe586d5cb5c1bc8b883ffe evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin da3b401b00dae39a2851740d00f2ed81d498ad9287b7ab9276f8b10021743d20 diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 2961094925..57a05ae411 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -28,6 +28,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin PriceRegistry price_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.abi ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.bin CCIPCapabilityConfiguration ccip_capability_configuration //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin MaybeRevertMessageReceiver maybe_revert_message_receiver //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin PingPongDemo ping_pong_demo