creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {ITypeAndVersion} from \"../../shared/interfaces/ITypeAndVersion.sol\";\nimport {IPool} from \"../interfaces/pools/IPool.sol\";\nimport {IARM} from \"../interfaces/IARM.sol\";\nimport {IPriceRegistry} from \"../interfaces/IPriceRegistry.sol\";\nimport {IEVM2AnyOnRamp} from \"../interfaces/IEVM2AnyOnRamp.sol\";\nimport {IEVM2AnyOnRampClient} from \"../interfaces/IEVM2AnyOnRampClient.sol\";\nimport {ILinkAvailable} from \"../interfaces/automation/ILinkAvailable.sol\";\n\nimport {AggregateRateLimiter} from \"../AggregateRateLimiter.sol\";\nimport {Client} from \"../libraries/Client.sol\";\nimport {Internal} from \"../libraries/Internal.sol\";\nimport {RateLimiter} from \"../libraries/RateLimiter.sol\";\nimport {USDPriceWith18Decimals} from \"../libraries/USDPriceWith18Decimals.sol\";\nimport {EnumerableMapAddresses} from \"../../shared/enumerable/EnumerableMapAddresses.sol\";\n\nimport {SafeERC20} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol\";\nimport {EnumerableMap} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/utils/structs/EnumerableMap.sol\";\n\n/// @notice The onRamp is a contract that handles lane-specific fee logic, NOP payments and\n/// bridgeable token support.\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.\ncontract EVM2EVMOnRamp is IEVM2AnyOnRamp, ILinkAvailable, AggregateRateLimiter, ITypeAndVersion {\n  using SafeERC20 for IERC20;\n  using EnumerableMap for EnumerableMap.AddressToUintMap;\n  using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap;\n  using USDPriceWith18Decimals for uint224;\n\n  error InvalidExtraArgsTag();\n  error OnlyCallableByOwnerOrAdmin();\n  error OnlyCallableByOwnerOrAdminOrNop();\n  error InvalidWithdrawParams();\n  error NoFeesToPay();\n  error NoNopsToPay();\n  error InsufficientBalance();\n  error TooManyNops();\n  error MaxFeeBalanceReached();\n  error MessageTooLarge(uint256 maxSize, uint256 actualSize);\n  error MessageGasLimitTooHigh();\n  error UnsupportedNumberOfTokens();\n  error UnsupportedToken(IERC20 token);\n  error MustBeCalledByRouter();\n  error RouterMustSetOriginalSender();\n  error InvalidTokenPoolConfig();\n  error PoolAlreadyAdded();\n  error PoolDoesNotExist(address token);\n  error TokenPoolMismatch();\n  error InvalidConfig();\n  error InvalidAddress(bytes encodedAddress);\n  error BadARMSignal();\n  error LinkBalanceNotSettled();\n  error InvalidNopAddress(address nop);\n  error NotAFeeToken(address token);\n  error CannotSendZeroTokens();\n  error SourceTokenDataTooLarge(address token);\n  error InvalidChainSelector(uint64 chainSelector);\n\n  event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);\n  event NopPaid(address indexed nop, uint256 amount);\n  event FeeConfigSet(FeeTokenConfigArgs[] feeConfig);\n  event TokenTransferFeeConfigSet(TokenTransferFeeConfigArgs[] transferFeeConfig);\n  /// RMN depends on this event, if changing, please notify the RMN maintainers.\n  event CCIPSendRequested(Internal.EVM2EVMMessage message);\n  event NopsSet(uint256 nopWeightsTotal, NopAndWeight[] nopsAndWeights);\n  event PoolAdded(address token, address pool);\n  event PoolRemoved(address token, address pool);\n\n  /// @dev Struct that contains the static configuration\n  /// RMN depends on this struct, if changing, please notify the RMN maintainers.\n  struct StaticConfig {\n    address linkToken; // ────────╮ Link token address\n    uint64 chainSelector; // ─────╯ Source chainSelector\n    uint64 destChainSelector; // ─╮ Destination chainSelector\n    uint64 defaultTxGasLimit; //  │ Default gas limit for a tx\n    uint96 maxNopFeesJuels; // ───╯ Max nop fee balance onramp can have\n    address prevOnRamp; //          Address of previous-version OnRamp\n    address armProxy; //            Address of ARM proxy\n  }\n\n  /// @dev Struct to contains the dynamic configuration\n  struct DynamicConfig {\n    address router; // ──────────────────────────╮ Router address\n    uint16 maxNumberOfTokensPerMsg; //           │ Maximum number of distinct ERC20 token transferred per message\n    uint32 destGasOverhead; //                   │ Gas charged on top of the gasLimit to cover destination chain costs\n    uint16 destGasPerPayloadByte; //             │ Destination chain gas charged for passing each byte of `data` payload to receiver\n    uint32 destDataAvailabilityOverheadGas; // ──╯ Extra data availability gas charged on top of the message, e.g. for OCR\n    uint16 destGasPerDataAvailabilityByte; // ───╮ Amount of gas to charge per byte of message data that needs availability\n    uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001\n    address priceRegistry; //                    │ Price registry address\n    uint32 maxDataBytes; //                      │ Maximum payload data size in bytes\n    uint32 maxPerMsgGasLimit; // ────────────────╯ Maximum gas limit for messages targeting EVMs\n  }\n\n  /// @dev Struct to hold the execution fee configuration for a fee token\n  struct FeeTokenConfig {\n    uint32 networkFeeUSDCents; // ─────────╮ Flat network fee to charge for messages,  multiples of 0.01 USD\n    uint64 gasMultiplierWeiPerEth; //      │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost.\n    uint64 premiumMultiplierWeiPerEth; //  │ Multiplier for fee-token-specific premiums\n    bool enabled; // ──────────────────────╯ Whether this fee token is enabled\n  }\n\n  /// @dev Struct to hold the fee configuration for a fee token, same as the FeeTokenConfig but with\n  /// token included so that an array of these can be passed in to setFeeTokenConfig to set the mapping\n  struct FeeTokenConfigArgs {\n    address token; // ─────────────────────╮ Token address\n    uint32 networkFeeUSDCents; //          │ Flat network fee to charge for messages,  multiples of 0.01 USD\n    uint64 gasMultiplierWeiPerEth; // ─────╯ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost\n    uint64 premiumMultiplierWeiPerEth; // ─╮ Multiplier for fee-token-specific premiums, 1e18 based\n    bool enabled; // ──────────────────────╯ Whether this fee token is enabled\n  }\n\n  /// @dev Struct to hold the transfer fee configuration for token transfers\n  struct TokenTransferFeeConfig {\n    uint32 minFeeUSDCents; // ────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD\n    uint32 maxFeeUSDCents; //     │ Maximum fee to charge per token transfer, multiples of 0.01 USD\n    uint16 deciBps; //            │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5\n    uint32 destGasOverhead; //    │ Gas charged to execute the token transfer on the destination chain\n    uint32 destBytesOverhead; // ─╯ Extra data availability bytes on top of fixed transfer data, including sourceTokenData and offchainData\n  }\n\n  /// @dev Same as TokenTransferFeeConfig\n  /// token included so that an array of these can be passed in to setTokenTransferFeeConfig\n  struct TokenTransferFeeConfigArgs {\n    address token; // ────────────╮ Token address\n    uint32 minFeeUSDCents; //     │ Minimum fee to charge per token transfer, multiples of 0.01 USD\n    uint32 maxFeeUSDCents; //     │ Maximum fee to charge per token transfer, multiples of 0.01 USD\n    uint16 deciBps; // ───────────╯ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5\n    uint32 destGasOverhead; // ───╮ Gas charged to execute the token transfer on the destination chain\n    uint32 destBytesOverhead; // ─╯ Extra data availability bytes on top of fixed transfer data, including sourceTokenData and offchainData\n  }\n\n  /// @dev Nop address and weight, used to set the nops and their weights\n  struct NopAndWeight {\n    address nop; // ────╮ Address of the node operator\n    uint16 weight; // ──╯ Weight for nop rewards\n  }\n\n  // STATIC CONFIG\n  // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables\n  string public constant override typeAndVersion = \"EVM2EVMOnRamp 1.2.0\";\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 offRamp.\n  bytes32 internal immutable i_metadataHash;\n  /// @dev Default gas limit for a transactions that did not specify\n  /// a gas limit in the extraArgs.\n  uint64 internal immutable i_defaultTxGasLimit;\n  /// @dev Maximum nop fee that can accumulate in this onramp\n  uint96 internal immutable i_maxNopFeesJuels;\n  /// @dev The link token address - known to pay nops for their work\n  address internal immutable i_linkToken;\n  /// @dev The chain ID of the source chain that this contract is deployed to\n  uint64 internal immutable i_chainSelector;\n  /// @dev The chain ID of the destination chain\n  uint64 internal immutable i_destChainSelector;\n  /// @dev The address of previous-version OnRamp for this lane\n  /// Used to be able to provide sequencing continuity during a zero downtime upgrade.\n  address internal immutable i_prevOnRamp;\n  /// @dev The address of the arm proxy\n  address internal immutable i_armProxy;\n  /// @dev the maximum number of nops that can be configured at the same time.\n  /// Used to bound gas for loops over nops.\n  uint256 private constant MAX_NUMBER_OF_NOPS = 64;\n\n  // DYNAMIC CONFIG\n  /// @dev The config for the onRamp\n  DynamicConfig internal s_dynamicConfig;\n  /// @dev (address nop => uint256 weight)\n  EnumerableMap.AddressToUintMap internal s_nops;\n  /// @dev source token => token pool\n  EnumerableMapAddresses.AddressToAddressMap private s_poolsBySourceToken;\n\n  /// @dev The execution fee token config that can be set by the owner or fee admin\n  mapping(address token => FeeTokenConfig feeTokenConfig) internal s_feeTokenConfig;\n  /// @dev The token transfer fee config that can be set by the owner or fee admin\n  mapping(address token => TokenTransferFeeConfig tranferFeeConfig) internal s_tokenTransferFeeConfig;\n\n  // STATE\n  /// @dev The current nonce per sender.\n  /// The offramp has a corresponding s_senderNonce mapping to ensure messages\n  /// are executed in the same order they are sent.\n  mapping(address sender => uint64 nonce) internal s_senderNonce;\n  /// @dev The amount of LINK available to pay NOPS\n  uint96 internal s_nopFeesJuels;\n  /// @dev The combined weight of all NOPs weights\n  uint32 internal s_nopWeightsTotal;\n  /// @dev The last used sequence number. This is zero in the case where no\n  /// messages has been sent yet. 0 is not a valid sequence number for any\n  /// real transaction.\n  uint64 internal s_sequenceNumber;\n\n  constructor(\n    StaticConfig memory staticConfig,\n    DynamicConfig memory dynamicConfig,\n    Internal.PoolUpdate[] memory tokensAndPools,\n    RateLimiter.Config memory rateLimiterConfig,\n    FeeTokenConfigArgs[] memory feeTokenConfigs,\n    TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs,\n    NopAndWeight[] memory nopsAndWeights\n  ) AggregateRateLimiter(rateLimiterConfig) {\n    if (\n      staticConfig.linkToken == address(0) ||\n      staticConfig.chainSelector == 0 ||\n      staticConfig.destChainSelector == 0 ||\n      staticConfig.defaultTxGasLimit == 0 ||\n      staticConfig.armProxy == address(0)\n    ) revert InvalidConfig();\n\n    i_metadataHash = keccak256(\n      abi.encode(\n        Internal.EVM_2_EVM_MESSAGE_HASH,\n        staticConfig.chainSelector,\n        staticConfig.destChainSelector,\n        address(this)\n      )\n    );\n    i_linkToken = staticConfig.linkToken;\n    i_chainSelector = staticConfig.chainSelector;\n    i_destChainSelector = staticConfig.destChainSelector;\n    i_defaultTxGasLimit = staticConfig.defaultTxGasLimit;\n    i_maxNopFeesJuels = staticConfig.maxNopFeesJuels;\n    i_prevOnRamp = staticConfig.prevOnRamp;\n    i_armProxy = staticConfig.armProxy;\n\n    _setDynamicConfig(dynamicConfig);\n    _setFeeTokenConfig(feeTokenConfigs);\n    _setTokenTransferFeeConfig(tokenTransferFeeConfigArgs);\n    _setNops(nopsAndWeights);\n\n    // Set new tokens and pools\n    _applyPoolUpdates(new Internal.PoolUpdate[](0), tokensAndPools);\n  }\n\n  // ================================================================\n  // │                          Messaging                           │\n  // ================================================================\n\n  /// @inheritdoc IEVM2AnyOnRamp\n  function getExpectedNextSequenceNumber() external view returns (uint64) {\n    return s_sequenceNumber + 1;\n  }\n\n  /// @inheritdoc IEVM2AnyOnRamp\n  function getSenderNonce(address sender) external view returns (uint64) {\n    uint256 senderNonce = s_senderNonce[sender];\n\n    if (senderNonce == 0 && i_prevOnRamp != address(0)) {\n      // If OnRamp was upgraded, check if sender has a nonce from the previous OnRamp.\n      return IEVM2AnyOnRamp(i_prevOnRamp).getSenderNonce(sender);\n    }\n    return uint64(senderNonce);\n  }\n\n  /// @inheritdoc IEVM2AnyOnRampClient\n  function forwardFromRouter(\n    uint64 destChainSelector,\n    Client.EVM2AnyMessage calldata message,\n    uint256 feeTokenAmount,\n    address originalSender\n  ) external whenHealthy returns (bytes32) {\n    // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven.\n    if (originalSender == address(0)) revert RouterMustSetOriginalSender();\n    // Router address may be zero intentionally to pause.\n    if (msg.sender != s_dynamicConfig.router) revert MustBeCalledByRouter();\n    if (destChainSelector != i_destChainSelector) revert InvalidChainSelector(destChainSelector);\n\n    // EVM destination addresses should be abi encoded and therefore always 32 bytes long\n    // Not duplicately validated in `getFee`. Invalid address is uncommon, gas cost outweighs UX gain.\n    if (message.receiver.length != 32) revert InvalidAddress(message.receiver);\n    uint256 decodedReceiver = abi.decode(message.receiver, (uint256));\n    // We want to disallow sending to address(0) and to precompiles, which exist on address(1) through address(9).\n    if (decodedReceiver > type(uint160).max || decodedReceiver < 10) revert InvalidAddress(message.receiver);\n\n    uint256 gasLimit = _fromBytes(message.extraArgs).gasLimit;\n    // Validate the message with various checks\n    uint256 numberOfTokens = message.tokenAmounts.length;\n    _validateMessage(message.data.length, gasLimit, numberOfTokens);\n\n    // Only check token value if there are tokens\n    if (numberOfTokens > 0) {\n      for (uint256 i = 0; i < numberOfTokens; ++i) {\n        if (message.tokenAmounts[i].amount == 0) revert CannotSendZeroTokens();\n      }\n      // Rate limit on aggregated token value\n      _rateLimitValue(message.tokenAmounts, IPriceRegistry(s_dynamicConfig.priceRegistry));\n    }\n\n    // Convert feeToken to link if not already in link\n    if (message.feeToken == i_linkToken) {\n      // Since there is only 1b link this is safe\n      s_nopFeesJuels += uint96(feeTokenAmount);\n    } else {\n      // the cast from uint256 to uint96 is considered safe, uint96 can store more than max supply of link token\n      s_nopFeesJuels += uint96(\n        IPriceRegistry(s_dynamicConfig.priceRegistry).convertTokenAmount(message.feeToken, feeTokenAmount, i_linkToken)\n      );\n    }\n    if (s_nopFeesJuels > i_maxNopFeesJuels) revert MaxFeeBalanceReached();\n\n    if (s_senderNonce[originalSender] == 0 && i_prevOnRamp != address(0)) {\n      // If this is first time send for a sender in new OnRamp, check if they have a nonce\n      // from the previous OnRamp and start from there instead of zero.\n      s_senderNonce[originalSender] = IEVM2AnyOnRamp(i_prevOnRamp).getSenderNonce(originalSender);\n    }\n\n    // We need the next available sequence number so we increment before we use the value\n    Internal.EVM2EVMMessage memory newMessage = Internal.EVM2EVMMessage({\n      sourceChainSelector: i_chainSelector,\n      sender: originalSender,\n      receiver: address(uint160(decodedReceiver)),\n      sequenceNumber: ++s_sequenceNumber,\n      gasLimit: gasLimit,\n      strict: false,\n      nonce: ++s_senderNonce[originalSender],\n      feeToken: message.feeToken,\n      feeTokenAmount: feeTokenAmount,\n      data: message.data,\n      tokenAmounts: message.tokenAmounts,\n      sourceTokenData: new bytes[](numberOfTokens), // will be filled in later\n      messageId: \"\"\n    });\n\n    // Lock the tokens as last step. TokenPools may not always be trusted.\n    // There should be no state changes after external call to TokenPools.\n    for (uint256 i = 0; i < numberOfTokens; ++i) {\n      Client.EVMTokenAmount memory tokenAndAmount = message.tokenAmounts[i];\n      bytes memory tokenData = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)).lockOrBurn(\n        originalSender,\n        message.receiver,\n        tokenAndAmount.amount,\n        i_destChainSelector,\n        bytes(\"\") // any future extraArgs component would be added here\n      );\n\n      // Since the DON has to pay for the tokenData to be included on the destination chain, we cap the length of the tokenData.\n      // This prevents gas bomb attacks on the NOPs. We use destBytesOverhead as a proxy to cap the number of bytes we accept.\n      // As destBytesOverhead accounts for tokenData + offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData.\n      // It therefore fully mitigates gas bombs for most tokens, as most tokens don't use offchainData.\n      if (tokenData.length > s_tokenTransferFeeConfig[tokenAndAmount.token].destBytesOverhead)\n        revert SourceTokenDataTooLarge(tokenAndAmount.token);\n\n      newMessage.sourceTokenData[i] = tokenData;\n    }\n\n    // Hash only after the sourceTokenData has been set\n    newMessage.messageId = Internal._hash(newMessage, i_metadataHash);\n\n    // Emit message request\n    // Note this must happen after pools, some tokens (eg USDC) emit events that we\n    // expect to directly precede this event.\n    emit CCIPSendRequested(newMessage);\n    return newMessage.messageId;\n  }\n\n  /// @dev Convert the extra args bytes into a struct\n  /// @param extraArgs The extra args bytes\n  /// @return The extra args struct\n  function _fromBytes(bytes calldata extraArgs) internal view returns (Client.EVMExtraArgsV1 memory) {\n    if (extraArgs.length == 0) {\n      return Client.EVMExtraArgsV1({gasLimit: i_defaultTxGasLimit});\n    }\n    if (bytes4(extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag();\n    // EVMExtraArgsV1 originally included a second boolean (strict) field which we have deprecated entirely.\n    // Clients may still send that version but it will be ignored.\n    return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV1));\n  }\n\n  /// @notice Validate the forwarded message with various checks.\n  /// @dev This function can be called multiple times during a CCIPSend,\n  /// only common user-driven mistakes are validated here to minimize duplicate validation cost.\n  /// @param dataLength The length of the data field of the message.\n  /// @param gasLimit The gasLimit set in message for destination execution.\n  /// @param numberOfTokens The number of tokens to be sent.\n  function _validateMessage(uint256 dataLength, uint256 gasLimit, uint256 numberOfTokens) internal view {\n    // Check that payload is formed correctly\n    uint256 maxDataBytes = uint256(s_dynamicConfig.maxDataBytes);\n    if (dataLength > maxDataBytes) revert MessageTooLarge(maxDataBytes, dataLength);\n    if (gasLimit > uint256(s_dynamicConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh();\n    if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens();\n  }\n\n  // ================================================================\n  // │                           Config                             │\n  // ================================================================\n\n  /// @notice Returns the static onRamp config.\n  /// @dev RMN depends on this function, if changing, please notify the RMN maintainers.\n  /// @return the configuration.\n  function getStaticConfig() external view returns (StaticConfig memory) {\n    return\n      StaticConfig({\n        linkToken: i_linkToken,\n        chainSelector: i_chainSelector,\n        destChainSelector: i_destChainSelector,\n        defaultTxGasLimit: i_defaultTxGasLimit,\n        maxNopFeesJuels: i_maxNopFeesJuels,\n        prevOnRamp: i_prevOnRamp,\n        armProxy: i_armProxy\n      });\n  }\n\n  /// @notice Returns the dynamic onRamp config.\n  /// @return dynamicConfig the configuration.\n  function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) {\n    return s_dynamicConfig;\n  }\n\n  /// @notice Sets the dynamic configuration.\n  /// @param dynamicConfig The configuration.\n  function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner {\n    _setDynamicConfig(dynamicConfig);\n  }\n\n  /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor.\n  function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal {\n    // We permit router to be set to zero as a way to pause the contract.\n    if (dynamicConfig.priceRegistry == address(0)) revert InvalidConfig();\n\n    s_dynamicConfig = dynamicConfig;\n\n    emit ConfigSet(\n      StaticConfig({\n        linkToken: i_linkToken,\n        chainSelector: i_chainSelector,\n        destChainSelector: i_destChainSelector,\n        defaultTxGasLimit: i_defaultTxGasLimit,\n        maxNopFeesJuels: i_maxNopFeesJuels,\n        prevOnRamp: i_prevOnRamp,\n        armProxy: i_armProxy\n      }),\n      dynamicConfig\n    );\n  }\n\n  // ================================================================\n  // │                      Tokens and pools                        │\n  // ================================================================\n\n  /// @inheritdoc IEVM2AnyOnRampClient\n  function getSupportedTokens(uint64 /*destChainSelector*/) external view returns (address[] memory) {\n    address[] memory sourceTokens = new address[](s_poolsBySourceToken.length());\n    for (uint256 i = 0; i < sourceTokens.length; ++i) {\n      (sourceTokens[i], ) = s_poolsBySourceToken.at(i);\n    }\n    return sourceTokens;\n  }\n\n  /// @inheritdoc IEVM2AnyOnRampClient\n  function getPoolBySourceToken(uint64 /*destChainSelector*/, IERC20 sourceToken) public view returns (IPool) {\n    if (!s_poolsBySourceToken.contains(address(sourceToken))) revert UnsupportedToken(sourceToken);\n    return IPool(s_poolsBySourceToken.get(address(sourceToken)));\n  }\n\n  /// @inheritdoc IEVM2AnyOnRamp\n  /// @dev This method can only be called by the owner of the contract.\n  function applyPoolUpdates(\n    Internal.PoolUpdate[] memory removes,\n    Internal.PoolUpdate[] memory adds\n  ) external onlyOwner {\n    _applyPoolUpdates(removes, adds);\n  }\n\n  function _applyPoolUpdates(Internal.PoolUpdate[] memory removes, Internal.PoolUpdate[] memory adds) internal {\n    for (uint256 i = 0; i < removes.length; ++i) {\n      address token = removes[i].token;\n      address pool = removes[i].pool;\n\n      if (!s_poolsBySourceToken.contains(token)) revert PoolDoesNotExist(token);\n      if (s_poolsBySourceToken.get(token) != pool) revert TokenPoolMismatch();\n\n      if (s_poolsBySourceToken.remove(token)) {\n        emit PoolRemoved(token, pool);\n      }\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      if (token != address(IPool(pool).getToken())) revert TokenPoolMismatch();\n\n      if (s_poolsBySourceToken.set(token, pool)) {\n        emit PoolAdded(token, pool);\n      } else {\n        revert PoolAlreadyAdded();\n      }\n    }\n  }\n\n  // ================================================================\n  // │                             Fees                             │\n  // ================================================================\n\n  /// @inheritdoc IEVM2AnyOnRampClient\n  /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does.\n  /// @param destChainSelector The destination chain selector.\n  /// @param message The message to get quote for.\n  /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token.\n  function getFee(\n    uint64 destChainSelector,\n    Client.EVM2AnyMessage calldata message\n  ) external view returns (uint256 feeTokenAmount) {\n    if (destChainSelector != i_destChainSelector) revert InvalidChainSelector(destChainSelector);\n\n    uint256 gasLimit = _fromBytes(message.extraArgs).gasLimit;\n    // Validate the message with various checks\n    _validateMessage(message.data.length, gasLimit, message.tokenAmounts.length);\n\n    FeeTokenConfig memory feeTokenConfig = s_feeTokenConfig[message.feeToken];\n    if (!feeTokenConfig.enabled) revert NotAFeeToken(message.feeToken);\n\n    (uint224 feeTokenPrice, uint224 packedGasPrice) = IPriceRegistry(s_dynamicConfig.priceRegistry)\n      .getTokenAndGasPrices(message.feeToken, destChainSelector);\n    uint112 executionGasPrice = uint112(packedGasPrice);\n\n    // Calculate premiumFee in USD with 18 decimals precision first.\n    // If message-only and no token transfers, a flat network fee is charged.\n    // If there are token transfers, premiumFee is calculated from token transfer fee.\n    // If there are both token transfers and message, premiumFee is only calculated from token transfer fee.\n    uint256 premiumFee = 0;\n    uint32 tokenTransferGas = 0;\n    uint32 tokenTransferBytesOverhead = 0;\n    if (message.tokenAmounts.length > 0) {\n      (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = _getTokenTransferCost(\n        message.feeToken,\n        feeTokenPrice,\n        message.tokenAmounts\n      );\n    } else {\n      // Convert USD cents with 2 decimals to 18 decimals.\n      premiumFee = uint256(feeTokenConfig.networkFeeUSDCents) * 1e16;\n    }\n\n    // Apply a feeToken-specific multiplier with 18 decimals, raising the premiumFee to 36 decimals\n    premiumFee = premiumFee * feeTokenConfig.premiumMultiplierWeiPerEth;\n\n    // Calculate execution gas fee on destination chain in USD with 36 decimals.\n    // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together.\n    // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals.\n    uint256 executionCost = executionGasPrice *\n      ((gasLimit +\n        s_dynamicConfig.destGasOverhead +\n        (message.data.length * s_dynamicConfig.destGasPerPayloadByte) +\n        tokenTransferGas) * feeTokenConfig.gasMultiplierWeiPerEth);\n\n    // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to post\n    // transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs.\n    uint256 dataAvailabilityCost = 0;\n    // Only calculate data availability cost if data availability multiplier is non-zero.\n    // The multiplier should be set to 0 if destination chain does not charge data availability cost.\n    if (s_dynamicConfig.destDataAvailabilityMultiplierBps > 0) {\n      // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price.\n      uint112 dataAvailabilityGasPrice = uint112(packedGasPrice >> Internal.GAS_PRICE_BITS);\n\n      dataAvailabilityCost = _getDataAvailabilityCost(\n        dataAvailabilityGasPrice,\n        message.data.length,\n        message.tokenAmounts.length,\n        tokenTransferBytesOverhead\n      );\n    }\n\n    // Calculate number of fee tokens to charge.\n    // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations.\n    // Result of the division is the number of smallest token denominations.\n    return (premiumFee + executionCost + dataAvailabilityCost) / feeTokenPrice;\n  }\n\n  /// @notice Returns the estimated data availability cost of the message.\n  /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes.\n  /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals.\n  /// @param messageDataLength length of the data field in the message.\n  /// @param numberOfTokens number of distinct token transfers in the message.\n  /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation.\n  /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals.\n  function _getDataAvailabilityCost(\n    uint112 dataAvailabilityGasPrice,\n    uint256 messageDataLength,\n    uint256 numberOfTokens,\n    uint32 tokenTransferBytesOverhead\n  ) internal view returns (uint256 dataAvailabilityCostUSD36Decimal) {\n    // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields.\n    // Fixed message fields do account for the offset and length slot of the dynamic fields.\n    uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES +\n      messageDataLength +\n      (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) +\n      tokenTransferBytesOverhead;\n\n    // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost.\n    // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR.\n    uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * s_dynamicConfig.destGasPerDataAvailabilityByte) +\n      s_dynamicConfig.destDataAvailabilityOverheadGas;\n\n    // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals\n    // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee.\n    return\n      ((dataAvailabilityGas * dataAvailabilityGasPrice) * s_dynamicConfig.destDataAvailabilityMultiplierBps) * 1e14;\n  }\n\n  /// @notice Returns the token transfer cost parameters.\n  /// A basis point fee is calculated from the USD value of each token transfer.\n  /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD].\n  /// Total transfer fee is the sum of each individual token transfer fee.\n  /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere.\n  /// @dev Splitting one token transfer into multiple transfers is discouraged,\n  /// as it will result in a transferFee equal or greater than the same amount aggregated/de-duped.\n  /// @param feeToken address of the feeToken.\n  /// @param feeTokenPrice price of feeToken in USD with 18 decimals.\n  /// @param tokenAmounts token transfers in the message.\n  /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals.\n  /// @return tokenTransferGas total execution gas of the token transfers.\n  /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation.\n  function _getTokenTransferCost(\n    address feeToken,\n    uint224 feeTokenPrice,\n    Client.EVMTokenAmount[] calldata tokenAmounts\n  ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) {\n    uint256 numberOfTokens = tokenAmounts.length;\n\n    for (uint256 i = 0; i < numberOfTokens; ++i) {\n      Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i];\n      TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[tokenAmount.token];\n\n      // Validate if the token is supported, do not calculate fee for unsupported tokens.\n      if (!s_poolsBySourceToken.contains(tokenAmount.token)) revert UnsupportedToken(IERC20(tokenAmount.token));\n\n      uint256 bpsFeeUSDWei = 0;\n      // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token.\n      // Useful for when the PriceRegistry cannot return a valid price for the token.\n      if (transferFeeConfig.deciBps > 0) {\n        uint224 tokenPrice = 0;\n        if (tokenAmount.token != feeToken) {\n          tokenPrice = IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedTokenPrice(tokenAmount.token);\n        } else {\n          tokenPrice = feeTokenPrice;\n        }\n\n        // Calculate token transfer value, then apply fee ratio\n        // ratio represents multiples of 0.1bps, or 1e-5\n        bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5;\n      }\n\n      tokenTransferGas += transferFeeConfig.destGasOverhead;\n      tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead;\n\n      // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD].\n      // Convert USD values with 2 decimals to 18 decimals.\n      uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16;\n      if (bpsFeeUSDWei < minFeeUSDWei) {\n        tokenTransferFeeUSDWei += minFeeUSDWei;\n        continue;\n      }\n\n      uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16;\n      if (bpsFeeUSDWei > maxFeeUSDWei) {\n        tokenTransferFeeUSDWei += maxFeeUSDWei;\n        continue;\n      }\n\n      tokenTransferFeeUSDWei += bpsFeeUSDWei;\n    }\n\n    return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead);\n  }\n\n  /// @notice Gets the fee configuration for a token\n  /// @param token The token to get the fee configuration for\n  /// @return feeTokenConfig FeeTokenConfig struct\n  function getFeeTokenConfig(address token) external view returns (FeeTokenConfig memory feeTokenConfig) {\n    return s_feeTokenConfig[token];\n  }\n\n  /// @notice Sets the fee configuration for a token\n  /// @param feeTokenConfigArgs Array of FeeTokenConfigArgs structs.\n  function setFeeTokenConfig(FeeTokenConfigArgs[] memory feeTokenConfigArgs) external onlyOwnerOrAdmin {\n    _setFeeTokenConfig(feeTokenConfigArgs);\n  }\n\n  /// @dev Set the fee config\n  /// @param feeTokenConfigArgs The fee token configs.\n  function _setFeeTokenConfig(FeeTokenConfigArgs[] memory feeTokenConfigArgs) internal {\n    for (uint256 i = 0; i < feeTokenConfigArgs.length; ++i) {\n      FeeTokenConfigArgs memory configArg = feeTokenConfigArgs[i];\n\n      s_feeTokenConfig[configArg.token] = FeeTokenConfig({\n        networkFeeUSDCents: configArg.networkFeeUSDCents,\n        gasMultiplierWeiPerEth: configArg.gasMultiplierWeiPerEth,\n        premiumMultiplierWeiPerEth: configArg.premiumMultiplierWeiPerEth,\n        enabled: configArg.enabled\n      });\n    }\n    emit FeeConfigSet(feeTokenConfigArgs);\n  }\n\n  /// @notice Gets the transfer fee config for a given token.\n  function getTokenTransferFeeConfig(\n    address token\n  ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) {\n    return s_tokenTransferFeeConfig[token];\n  }\n\n  /// @notice Sets the transfer fee config.\n  /// @dev only callable by the owner or admin.\n  function setTokenTransferFeeConfig(\n    TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs\n  ) external onlyOwnerOrAdmin {\n    _setTokenTransferFeeConfig(tokenTransferFeeConfigArgs);\n  }\n\n  /// @notice internal helper to set the token transfer fee config.\n  function _setTokenTransferFeeConfig(TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs) internal {\n    for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) {\n      TokenTransferFeeConfigArgs memory configArg = tokenTransferFeeConfigArgs[i];\n\n      s_tokenTransferFeeConfig[configArg.token] = TokenTransferFeeConfig({\n        minFeeUSDCents: configArg.minFeeUSDCents,\n        maxFeeUSDCents: configArg.maxFeeUSDCents,\n        deciBps: configArg.deciBps,\n        destGasOverhead: configArg.destGasOverhead,\n        destBytesOverhead: configArg.destBytesOverhead\n      });\n    }\n    emit TokenTransferFeeConfigSet(tokenTransferFeeConfigArgs);\n  }\n\n  // ================================================================\n  // │                         NOP payments                         │\n  // ================================================================\n\n  /// @notice Get the total amount of fees to be paid to the Nops (in LINK)\n  /// @return totalNopFees\n  function getNopFeesJuels() external view returns (uint96) {\n    return s_nopFeesJuels;\n  }\n\n  /// @notice Gets the Nops and their weights\n  /// @return nopsAndWeights Array of NopAndWeight structs\n  /// @return weightsTotal The sum weight of all Nops\n  function getNops() external view returns (NopAndWeight[] memory nopsAndWeights, uint256 weightsTotal) {\n    uint256 length = s_nops.length();\n    nopsAndWeights = new NopAndWeight[](length);\n    for (uint256 i = 0; i < length; ++i) {\n      (address nopAddress, uint256 nopWeight) = s_nops.at(i);\n      nopsAndWeights[i] = NopAndWeight({nop: nopAddress, weight: uint16(nopWeight)});\n    }\n    weightsTotal = s_nopWeightsTotal;\n    return (nopsAndWeights, weightsTotal);\n  }\n\n  /// @notice Sets the Nops and their weights\n  /// @param nopsAndWeights Array of NopAndWeight structs\n  function setNops(NopAndWeight[] calldata nopsAndWeights) external onlyOwnerOrAdmin {\n    _setNops(nopsAndWeights);\n  }\n\n  /// @param nopsAndWeights New set of nops and weights\n  /// @dev Clears existing nops, sets new nops and weights\n  /// @dev We permit fees to accrue before nops are configured, in which case\n  /// they will go to the first set of configured nops.\n  function _setNops(NopAndWeight[] memory nopsAndWeights) internal {\n    uint256 numberOfNops = nopsAndWeights.length;\n    if (numberOfNops > MAX_NUMBER_OF_NOPS) revert TooManyNops();\n\n    // Make sure all nops have been paid before removing nops\n    // We only have to pay when there are nops and there is enough\n    // outstanding NOP balance to trigger a payment.\n    if (s_nopWeightsTotal > 0 && s_nopFeesJuels >= s_nopWeightsTotal) {\n      payNops();\n    }\n\n    // Remove all previous nops, move from end to start to avoid shifting\n    for (uint256 i = s_nops.length(); i > 0; --i) {\n      (address nop, ) = s_nops.at(i - 1);\n      s_nops.remove(nop);\n    }\n\n    // Add new\n    uint32 nopWeightsTotal = 0;\n    // nopWeightsTotal is bounded by the MAX_NUMBER_OF_NOPS and the weight of\n    // a single nop being of type uint16. This ensures nopWeightsTotal will\n    // always fit into the uint32 type.\n    for (uint256 i = 0; i < numberOfNops; ++i) {\n      // Make sure the LINK token is not a nop because the link token doesn't allow\n      // self transfers. If set as nop, payNops would always revert. Since setNops\n      // calls payNops, we can never remove the LINK token as a nop.\n      address nop = nopsAndWeights[i].nop;\n      uint16 weight = nopsAndWeights[i].weight;\n      if (nop == i_linkToken || nop == address(0)) revert InvalidNopAddress(nop);\n      s_nops.set(nop, weight);\n      nopWeightsTotal += weight;\n    }\n    s_nopWeightsTotal = nopWeightsTotal;\n    emit NopsSet(nopWeightsTotal, nopsAndWeights);\n  }\n\n  /// @notice Pays the Node Ops their outstanding balances.\n  /// @dev some balance can remain after payments are done. This is at most the sum\n  /// of the weight of all nops. Since nop weights are uint16s and we can have at\n  /// most MAX_NUMBER_OF_NOPS NOPs, the highest possible value is 2**22 or 0.04 gjuels.\n  function payNops() public onlyOwnerOrAdminOrNop {\n    uint256 weightsTotal = s_nopWeightsTotal;\n    if (weightsTotal == 0) revert NoNopsToPay();\n\n    uint96 totalFeesToPay = s_nopFeesJuels;\n    if (totalFeesToPay < weightsTotal) revert NoFeesToPay();\n    if (_linkLeftAfterNopFees() < 0) revert InsufficientBalance();\n\n    uint96 fundsLeft = totalFeesToPay;\n    uint256 numberOfNops = s_nops.length();\n    for (uint256 i = 0; i < numberOfNops; ++i) {\n      (address nop, uint256 weight) = s_nops.at(i);\n      // amount can never be higher than totalFeesToPay so the cast to uint96 is safe\n      uint96 amount = uint96((totalFeesToPay * weight) / weightsTotal);\n      fundsLeft -= amount;\n      IERC20(i_linkToken).safeTransfer(nop, amount);\n      emit NopPaid(nop, amount);\n    }\n    // Some funds can remain, since this is an incredibly small\n    // amount we consider this OK.\n    s_nopFeesJuels = fundsLeft;\n  }\n\n  /// @notice Allows the owner to withdraw any ERC20 token that is not the fee token\n  /// @param feeToken The token to withdraw\n  /// @param to The address to send the tokens to\n  function withdrawNonLinkFees(address feeToken, address to) external onlyOwnerOrAdmin {\n    if (feeToken == i_linkToken || to == address(0)) revert InvalidWithdrawParams();\n\n    // We require the link balance to be settled before allowing withdrawal\n    // of non-link fees.\n    if (_linkLeftAfterNopFees() < 0) revert LinkBalanceNotSettled();\n\n    IERC20(feeToken).safeTransfer(to, IERC20(feeToken).balanceOf(address(this)));\n  }\n\n  // ================================================================\n  // │                        Link monitoring                       │\n  // ================================================================\n\n  /// @notice Calculate remaining LINK balance after paying nops\n  /// @return balance if nops were to be paid\n  function _linkLeftAfterNopFees() private view returns (int256) {\n    // Since LINK caps at uint96, casting to int256 is safe\n    return int256(IERC20(i_linkToken).balanceOf(address(this))) - int256(uint256(s_nopFeesJuels));\n  }\n\n  /// @notice Allow keeper to monitor funds available for paying nops\n  function linkAvailableForPayment() external view returns (int256) {\n    return _linkLeftAfterNopFees();\n  }\n\n  // ================================================================\n  // │                        Access and ARM                        │\n  // ================================================================\n\n  /// @dev Require that the sender is the owner or the fee admin or a nop\n  modifier onlyOwnerOrAdminOrNop() {\n    if (msg.sender != owner() && msg.sender != s_admin && !s_nops.contains(msg.sender))\n      revert OnlyCallableByOwnerOrAdminOrNop();\n    _;\n  }\n\n  /// @dev Require that the sender is the owner or the fee admin\n  modifier onlyOwnerOrAdmin() {\n    if (msg.sender != owner() && msg.sender != s_admin) revert OnlyCallableByOwnerOrAdmin();\n    _;\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/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/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/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/IEVM2AnyOnRamp.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IEVM2AnyOnRampClient} from \"./IEVM2AnyOnRampClient.sol\";\n\nimport {Internal} from \"../libraries/Internal.sol\";\n\ninterface IEVM2AnyOnRamp is IEVM2AnyOnRampClient {\n  /// @notice Gets the next sequence number to be used in the onRamp\n  /// @return the next sequence number to be used\n  function getExpectedNextSequenceNumber() external view returns (uint64);\n\n  /// @notice Get the next nonce for a given sender\n  /// @param sender The sender to get the nonce for\n  /// @return nonce The next nonce for the sender\n  function getSenderNonce(address sender) external view returns (uint64 nonce);\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(Internal.PoolUpdate[] memory removes, Internal.PoolUpdate[] memory adds) external;\n}\n"
      },
      "src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IPool} from \"./pools/IPool.sol\";\n\nimport {Client} from \"../libraries/Client.sol\";\n\nimport {IERC20} from \"../../vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol\";\n\ninterface IEVM2AnyOnRampClient {\n  /// @notice Get the fee for a given ccip message\n  /// @param destChainSelector The destination chain selector\n  /// @param message The message to calculate the cost for\n  /// @return fee The calculated fee\n  function getFee(uint64 destChainSelector, Client.EVM2AnyMessage calldata message) external view returns (uint256 fee);\n\n  /// @notice Get the pool for a specific token\n  /// @param destChainSelector The destination chain selector\n  /// @param sourceToken The source chain token to get the pool for\n  /// @return pool Token pool\n  function getPoolBySourceToken(uint64 destChainSelector, IERC20 sourceToken) external view returns (IPool);\n\n  /// @notice Gets a list of all supported source chain tokens.\n  /// @param destChainSelector The destination chain selector\n  /// @return tokens The addresses of all tokens that this onRamp supports the given destination chain\n  function getSupportedTokens(uint64 destChainSelector) external view returns (address[] memory tokens);\n\n  /// @notice Send a message to the remote chain\n  /// @dev only callable by the Router\n  /// @dev approve() must have already been called on the token using the this ramp address as the spender.\n  /// @dev if the contract is paused, this function will revert.\n  /// @param destChainSelector The destination chain selector\n  /// @param message Message struct to send\n  /// @param feeTokenAmount Amount of fee tokens for payment\n  /// @param originalSender The original initiator of the CCIP request\n  function forwardFromRouter(\n    uint64 destChainSelector,\n    Client.EVM2AnyMessage memory message,\n    uint256 feeTokenAmount,\n    address originalSender\n  ) external returns (bytes32);\n}\n"
      },
      "src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice Implement this contract so that a keeper-compatible contract can monitor\n/// and fund the implementation contract with LINK if it falls below a defined threshold.\ninterface ILinkAvailable {\n  function linkAvailableForPayment() external view returns (int256 availableBalance);\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/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/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/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/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n  using Address for address;\n\n  function safeTransfer(IERC20 token, address to, uint256 value) internal {\n    _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n  }\n\n  function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n    _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n  }\n\n  /**\n   * @dev Deprecated. This function has issues similar to the ones found in\n   * {IERC20-approve}, and its usage is discouraged.\n   *\n   * Whenever possible, use {safeIncreaseAllowance} and\n   * {safeDecreaseAllowance} instead.\n   */\n  function safeApprove(IERC20 token, address spender, uint256 value) internal {\n    // safeApprove should only be called when setting an initial allowance,\n    // or when resetting it to zero. To increase and decrease it, use\n    // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n    require(\n      (value == 0) || (token.allowance(address(this), spender) == 0),\n      \"SafeERC20: approve from non-zero to non-zero allowance\"\n    );\n    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n  }\n\n  function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n    uint256 newAllowance = token.allowance(address(this), spender) + value;\n    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n  }\n\n  function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n    unchecked {\n      uint256 oldAllowance = token.allowance(address(this), spender);\n      require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n      uint256 newAllowance = oldAllowance - value;\n      _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n  }\n\n  function safePermit(\n    IERC20Permit token,\n    address owner,\n    address spender,\n    uint256 value,\n    uint256 deadline,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n  ) internal {\n    uint256 nonceBefore = token.nonces(owner);\n    token.permit(owner, spender, value, deadline, v, r, s);\n    uint256 nonceAfter = token.nonces(owner);\n    require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n  }\n\n  /**\n   * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n   * on the return value: the return value is optional (but if data is returned, it must not be false).\n   * @param token The token targeted by the call.\n   * @param data The call data (encoded using abi.encode or one of its variants).\n   */\n  function _callOptionalReturn(IERC20 token, bytes memory data) private {\n    // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n    // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n    // the target address contains contract code and also asserts for success in the low-level call.\n\n    bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n    if (returndata.length > 0) {\n      // Return data is optional\n      require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\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/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/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/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/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n  /**\n   * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n   * given ``owner``'s signed approval.\n   *\n   * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n   * ordering also apply here.\n   *\n   * Emits an {Approval} event.\n   *\n   * Requirements:\n   *\n   * - `spender` cannot be the zero address.\n   * - `deadline` must be a timestamp in the future.\n   * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n   * over the EIP712-formatted function arguments.\n   * - the signature must use ``owner``'s current nonce (see {nonces}).\n   *\n   * For more information on the signature format, see the\n   * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n   * section].\n   */\n  function permit(\n    address owner,\n    address spender,\n    uint256 value,\n    uint256 deadline,\n    uint8 v,\n    bytes32 r,\n    bytes32 s\n  ) external;\n\n  /**\n   * @dev Returns the current nonce for `owner`. This value must be\n   * included whenever a signature is generated for {permit}.\n   *\n   * Every successful call to {permit} increases ``owner``'s nonce by one. This\n   * prevents a signature from being used multiple times.\n   */\n  function nonces(address owner) external view returns (uint256);\n\n  /**\n   * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n   */\n  // solhint-disable-next-line func-name-mixedcase\n  function DOMAIN_SEPARATOR() external view returns (bytes32);\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/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/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/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/",
        "@ensdomains/=node_modules/@ensdomains/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {}
    }
  }}