creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {ITypeAndVersion} from \"../../shared/interfaces/ITypeAndVersion.sol\";\nimport {ICommitStore} from \"../interfaces/ICommitStore.sol\";\nimport {IARM} from \"../interfaces/IARM.sol\";\nimport {IPool} from \"../interfaces/pools/IPool.sol\";\nimport {IRouter} from \"../interfaces/IRouter.sol\";\nimport {IPriceRegistry} from \"../interfaces/IPriceRegistry.sol\";\nimport {IAny2EVMMessageReceiver} from \"../interfaces/IAny2EVMMessageReceiver.sol\";\nimport {IAny2EVMOffRamp} from \"../interfaces/IAny2EVMOffRamp.sol\";\n\nimport {Client} from \"../libraries/Client.sol\";\nimport {Internal} from \"../libraries/Internal.sol\";\nimport {RateLimiter} from \"../libraries/RateLimiter.sol\";\nimport {CallWithExactGas} from \"../../shared/call/CallWithExactGas.sol\";\nimport {OCR2BaseNoChecks} from \"../ocr/OCR2BaseNoChecks.sol\";\nimport {AggregateRateLimiter} from \"../AggregateRateLimiter.sol\";\nimport {EnumerableMapAddresses} from \"../../shared/enumerable/EnumerableMapAddresses.sol\";\n\nimport {IERC20} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol\";\nimport {Address} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol\";\nimport {ERC165Checker} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/ERC165Checker.sol\";\n\n/// @notice EVM2EVMOffRamp enables OCR networks to execute multiple messages\n/// in an OffRamp in a single transaction.\n/// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them\n/// results an onchain upgrade of all 3.\n/// @dev OCR2BaseNoChecks is used to save gas, signatures are not required as the offramp can only execute\n/// messages which are committed in the commitStore. We still make use of OCR2 as an executor whitelist\n/// and turn-taking mechanism.\ncontract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersion, OCR2BaseNoChecks {\n  using Address for address;\n  using ERC165Checker for address;\n  using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap;\n\n  error AlreadyAttempted(uint64 sequenceNumber);\n  error AlreadyExecuted(uint64 sequenceNumber);\n  error ZeroAddressNotAllowed();\n  error CommitStoreAlreadyInUse();\n  error ExecutionError(bytes error);\n  error InvalidSourceChain(uint64 sourceChainSelector);\n  error MessageTooLarge(uint256 maxSize, uint256 actualSize);\n  error TokenDataMismatch(uint64 sequenceNumber);\n  error UnexpectedTokenData();\n  error UnsupportedNumberOfTokens(uint64 sequenceNumber);\n  error ManualExecutionNotYetEnabled();\n  error ManualExecutionGasLimitMismatch();\n  error InvalidManualExecutionGasLimit(uint256 index, uint256 newLimit);\n  error RootNotCommitted();\n  error UnsupportedToken(IERC20 token);\n  error CanOnlySelfCall();\n  error ReceiverError(bytes error);\n  error TokenHandlingError(bytes error);\n  error EmptyReport();\n  error BadARMSignal();\n  error InvalidMessageId();\n  error InvalidTokenPoolConfig();\n  error PoolAlreadyAdded();\n  error PoolDoesNotExist();\n  error TokenPoolMismatch();\n  error InvalidNewState(uint64 sequenceNumber, Internal.MessageExecutionState newState);\n\n  event PoolAdded(address token, address pool);\n  event PoolRemoved(address token, address pool);\n  /// @dev Atlas depends on this event, if changing, please notify Atlas.\n  event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);\n  event SkippedIncorrectNonce(uint64 indexed nonce, address indexed sender);\n  event SkippedSenderWithPreviousRampMessageInflight(uint64 indexed nonce, address indexed sender);\n  /// @dev RMN depends on this event, if changing, please notify the RMN maintainers.\n  event ExecutionStateChanged(\n    uint64 indexed sequenceNumber,\n    bytes32 indexed messageId,\n    Internal.MessageExecutionState state,\n    bytes returnData\n  );\n\n  /// @notice Static offRamp config\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct StaticConfig {\n    address commitStore; // ────────╮  CommitStore address on the destination chain\n    uint64 chainSelector; // ───────╯  Destination chainSelector\n    uint64 sourceChainSelector; // ─╮  Source chainSelector\n    address onRamp; // ─────────────╯  OnRamp address on the source chain\n    address prevOffRamp; //            Address of previous-version OffRamp\n    address armProxy; //               ARM proxy address\n  }\n\n  /// @notice Dynamic offRamp config\n  /// @dev since OffRampConfig is part of OffRampConfigChanged event, if changing it, we should update the ABI on Atlas\n  struct DynamicConfig {\n    uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled\n    address router; // ─────────────────────────────────╯ Router address\n    address priceRegistry; // ──────────╮ Price registry address\n    uint16 maxNumberOfTokensPerMsg; //  │ Maximum number of ERC20 token transfers that can be included per message\n    uint32 maxDataBytes; //             │ Maximum payload data size in bytes\n    uint32 maxPoolReleaseOrMintGas; // ─╯ Maximum amount of gas passed on to token pool when calling releaseOrMint\n  }\n\n  // STATIC CONFIG\n  // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables\n  string public constant override typeAndVersion = \"EVM2EVMOffRamp 1.2.0\";\n  /// @dev Commit store address on the destination chain\n  address internal immutable i_commitStore;\n  /// @dev ChainSelector of the source chain\n  uint64 internal immutable i_sourceChainSelector;\n  /// @dev ChainSelector of this chain\n  uint64 internal immutable i_chainSelector;\n  /// @dev OnRamp address on the source chain\n  address internal immutable i_onRamp;\n  /// @dev metadataHash is a lane-specific prefix for a message hash preimage which ensures global uniqueness.\n  /// Ensures that 2 identical messages sent to 2 different lanes will have a distinct hash.\n  /// Must match the metadataHash used in computing leaf hashes offchain for the root committed in\n  /// the commitStore and i_metadataHash in the onRamp.\n  bytes32 internal immutable i_metadataHash;\n  /// @dev The address of previous-version OffRamp for this lane.\n  /// Used to be able to provide sequencing continuity during a zero downtime upgrade.\n  address internal immutable i_prevOffRamp;\n  /// @dev The address of the arm proxy\n  address internal immutable i_armProxy;\n\n  // DYNAMIC CONFIG\n  DynamicConfig internal s_dynamicConfig;\n  /// @dev source token => token pool\n  EnumerableMapAddresses.AddressToAddressMap private s_poolsBySourceToken;\n  /// @dev dest token => token pool\n  EnumerableMapAddresses.AddressToAddressMap private s_poolsByDestToken;\n\n  // STATE\n  /// @dev The expected nonce for a given sender.\n  /// Corresponds to s_senderNonce in the OnRamp, used to enforce that messages are\n  /// executed in the same order they are sent (assuming they are DON). Note that re-execution\n  /// of FAILED messages however, can be out of order.\n  mapping(address sender => uint64 nonce) internal s_senderNonce;\n  /// @dev A mapping of sequence numbers to execution state using a bitmap with each execution\n  /// state only taking up 2 bits of the uint256, packing 128 states into a single slot.\n  /// Message state is tracked to ensure message can only be executed successfully once.\n  mapping(uint64 seqNum => uint256 executionStateBitmap) internal s_executionStates;\n\n  constructor(\n    StaticConfig memory staticConfig,\n    IERC20[] memory sourceTokens,\n    IPool[] memory pools,\n    RateLimiter.Config memory rateLimiterConfig\n  ) OCR2BaseNoChecks() AggregateRateLimiter(rateLimiterConfig) {\n    if (sourceTokens.length != pools.length) revert InvalidTokenPoolConfig();\n    if (staticConfig.onRamp == address(0) || staticConfig.commitStore == address(0)) revert ZeroAddressNotAllowed();\n    // Ensures we can never deploy a new offRamp that points to a commitStore that\n    // already has roots committed.\n    if (ICommitStore(staticConfig.commitStore).getExpectedNextSequenceNumber() != 1) revert CommitStoreAlreadyInUse();\n\n    i_commitStore = staticConfig.commitStore;\n    i_sourceChainSelector = staticConfig.sourceChainSelector;\n    i_chainSelector = staticConfig.chainSelector;\n    i_onRamp = staticConfig.onRamp;\n    i_prevOffRamp = staticConfig.prevOffRamp;\n    i_armProxy = staticConfig.armProxy;\n\n    i_metadataHash = _metadataHash(Internal.EVM_2_EVM_MESSAGE_HASH);\n\n    // Set new tokens and pools\n    for (uint256 i = 0; i < sourceTokens.length; ++i) {\n      s_poolsBySourceToken.set(address(sourceTokens[i]), address(pools[i]));\n      s_poolsByDestToken.set(address(pools[i].getToken()), address(pools[i]));\n      emit PoolAdded(address(sourceTokens[i]), address(pools[i]));\n    }\n  }\n\n  // ================================================================\n  // │                          Messaging                           │\n  // ================================================================\n\n  // The size of the execution state in bits\n  uint256 private constant MESSAGE_EXECUTION_STATE_BIT_WIDTH = 2;\n  // The mask for the execution state bits\n  uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1;\n\n  /// @notice Returns the current execution state of a message based on its sequenceNumber.\n  /// @param sequenceNumber The sequence number of the message to get the execution state for.\n  /// @return The current execution state of the message.\n  /// @dev we use the literal number 128 because using a constant increased gas usage.\n  function getExecutionState(uint64 sequenceNumber) public view returns (Internal.MessageExecutionState) {\n    return\n      Internal.MessageExecutionState(\n        (s_executionStates[sequenceNumber / 128] >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH)) &\n          MESSAGE_EXECUTION_STATE_MASK\n      );\n  }\n\n  /// @notice Sets a new execution state for a given sequence number. It will overwrite any existing state.\n  /// @param sequenceNumber The sequence number for which the state will be saved.\n  /// @param newState The new value the state will be in after this function is called.\n  /// @dev we use the literal number 128 because using a constant increased gas usage.\n  function _setExecutionState(uint64 sequenceNumber, Internal.MessageExecutionState newState) internal {\n    uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH;\n    uint256 bitmap = s_executionStates[sequenceNumber / 128];\n    // to unset any potential existing state we zero the bits of the section the state occupies,\n    // then we do an AND operation to blank out any existing state for the section.\n    bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset);\n    // Set the new state\n    bitmap |= uint256(newState) << offset;\n\n    s_executionStates[sequenceNumber / 128] = bitmap;\n  }\n\n  /// @inheritdoc IAny2EVMOffRamp\n  function getSenderNonce(address sender) public view returns (uint64 nonce) {\n    uint256 senderNonce = s_senderNonce[sender];\n\n    if (senderNonce == 0 && i_prevOffRamp != address(0)) {\n      // If OffRamp was upgraded, check if sender has a nonce from the previous OffRamp.\n      return IAny2EVMOffRamp(i_prevOffRamp).getSenderNonce(sender);\n    }\n    return uint64(senderNonce);\n  }\n\n  /// @notice Manually execute a message.\n  /// @param report Internal.ExecutionReport.\n  /// @param gasLimitOverrides New gasLimit for each message in the report.\n  /// @dev We permit gas limit overrides so that users may manually execute messages which failed due to\n  /// insufficient gas provided.\n  function manuallyExecute(Internal.ExecutionReport memory report, uint256[] memory gasLimitOverrides) external {\n    // We do this here because the other _execute path is already covered OCR2BaseXXX.\n    if (i_chainID != block.chainid) revert OCR2BaseNoChecks.ForkedChain(i_chainID, uint64(block.chainid));\n\n    uint256 numMsgs = report.messages.length;\n    if (numMsgs != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch();\n    for (uint256 i = 0; i < numMsgs; ++i) {\n      uint256 newLimit = gasLimitOverrides[i];\n      // Checks to ensure message cannot be executed with less gas than specified.\n      if (newLimit != 0 && newLimit < report.messages[i].gasLimit) revert InvalidManualExecutionGasLimit(i, newLimit);\n    }\n\n    _execute(report, gasLimitOverrides);\n  }\n\n  /// @notice Entrypoint for execution, called by the OCR network\n  /// @dev Expects an encoded ExecutionReport\n  function _report(bytes calldata report) internal override {\n    _execute(abi.decode(report, (Internal.ExecutionReport)), new uint256[](0));\n  }\n\n  /// @notice Executes a report, executing each message in order.\n  /// @param report The execution report containing the messages and proofs.\n  /// @param manualExecGasLimits An array of gas limits to use for manual execution.\n  /// @dev If called from the DON, this array is always empty.\n  /// @dev If called from manual execution, this array is always same length as messages.\n  function _execute(Internal.ExecutionReport memory report, uint256[] memory manualExecGasLimits) internal whenHealthy {\n    uint256 numMsgs = report.messages.length;\n    if (numMsgs == 0) revert EmptyReport();\n    if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData();\n\n    bytes32[] memory hashedLeaves = new bytes32[](numMsgs);\n\n    for (uint256 i = 0; i < numMsgs; ++i) {\n      Internal.EVM2EVMMessage memory message = report.messages[i];\n      // We do this hash here instead of in _verifyMessages to avoid two separate loops\n      // over the same data, which increases gas cost\n      hashedLeaves[i] = Internal._hash(message, i_metadataHash);\n      // For EVM2EVM offramps, the messageID is the leaf hash.\n      // Asserting that this is true ensures we don't accidentally commit and then execute\n      // a message with an unexpected hash.\n      if (hashedLeaves[i] != message.messageId) revert InvalidMessageId();\n    }\n\n    // SECURITY CRITICAL CHECK\n    uint256 timestampCommitted = ICommitStore(i_commitStore).verify(hashedLeaves, report.proofs, report.proofFlagBits);\n    if (timestampCommitted == 0) revert RootNotCommitted();\n\n    // Execute messages\n    bool manualExecution = manualExecGasLimits.length != 0;\n    for (uint256 i = 0; i < numMsgs; ++i) {\n      Internal.EVM2EVMMessage memory message = report.messages[i];\n      Internal.MessageExecutionState originalState = getExecutionState(message.sequenceNumber);\n      // Two valid cases here, we either have never touched this message before, or we tried to execute\n      // and failed. This check protects against reentry and re-execution because the other states are\n      // IN_PROGRESS and SUCCESS, both should not be allowed to execute.\n      if (\n        !(originalState == Internal.MessageExecutionState.UNTOUCHED ||\n          originalState == Internal.MessageExecutionState.FAILURE)\n      ) revert AlreadyExecuted(message.sequenceNumber);\n\n      if (manualExecution) {\n        bool isOldCommitReport = (block.timestamp - timestampCommitted) >\n          s_dynamicConfig.permissionLessExecutionThresholdSeconds;\n        // Manually execution is fine if we previously failed or if the commit report is just too old\n        // Acceptable state transitions: FAILURE->SUCCESS, UNTOUCHED->SUCCESS, FAILURE->FAILURE\n        if (!(isOldCommitReport || originalState == Internal.MessageExecutionState.FAILURE))\n          revert ManualExecutionNotYetEnabled();\n\n        // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override.\n        if (manualExecGasLimits[i] != 0) {\n          message.gasLimit = manualExecGasLimits[i];\n        }\n      } else {\n        // DON can only execute a message once\n        // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE\n        if (originalState != Internal.MessageExecutionState.UNTOUCHED) revert AlreadyAttempted(message.sequenceNumber);\n      }\n\n      // In the scenario where we upgrade offRamps, we still want to have sequential nonces.\n      // Referencing the old offRamp to check the expected nonce if none is set for a\n      // given sender allows us to skip the current message if it would not be the next according\n      // to the old offRamp. This preserves sequencing between updates.\n      uint64 prevNonce = s_senderNonce[message.sender];\n      if (prevNonce == 0 && i_prevOffRamp != address(0)) {\n        prevNonce = IAny2EVMOffRamp(i_prevOffRamp).getSenderNonce(message.sender);\n        if (prevNonce + 1 != message.nonce) {\n          // the starting v2 onramp nonce, i.e. the 1st message nonce v2 offramp is expected to receive,\n          // is guaranteed to equal (largest v1 onramp nonce + 1).\n          // if this message's nonce isn't (v1 offramp nonce + 1), then v1 offramp nonce != largest v1 onramp nonce,\n          // it tells us there are still messages inflight for v1 offramp\n          emit SkippedSenderWithPreviousRampMessageInflight(message.nonce, message.sender);\n          continue;\n        }\n        // Otherwise this nonce is indeed the \"transitional nonce\", that is\n        // all messages sent to v1 ramp have been executed by the DON and the sequence can resume in V2.\n        // Note if first time user in V2, then prevNonce will be 0, and message.nonce = 1, so this will be a no-op.\n        s_senderNonce[message.sender] = prevNonce;\n      }\n\n      // UNTOUCHED messages MUST be executed in order always\n      if (originalState == Internal.MessageExecutionState.UNTOUCHED) {\n        if (prevNonce + 1 != message.nonce) {\n          // We skip the message if the nonce is incorrect\n          emit SkippedIncorrectNonce(message.nonce, message.sender);\n          continue;\n        }\n      }\n\n      // Although we expect only valid messages will be committed, we check again\n      // when executing as a defense in depth measure.\n      bytes[] memory offchainTokenData = report.offchainTokenData[i];\n      _isWellFormed(\n        message.sequenceNumber,\n        message.sourceChainSelector,\n        message.tokenAmounts.length,\n        message.data.length,\n        offchainTokenData.length\n      );\n\n      _setExecutionState(message.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS);\n      (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData);\n      _setExecutionState(message.sequenceNumber, newState);\n\n      // The only valid prior states are UNTOUCHED and FAILURE (checked above)\n      // The only valid post states are FAILURE and SUCCESS (checked below)\n      if (newState != Internal.MessageExecutionState.FAILURE && newState != Internal.MessageExecutionState.SUCCESS)\n        revert InvalidNewState(message.sequenceNumber, newState);\n\n      // Nonce changes per state transition\n      // UNTOUCHED -> FAILURE  nonce bump\n      // UNTOUCHED -> SUCCESS  nonce bump\n      // FAILURE   -> FAILURE  no nonce bump\n      // FAILURE   -> SUCCESS  no nonce bump\n      if (originalState == Internal.MessageExecutionState.UNTOUCHED) {\n        s_senderNonce[message.sender]++;\n      }\n\n      emit ExecutionStateChanged(message.sequenceNumber, message.messageId, newState, returnData);\n    }\n  }\n\n  /// @notice Does basic message validation. Should never fail.\n  /// @param sequenceNumber Sequence number of the message.\n  /// @param sourceChainSelector SourceChainSelector of the message.\n  /// @param numberOfTokens Length of tokenAmounts array in the message.\n  /// @param dataLength Length of data field in the message.\n  /// @param offchainTokenDataLength Length of offchainTokenData array.\n  /// @dev reverts on validation failures.\n  function _isWellFormed(\n    uint64 sequenceNumber,\n    uint64 sourceChainSelector,\n    uint256 numberOfTokens,\n    uint256 dataLength,\n    uint256 offchainTokenDataLength\n  ) private view {\n    if (sourceChainSelector != i_sourceChainSelector) revert InvalidSourceChain(sourceChainSelector);\n    if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg))\n      revert UnsupportedNumberOfTokens(sequenceNumber);\n    if (numberOfTokens != offchainTokenDataLength) revert TokenDataMismatch(sequenceNumber);\n    if (dataLength > uint256(s_dynamicConfig.maxDataBytes))\n      revert MessageTooLarge(uint256(s_dynamicConfig.maxDataBytes), dataLength);\n  }\n\n  /// @notice Try executing a message.\n  /// @param message Internal.EVM2EVMMessage memory message.\n  /// @param offchainTokenData Data provided by the DON for token transfers.\n  /// @return the new state of the message, being either SUCCESS or FAILURE.\n  /// @return revert data in bytes if CCIP receiver reverted during execution.\n  function _trialExecute(\n    Internal.EVM2EVMMessage memory message,\n    bytes[] memory offchainTokenData\n  ) internal returns (Internal.MessageExecutionState, bytes memory) {\n    try this.executeSingleMessage(message, offchainTokenData) {} catch (bytes memory err) {\n      if (ReceiverError.selector == bytes4(err) || TokenHandlingError.selector == bytes4(err)) {\n        // If CCIP receiver execution is not successful, bubble up receiver revert data,\n        // prepended by the 4 bytes of ReceiverError.selector or TokenHandlingError.selector\n        // Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES\n        return (Internal.MessageExecutionState.FAILURE, err);\n      } else {\n        // If revert is not caused by CCIP receiver, it is unexpected, bubble up the revert.\n        revert ExecutionError(err);\n      }\n    }\n    // If message execution succeeded, no CCIP receiver return data is expected, return with empty bytes.\n    return (Internal.MessageExecutionState.SUCCESS, \"\");\n  }\n\n  /// @notice Execute a single message.\n  /// @param message The message that will be executed.\n  /// @param offchainTokenData Token transfer data to be passed to TokenPool.\n  /// @dev We make this external and callable by the contract itself, in order to try/catch\n  /// its execution and enforce atomicity among successful message processing and token transfer.\n  /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts\n  /// (for example smart contract wallets) without an associated message.\n  function executeSingleMessage(Internal.EVM2EVMMessage memory message, bytes[] memory offchainTokenData) external {\n    if (msg.sender != address(this)) revert CanOnlySelfCall();\n    Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0);\n    if (message.tokenAmounts.length > 0) {\n      destTokenAmounts = _releaseOrMintTokens(\n        message.tokenAmounts,\n        abi.encode(message.sender),\n        message.receiver,\n        message.sourceTokenData,\n        offchainTokenData\n      );\n    }\n    if (\n      !message.receiver.isContract() || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId)\n    ) return;\n\n    (bool success, bytes memory returnData, ) = IRouter(s_dynamicConfig.router).routeMessage(\n      Internal._toAny2EVMMessage(message, destTokenAmounts),\n      Internal.GAS_FOR_CALL_EXACT_CHECK,\n      message.gasLimit,\n      message.receiver\n    );\n    // If CCIP receiver execution is not successful, revert the call including token transfers\n    if (!success) revert ReceiverError(returnData);\n  }\n\n  /// @notice creates a unique hash to be used in message hashing.\n  function _metadataHash(bytes32 prefix) internal view returns (bytes32) {\n    return keccak256(abi.encode(prefix, i_sourceChainSelector, i_chainSelector, i_onRamp));\n  }\n\n  // ================================================================\n  // │                           Config                             │\n  // ================================================================\n\n  /// @notice Returns the static config.\n  /// @dev This function will always return the same struct as the contents is static and can never change.\n  /// RMN depends on this function, if changing, please notify the RMN maintainers.\n  function getStaticConfig() external view returns (StaticConfig memory) {\n    return\n      StaticConfig({\n        commitStore: i_commitStore,\n        chainSelector: i_chainSelector,\n        sourceChainSelector: i_sourceChainSelector,\n        onRamp: i_onRamp,\n        prevOffRamp: i_prevOffRamp,\n        armProxy: i_armProxy\n      });\n  }\n\n  /// @notice Returns the current dynamic config.\n  /// @return The current config.\n  function getDynamicConfig() external view returns (DynamicConfig memory) {\n    return s_dynamicConfig;\n  }\n\n  /// @notice Sets the dynamic config. This function is called during `setOCR2Config` flow\n  function _beforeSetConfig(bytes memory onchainConfig) internal override {\n    DynamicConfig memory dynamicConfig = abi.decode(onchainConfig, (DynamicConfig));\n\n    if (dynamicConfig.router == address(0)) revert ZeroAddressNotAllowed();\n\n    s_dynamicConfig = dynamicConfig;\n\n    emit ConfigSet(\n      StaticConfig({\n        commitStore: i_commitStore,\n        chainSelector: i_chainSelector,\n        sourceChainSelector: i_sourceChainSelector,\n        onRamp: i_onRamp,\n        prevOffRamp: i_prevOffRamp,\n        armProxy: i_armProxy\n      }),\n      dynamicConfig\n    );\n  }\n\n  // ================================================================\n  // │                      Tokens and pools                        │\n  // ================================================================\n\n  /// @notice Get all supported source tokens\n  /// @return sourceTokens of supported source tokens\n  function getSupportedTokens() external view returns (IERC20[] memory sourceTokens) {\n    sourceTokens = new IERC20[](s_poolsBySourceToken.length());\n    for (uint256 i = 0; i < sourceTokens.length; ++i) {\n      (address token, ) = s_poolsBySourceToken.at(i);\n      sourceTokens[i] = IERC20(token);\n    }\n  }\n\n  /// @notice Get a token pool by its source token\n  /// @param sourceToken token\n  /// @return Token Pool\n  function getPoolBySourceToken(IERC20 sourceToken) public view returns (IPool) {\n    (bool success, address pool) = s_poolsBySourceToken.tryGet(address(sourceToken));\n    if (!success) revert UnsupportedToken(sourceToken);\n    return IPool(pool);\n  }\n\n  /// @notice Get the destination token from the pool based on a given source token.\n  /// @param sourceToken The source token\n  /// @return the destination token\n  function getDestinationToken(IERC20 sourceToken) external view returns (IERC20) {\n    return getPoolBySourceToken(sourceToken).getToken();\n  }\n\n  /// @notice Get a token pool by its dest token\n  /// @param destToken token\n  /// @return Token Pool\n  function getPoolByDestToken(IERC20 destToken) external view returns (IPool) {\n    (bool success, address pool) = s_poolsByDestToken.tryGet(address(destToken));\n    if (!success) revert UnsupportedToken(destToken);\n    return IPool(pool);\n  }\n\n  /// @notice Get all configured destination tokens\n  /// @return destTokens Array of configured destination tokens\n  function getDestinationTokens() external view returns (IERC20[] memory destTokens) {\n    destTokens = new IERC20[](s_poolsByDestToken.length());\n    for (uint256 i = 0; i < destTokens.length; ++i) {\n      (address token, ) = s_poolsByDestToken.at(i);\n      destTokens[i] = IERC20(token);\n    }\n  }\n\n  /// @notice Adds and removed token pools.\n  /// @param removes The tokens and pools to be removed\n  /// @param adds The tokens and pools to be added.\n  function applyPoolUpdates(\n    Internal.PoolUpdate[] calldata removes,\n    Internal.PoolUpdate[] calldata adds\n  ) external onlyOwner {\n    for (uint256 i = 0; i < removes.length; ++i) {\n      address token = removes[i].token;\n      address pool = removes[i].pool;\n\n      // Check if the pool exists\n      if (!s_poolsBySourceToken.contains(token)) revert PoolDoesNotExist();\n      // Sanity check\n      if (s_poolsBySourceToken.get(token) != pool) revert TokenPoolMismatch();\n\n      s_poolsBySourceToken.remove(token);\n      s_poolsByDestToken.remove(address(IPool(pool).getToken()));\n\n      emit PoolRemoved(token, pool);\n    }\n\n    for (uint256 i = 0; i < adds.length; ++i) {\n      address token = adds[i].token;\n      address pool = adds[i].pool;\n\n      if (token == address(0) || pool == address(0)) revert InvalidTokenPoolConfig();\n      // Check if the pool is already set\n      if (s_poolsBySourceToken.contains(token)) revert PoolAlreadyAdded();\n\n      // Set the s_pools with new config values\n      s_poolsBySourceToken.set(token, pool);\n      s_poolsByDestToken.set(address(IPool(pool).getToken()), pool);\n\n      emit PoolAdded(token, pool);\n    }\n  }\n\n  /// @notice Uses pools to release or mint a number of different tokens to a receiver address.\n  /// @param sourceTokenAmounts List of tokens and amount values to be released/minted.\n  /// @param originalSender The message sender.\n  /// @param receiver The address that will receive the tokens.\n  /// @param sourceTokenData Array of token data returned by token pools on the source chain.\n  /// @param offchainTokenData Array of token data fetched offchain by the DON.\n  /// @dev This function wrappes the token pool call in a try catch block to gracefully handle\n  /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error\n  /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError.\n  function _releaseOrMintTokens(\n    Client.EVMTokenAmount[] memory sourceTokenAmounts,\n    bytes memory originalSender,\n    address receiver,\n    bytes[] memory sourceTokenData,\n    bytes[] memory offchainTokenData\n  ) internal returns (Client.EVMTokenAmount[] memory) {\n    Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length);\n    for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) {\n      IPool pool = getPoolBySourceToken(IERC20(sourceTokenAmounts[i].token));\n      uint256 sourceTokenAmount = sourceTokenAmounts[i].amount;\n\n      // Call the pool with exact gas to increase resistance against malicious tokens or token pools.\n      // _callWithExactGas also protects against return data bombs by capping the return data size\n      // at MAX_RET_BYTES.\n      (bool success, bytes memory returnData, ) = CallWithExactGas._callWithExactGasSafeReturnData(\n        abi.encodeWithSelector(\n          pool.releaseOrMint.selector,\n          originalSender,\n          receiver,\n          sourceTokenAmount,\n          i_sourceChainSelector,\n          abi.encode(sourceTokenData[i], offchainTokenData[i])\n        ),\n        address(pool),\n        s_dynamicConfig.maxPoolReleaseOrMintGas,\n        Internal.GAS_FOR_CALL_EXACT_CHECK,\n        Internal.MAX_RET_BYTES\n      );\n\n      // wrap and rethrow the error so we can catch it lower in the stack\n      if (!success) revert TokenHandlingError(returnData);\n\n      destTokenAmounts[i].token = address(pool.getToken());\n      destTokenAmounts[i].amount = sourceTokenAmount;\n    }\n    _rateLimitValue(destTokenAmounts, IPriceRegistry(s_dynamicConfig.priceRegistry));\n    return destTokenAmounts;\n  }\n\n  // ================================================================\n  // │                        Access and ARM                        │\n  // ================================================================\n\n  /// @notice Reverts as this contract should not access CCIP messages\n  function ccipReceive(Client.Any2EVMMessage calldata) external pure {\n    /* solhint-disable */\n    revert();\n    /* solhint-enable*/\n  }\n\n  /// @notice Ensure that the ARM has not emitted a bad signal, and that the latest heartbeat is not stale.\n  modifier whenHealthy() {\n    if (IARM(i_armProxy).isCursed()) revert BadARMSignal();\n    _;\n  }\n}\n"
      },
      "src/v0.8/shared/interfaces/ITypeAndVersion.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITypeAndVersion {\n  function typeAndVersion() external pure returns (string memory);\n}\n"
      },
      "src/v0.8/ccip/interfaces/ICommitStore.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ICommitStore {\n  /// @notice Returns timestamp of when root was accepted or 0 if verification fails.\n  /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves,\n  /// proofs and proofFlagBits being used to get the root of the inner tree.\n  /// This root is then used as the singular leaf of the outer tree.\n  function verify(\n    bytes32[] calldata hashedLeaves,\n    bytes32[] calldata proofs,\n    uint256 proofFlagBits\n  ) external view returns (uint256 timestamp);\n\n  /// @notice Returns the expected next sequence number\n  function getExpectedNextSequenceNumber() external view returns (uint64 sequenceNumber);\n}\n"
      },
      "src/v0.8/ccip/interfaces/IARM.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice This interface contains the only ARM-related functions that might be used on-chain by other CCIP contracts.\ninterface IARM {\n  /// @notice A Merkle root tagged with the address of the commit store contract it is destined for.\n  struct TaggedRoot {\n    address commitStore;\n    bytes32 root;\n  }\n\n  /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed.\n  function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool);\n\n  /// @notice When the ARM is \"cursed\", CCIP pauses until the curse is lifted.\n  function isCursed() external view returns (bool);\n}\n"
      },
      "src/v0.8/ccip/interfaces/pools/IPool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"../../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol\";\n\n// Shared public interface for multiple pool types.\n// Each pool type handles a different child token model (lock/unlock, mint/burn.)\ninterface IPool {\n  /// @notice Lock tokens into the pool or burn the tokens.\n  /// @param originalSender Original sender of the tokens.\n  /// @param receiver Receiver of the tokens on destination chain.\n  /// @param amount Amount to lock or burn.\n  /// @param destChainSelector Destination chain Id.\n  /// @param extraArgs Additional data passed in by sender for lockOrBurn processing\n  /// in custom pools on source chain.\n  /// @return retData Optional field that contains bytes. Unused for now but already\n  /// implemented to allow future upgrades while preserving the interface.\n  function lockOrBurn(\n    address originalSender,\n    bytes calldata receiver,\n    uint256 amount,\n    uint64 destChainSelector,\n    bytes calldata extraArgs\n  ) external returns (bytes memory);\n\n  /// @notice Releases or mints tokens to the receiver address.\n  /// @param originalSender Original sender of the tokens.\n  /// @param receiver Receiver of the tokens.\n  /// @param amount Amount to release or mint.\n  /// @param sourceChainSelector Source chain Id.\n  /// @param extraData Additional data supplied offchain for releaseOrMint processing in\n  /// custom pools on dest chain. This could be an attestation that was retrieved through a\n  /// third party API.\n  /// @dev offchainData can come from any untrusted source.\n  function releaseOrMint(\n    bytes memory originalSender,\n    address receiver,\n    uint256 amount,\n    uint64 sourceChainSelector,\n    bytes memory extraData\n  ) external;\n\n  /// @notice Gets the IERC20 token that this pool can lock or burn.\n  /// @return token The IERC20 token representation.\n  function getToken() external view returns (IERC20 token);\n}\n"
      },
      "src/v0.8/ccip/interfaces/IRouter.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Client} from \"../libraries/Client.sol\";\n\ninterface IRouter {\n  error OnlyOffRamp();\n\n  /// @notice Route the message to its intended receiver contract.\n  /// @param message Client.Any2EVMMessage struct.\n  /// @param gasForCallExactCheck of params for exec\n  /// @param gasLimit set of params for exec\n  /// @param receiver set of params for exec\n  /// @dev if the receiver is a contracts that signals support for CCIP execution through EIP-165.\n  /// the contract is called. If not, only tokens are transferred.\n  /// @return success A boolean value indicating whether the ccip message was received without errors.\n  /// @return retBytes A bytes array containing return data form CCIP receiver.\n  /// @return gasUsed the gas used by the external customer call. Does not include any overhead.\n  function routeMessage(\n    Client.Any2EVMMessage calldata message,\n    uint16 gasForCallExactCheck,\n    uint256 gasLimit,\n    address receiver\n  ) external returns (bool success, bytes memory retBytes, uint256 gasUsed);\n}\n"
      },
      "src/v0.8/ccip/interfaces/IPriceRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Internal} from \"../libraries/Internal.sol\";\n\ninterface IPriceRegistry {\n  /// @notice Update the price for given tokens and gas prices for given chains.\n  /// @param priceUpdates The price updates to apply.\n  function updatePrices(Internal.PriceUpdates memory priceUpdates) external;\n\n  /// @notice Get the `tokenPrice` for a given token.\n  /// @param token The token to get the price for.\n  /// @return tokenPrice The tokenPrice for the given token.\n  function getTokenPrice(address token) external view returns (Internal.TimestampedPackedUint224 memory);\n\n  /// @notice Get the `tokenPrice` for a given token, checks if the price is valid.\n  /// @param token The token to get the price for.\n  /// @return tokenPrice The tokenPrice for the given token if it exists and is valid.\n  function getValidatedTokenPrice(address token) external view returns (uint224);\n\n  /// @notice Get the `tokenPrice` for an array of tokens.\n  /// @param tokens The tokens to get prices for.\n  /// @return tokenPrices The tokenPrices for the given tokens.\n  function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory);\n\n  /// @notice Get an encoded `gasPrice` for a given destination chain ID.\n  /// The 224-bit result encodes necessary gas price components.\n  /// On L1 chains like Ethereum or Avax, the only component is the gas price.\n  /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability.\n  /// On future chains, there could be more or differing price components.\n  /// PriceRegistry does not contain chain-specific logic to parse destination chain price components.\n  /// @param destChainSelector The destination chain to get the price for.\n  /// @return gasPrice The encoded gasPrice for the given destination chain ID.\n  function getDestinationChainGasPrice(\n    uint64 destChainSelector\n  ) external view returns (Internal.TimestampedPackedUint224 memory);\n\n  /// @notice Gets the fee token price and the gas price, both denominated in dollars.\n  /// @param token The source token to get the price for.\n  /// @param destChainSelector The destination chain to get the gas price for.\n  /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit.\n  /// @return gasPrice The price of gas in 1e18 dollars per base unit.\n  function getTokenAndGasPrices(\n    address token,\n    uint64 destChainSelector\n  ) external view returns (uint224 tokenPrice, uint224 gasPrice);\n\n  /// @notice Convert a given token amount to target token amount.\n  /// @param fromToken The given token address.\n  /// @param fromTokenAmount The given token amount.\n  /// @param toToken The target token address.\n  /// @return toTokenAmount The target token amount.\n  function convertTokenAmount(\n    address fromToken,\n    uint256 fromTokenAmount,\n    address toToken\n  ) external view returns (uint256 toTokenAmount);\n}\n"
      },
      "src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Client} from \"../libraries/Client.sol\";\n\n/// @notice Application contracts that intend to receive messages from\n/// the router should implement this interface.\ninterface IAny2EVMMessageReceiver {\n  /// @notice Called by the Router to deliver a message.\n  /// If this reverts, any token transfers also revert. The message\n  /// will move to a FAILED state and become available for manual execution.\n  /// @param message CCIP Message\n  /// @dev Note ensure you check the msg.sender is the OffRampRouter\n  function ccipReceive(Client.Any2EVMMessage calldata message) external;\n}\n"
      },
      "src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IAny2EVMOffRamp {\n  /// @notice Returns the the current nonce for a receiver.\n  /// @param sender The sender address\n  /// @return nonce The nonce value belonging to the sender address.\n  function getSenderNonce(address sender) external view returns (uint64 nonce);\n}\n"
      },
      "src/v0.8/ccip/libraries/Client.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// End consumer library.\nlibrary Client {\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct EVMTokenAmount {\n    address token; // token address on the local chain.\n    uint256 amount; // Amount of tokens.\n  }\n\n  struct Any2EVMMessage {\n    bytes32 messageId; // MessageId corresponding to ccipSend on source.\n    uint64 sourceChainSelector; // Source chain selector.\n    bytes sender; // abi.decode(sender) if coming from an EVM chain.\n    bytes data; // payload sent in original message.\n    EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.\n  }\n\n  // If extraArgs is empty bytes, the default is 200k gas limit.\n  struct EVM2AnyMessage {\n    bytes receiver; // abi.encode(receiver address) for dest EVM chains\n    bytes data; // Data payload\n    EVMTokenAmount[] tokenAmounts; // Token transfers\n    address feeToken; // Address of feeToken. address(0) means you will send msg.value.\n    bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)\n  }\n\n  // bytes4(keccak256(\"CCIP EVMExtraArgsV1\"));\n  bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;\n  struct EVMExtraArgsV1 {\n    uint256 gasLimit;\n  }\n\n  function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {\n    return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);\n  }\n}\n"
      },
      "src/v0.8/ccip/libraries/Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Client} from \"./Client.sol\";\nimport {MerkleMultiProof} from \"../libraries/MerkleMultiProof.sol\";\n\n// Library for CCIP internal definitions common to multiple contracts.\nlibrary Internal {\n  /// @dev The minimum amount of gas to perform the call with exact gas.\n  /// We include this in the offramp so that we can redeploy to adjust it\n  /// should a hardfork change the gas costs of relevant opcodes in callWithExactGas.\n  uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000;\n  // @dev We limit return data to a selector plus 4 words. This is to avoid\n  // malicious contracts from returning large amounts of data and causing\n  // repeated out-of-gas scenarios.\n  uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32;\n\n  /// @notice A collection of token price and gas price updates.\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct PriceUpdates {\n    TokenPriceUpdate[] tokenPriceUpdates;\n    GasPriceUpdate[] gasPriceUpdates;\n  }\n\n  /// @notice Token price in USD.\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct TokenPriceUpdate {\n    address sourceToken; // Source token\n    uint224 usdPerToken; // 1e18 USD per smallest unit of token\n  }\n\n  /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields.\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct GasPriceUpdate {\n    uint64 destChainSelector; // Destination chain selector\n    uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas\n  }\n\n  /// @notice A timestamped uint224 value that can contain several tightly packed fields.\n  struct TimestampedPackedUint224 {\n    uint224 value; // ───────╮ Value in uint224, packed.\n    uint32 timestamp; // ────╯ Timestamp of the most recent price update.\n  }\n\n  /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices.\n  /// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits.\n  /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning.\n  uint8 public constant GAS_PRICE_BITS = 112;\n\n  struct PoolUpdate {\n    address token; // The IERC20 token address\n    address pool; // The token pool address\n  }\n\n  /// @notice Report that is submitted by the execution DON at the execution phase.\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct ExecutionReport {\n    EVM2EVMMessage[] messages;\n    // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token\n    bytes[][] offchainTokenData;\n    bytes32[] proofs;\n    uint256 proofFlagBits;\n  }\n\n  /// @notice The cross chain message that gets committed to EVM chains.\n  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct EVM2EVMMessage {\n    uint64 sourceChainSelector; // ─────────╮ the chain selector of the source chain, note: not chainId\n    address sender; // ─────────────────────╯ sender address on the source chain\n    address receiver; // ───────────────────╮ receiver address on the destination chain\n    uint64 sequenceNumber; // ──────────────╯ sequence number, not unique across lanes\n    uint256 gasLimit; //                      user supplied maximum gas amount available for dest chain execution\n    bool strict; // ────────────────────────╮ DEPRECATED\n    uint64 nonce; //                        │ nonce for this lane for this sender, not unique across senders/lanes\n    address feeToken; // ───────────────────╯ fee token\n    uint256 feeTokenAmount; //                fee token amount\n    bytes data; //                            arbitrary data payload supplied by the message sender\n    Client.EVMTokenAmount[] tokenAmounts; //  array of tokens and amounts to transfer\n    bytes[] sourceTokenData; //               array of token pool return values, one per token\n    bytes32 messageId; //                     a hash of the message data\n  }\n\n  /// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays.\n  /// Each variable array takes 1 more slot to store its length.\n  /// When abi encoded, excluding array contents,\n  /// EVM2EVMMessage takes up a fixed number of 16 lots, 32 bytes each.\n  /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17.\n  uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17;\n\n  /// @dev Each token transfer adds 1 EVMTokenAmount and 1 bytes.\n  /// When abiEncoded, each EVMTokenAmount takes 2 slots, each bytes takes 2 slots, excl bytes contents\n  uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 4;\n\n  function _toAny2EVMMessage(\n    EVM2EVMMessage memory original,\n    Client.EVMTokenAmount[] memory destTokenAmounts\n  ) internal pure returns (Client.Any2EVMMessage memory message) {\n    message = Client.Any2EVMMessage({\n      messageId: original.messageId,\n      sourceChainSelector: original.sourceChainSelector,\n      sender: abi.encode(original.sender),\n      data: original.data,\n      destTokenAmounts: destTokenAmounts\n    });\n  }\n\n  bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256(\"EVM2EVMMessageHashV2\");\n\n  function _hash(EVM2EVMMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) {\n    // Fixed-size message fields are included in nested hash to reduce stack pressure.\n    // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers.\n    return\n      keccak256(\n        abi.encode(\n          MerkleMultiProof.LEAF_DOMAIN_SEPARATOR,\n          metadataHash,\n          keccak256(\n            abi.encode(\n              original.sender,\n              original.receiver,\n              original.sequenceNumber,\n              original.gasLimit,\n              original.strict,\n              original.nonce,\n              original.feeToken,\n              original.feeTokenAmount\n            )\n          ),\n          keccak256(original.data),\n          keccak256(abi.encode(original.tokenAmounts)),\n          keccak256(abi.encode(original.sourceTokenData))\n        )\n      );\n  }\n\n  /// @notice Enum listing the possible message execution states within\n  /// the offRamp contract.\n  /// UNTOUCHED never executed\n  /// IN_PROGRESS currently being executed, used a replay protection\n  /// SUCCESS successfully executed. End state\n  /// FAILURE unsuccessfully executed, manual execution is now enabled.\n  /// @dev RMN depends on this enum, if changing, please notify the RMN maintainers.\n  enum MessageExecutionState {\n    UNTOUCHED,\n    IN_PROGRESS,\n    SUCCESS,\n    FAILURE\n  }\n}\n"
      },
      "src/v0.8/ccip/libraries/RateLimiter.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/// @notice Implements Token Bucket rate limiting.\n/// @dev uint128 is safe for rate limiter state.\n/// For USD value rate limiting, it can adequately store USD value in 18 decimals.\n/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most\n/// a supply of uint128.max tokens, and it will therefore not overflow the bucket.\n/// In exceptional scenarios where tokens consumed may be larger than uint128,\n/// e.g. compromised issuer, an enabled RateLimiter will check and revert.\nlibrary RateLimiter {\n  error BucketOverfilled();\n  error OnlyCallableByAdminOrOwner();\n  error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress);\n  error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress);\n  error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested);\n  error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available);\n\n  event TokensConsumed(uint256 tokens);\n  event ConfigChanged(Config config);\n\n  struct TokenBucket {\n    uint128 tokens; // ──────╮ Current number of tokens that are in the bucket.\n    uint32 lastUpdated; //   │ Timestamp in seconds of the last token refill, good for 100+ years.\n    bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not\n    uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket.\n    uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled.\n  }\n\n  struct Config {\n    bool isEnabled; // Indication whether the rate limiting should be enabled\n    uint128 capacity; // ────╮ Specifies the capacity of the rate limiter\n    uint128 rate; //  ───────╯ Specifies the rate of the rate limiter\n  }\n\n  /// @notice _consume removes the given tokens from the pool, lowering the\n  /// rate tokens allowed to be consumed for subsequent calls.\n  /// @param requestTokens The total tokens to be consumed from the bucket.\n  /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity.\n  /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket\n  /// @dev emits removal of requestTokens if requestTokens is > 0\n  function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal {\n    // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage\n    if (!s_bucket.isEnabled || requestTokens == 0) {\n      return;\n    }\n\n    uint256 tokens = s_bucket.tokens;\n    uint256 capacity = s_bucket.capacity;\n    uint256 timeDiff = block.timestamp - s_bucket.lastUpdated;\n\n    if (timeDiff != 0) {\n      if (tokens > capacity) revert BucketOverfilled();\n\n      // Refill tokens when arriving at a new block time\n      tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate);\n\n      s_bucket.lastUpdated = uint32(block.timestamp);\n    }\n\n    if (capacity < requestTokens) {\n      // Token address 0 indicates consuming aggregate value rate limit capacity.\n      if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens);\n      revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress);\n    }\n    if (tokens < requestTokens) {\n      uint256 rate = s_bucket.rate;\n      // Wait required until the bucket is refilled enough to accept this value, round up to next higher second\n      // Consume is not guaranteed to succeed after wait time passes if there is competing traffic.\n      // This acts as a lower bound of wait time.\n      uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate;\n\n      if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens);\n      revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress);\n    }\n    tokens -= requestTokens;\n\n    // Downcast is safe here, as tokens is not larger than capacity\n    s_bucket.tokens = uint128(tokens);\n    emit TokensConsumed(requestTokens);\n  }\n\n  /// @notice Gets the token bucket with its values for the block it was requested at.\n  /// @return The token bucket.\n  function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) {\n    // We update the bucket to reflect the status at the exact time of the\n    // call. This means we might need to refill a part of the bucket based\n    // on the time that has passed since the last update.\n    bucket.tokens = uint128(\n      _calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)\n    );\n    bucket.lastUpdated = uint32(block.timestamp);\n    return bucket;\n  }\n\n  /// @notice Sets the rate limited config.\n  /// @param s_bucket The token bucket\n  /// @param config The new config\n  function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal {\n    // First update the bucket to make sure the proper rate is used for all the time\n    // up until the config change.\n    uint256 timeDiff = block.timestamp - s_bucket.lastUpdated;\n    if (timeDiff != 0) {\n      s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate));\n\n      s_bucket.lastUpdated = uint32(block.timestamp);\n    }\n\n    s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens));\n    s_bucket.isEnabled = config.isEnabled;\n    s_bucket.capacity = config.capacity;\n    s_bucket.rate = config.rate;\n\n    emit ConfigChanged(config);\n  }\n\n  /// @notice Calculate refilled tokens\n  /// @param capacity bucket capacity\n  /// @param tokens current bucket tokens\n  /// @param timeDiff block time difference since last refill\n  /// @param rate bucket refill rate\n  /// @return the value of tokens after refill\n  function _calculateRefill(\n    uint256 capacity,\n    uint256 tokens,\n    uint256 timeDiff,\n    uint256 rate\n  ) private pure returns (uint256) {\n    return _min(capacity, tokens + timeDiff * rate);\n  }\n\n  /// @notice Return the smallest of two integers\n  /// @param a first int\n  /// @param b second int\n  /// @return smallest\n  function _min(uint256 a, uint256 b) internal pure returns (uint256) {\n    return a < b ? a : b;\n  }\n}\n"
      },
      "src/v0.8/shared/call/CallWithExactGas.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable chainlink-solidity/all-caps-constant-storage-variables\nlibrary CallWithExactGas {\n  error NoContract();\n  error NoGasForCallExactCheck();\n  error NotEnoughGasForCall();\n\n  bytes4 internal constant NoContractSig = 0x0c3b563c;\n  bytes4 internal constant NoGasForCallExactCheckSig = 0xafa32a2c;\n  bytes4 internal constant NotEnoughGasForCallSig = 0x37c3be29;\n\n  /// @notice calls target address with exactly gasAmount gas and payload as calldata.\n  /// Account for gasForCallExactCheck gas that will be used by this function. Will revert\n  /// if the target is not a contact. Will revert when there is not enough gas to call the\n  /// target with gasAmount gas.\n  /// @dev Caps the return data length, which makes it immune to gas bomb attacks.\n  /// @dev Return data cap logic borrowed from\n  /// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol.\n  /// @return success whether the call succeeded\n  /// @return retData the return data from the call, capped at maxReturnBytes bytes\n  /// @return gasUsed the gas used by the external call. Does not include the overhead of this function.\n  function _callWithExactGasSafeReturnData(\n    bytes memory payload,\n    address target,\n    uint256 gasLimit,\n    uint16 gasForCallExactCheck,\n    uint16 maxReturnBytes\n  ) internal returns (bool success, bytes memory retData, uint256 gasUsed) {\n    // allocate retData memory ahead of time\n    retData = new bytes(maxReturnBytes);\n\n    assembly {\n      // solidity calls check that a contract actually exists at the destination, so we do the same\n      // Note we do this check prior to measuring gas so gasForCallExactCheck (our \"cushion\")\n      // doesn't need to account for it.\n      if iszero(extcodesize(target)) {\n        mstore(0, NoContractSig)\n        revert(0, 0x4)\n      }\n\n      let g := gas()\n      // Compute g -= gasForCallExactCheck and check for underflow\n      // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available).\n      // We want to ensure that we revert if gasAmount >  63//64*gas available\n      // as we do not want to provide them with less, however that check itself costs\n      // gas. gasForCallExactCheck ensures we have at least enough gas to be able\n      // to revert if gasAmount >  63//64*gas available.\n      if lt(g, gasForCallExactCheck) {\n        mstore(0, NoGasForCallExactCheckSig)\n        revert(0, 0x4)\n      }\n      g := sub(g, gasForCallExactCheck)\n      // if g - g//64 <= gasAmount, revert. We subtract g//64 because of EIP-150\n      if iszero(gt(sub(g, div(g, 64)), gasLimit)) {\n        mstore(0, NotEnoughGasForCallSig)\n        revert(0, 0x4)\n      }\n\n      // We save the gas before the call so we can calculate how much gas the call used\n      let gasBeforeCall := gas()\n      // call and return whether we succeeded. ignore return data\n      // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength)\n      success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0, 0)\n      gasUsed := sub(gasBeforeCall, gas())\n\n      // limit our copy to maxReturnBytes bytes\n      let toCopy := returndatasize()\n      if gt(toCopy, maxReturnBytes) {\n        toCopy := maxReturnBytes\n      }\n      // Store the length of the copied bytes\n      mstore(retData, toCopy)\n      // copy the bytes from retData[0:_toCopy]\n      returndatacopy(add(retData, 0x20), 0, toCopy)\n    }\n    return (success, retData, gasUsed);\n  }\n}\n"
      },
      "src/v0.8/ccip/ocr/OCR2BaseNoChecks.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {OwnerIsCreator} from \"../../shared/access/OwnerIsCreator.sol\";\nimport {OCR2Abstract} from \"./OCR2Abstract.sol\";\n\n/// @notice Onchain verification of reports from the offchain reporting protocol\n/// @dev For details on its operation, see the offchain reporting protocol design\n/// doc, which refers to this contract as simply the \"contract\".\n/// @dev This contract does ***NOT*** check the supplied signatures on `transmit`\n/// This is intentional.\nabstract contract OCR2BaseNoChecks is OwnerIsCreator, OCR2Abstract {\n  error InvalidConfig(string message);\n  error WrongMessageLength(uint256 expected, uint256 actual);\n  error ConfigDigestMismatch(bytes32 expected, bytes32 actual);\n  error ForkedChain(uint256 expected, uint256 actual);\n  error UnauthorizedTransmitter();\n  error OracleCannotBeZeroAddress();\n\n  // Packing these fields used on the hot path in a ConfigInfo variable reduces the\n  // retrieval of all of them to a minimum number of SLOADs.\n  struct ConfigInfo {\n    bytes32 latestConfigDigest;\n    uint8 f;\n    uint8 n;\n  }\n\n  // Used for s_oracles[a].role, where a is an address, to track the purpose\n  // of the address, or to indicate that the address is unset.\n  enum Role {\n    // No oracle role has been set for address a\n    Unset,\n    // Unused\n    Signer,\n    // Transmission address for the s_oracles[a].index'th oracle. I.e., if a\n    // report is received by OCR2Aggregator.transmit in which msg.sender is\n    // a, it is attributed to the s_oracles[a].index'th oracle.\n    Transmitter\n  }\n\n  struct Oracle {\n    uint8 index; // Index of oracle in s_transmitters\n    Role role; // Role of the address which mapped to this struct\n  }\n\n  // The current config\n  ConfigInfo internal s_configInfo;\n\n  // incremented each time a new config is posted. This count is incorporated\n  // into the config digest, to prevent replay attacks.\n  uint32 internal s_configCount;\n  // makes it easier for offchain systems to extract config from logs.\n  uint32 internal s_latestConfigBlockNumber;\n\n  // Transmitter address\n  mapping(address transmitter => Oracle oracle) internal s_oracles;\n\n  // s_transmitters contains the transmission address of each oracle,\n  // i.e. the address the oracle actually sends transactions to the contract from\n  address[] internal s_transmitters;\n\n  // The constant-length components of the msg.data sent to transmit.\n  // See the \"If we wanted to call sam\" example on for example reasoning\n  // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html\n  uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT =\n    4 + // function selector\n      32 *\n      3 + // 3 words containing reportContext\n      32 + // word containing start location of abiencoded report value\n      32 + // word containing location start of abiencoded rs value\n      32 + // word containing start location of abiencoded ss value\n      32 + // rawVs value\n      32 + // word containing length of report\n      32 + // word containing length rs\n      32; // word containing length of ss\n\n  uint256 internal immutable i_chainID;\n\n  // Reverts transaction if config args are invalid\n  modifier checkConfigValid(uint256 numTransmitters, uint256 f) {\n    if (numTransmitters > MAX_NUM_ORACLES) revert InvalidConfig(\"too many transmitters\");\n    if (f == 0) revert InvalidConfig(\"f must be positive\");\n    _;\n  }\n\n  constructor() {\n    i_chainID = block.chainid;\n  }\n\n  /// @notice sets offchain reporting protocol configuration incl. participating oracles\n  /// @param signers addresses with which oracles sign the reports\n  /// @param transmitters addresses oracles use to transmit the reports\n  /// @param f number of faulty oracles the system can tolerate\n  /// @param onchainConfig encoded on-chain contract configuration\n  /// @param offchainConfigVersion version number for offchainEncoding schema\n  /// @param offchainConfig encoded off-chain oracle configuration\n  function setOCR2Config(\n    address[] memory signers,\n    address[] memory transmitters,\n    uint8 f,\n    bytes memory onchainConfig,\n    uint64 offchainConfigVersion,\n    bytes memory offchainConfig\n  ) external override checkConfigValid(transmitters.length, f) onlyOwner {\n    _beforeSetConfig(onchainConfig);\n    uint256 oldTransmitterLength = s_transmitters.length;\n    for (uint256 i = 0; i < oldTransmitterLength; ++i) {\n      delete s_oracles[s_transmitters[i]];\n    }\n\n    uint256 newTransmitterLength = transmitters.length;\n    for (uint256 i = 0; i < newTransmitterLength; ++i) {\n      address transmitter = transmitters[i];\n      if (s_oracles[transmitter].role != Role.Unset) revert InvalidConfig(\"repeated transmitter address\");\n      if (transmitter == address(0)) revert OracleCannotBeZeroAddress();\n      s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter);\n    }\n\n    s_transmitters = transmitters;\n\n    s_configInfo.f = f;\n    s_configInfo.n = uint8(newTransmitterLength);\n    s_configInfo.latestConfigDigest = _configDigestFromConfigData(\n      block.chainid,\n      address(this),\n      ++s_configCount,\n      signers,\n      transmitters,\n      f,\n      onchainConfig,\n      offchainConfigVersion,\n      offchainConfig\n    );\n\n    uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;\n    s_latestConfigBlockNumber = uint32(block.number);\n\n    emit ConfigSet(\n      previousConfigBlockNumber,\n      s_configInfo.latestConfigDigest,\n      s_configCount,\n      signers,\n      transmitters,\n      f,\n      onchainConfig,\n      offchainConfigVersion,\n      offchainConfig\n    );\n  }\n\n  /// @dev Hook that is run from setOCR2Config() right after validating configuration.\n  /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing\n  function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {}\n\n  /// @return list of addresses permitted to transmit reports to this contract\n  /// @dev The list will match the order used to specify the transmitter during setConfig\n  function getTransmitters() external view returns (address[] memory) {\n    return s_transmitters;\n  }\n\n  /// @notice transmit is called to post a new report to the contract\n  /// @param report serialized report, which the signatures are signing.\n  /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries\n  /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries\n  function transmit(\n    // NOTE: If these parameters are changed, expectedMsgDataLength and/or\n    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly\n    bytes32[3] calldata reportContext,\n    bytes calldata report,\n    bytes32[] calldata rs,\n    bytes32[] calldata ss,\n    bytes32 // signatures\n  ) external override {\n    _report(report);\n\n    // reportContext consists of:\n    // reportContext[0]: ConfigDigest\n    // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round\n    // reportContext[2]: ExtraHash\n    bytes32 configDigest = reportContext[0];\n    bytes32 latestConfigDigest = s_configInfo.latestConfigDigest;\n    if (latestConfigDigest != configDigest) revert ConfigDigestMismatch(latestConfigDigest, configDigest);\n    // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports.\n    // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest\n    // calculated from chain A and so OCR reports will be valid on both forks.\n    if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid);\n\n    emit Transmitted(configDigest, uint32(uint256(reportContext[1]) >> 8));\n\n    // Scoping this reduces stack pressure and gas usage\n    {\n      Oracle memory transmitter = s_oracles[msg.sender];\n      // Check that sender is authorized to report\n      if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index]))\n        revert UnauthorizedTransmitter();\n    }\n\n    uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) +\n      report.length + // one byte pure entry in _report\n      rs.length *\n      32 + // 32 bytes per entry in _rs\n      ss.length *\n      32; // 32 bytes per entry in _ss)\n    if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length);\n  }\n\n  /// @notice information about current offchain reporting protocol configuration\n  /// @return configCount ordinal number of current config, out of all configs applied to this contract so far\n  /// @return blockNumber block at which this config was set\n  /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)\n  function latestConfigDetails()\n    external\n    view\n    override\n    returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest)\n  {\n    return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest);\n  }\n\n  /// @inheritdoc OCR2Abstract\n  function latestConfigDigestAndEpoch()\n    external\n    view\n    virtual\n    override\n    returns (bool scanLogs, bytes32 configDigest, uint32 epoch)\n  {\n    return (true, bytes32(0), uint32(0));\n  }\n\n  function _report(bytes calldata report) internal virtual;\n}\n"
      },
      "src/v0.8/ccip/AggregateRateLimiter.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IPriceRegistry} from \"./interfaces/IPriceRegistry.sol\";\n\nimport {OwnerIsCreator} from \"./../shared/access/OwnerIsCreator.sol\";\nimport {Client} from \"./libraries/Client.sol\";\nimport {RateLimiter} from \"./libraries/RateLimiter.sol\";\nimport {USDPriceWith18Decimals} from \"./libraries/USDPriceWith18Decimals.sol\";\n\n/// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter\n/// which permits rate limiting based on the aggregate value of a group of\n/// token transfers, using a price registry to convert to a numeraire asset (e.g. USD).\ncontract AggregateRateLimiter is OwnerIsCreator {\n  using RateLimiter for RateLimiter.TokenBucket;\n  using USDPriceWith18Decimals for uint224;\n\n  error PriceNotFoundForToken(address token);\n\n  event AdminSet(address newAdmin);\n\n  // The address of the token limit admin that has the same permissions as the owner.\n  address internal s_admin;\n\n  // The token bucket object that contains the bucket state.\n  RateLimiter.TokenBucket private s_rateLimiter;\n\n  /// @param config The RateLimiter.Config containing the capacity and refill rate\n  /// of the bucket, plus the admin address.\n  constructor(RateLimiter.Config memory config) {\n    s_rateLimiter = RateLimiter.TokenBucket({\n      rate: config.rate,\n      capacity: config.capacity,\n      tokens: config.capacity,\n      lastUpdated: uint32(block.timestamp),\n      isEnabled: config.isEnabled\n    });\n  }\n\n  /// @notice Consumes value from the rate limiter bucket based on the\n  /// token value given. First, calculate the prices\n  function _rateLimitValue(Client.EVMTokenAmount[] memory tokenAmounts, IPriceRegistry priceRegistry) internal {\n    uint256 numberOfTokens = tokenAmounts.length;\n\n    uint256 value = 0;\n    for (uint256 i = 0; i < numberOfTokens; ++i) {\n      // not fetching validated price, as price staleness is not important for value-based rate limiting\n      // we only need to verify price is not 0\n      uint224 pricePerToken = priceRegistry.getTokenPrice(tokenAmounts[i].token).value;\n      if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmounts[i].token);\n      value += pricePerToken._calcUSDValueFromTokenAmount(tokenAmounts[i].amount);\n    }\n\n    s_rateLimiter._consume(value, address(0));\n  }\n\n  /// @notice Gets the token bucket with its values for the block it was requested at.\n  /// @return The token bucket.\n  function currentRateLimiterState() external view returns (RateLimiter.TokenBucket memory) {\n    return s_rateLimiter._currentTokenBucketState();\n  }\n\n  /// @notice Sets the rate limited config.\n  /// @param config The new rate limiter config.\n  /// @dev should only be callable by the owner or token limit admin.\n  function setRateLimiterConfig(RateLimiter.Config memory config) external onlyAdminOrOwner {\n    s_rateLimiter._setTokenBucketConfig(config);\n  }\n\n  // ================================================================\n  // │                           Access                             │\n  // ================================================================\n\n  /// @notice Gets the token limit admin address.\n  /// @return the token limit admin address.\n  function getTokenLimitAdmin() external view returns (address) {\n    return s_admin;\n  }\n\n  /// @notice Sets the token limit admin address.\n  /// @param newAdmin the address of the new admin.\n  /// @dev setting this to address(0) indicates there is no active admin.\n  function setAdmin(address newAdmin) external onlyAdminOrOwner {\n    s_admin = newAdmin;\n    emit AdminSet(newAdmin);\n  }\n\n  /// @notice a modifier that allows the owner or the s_tokenLimitAdmin call the functions\n  /// it is applied to.\n  modifier onlyAdminOrOwner() {\n    if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiter.OnlyCallableByAdminOrOwner();\n    _;\n  }\n}\n"
      },
      "src/v0.8/shared/enumerable/EnumerableMapAddresses.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {EnumerableMap} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol\";\n\nlibrary EnumerableMapAddresses {\n  using EnumerableMap for EnumerableMap.UintToAddressMap;\n\n  struct AddressToAddressMap {\n    EnumerableMap.UintToAddressMap _inner;\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) {\n    return map._inner.set(uint256(uint160(key)), value);\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function remove(AddressToAddressMap storage map, address key) internal returns (bool) {\n    return map._inner.remove(uint256(uint160(key)));\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function contains(AddressToAddressMap storage map, address key) internal view returns (bool) {\n    return map._inner.contains(uint256(uint160(key)));\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function length(AddressToAddressMap storage map) internal view returns (uint256) {\n    return map._inner.length();\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) {\n    (uint256 key, address value) = map._inner.at(index);\n    return (address(uint160(key)), value);\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) {\n    return map._inner.tryGet(uint256(uint160(key)));\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function get(AddressToAddressMap storage map, address key) internal view returns (address) {\n    return map._inner.get(uint256(uint160(key)));\n  }\n\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function get(\n    AddressToAddressMap storage map,\n    address key,\n    string memory errorMessage\n  ) internal view returns (address) {\n    return map._inner.get(uint256(uint160(key)), errorMessage);\n  }\n}\n"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n  /**\n   * @dev Emitted when `value` tokens are moved from one account (`from`) to\n   * another (`to`).\n   *\n   * Note that `value` may be zero.\n   */\n  event Transfer(address indexed from, address indexed to, uint256 value);\n\n  /**\n   * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n   * a call to {approve}. `value` is the new allowance.\n   */\n  event Approval(address indexed owner, address indexed spender, uint256 value);\n\n  /**\n   * @dev Returns the amount of tokens in existence.\n   */\n  function totalSupply() external view returns (uint256);\n\n  /**\n   * @dev Returns the amount of tokens owned by `account`.\n   */\n  function balanceOf(address account) external view returns (uint256);\n\n  /**\n   * @dev Moves `amount` tokens from the caller's account to `to`.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transfer(address to, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Returns the remaining number of tokens that `spender` will be\n   * allowed to spend on behalf of `owner` through {transferFrom}. This is\n   * zero by default.\n   *\n   * This value changes when {approve} or {transferFrom} are called.\n   */\n  function allowance(address owner, address spender) external view returns (uint256);\n\n  /**\n   * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * IMPORTANT: Beware that changing an allowance with this method brings the risk\n   * that someone may use both the old and the new allowance by unfortunate\n   * transaction ordering. One possible solution to mitigate this race\n   * condition is to first reduce the spender's allowance to 0 and set the\n   * desired value afterwards:\n   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n   *\n   * Emits an {Approval} event.\n   */\n  function approve(address spender, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Moves `amount` tokens from `from` to `to` using the\n   * allowance mechanism. `amount` is then deducted from the caller's\n   * allowance.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n  /**\n   * @dev Returns true if `account` is a contract.\n   *\n   * [IMPORTANT]\n   * ====\n   * It is unsafe to assume that an address for which this function returns\n   * false is an externally-owned account (EOA) and not a contract.\n   *\n   * Among others, `isContract` will return false for the following\n   * types of addresses:\n   *\n   *  - an externally-owned account\n   *  - a contract in construction\n   *  - an address where a contract will be created\n   *  - an address where a contract lived, but was destroyed\n   * ====\n   *\n   * [IMPORTANT]\n   * ====\n   * You shouldn't rely on `isContract` to protect against flash loan attacks!\n   *\n   * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n   * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n   * constructor.\n   * ====\n   */\n  function isContract(address account) internal view returns (bool) {\n    // This method relies on extcodesize/address.code.length, which returns 0\n    // for contracts in construction, since the code is only stored at the end\n    // of the constructor execution.\n\n    return account.code.length > 0;\n  }\n\n  /**\n   * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n   * `recipient`, forwarding all available gas and reverting on errors.\n   *\n   * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n   * of certain opcodes, possibly making contracts go over the 2300 gas limit\n   * imposed by `transfer`, making them unable to receive funds via\n   * `transfer`. {sendValue} removes this limitation.\n   *\n   * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n   *\n   * IMPORTANT: because control is transferred to `recipient`, care must be\n   * taken to not create reentrancy vulnerabilities. Consider using\n   * {ReentrancyGuard} or the\n   * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n   */\n  function sendValue(address payable recipient, uint256 amount) internal {\n    require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n    (bool success, ) = recipient.call{value: amount}(\"\");\n    require(success, \"Address: unable to send value, recipient may have reverted\");\n  }\n\n  /**\n   * @dev Performs a Solidity function call using a low level `call`. A\n   * plain `call` is an unsafe replacement for a function call: use this\n   * function instead.\n   *\n   * If `target` reverts with a revert reason, it is bubbled up by this\n   * function (like regular Solidity function calls).\n   *\n   * Returns the raw returned data. To convert to the expected return value,\n   * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n   *\n   * Requirements:\n   *\n   * - `target` must be a contract.\n   * - calling `target` with `data` must not revert.\n   *\n   * _Available since v3.1._\n   */\n  function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n    return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n   * `errorMessage` as a fallback revert reason when `target` reverts.\n   *\n   * _Available since v3.1._\n   */\n  function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n    return functionCallWithValue(target, data, 0, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but also transferring `value` wei to `target`.\n   *\n   * Requirements:\n   *\n   * - the calling contract must have an ETH balance of at least `value`.\n   * - the called Solidity function must be `payable`.\n   *\n   * _Available since v3.1._\n   */\n  function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n    return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n   * with `errorMessage` as a fallback revert reason when `target` reverts.\n   *\n   * _Available since v3.1._\n   */\n  function functionCallWithValue(\n    address target,\n    bytes memory data,\n    uint256 value,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    require(address(this).balance >= value, \"Address: insufficient balance for call\");\n    (bool success, bytes memory returndata) = target.call{value: value}(data);\n    return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n    return functionStaticCall(target, data, \"Address: low-level static call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal view returns (bytes memory) {\n    (bool success, bytes memory returndata) = target.staticcall(data);\n    return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but performing a delegate call.\n   *\n   * _Available since v3.4._\n   */\n  function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n    return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n   * but performing a delegate call.\n   *\n   * _Available since v3.4._\n   */\n  function functionDelegateCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    (bool success, bytes memory returndata) = target.delegatecall(data);\n    return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n   * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n   *\n   * _Available since v4.8._\n   */\n  function verifyCallResultFromTarget(\n    address target,\n    bool success,\n    bytes memory returndata,\n    string memory errorMessage\n  ) internal view returns (bytes memory) {\n    if (success) {\n      if (returndata.length == 0) {\n        // only check isContract if the call was successful and the return data is empty\n        // otherwise we already know that it was a contract\n        require(isContract(target), \"Address: call to non-contract\");\n      }\n      return returndata;\n    } else {\n      _revert(returndata, errorMessage);\n    }\n  }\n\n  /**\n   * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n   * revert reason or using the provided one.\n   *\n   * _Available since v4.3._\n   */\n  function verifyCallResult(\n    bool success,\n    bytes memory returndata,\n    string memory errorMessage\n  ) internal pure returns (bytes memory) {\n    if (success) {\n      return returndata;\n    } else {\n      _revert(returndata, errorMessage);\n    }\n  }\n\n  function _revert(bytes memory returndata, string memory errorMessage) private pure {\n    // Look for revert reason and bubble it up if present\n    if (returndata.length > 0) {\n      // The easiest way to bubble the revert reason is using memory via assembly\n      /// @solidity memory-safe-assembly\n      assembly {\n        let returndata_size := mload(returndata)\n        revert(add(32, returndata), returndata_size)\n      }\n    } else {\n      revert(errorMessage);\n    }\n  }\n}\n"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/ERC165Checker.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n  // As per the EIP-165 spec, no interface should ever match 0xffffffff\n  bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n  /**\n    * @dev Returns true if `account` supports the {IERC165} interface.\n    */\n  function supportsERC165(address account) internal view returns (bool) {\n    // Any contract that implements ERC165 must explicitly indicate support of\n    // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n    return\n      supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\n      !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\n  }\n\n  /**\n    * @dev Returns true if `account` supports the interface defined by\n    * `interfaceId`. Support for {IERC165} itself is queried automatically.\n    *\n    * See {IERC165-supportsInterface}.\n    */\n  function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n    // query support of both ERC165 as per the spec and support of _interfaceId\n    return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\n  }\n\n  /**\n    * @dev Returns a boolean array where each value corresponds to the\n    * interfaces passed in and whether they're supported or not. This allows\n    * you to batch check interfaces for a contract where your expectation\n    * is that some interfaces may not be supported.\n    *\n    * See {IERC165-supportsInterface}.\n    *\n    * _Available since v3.4._\n    */\n  function getSupportedInterfaces(\n      address account,\n      bytes4[] memory interfaceIds\n  ) internal view returns (bool[] memory) {\n    // an array of booleans corresponding to interfaceIds and whether they're supported or not\n    bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n    // query support of ERC165 itself\n    if (supportsERC165(account)) {\n      // query support of each interface in interfaceIds\n      for (uint256 i = 0; i < interfaceIds.length; i++) {\n        interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\n      }\n    }\n\n    return interfaceIdsSupported;\n  }\n\n  /**\n    * @dev Returns true if `account` supports all the interfaces defined in\n    * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n    *\n    * Batch-querying can lead to gas savings by skipping repeated checks for\n    * {IERC165} support.\n    *\n    * See {IERC165-supportsInterface}.\n    */\n  function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n    // query support of ERC165 itself\n    if (!supportsERC165(account)) {\n      return false;\n    }\n\n    // query support of each interface in interfaceIds\n    for (uint256 i = 0; i < interfaceIds.length; i++) {\n      if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\n        return false;\n      }\n    }\n\n    // all interfaces supported\n    return true;\n  }\n\n  /**\n    * @notice Query if a contract implements an interface, does not check ERC165 support\n    * @param account The address of the contract to query for support of an interface\n    * @param interfaceId The interface identifier, as specified in ERC-165\n    * @return true if the contract at account indicates support of the interface with\n    * identifier interfaceId, false otherwise\n    * @dev Assumes that account contains a contract that supports ERC165, otherwise\n    * the behavior of this method is undefined. This precondition can be checked\n    * with {supportsERC165}.\n    * Interface identification is specified in ERC-165.\n    */\n  function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\n    // prepare call\n    bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n    // perform static call\n    bool success;\n    uint256 returnSize;\n    uint256 returnValue;\n    assembly {\n      success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n      returnSize := returndatasize()\n      returnValue := mload(0x00)\n    }\n\n    return success && returnSize >= 0x20 && returnValue > 0;\n  }\n}"
      },
      "src/v0.8/ccip/libraries/MerkleMultiProof.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nlibrary MerkleMultiProof {\n  /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage.\n  bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000;\n  /// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preiimage.\n  bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR =\n    0x0000000000000000000000000000000000000000000000000000000000000001;\n\n  uint256 internal constant MAX_NUM_HASHES = 256;\n\n  error InvalidProof();\n  error LeavesCannotBeEmpty();\n\n  /// @notice Computes the root based on provided pre-hashed leaf nodes in\n  /// leaves, internal nodes in proofs, and using proofFlagBits' i-th bit to\n  /// determine if an element of proofs or one of the previously computed leafs\n  /// or internal nodes will be used for the i-th hash.\n  /// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's\n  /// preimage should match LEAF_DOMAIN_SEPARATOR.\n  /// @param proofs The hashes to be used instead of a leaf hash when the proofFlagBits\n  ///  indicates a proof should be used.\n  /// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or\n  ///  a proof needs to be used in a hash operation.\n  /// @dev the maximum number of hash operations it set to 256. Any input that would require\n  ///  more than 256 hashes to get to a root will revert.\n  /// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5\n  ///     totalHashes = 3 + 1 - 1 = 3\n  ///  ** round 1 **\n  ///    proofFlagBits = (5 >> 0) & 1 = true\n  ///    hashes[0] = hashPair(a, b)\n  ///    (leafPos, hashPos, proofPos) = (2, 0, 0);\n  ///\n  ///  ** round 2 **\n  ///    proofFlagBits = (5 >> 1) & 1 = false\n  ///    hashes[1] = hashPair(D, c)\n  ///    (leafPos, hashPos, proofPos) = (3, 0, 1);\n  ///\n  ///  ** round 3 **\n  ///    proofFlagBits = (5 >> 2) & 1 = true\n  ///    hashes[2] = hashPair(hashes[0], hashes[1])\n  ///    (leafPos, hashPos, proofPos) = (3, 2, 1);\n  ///\n  ///    i = 3 and no longer < totalHashes. The algorithm is done\n  ///    return hashes[totalHashes - 1] = hashes[2]; the last hash we computed.\n  // We mark this function as internal to force it to be inlined in contracts\n  // that use it, but semantically it is public.\n  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore\n  function merkleRoot(\n    bytes32[] memory leaves,\n    bytes32[] memory proofs,\n    uint256 proofFlagBits\n  ) internal pure returns (bytes32) {\n    unchecked {\n      uint256 leavesLen = leaves.length;\n      uint256 proofsLen = proofs.length;\n      if (leavesLen == 0) revert LeavesCannotBeEmpty();\n      if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof();\n      uint256 totalHashes = leavesLen + proofsLen - 1;\n      if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof();\n      if (totalHashes == 0) {\n        return leaves[0];\n      }\n      bytes32[] memory hashes = new bytes32[](totalHashes);\n      (uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0);\n\n      for (uint256 i = 0; i < totalHashes; ++i) {\n        // Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash.\n        bytes32 a;\n        if (proofFlagBits & (1 << i) == (1 << i)) {\n          // Use a leaf or a previously computed hash.\n          if (leafPos < leavesLen) {\n            a = leaves[leafPos++];\n          } else {\n            a = hashes[hashPos++];\n          }\n        } else {\n          // Use a supplied proof.\n          a = proofs[proofPos++];\n        }\n\n        // The second part of the hashed pair is never a proof as hashing two proofs would result in a\n        // hash that can already be computed offchain.\n        bytes32 b;\n        if (leafPos < leavesLen) {\n          b = leaves[leafPos++];\n        } else {\n          b = hashes[hashPos++];\n        }\n\n        if (!(hashPos <= i)) revert InvalidProof();\n\n        hashes[i] = _hashPair(a, b);\n      }\n      if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof();\n      // Return the last hash.\n      return hashes[totalHashes - 1];\n    }\n  }\n\n  /// @notice Hashes two bytes32 objects in their given order, prepended by the\n  /// INTERNAL_DOMAIN_SEPARATOR.\n  function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) {\n    return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right));\n  }\n\n  /// @notice Hashes two bytes32 objects. The order is taken into account,\n  /// using the lower value first.\n  function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n    return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a);\n  }\n}\n"
      },
      "src/v0.8/shared/access/OwnerIsCreator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {ConfirmedOwner} from \"./ConfirmedOwner.sol\";\n\n/// @title The OwnerIsCreator contract\n/// @notice A contract with helpers for basic contract ownership.\ncontract OwnerIsCreator is ConfirmedOwner {\n  constructor() ConfirmedOwner(msg.sender) {}\n}\n"
      },
      "src/v0.8/ccip/ocr/OCR2Abstract.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {ITypeAndVersion} from \"../../shared/interfaces/ITypeAndVersion.sol\";\n\nabstract contract OCR2Abstract is ITypeAndVersion {\n  // Maximum number of oracles the offchain reporting protocol is designed for\n  uint256 internal constant MAX_NUM_ORACLES = 31;\n\n  /// @notice triggers a new run of the offchain reporting protocol\n  /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis\n  /// @param configDigest configDigest of this configuration\n  /// @param configCount ordinal number of this config setting among all config settings over the life of this contract\n  /// @param signers ith element is address ith oracle uses to sign a report\n  /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method\n  /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly\n  /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)\n  /// @param offchainConfigVersion version of the serialization format used for \"offchainConfig\" parameter\n  /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract\n  event ConfigSet(\n    uint32 previousConfigBlockNumber,\n    bytes32 configDigest,\n    uint64 configCount,\n    address[] signers,\n    address[] transmitters,\n    uint8 f,\n    bytes onchainConfig,\n    uint64 offchainConfigVersion,\n    bytes offchainConfig\n  );\n\n  /// @notice sets offchain reporting protocol configuration incl. participating oracles\n  /// @param signers addresses with which oracles sign the reports\n  /// @param transmitters addresses oracles use to transmit the reports\n  /// @param f number of faulty oracles the system can tolerate\n  /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)\n  /// @param offchainConfigVersion version number for offchainEncoding schema\n  /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract\n  function setOCR2Config(\n    address[] memory signers,\n    address[] memory transmitters,\n    uint8 f,\n    bytes memory onchainConfig,\n    uint64 offchainConfigVersion,\n    bytes memory offchainConfig\n  ) external virtual;\n\n  /// @notice information about current offchain reporting protocol configuration\n  /// @return configCount ordinal number of current config, out of all configs applied to this contract so far\n  /// @return blockNumber block at which this config was set\n  /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)\n  function latestConfigDetails()\n    external\n    view\n    virtual\n    returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest);\n\n  function _configDigestFromConfigData(\n    uint256 chainId,\n    address contractAddress,\n    uint64 configCount,\n    address[] memory signers,\n    address[] memory transmitters,\n    uint8 f,\n    bytes memory onchainConfig,\n    uint64 offchainConfigVersion,\n    bytes memory offchainConfig\n  ) internal pure returns (bytes32) {\n    uint256 h = uint256(\n      keccak256(\n        abi.encode(\n          chainId,\n          contractAddress,\n          configCount,\n          signers,\n          transmitters,\n          f,\n          onchainConfig,\n          offchainConfigVersion,\n          offchainConfig\n        )\n      )\n    );\n    uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00\n    uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00\n    return bytes32((prefix & prefixMask) | (h & ~prefixMask));\n  }\n\n  /// @notice optionally emitted to indicate the latest configDigest and epoch for\n  /// which a report was successfully transmitted. Alternatively, the contract may\n  /// use latestConfigDigestAndEpoch with scanLogs set to false.\n  event Transmitted(bytes32 configDigest, uint32 epoch);\n\n  /// @notice optionally returns the latest configDigest and epoch for which a\n  /// report was successfully transmitted. Alternatively, the contract may return\n  /// scanLogs set to true and use Transmitted events to provide this information\n  /// to offchain watchers.\n  /// @return scanLogs indicates whether to rely on the configDigest and epoch\n  /// returned or whether to scan logs for the Transmitted event instead.\n  /// @return configDigest\n  /// @return epoch\n  function latestConfigDigestAndEpoch()\n    external\n    view\n    virtual\n    returns (bool scanLogs, bytes32 configDigest, uint32 epoch);\n\n  /// @notice transmit is called to post a new report to the contract\n  /// @param report serialized report, which the signatures are signing.\n  /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries\n  /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries\n  /// @param rawVs ith element is the the V component of the ith signature\n  function transmit(\n    // NOTE: If these parameters are changed, expectedMsgDataLength and/or\n    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly\n    bytes32[3] calldata reportContext,\n    bytes calldata report,\n    bytes32[] calldata rs,\n    bytes32[] calldata ss,\n    bytes32 rawVs // signatures\n  ) external virtual;\n}\n"
      },
      "src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nlibrary USDPriceWith18Decimals {\n  /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount,\n  /// and amount of the smallest token denomination,\n  /// calculates the value in USD with 18 decimals.\n  /// @param tokenPrice The USD price of the token.\n  /// @param tokenAmount Amount of the smallest token denomination.\n  /// @return USD value with 18 decimals.\n  /// @dev this function assumes that no more than 1e59 US dollar worth of token is passed in.\n  /// If more is sent, this function will overflow and revert.\n  /// Since there isn't even close to 1e59 dollars, this is ok for all legit tokens.\n  function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) {\n    /// LINK Example:\n    /// tokenPrice:         8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals\n    /// tokenAmount:        2e18 -> 2 LINK\n    /// result:             8e18 * 2e18 / 1e18 -> 16e18 with 18 decimals = $16\n\n    /// USDC Example:\n    /// tokenPrice:         1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals\n    /// tokenAmount:        5e6  -> 5 USDC\n    /// result:             1e30 * 5e6 / 1e18 -> 5e18 with 18 decimals = $5\n    return (tokenPrice * tokenAmount) / 1e18;\n  }\n\n  /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount,\n  /// and USD value with 18 decimals,\n  /// calculates amount of the smallest token denomination.\n  /// @param tokenPrice The USD price of the token.\n  /// @param usdValue USD value with 18 decimals.\n  /// @return Amount of the smallest token denomination.\n  function _calcTokenAmountFromUSDValue(uint224 tokenPrice, uint256 usdValue) internal pure returns (uint256) {\n    /// LINK Example:\n    /// tokenPrice:          8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals\n    /// usdValue:           16e18 -> $16\n    /// result:             16e18 * 1e18 / 8e18 -> 2e18 = 2 LINK\n\n    /// USDC Example:\n    /// tokenPrice:         1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals\n    /// usdValue:           5e18 -> $5\n    /// result:             5e18 * 1e18 / 1e30 -> 5e6 = 5 USDC\n    return (usdValue * 1e18) / tokenPrice;\n  }\n}\n"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableMap.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.\n\npragma solidity ^0.8.0;\n\nimport \"./EnumerableSet.sol\";\n\n/**\n * @dev Library for managing an enumerable variant of Solidity's\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\n * type.\n *\n * Maps have the following properties:\n *\n * - Entries are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\n *\n *     // Declare a set state variable\n *     EnumerableMap.UintToAddressMap private myMap;\n * }\n * ```\n *\n * The following map types are supported:\n *\n * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0\n * - `address -> uint256` (`AddressToUintMap`) since v4.6.0\n * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0\n * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0\n * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableMap.\n * ====\n */\nlibrary EnumerableMap {\n  using EnumerableSet for EnumerableSet.Bytes32Set;\n\n  // To implement this library for multiple types with as little code\n  // repetition as possible, we write it in terms of a generic Map type with\n  // bytes32 keys and values.\n  // The Map implementation uses private functions, and user-facing\n  // implementations (such as Uint256ToAddressMap) are just wrappers around\n  // the underlying Map.\n  // This means that we can only create new EnumerableMaps for types that fit\n  // in bytes32.\n\n  struct Bytes32ToBytes32Map {\n    // Storage of keys\n    EnumerableSet.Bytes32Set _keys;\n    mapping(bytes32 => bytes32) _values;\n  }\n\n  /**\n   * @dev Adds a key-value pair to a map, or updates the value for an existing\n   * key. O(1).\n   *\n   * Returns true if the key was added to the map, that is if it was not\n   * already present.\n   */\n  function set(\n    Bytes32ToBytes32Map storage map,\n    bytes32 key,\n    bytes32 value\n  ) internal returns (bool) {\n    map._values[key] = value;\n    return map._keys.add(key);\n  }\n\n  /**\n   * @dev Removes a key-value pair from a map. O(1).\n   *\n   * Returns true if the key was removed from the map, that is if it was present.\n   */\n  function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {\n    delete map._values[key];\n    return map._keys.remove(key);\n  }\n\n  /**\n   * @dev Returns true if the key is in the map. O(1).\n   */\n  function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {\n    return map._keys.contains(key);\n  }\n\n  /**\n   * @dev Returns the number of key-value pairs in the map. O(1).\n   */\n  function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {\n    return map._keys.length();\n  }\n\n  /**\n   * @dev Returns the key-value pair stored at position `index` in the map. O(1).\n   *\n   * Note that there are no guarantees on the ordering of entries inside the\n   * array, and it may change when more entries are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {\n    bytes32 key = map._keys.at(index);\n    return (key, map._values[key]);\n  }\n\n  /**\n   * @dev Tries to returns the value associated with `key`. O(1).\n   * Does not revert if `key` is not in the map.\n   */\n  function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {\n    bytes32 value = map._values[key];\n    if (value == bytes32(0)) {\n      return (contains(map, key), bytes32(0));\n    } else {\n      return (true, value);\n    }\n  }\n\n  /**\n   * @dev Returns the value associated with `key`. O(1).\n   *\n   * Requirements:\n   *\n   * - `key` must be in the map.\n   */\n  function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {\n    bytes32 value = map._values[key];\n    require(value != 0 || contains(map, key), \"EnumerableMap: nonexistent key\");\n    return value;\n  }\n\n  /**\n   * @dev Same as {get}, with a custom error message when `key` is not in the map.\n   *\n   * CAUTION: This function is deprecated because it requires allocating memory for the error\n   * message unnecessarily. For custom revert reasons use {tryGet}.\n   */\n  function get(\n    Bytes32ToBytes32Map storage map,\n    bytes32 key,\n    string memory errorMessage\n  ) internal view returns (bytes32) {\n    bytes32 value = map._values[key];\n    require(value != 0 || contains(map, key), errorMessage);\n    return value;\n  }\n\n  // UintToUintMap\n\n  struct UintToUintMap {\n    Bytes32ToBytes32Map _inner;\n  }\n\n  /**\n   * @dev Adds a key-value pair to a map, or updates the value for an existing\n   * key. O(1).\n   *\n   * Returns true if the key was added to the map, that is if it was not\n   * already present.\n   */\n  function set(\n    UintToUintMap storage map,\n    uint256 key,\n    uint256 value\n  ) internal returns (bool) {\n    return set(map._inner, bytes32(key), bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the key was removed from the map, that is if it was present.\n   */\n  function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {\n    return remove(map._inner, bytes32(key));\n  }\n\n  /**\n   * @dev Returns true if the key is in the map. O(1).\n   */\n  function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {\n    return contains(map._inner, bytes32(key));\n  }\n\n  /**\n   * @dev Returns the number of elements in the map. O(1).\n   */\n  function length(UintToUintMap storage map) internal view returns (uint256) {\n    return length(map._inner);\n  }\n\n  /**\n   * @dev Returns the element stored at position `index` in the set. O(1).\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {\n    (bytes32 key, bytes32 value) = at(map._inner, index);\n    return (uint256(key), uint256(value));\n  }\n\n  /**\n   * @dev Tries to returns the value associated with `key`. O(1).\n   * Does not revert if `key` is not in the map.\n   */\n  function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {\n    (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));\n    return (success, uint256(value));\n  }\n\n  /**\n   * @dev Returns the value associated with `key`. O(1).\n   *\n   * Requirements:\n   *\n   * - `key` must be in the map.\n   */\n  function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {\n    return uint256(get(map._inner, bytes32(key)));\n  }\n\n  /**\n   * @dev Same as {get}, with a custom error message when `key` is not in the map.\n   *\n   * CAUTION: This function is deprecated because it requires allocating memory for the error\n   * message unnecessarily. For custom revert reasons use {tryGet}.\n   */\n  function get(\n    UintToUintMap storage map,\n    uint256 key,\n    string memory errorMessage\n  ) internal view returns (uint256) {\n    return uint256(get(map._inner, bytes32(key), errorMessage));\n  }\n\n  // UintToAddressMap\n\n  struct UintToAddressMap {\n    Bytes32ToBytes32Map _inner;\n  }\n\n  /**\n   * @dev Adds a key-value pair to a map, or updates the value for an existing\n   * key. O(1).\n   *\n   * Returns true if the key was added to the map, that is if it was not\n   * already present.\n   */\n  function set(\n    UintToAddressMap storage map,\n    uint256 key,\n    address value\n  ) internal returns (bool) {\n    return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the key was removed from the map, that is if it was present.\n   */\n  function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\n    return remove(map._inner, bytes32(key));\n  }\n\n  /**\n   * @dev Returns true if the key is in the map. O(1).\n   */\n  function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\n    return contains(map._inner, bytes32(key));\n  }\n\n  /**\n   * @dev Returns the number of elements in the map. O(1).\n   */\n  function length(UintToAddressMap storage map) internal view returns (uint256) {\n    return length(map._inner);\n  }\n\n  /**\n   * @dev Returns the element stored at position `index` in the set. O(1).\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\n    (bytes32 key, bytes32 value) = at(map._inner, index);\n    return (uint256(key), address(uint160(uint256(value))));\n  }\n\n  /**\n   * @dev Tries to returns the value associated with `key`. O(1).\n   * Does not revert if `key` is not in the map.\n   */\n  function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\n    (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));\n    return (success, address(uint160(uint256(value))));\n  }\n\n  /**\n   * @dev Returns the value associated with `key`. O(1).\n   *\n   * Requirements:\n   *\n   * - `key` must be in the map.\n   */\n  function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\n    return address(uint160(uint256(get(map._inner, bytes32(key)))));\n  }\n\n  /**\n   * @dev Same as {get}, with a custom error message when `key` is not in the map.\n   *\n   * CAUTION: This function is deprecated because it requires allocating memory for the error\n   * message unnecessarily. For custom revert reasons use {tryGet}.\n   */\n  function get(\n    UintToAddressMap storage map,\n    uint256 key,\n    string memory errorMessage\n  ) internal view returns (address) {\n    return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));\n  }\n\n  // AddressToUintMap\n\n  struct AddressToUintMap {\n    Bytes32ToBytes32Map _inner;\n  }\n\n  /**\n   * @dev Adds a key-value pair to a map, or updates the value for an existing\n   * key. O(1).\n   *\n   * Returns true if the key was added to the map, that is if it was not\n   * already present.\n   */\n  function set(\n    AddressToUintMap storage map,\n    address key,\n    uint256 value\n  ) internal returns (bool) {\n    return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the key was removed from the map, that is if it was present.\n   */\n  function remove(AddressToUintMap storage map, address key) internal returns (bool) {\n    return remove(map._inner, bytes32(uint256(uint160(key))));\n  }\n\n  /**\n   * @dev Returns true if the key is in the map. O(1).\n   */\n  function contains(AddressToUintMap storage map, address key) internal view returns (bool) {\n    return contains(map._inner, bytes32(uint256(uint160(key))));\n  }\n\n  /**\n   * @dev Returns the number of elements in the map. O(1).\n   */\n  function length(AddressToUintMap storage map) internal view returns (uint256) {\n    return length(map._inner);\n  }\n\n  /**\n   * @dev Returns the element stored at position `index` in the set. O(1).\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {\n    (bytes32 key, bytes32 value) = at(map._inner, index);\n    return (address(uint160(uint256(key))), uint256(value));\n  }\n\n  /**\n   * @dev Tries to returns the value associated with `key`. O(1).\n   * Does not revert if `key` is not in the map.\n   */\n  function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {\n    (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));\n    return (success, uint256(value));\n  }\n\n  /**\n   * @dev Returns the value associated with `key`. O(1).\n   *\n   * Requirements:\n   *\n   * - `key` must be in the map.\n   */\n  function get(AddressToUintMap storage map, address key) internal view returns (uint256) {\n    return uint256(get(map._inner, bytes32(uint256(uint160(key)))));\n  }\n\n  /**\n   * @dev Same as {get}, with a custom error message when `key` is not in the map.\n   *\n   * CAUTION: This function is deprecated because it requires allocating memory for the error\n   * message unnecessarily. For custom revert reasons use {tryGet}.\n   */\n  function get(\n    AddressToUintMap storage map,\n    address key,\n    string memory errorMessage\n  ) internal view returns (uint256) {\n    return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));\n  }\n\n  // Bytes32ToUintMap\n\n  struct Bytes32ToUintMap {\n    Bytes32ToBytes32Map _inner;\n  }\n\n  /**\n   * @dev Adds a key-value pair to a map, or updates the value for an existing\n   * key. O(1).\n   *\n   * Returns true if the key was added to the map, that is if it was not\n   * already present.\n   */\n  function set(\n    Bytes32ToUintMap storage map,\n    bytes32 key,\n    uint256 value\n  ) internal returns (bool) {\n    return set(map._inner, key, bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the key was removed from the map, that is if it was present.\n   */\n  function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {\n    return remove(map._inner, key);\n  }\n\n  /**\n   * @dev Returns true if the key is in the map. O(1).\n   */\n  function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {\n    return contains(map._inner, key);\n  }\n\n  /**\n   * @dev Returns the number of elements in the map. O(1).\n   */\n  function length(Bytes32ToUintMap storage map) internal view returns (uint256) {\n    return length(map._inner);\n  }\n\n  /**\n   * @dev Returns the element stored at position `index` in the set. O(1).\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {\n    (bytes32 key, bytes32 value) = at(map._inner, index);\n    return (key, uint256(value));\n  }\n\n  /**\n   * @dev Tries to returns the value associated with `key`. O(1).\n   * Does not revert if `key` is not in the map.\n   */\n  function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {\n    (bool success, bytes32 value) = tryGet(map._inner, key);\n    return (success, uint256(value));\n  }\n\n  /**\n   * @dev Returns the value associated with `key`. O(1).\n   *\n   * Requirements:\n   *\n   * - `key` must be in the map.\n   */\n  function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {\n    return uint256(get(map._inner, key));\n  }\n\n  /**\n   * @dev Same as {get}, with a custom error message when `key` is not in the map.\n   *\n   * CAUTION: This function is deprecated because it requires allocating memory for the error\n   * message unnecessarily. For custom revert reasons use {tryGet}.\n   */\n  function get(\n    Bytes32ToUintMap storage map,\n    bytes32 key,\n    string memory errorMessage\n  ) internal view returns (uint256) {\n    return uint256(get(map._inner, key, errorMessage));\n  }\n}"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}"
      },
      "src/v0.8/shared/access/ConfirmedOwner.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {ConfirmedOwnerWithProposal} from \"./ConfirmedOwnerWithProposal.sol\";\n\n/**\n * @title The ConfirmedOwner contract\n * @notice A contract with helpers for basic contract ownership.\n */\ncontract ConfirmedOwner is ConfirmedOwnerWithProposal {\n  constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}\n}\n"
      },
      "src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n  // To implement this library for multiple types with as little code\n  // repetition as possible, we write it in terms of a generic Set type with\n  // bytes32 values.\n  // The Set implementation uses private functions, and user-facing\n  // implementations (such as AddressSet) are just wrappers around the\n  // underlying Set.\n  // This means that we can only create new EnumerableSets for types that fit\n  // in bytes32.\n\n  struct Set {\n    // Storage of set values\n    bytes32[] _values;\n    // Position of the value in the `values` array, plus 1 because index 0\n    // means a value is not in the set.\n    mapping(bytes32 => uint256) _indexes;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function _add(Set storage set, bytes32 value) private returns (bool) {\n    if (!_contains(set, value)) {\n      set._values.push(value);\n      // The value is stored at length-1, but we add 1 to all indexes\n      // and use 0 as a sentinel value\n      set._indexes[value] = set._values.length;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function _remove(Set storage set, bytes32 value) private returns (bool) {\n    // We read and store the value's index to prevent multiple reads from the same storage slot\n    uint256 valueIndex = set._indexes[value];\n\n    if (valueIndex != 0) {\n      // Equivalent to contains(set, value)\n      // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n      // the array, and then remove the last element (sometimes called as 'swap and pop').\n      // This modifies the order of the array, as noted in {at}.\n\n      uint256 toDeleteIndex = valueIndex - 1;\n      uint256 lastIndex = set._values.length - 1;\n\n      if (lastIndex != toDeleteIndex) {\n        bytes32 lastValue = set._values[lastIndex];\n\n        // Move the last value to the index where the value to delete is\n        set._values[toDeleteIndex] = lastValue;\n        // Update the index for the moved value\n        set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n      }\n\n      // Delete the slot where the moved value was stored\n      set._values.pop();\n\n      // Delete the index for the deleted slot\n      delete set._indexes[value];\n\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function _contains(Set storage set, bytes32 value) private view returns (bool) {\n    return set._indexes[value] != 0;\n  }\n\n  /**\n   * @dev Returns the number of values on the set. O(1).\n   */\n  function _length(Set storage set) private view returns (uint256) {\n    return set._values.length;\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function _at(Set storage set, uint256 index) private view returns (bytes32) {\n    return set._values[index];\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function _values(Set storage set) private view returns (bytes32[] memory) {\n    return set._values;\n  }\n\n  // Bytes32Set\n\n  struct Bytes32Set {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n    return _add(set._inner, value);\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n    return _remove(set._inner, value);\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n    return _contains(set._inner, value);\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(Bytes32Set storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n    return _at(set._inner, index);\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n    bytes32[] memory store = _values(set._inner);\n    bytes32[] memory result;\n\n    /// @solidity memory-safe-assembly\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n\n  // AddressSet\n\n  struct AddressSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(AddressSet storage set, address value) internal returns (bool) {\n    return _add(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(AddressSet storage set, address value) internal returns (bool) {\n    return _remove(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(AddressSet storage set, address value) internal view returns (bool) {\n    return _contains(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(AddressSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(AddressSet storage set, uint256 index) internal view returns (address) {\n    return address(uint160(uint256(_at(set._inner, index))));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(AddressSet storage set) internal view returns (address[] memory) {\n    bytes32[] memory store = _values(set._inner);\n    address[] memory result;\n\n    /// @solidity memory-safe-assembly\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n\n  // UintSet\n\n  struct UintSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(UintSet storage set, uint256 value) internal returns (bool) {\n    return _add(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(UintSet storage set, uint256 value) internal returns (bool) {\n    return _remove(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n    return _contains(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(UintSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n    return uint256(_at(set._inner, index));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(UintSet storage set) internal view returns (uint256[] memory) {\n    bytes32[] memory store = _values(set._inner);\n    uint256[] memory result;\n\n    /// @solidity memory-safe-assembly\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n}\n"
      },
      "src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IOwnable} from \"../interfaces/IOwnable.sol\";\n\n/**\n * @title The ConfirmedOwner contract\n * @notice A contract with helpers for basic contract ownership.\n */\ncontract ConfirmedOwnerWithProposal is IOwnable {\n  address private s_owner;\n  address private s_pendingOwner;\n\n  event OwnershipTransferRequested(address indexed from, address indexed to);\n  event OwnershipTransferred(address indexed from, address indexed to);\n\n  constructor(address newOwner, address pendingOwner) {\n    // solhint-disable-next-line custom-errors\n    require(newOwner != address(0), \"Cannot set owner to zero\");\n\n    s_owner = newOwner;\n    if (pendingOwner != address(0)) {\n      _transferOwnership(pendingOwner);\n    }\n  }\n\n  /**\n   * @notice Allows an owner to begin transferring ownership to a new address,\n   * pending.\n   */\n  function transferOwnership(address to) public override onlyOwner {\n    _transferOwnership(to);\n  }\n\n  /**\n   * @notice Allows an ownership transfer to be completed by the recipient.\n   */\n  function acceptOwnership() external override {\n    // solhint-disable-next-line custom-errors\n    require(msg.sender == s_pendingOwner, \"Must be proposed owner\");\n\n    address oldOwner = s_owner;\n    s_owner = msg.sender;\n    s_pendingOwner = address(0);\n\n    emit OwnershipTransferred(oldOwner, msg.sender);\n  }\n\n  /**\n   * @notice Get the current owner\n   */\n  function owner() public view override returns (address) {\n    return s_owner;\n  }\n\n  /**\n   * @notice validate, transfer ownership, and emit relevant events\n   */\n  function _transferOwnership(address to) private {\n    // solhint-disable-next-line custom-errors\n    require(to != msg.sender, \"Cannot transfer to self\");\n\n    s_pendingOwner = to;\n\n    emit OwnershipTransferRequested(s_owner, to);\n  }\n\n  /**\n   * @notice validate access\n   */\n  function _validateOwnership() internal view {\n    // solhint-disable-next-line custom-errors\n    require(msg.sender == s_owner, \"Only callable by owner\");\n  }\n\n  /**\n   * @notice Reverts if called by anyone other than the contract owner.\n   */\n  modifier onlyOwner() {\n    _validateOwnership();\n    _;\n  }\n}\n"
      },
      "src/v0.8/shared/interfaces/IOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IOwnable {\n  function owner() external returns (address);\n\n  function transferOwnership(address recipient) external;\n\n  function acceptOwnership() external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=foundry-lib/forge-std/lib/ds-test/src/",
        "forge-std/=foundry-lib/forge-std/src/",
        "@openzeppelin/=node_modules/@openzeppelin/",
        "hardhat/=node_modules/hardhat/",
        "@eth-optimism/=node_modules/@eth-optimism/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 26000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {}
    }
  }}