Sepolia Testnet

Contract

0x673354B772141F358827C5607D3e3418b847D765

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Transmit68496182024-10-10 9:52:2428 days ago1728553944IN
0x673354B7...8b847D765
0 ETH0.000261432.06605117
Transmit68487102024-10-10 6:18:0028 days ago1728541080IN
0x673354B7...8b847D765
0 ETH0.000000190.00156257
Transmit67922622024-10-01 5:21:3637 days ago1727760096IN
0x673354B7...8b847D765
0 ETH0.03230844278.15660143
Transmit67922622024-10-01 5:21:3637 days ago1727760096IN
0x673354B7...8b847D765
0 ETH0.03347479268.15660143
Transmit67922062024-10-01 5:08:4837 days ago1727759328IN
0x673354B7...8b847D765
0 ETH0.02028444224.9228966
Transmit67918182024-10-01 3:41:2437 days ago1727754084IN
0x673354B7...8b847D765
0 ETH0.03482501261.25684284
Transmit67918072024-10-01 3:38:2437 days ago1727753904IN
0x673354B7...8b847D765
0 ETH0.0283082199.23151227
Transmit67917992024-10-01 3:36:2437 days ago1727753784IN
0x673354B7...8b847D765
0 ETH0.02219429177.67232701
Transmit67633492024-09-26 13:32:2441 days ago1727357544IN
0x673354B7...8b847D765
0 ETH0.03732326279.82236514
Transmit67633482024-09-26 13:32:1241 days ago1727357532IN
0x673354B7...8b847D765
0 ETH0.03908629293.22490006
Transmit67631412024-09-26 12:40:2442 days ago1727354424IN
0x673354B7...8b847D765
0 ETH0.02260762169.60212821
Transmit67631402024-09-26 12:40:1242 days ago1727354412IN
0x673354B7...8b847D765
0 ETH0.01682546156.78429318
Transmit67627252024-09-26 11:01:4842 days ago1727348508IN
0x673354B7...8b847D765
0 ETH0.02214539166.02987449
Transmit67627242024-09-26 11:01:3642 days ago1727348496IN
0x673354B7...8b847D765
0 ETH0.02327515174.54706439
Transmit67625942024-09-26 10:31:0042 days ago1727346660IN
0x673354B7...8b847D765
0 ETH0.03435698257.65292985
Transmit67625842024-09-26 10:28:3642 days ago1727346516IN
0x673354B7...8b847D765
0 ETH0.0333287249.6494512
Transmit67625592024-09-26 10:22:4842 days ago1727346168IN
0x673354B7...8b847D765
0 ETH0.04263255367.04103983
Transmit67625592024-09-26 10:22:4842 days ago1727346168IN
0x673354B7...8b847D765
0 ETH0.04762284357.04103983
Transmit67625182024-09-26 10:12:1242 days ago1727345532IN
0x673354B7...8b847D765
0 ETH0.0580254435.03176061
Transmit67625142024-09-26 10:11:2442 days ago1727345484IN
0x673354B7...8b847D765
0 ETH0.0414499385.72407179
Transmit67625132024-09-26 10:10:3642 days ago1727345436IN
0x673354B7...8b847D765
0 ETH0.04912122368.50685447
Transmit67624732024-09-26 10:01:2442 days ago1727344884IN
0x673354B7...8b847D765
0 ETH0.04230062394.16890206
Transmit67624642024-09-26 9:59:3642 days ago1727344776IN
0x673354B7...8b847D765
0 ETH0.0422261363.54182262
Transmit67624642024-09-26 9:59:3642 days ago1727344776IN
0x673354B7...8b847D765
0 ETH0.04782302358.54182262
Transmit67624622024-09-26 9:58:3642 days ago1727344716IN
0x673354B7...8b847D765
0 ETH0.05090025381.71568068
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x2541d55F...40280F5E4
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
CommitStore

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 26000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : CommitStore.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;

import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
import {ICommitStore} from "./interfaces/ICommitStore.sol";
import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol";
import {IRMN} from "./interfaces/IRMN.sol";

import {Internal} from "./libraries/Internal.sol";
import {MerkleMultiProof} from "./libraries/MerkleMultiProof.sol";
import {OCR2Base} from "./ocr/OCR2Base.sol";

contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
  error StaleReport();
  error PausedError();
  error InvalidInterval(Interval interval);
  error InvalidRoot();
  error InvalidCommitStoreConfig();
  error CursedByRMN();
  error RootAlreadyCommitted();

  event Paused(address account);
  event Unpaused(address account);
  /// @dev RMN depends on this event, if changing, please notify the RMN maintainers.
  event ReportAccepted(CommitReport report);
  event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig);
  event RootRemoved(bytes32 root);
  event SequenceNumberSet(uint64 oldSeqNum, uint64 newSeqNum);
  event LatestPriceEpochAndRoundSet(uint40 oldEpochAndRound, uint40 newEpochAndRound);

  /// @notice Static commit store config
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  //solhint-disable gas-struct-packing
  struct StaticConfig {
    uint64 chainSelector; // ───────╮  Destination chainSelector
    uint64 sourceChainSelector; // ─╯  Source chainSelector
    address onRamp; // OnRamp address on the source chain
    address rmnProxy; // RMN proxy address
  }

  /// @notice Dynamic commit store config
  struct DynamicConfig {
    address priceRegistry; // Price registry address on the destination chain
  }

  /// @notice a sequenceNumber interval
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct Interval {
    uint64 min; // ───╮ Minimum sequence number, inclusive
    uint64 max; // ───╯ Maximum sequence number, inclusive
  }

  /// @notice Report that is committed by the observing DON at the committing phase
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct CommitReport {
    Internal.PriceUpdates priceUpdates;
    Interval interval;
    bytes32 merkleRoot;
  }

  // STATIC CONFIG
  string public constant override typeAndVersion = "CommitStore 1.5.0";
  // Chain ID of this chain
  uint64 internal immutable i_chainSelector;
  // Chain ID of the source chain
  uint64 internal immutable i_sourceChainSelector;
  // The onRamp address on the source chain
  address internal immutable i_onRamp;
  // The address of the rmn proxy
  address internal immutable i_rmnProxy;

  // DYNAMIC CONFIG
  // The dynamic commitStore config
  DynamicConfig internal s_dynamicConfig;

  // STATE
  // The min sequence number expected for future messages
  uint64 private s_minSeqNr = 1;
  /// @dev The epoch and round of the last report
  uint40 private s_latestPriceEpochAndRound;
  /// @dev Whether this CommitStore is paused or not
  bool private s_paused = false;
  // merkleRoot => timestamp when received
  mapping(bytes32 merkleRoot => uint256 timestamp) private s_roots;

  /// @param staticConfig Containing the static part of the commitStore config
  /// @dev When instantiating OCR2Base we set UNIQUE_REPORTS to false, which means
  /// that we do not require 2f+1 signatures on a report, only f+1 to save gas. 2f+1 is required
  /// only if one must strictly ensure that for a given round there is only one valid report ever generated by
  /// the DON. In our case additional valid reports (i.e. approved by >= f+1 oracles) are not a problem, as they will
  /// will either be ignored (reverted as an invalid interval) or will be accepted as an additional valid price update.
  constructor(StaticConfig memory staticConfig) OCR2Base(false) {
    if (
      staticConfig.onRamp == address(0) || staticConfig.chainSelector == 0 || staticConfig.sourceChainSelector == 0
        || staticConfig.rmnProxy == address(0)
    ) revert InvalidCommitStoreConfig();

    i_chainSelector = staticConfig.chainSelector;
    i_sourceChainSelector = staticConfig.sourceChainSelector;
    i_onRamp = staticConfig.onRamp;
    i_rmnProxy = staticConfig.rmnProxy;
  }

  // ================================================================
  // │                        Verification                          │
  // ================================================================

  /// @notice Returns the next expected sequence number.
  /// @return the next expected sequenceNumber.
  function getExpectedNextSequenceNumber() external view returns (uint64) {
    return s_minSeqNr;
  }

  /// @notice Sets the minimum sequence number.
  /// @param minSeqNr The new minimum sequence number.
  function setMinSeqNr(uint64 minSeqNr) external onlyOwner {
    uint64 oldSeqNum = s_minSeqNr;

    s_minSeqNr = minSeqNr;

    emit SequenceNumberSet(oldSeqNum, minSeqNr);
  }

  /// @notice Returns the epoch and round of the last price update.
  /// @return the latest price epoch and round.
  function getLatestPriceEpochAndRound() external view returns (uint64) {
    return s_latestPriceEpochAndRound;
  }

  /// @notice Sets the latest epoch and round for price update.
  /// @param latestPriceEpochAndRound The new epoch and round for prices.
  function setLatestPriceEpochAndRound(uint40 latestPriceEpochAndRound) external onlyOwner {
    uint40 oldEpochAndRound = s_latestPriceEpochAndRound;

    s_latestPriceEpochAndRound = latestPriceEpochAndRound;

    emit LatestPriceEpochAndRoundSet(oldEpochAndRound, latestPriceEpochAndRound);
  }

  /// @notice Returns the timestamp of a potentially previously committed merkle root.
  /// If the root was never committed 0 will be returned.
  /// @param root The merkle root to check the commit status for.
  /// @return the timestamp of the committed root or zero in the case that it was never
  /// committed.
  function getMerkleRoot(bytes32 root) external view returns (uint256) {
    return s_roots[root];
  }

  /// @notice Returns if a root is blessed or not.
  /// @param root The merkle root to check the blessing status for.
  /// @return whether the root is blessed or not.
  function isBlessed(bytes32 root) public view returns (bool) {
    return IRMN(i_rmnProxy).isBlessed(IRMN.TaggedRoot({commitStore: address(this), root: root}));
  }

  /// @notice Used by the owner in case an invalid sequence of roots has been
  /// posted and needs to be removed. The interval in the report is trusted.
  /// @param rootToReset The roots that will be reset. This function will only
  /// reset roots that are not blessed.
  function resetUnblessedRoots(bytes32[] calldata rootToReset) external onlyOwner {
    for (uint256 i = 0; i < rootToReset.length; ++i) {
      bytes32 root = rootToReset[i];
      if (!isBlessed(root)) {
        delete s_roots[root];
        emit RootRemoved(root);
      }
    }
  }

  /// @inheritdoc ICommitStore
  function verify(
    bytes32[] calldata hashedLeaves,
    bytes32[] calldata proofs,
    uint256 proofFlagBits
  ) external view override whenNotPaused returns (uint256 timestamp) {
    bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits);
    // Only return non-zero if present and blessed.
    if (!isBlessed(root)) {
      return 0;
    }
    return s_roots[root];
  }

  /// @inheritdoc OCR2Base
  /// @dev A commitReport can have two distinct parts (batched together to amortize the cost of checking sigs):
  /// 1. Price updates
  /// 2. A merkle root and sequence number interval
  /// Both have their own, separate, staleness checks, with price updates using the epoch and round
  /// number of the latest price update. The merkle root checks for staleness based on the seqNums.
  /// They need to be separate because a price report for round t+2 might be included before a report
  /// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid
  /// and should not be rejected. When a report with a stale root but valid price updates is submitted,
  /// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges.
  /// If that happens, prices will be updates in later rounds.
  function _report(bytes calldata encodedReport, uint40 epochAndRound) internal override whenNotPaused {
    if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector)))) revert CursedByRMN();

    CommitReport memory report = abi.decode(encodedReport, (CommitReport));

    // Check if the report contains price updates
    if (report.priceUpdates.tokenPriceUpdates.length > 0 || report.priceUpdates.gasPriceUpdates.length > 0) {
      // Check for price staleness based on the epoch and round
      if (s_latestPriceEpochAndRound < epochAndRound) {
        // If prices are not stale, update the latest epoch and round
        s_latestPriceEpochAndRound = epochAndRound;
        // And update the prices in the price registry
        IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(report.priceUpdates);

        // If there is no root, the report only contained fee updated and
        // we return to not revert on the empty root check below.
        if (report.merkleRoot == bytes32(0)) return;
      } else {
        // If prices are stale and the report doesn't contain a root, this report
        // does not have any valid information and we revert.
        // If it does contain a merkle root, continue to the root checking section.
        if (report.merkleRoot == bytes32(0)) revert StaleReport();
      }
    }

    // If we reached this section, the report should contain a valid root
    if (s_minSeqNr != report.interval.min || report.interval.min > report.interval.max) {
      revert InvalidInterval(report.interval);
    }

    if (report.merkleRoot == bytes32(0)) revert InvalidRoot();
    // Disallow duplicate roots as that would reset the timestamp and
    // delay potential manual execution.
    if (s_roots[report.merkleRoot] != 0) revert RootAlreadyCommitted();

    s_minSeqNr = report.interval.max + 1;
    s_roots[report.merkleRoot] = block.timestamp;
    emit ReportAccepted(report);
  }

  // ================================================================
  // │                           Config                             │
  // ================================================================

  /// @notice Returns the static commit store config.
  /// @dev RMN depends on this function, if changing, please notify the RMN maintainers.
  /// @return the configuration.
  function getStaticConfig() external view returns (StaticConfig memory) {
    return StaticConfig({
      chainSelector: i_chainSelector,
      sourceChainSelector: i_sourceChainSelector,
      onRamp: i_onRamp,
      rmnProxy: i_rmnProxy
    });
  }

  /// @notice Returns the dynamic commit store config.
  /// @return the configuration.
  function getDynamicConfig() external view returns (DynamicConfig memory) {
    return s_dynamicConfig;
  }

  /// @notice Sets the dynamic config. This function is called during `setOCR2Config` flow
  function _beforeSetConfig(bytes memory onchainConfig) internal override {
    DynamicConfig memory dynamicConfig = abi.decode(onchainConfig, (DynamicConfig));

    if (dynamicConfig.priceRegistry == address(0)) revert InvalidCommitStoreConfig();

    s_dynamicConfig = dynamicConfig;
    // When the OCR config changes, we reset the price epoch and round
    // since epoch and rounds are scoped per config digest.
    // Note that s_minSeqNr/roots do not need to be reset as the roots persist
    // across reconfigurations and are de-duplicated separately.
    s_latestPriceEpochAndRound = 0;

    emit ConfigSet(
      StaticConfig({
        chainSelector: i_chainSelector,
        sourceChainSelector: i_sourceChainSelector,
        onRamp: i_onRamp,
        rmnProxy: i_rmnProxy
      }),
      dynamicConfig
    );
  }

  // ================================================================
  // │                        Access and RMN                        │
  // ================================================================

  /// @notice Single function to check the status of the commitStore.
  function isUnpausedAndNotCursed() external view returns (bool) {
    return !IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector))) && !s_paused;
  }

  /// @notice Modifier to make a function callable only when the contract is not paused.
  modifier whenNotPaused() {
    if (paused()) revert PausedError();
    _;
  }

  /// @notice Returns true if the contract is paused, and false otherwise.
  function paused() public view returns (bool) {
    return s_paused;
  }

  /// @notice Pause the contract
  /// @dev only callable by the owner
  function pause() external onlyOwner {
    s_paused = true;
    emit Paused(msg.sender);
  }

  /// @notice Unpause the contract
  /// @dev only callable by the owner
  function unpause() external onlyOwner {
    s_paused = false;
    emit Unpaused(msg.sender);
  }
}

File 2 of 14 : ITypeAndVersion.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ITypeAndVersion {
  function typeAndVersion() external pure returns (string memory);
}

File 3 of 14 : ICommitStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ICommitStore {
  /// @notice Returns timestamp of when root was accepted or 0 if verification fails.
  /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves,
  /// proofs and proofFlagBits being used to get the root of the inner tree.
  /// This root is then used as the singular leaf of the outer tree.
  function verify(
    bytes32[] calldata hashedLeaves,
    bytes32[] calldata proofs,
    uint256 proofFlagBits
  ) external view returns (uint256 timestamp);

  /// @notice Returns the expected next sequence number
  function getExpectedNextSequenceNumber() external view returns (uint64 sequenceNumber);
}

File 4 of 14 : IPriceRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Client} from "../libraries/Client.sol";
import {Internal} from "../libraries/Internal.sol";

interface IPriceRegistry {
  /// @notice Token price data feed configuration
  struct TokenPriceFeedConfig {
    address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset)
    uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents
  }

  /// @notice Update the price for given tokens and gas prices for given chains.
  /// @param priceUpdates The price updates to apply.
  function updatePrices(Internal.PriceUpdates memory priceUpdates) external;

  /// @notice Get the `tokenPrice` for a given token.
  /// @param token The token to get the price for.
  /// @return tokenPrice The tokenPrice for the given token.
  function getTokenPrice(address token) external view returns (Internal.TimestampedPackedUint224 memory);

  /// @notice Get the `tokenPrice` for a given token, checks if the price is valid.
  /// @param token The token to get the price for.
  /// @return tokenPrice The tokenPrice for the given token if it exists and is valid.
  function getValidatedTokenPrice(address token) external view returns (uint224);

  /// @notice Get the `tokenPrice` for an array of tokens.
  /// @param tokens The tokens to get prices for.
  /// @return tokenPrices The tokenPrices for the given tokens.
  function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory);

  /// @notice Returns the token price data feed configuration
  /// @param token The token to retrieve the feed config for
  /// @return dataFeedAddress The token price data feed config (if feed address is 0, the feed config is disabled)
  function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory);

  /// @notice Get an encoded `gasPrice` for a given destination chain ID.
  /// The 224-bit result encodes necessary gas price components.
  /// On L1 chains like Ethereum or Avax, the only component is the gas price.
  /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability.
  /// On future chains, there could be more or differing price components.
  /// PriceRegistry does not contain chain-specific logic to parse destination chain price components.
  /// @param destChainSelector The destination chain to get the price for.
  /// @return gasPrice The encoded gasPrice for the given destination chain ID.
  function getDestinationChainGasPrice(uint64 destChainSelector)
    external
    view
    returns (Internal.TimestampedPackedUint224 memory);

  /// @notice Gets the fee token price and the gas price, both denominated in dollars.
  /// @param token The source token to get the price for.
  /// @param destChainSelector The destination chain to get the gas price for.
  /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit.
  /// @return gasPrice The price of gas in 1e18 dollars per base unit.
  function getTokenAndGasPrices(
    address token,
    uint64 destChainSelector
  ) external view returns (uint224 tokenPrice, uint224 gasPrice);

  /// @notice Convert a given token amount to target token amount.
  /// @param fromToken The given token address.
  /// @param fromTokenAmount The given token amount.
  /// @param toToken The target token address.
  /// @return toTokenAmount The target token amount.
  function convertTokenAmount(
    address fromToken,
    uint256 fromTokenAmount,
    address toToken
  ) external view returns (uint256 toTokenAmount);

  /// @notice Get the list of fee tokens.
  /// @return The tokens set as fee tokens.
  function getFeeTokens() external view returns (address[] memory);

  /// @notice Validates the ccip message & returns the fee
  /// @param destChainSelector The destination chain selector.
  /// @param message The message to get quote for.
  /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token.
  function getValidatedFee(
    uint64 destChainSelector,
    Client.EVM2AnyMessage calldata message
  ) external view returns (uint256 feeTokenAmount);

  /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels
  /// @param destChainSelector destination chain selector to process
  /// @param feeToken Fee token address used to pay for message fees
  /// @param feeTokenAmount Fee token amount
  /// @param extraArgs Message extra args that were passed in by the client
  /// @return msgFeeJuels message fee in juels
  /// @return isOutOfOrderExecution true if the message should be executed out of order
  /// @return convertedExtraArgs extra args converted to the latest family-specific args version
  function processMessageArgs(
    uint64 destChainSelector,
    address feeToken,
    uint256 feeTokenAmount,
    bytes memory extraArgs
  ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs);

  /// @notice Validates pool return data
  /// @param destChainSelector Destination chain selector to which the token amounts are sent to
  /// @param rampTokenAmounts Token amounts with populated pool return data
  /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message
  function validatePoolReturnData(
    uint64 destChainSelector,
    Internal.RampTokenAmount[] calldata rampTokenAmounts,
    Client.EVMTokenAmount[] calldata sourceTokenAmounts
  ) external view;
}

File 5 of 14 : IRMN.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts.
interface IRMN {
  /// @notice A Merkle root tagged with the address of the commit store contract it is destined for.
  struct TaggedRoot {
    address commitStore;
    bytes32 root;
  }

  /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed.
  function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool);

  /// @notice Iff there is an active global or legacy curse, this function returns true.
  function isCursed() external view returns (bool);

  /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true.
  /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)).
  function isCursed(bytes16 subject) external view returns (bool);
}

File 6 of 14 : Internal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol";
import {Client} from "./Client.sol";

// Library for CCIP internal definitions common to multiple contracts.
library Internal {
  error InvalidEVMAddress(bytes encodedAddress);

  /// @dev The minimum amount of gas to perform the call with exact gas.
  /// We include this in the offramp so that we can redeploy to adjust it
  /// should a hardfork change the gas costs of relevant opcodes in callWithExactGas.
  uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000;
  // @dev We limit return data to a selector plus 4 words. This is to avoid
  // malicious contracts from returning large amounts of data and causing
  // repeated out-of-gas scenarios.
  uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32;
  /// @dev The expected number of bytes returned by the balanceOf function.
  uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32;

  /// @notice A collection of token price and gas price updates.
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct PriceUpdates {
    TokenPriceUpdate[] tokenPriceUpdates;
    GasPriceUpdate[] gasPriceUpdates;
  }

  /// @notice Token price in USD.
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct TokenPriceUpdate {
    address sourceToken; // Source token
    uint224 usdPerToken; // 1e18 USD per 1e18 of the smallest token denomination.
  }

  /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields.
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct GasPriceUpdate {
    uint64 destChainSelector; // Destination chain selector
    uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas
  }

  /// @notice A timestamped uint224 value that can contain several tightly packed fields.
  struct TimestampedPackedUint224 {
    uint224 value; // ───────╮ Value in uint224, packed.
    uint32 timestamp; // ────╯ Timestamp of the most recent price update.
  }

  /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices.
  /// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits.
  /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning.
  uint8 public constant GAS_PRICE_BITS = 112;

  struct PoolUpdate {
    address token; // The IERC20 token address
    address pool; // The token pool address
  }

  struct SourceTokenData {
    // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be
    // relied upon by the destination pool to validate the source pool.
    bytes sourcePoolAddress;
    // The address of the destination token, abi encoded in the case of EVM chains
    // This value is UNTRUSTED as any pool owner can return whatever value they want.
    bytes destTokenAddress;
    // Optional pool data to be transferred to the destination chain. Be default this is capped at
    // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead
    // has to be set for the specific token.
    bytes extraData;
    uint32 destGasAmount; // The amount of gas available for the releaseOrMint and transfer calls on the offRamp
  }

  /// @notice Report that is submitted by the execution DON at the execution phase. (including chain selector data)
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct ExecutionReportSingleChain {
    uint64 sourceChainSelector; // Source chain selector for which the report is submitted
    Any2EVMRampMessage[] messages;
    // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token
    bytes[][] offchainTokenData;
    bytes32[] proofs;
    uint256 proofFlagBits;
  }

  /// @notice Report that is submitted by the execution DON at the execution phase.
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct ExecutionReport {
    EVM2EVMMessage[] messages;
    // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token
    bytes[][] offchainTokenData;
    bytes32[] proofs;
    uint256 proofFlagBits;
  }

  /// @notice The cross chain message that gets committed to EVM chains.
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct EVM2EVMMessage {
    uint64 sourceChainSelector; // ────────╮ the chain selector of the source chain, note: not chainId
    address sender; // ────────────────────╯ sender address on the source chain
    address receiver; // ──────────────────╮ receiver address on the destination chain
    uint64 sequenceNumber; // ─────────────╯ sequence number, not unique across lanes
    uint256 gasLimit; //                     user supplied maximum gas amount available for dest chain execution
    bool strict; // ───────────────────────╮ DEPRECATED
    uint64 nonce; //                       │ nonce for this lane for this sender, not unique across senders/lanes
    address feeToken; // ──────────────────╯ fee token
    uint256 feeTokenAmount; //               fee token amount
    bytes data; //                           arbitrary data payload supplied by the message sender
    Client.EVMTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer
    bytes[] sourceTokenData; //              array of token data, one per token
    bytes32 messageId; //                    a hash of the message data
  }

  /// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays.
  /// Each variable array takes 1 more slot to store its length.
  /// When abi encoded, excluding array contents,
  /// EVM2EVMMessage takes up a fixed number of 16 lots, 32 bytes each.
  /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17.
  uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17;

  /// @dev Each token transfer adds 1 EVMTokenAmount and 3 bytes at 3 slots each and one slot for the destGasAmount.
  /// When abi encoded, each EVMTokenAmount takes 2 slots, each bytes takes 1 slot for length, one slot of data and one
  /// slot for the offset. This results in effectively 3*3 slots per SourceTokenData.
  /// 0x20
  /// destGasAmount
  /// sourcePoolAddress_offset
  /// destTokenAddress_offset
  /// extraData_offset
  /// sourcePoolAddress_length
  /// sourcePoolAddress_content // assume 1 slot
  /// destTokenAddress_length
  /// destTokenAddress_content // assume 1 slot
  /// extraData_length // contents billed separately
  uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((1 + 3 * 3) + 2);

  /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts).
  /// Each variable array takes 1 more slot to store its length.
  /// When abi encoded, excluding array contents,
  /// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each.
  /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14.
  /// The fixed bytes does not cover struct data (this is represented by ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN)
  uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES = 32 * 14;

  /// @dev Each token transfer adds 1 RampTokenAmount
  /// RampTokenAmount has 4 fields, including 3 bytes.
  /// Each bytes takes 1 more slot to store its length, and one slot to store the offset.
  /// When abi encoded, each token transfer takes up 10 slots, excl bytes contents.
  uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 10;

  bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2");

  /// @dev Used to hash messages for single-lane ramps.
  /// OnRamp hash(EVM2EVMMessage) = OffRamp hash(EVM2EVMMessage)
  /// The EVM2EVMMessage's messageId is expected to be the output of this hash function
  /// @param original Message to hash
  /// @param metadataHash Immutable metadata hash representing a lane with a fixed OnRamp
  /// @return hashedMessage hashed message as a keccak256
  function _hash(EVM2EVMMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) {
    // Fixed-size message fields are included in nested hash to reduce stack pressure.
    // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers.
    return keccak256(
      abi.encode(
        MerkleMultiProof.LEAF_DOMAIN_SEPARATOR,
        metadataHash,
        keccak256(
          abi.encode(
            original.sender,
            original.receiver,
            original.sequenceNumber,
            original.gasLimit,
            original.strict,
            original.nonce,
            original.feeToken,
            original.feeTokenAmount
          )
        ),
        keccak256(original.data),
        keccak256(abi.encode(original.tokenAmounts)),
        keccak256(abi.encode(original.sourceTokenData))
      )
    );
  }

  bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1");
  bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1");

  /// @dev Used to hash messages for multi-lane family-agnostic OffRamps.
  /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId
  /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage)
  /// @param original OffRamp message to hash
  /// @param onRamp OnRamp to hash the message with - used to compute the metadataHash
  /// @return hashedMessage hashed message as a keccak256
  function _hash(Any2EVMRampMessage memory original, bytes memory onRamp) internal pure returns (bytes32) {
    // Fixed-size message fields are included in nested hash to reduce stack pressure.
    // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers.
    return keccak256(
      abi.encode(
        MerkleMultiProof.LEAF_DOMAIN_SEPARATOR,
        // Implicit metadata hash
        keccak256(
          abi.encode(
            ANY_2_EVM_MESSAGE_HASH, original.header.sourceChainSelector, original.header.destChainSelector, onRamp
          )
        ),
        keccak256(
          abi.encode(
            original.header.messageId,
            original.sender,
            original.receiver,
            original.header.sequenceNumber,
            original.gasLimit,
            original.header.nonce
          )
        ),
        keccak256(original.data),
        keccak256(abi.encode(original.tokenAmounts))
      )
    );
  }

  function _hash(EVM2AnyRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) {
    // Fixed-size message fields are included in nested hash to reduce stack pressure.
    // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers.
    return keccak256(
      abi.encode(
        MerkleMultiProof.LEAF_DOMAIN_SEPARATOR,
        metadataHash,
        keccak256(
          abi.encode(
            original.sender,
            original.receiver,
            original.header.sequenceNumber,
            original.header.nonce,
            original.feeToken,
            original.feeTokenAmount
          )
        ),
        keccak256(original.data),
        keccak256(abi.encode(original.tokenAmounts)),
        keccak256(original.extraArgs)
      )
    );
  }

  /// @dev We disallow the first 1024 addresses to avoid calling into a range known for hosting precompiles. Calling
  /// into precompiles probably won't cause any issues, but to be safe we can disallow this range. It is extremely
  /// unlikely that anyone would ever be able to generate an address in this range. There is no official range of
  /// precompiles, but EIP-7587 proposes to reserve the range 0x100 to 0x1ff. Our range is more conservative, even
  /// though it might not be exhaustive for all chains, which is OK. We also disallow the zero address, which is a
  /// common practice.
  uint256 public constant PRECOMPILE_SPACE = 1024;

  /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the
  /// address is within the EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which
  /// we can catch and handle more gracefully than a revert from abi.decode.
  /// @return The address if it is valid, the function will revert otherwise.
  function _validateEVMAddress(bytes memory encodedAddress) internal pure returns (address) {
    if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress);
    uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256));
    if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) {
      revert InvalidEVMAddress(encodedAddress);
    }
    return address(uint160(encodedAddressUint));
  }

  /// @notice Enum listing the possible message execution states within
  /// the offRamp contract.
  /// UNTOUCHED never executed
  /// IN_PROGRESS currently being executed, used a replay protection
  /// SUCCESS successfully executed. End state
  /// FAILURE unsuccessfully executed, manual execution is now enabled.
  /// @dev RMN depends on this enum, if changing, please notify the RMN maintainers.
  enum MessageExecutionState {
    UNTOUCHED,
    IN_PROGRESS,
    SUCCESS,
    FAILURE
  }

  /// @notice CCIP OCR plugin type, used to separate execution & commit transmissions and configs
  enum OCRPluginType {
    Commit,
    Execution
  }

  /// @notice Family-agnostic token amounts used for both OnRamp & OffRamp messages
  struct RampTokenAmount {
    // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be
    // relied upon by the destination pool to validate the source pool.
    bytes sourcePoolAddress;
    // The address of the destination token, abi encoded in the case of EVM chains
    // This value is UNTRUSTED as any pool owner can return whatever value they want.
    bytes destTokenAddress;
    // Optional pool data to be transferred to the destination chain. Be default this is capped at
    // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead
    // has to be set for the specific token.
    bytes extraData;
    uint256 amount; // Amount of tokens.
  }

  /// @notice Family-agnostic header for OnRamp & OffRamp messages.
  /// The messageId is not expected to match hash(message), since it may originate from another ramp family
  struct RampMessageHeader {
    bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded)
    uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId
    uint64 destChainSelector; //     | the chain selector of the destination chain, note: not chainId
    uint64 sequenceNumber; //        │ sequence number, not unique across lanes
    uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes
  }

  /// @notice Family-agnostic message routed to an OffRamp
  /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage), hash(Any2EVMRampMessage) != messageId
  /// due to encoding & parameter differences
  struct Any2EVMRampMessage {
    RampMessageHeader header; // Message header
    bytes sender; // sender address on the source chain
    bytes data; // arbitrary data payload supplied by the message sender
    address receiver; // receiver address on the destination chain
    uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution
    RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer
  }

  /// @notice Family-agnostic message emitted from the OnRamp
  /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage) due to encoding & parameter differences
  /// messageId = hash(EVM2AnyRampMessage) using the source EVM chain's encoding format
  struct EVM2AnyRampMessage {
    RampMessageHeader header; // Message header
    address sender; // sender address on the source chain
    bytes data; // arbitrary data payload supplied by the message sender
    bytes receiver; // receiver address on the destination chain
    bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains
    address feeToken; // fee token
    uint256 feeTokenAmount; // fee token amount
    RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer
  }

  // bytes4(keccak256("CCIP ChainFamilySelector EVM"))
  bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c;
}

File 7 of 14 : MerkleMultiProof.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

library MerkleMultiProof {
  /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage.
  bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000;
  /// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preiimage.
  bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR =
    0x0000000000000000000000000000000000000000000000000000000000000001;

  uint256 internal constant MAX_NUM_HASHES = 256;

  error InvalidProof();
  error LeavesCannotBeEmpty();

  /// @notice Computes the root based on provided pre-hashed leaf nodes in
  /// leaves, internal nodes in proofs, and using proofFlagBits' i-th bit to
  /// determine if an element of proofs or one of the previously computed leafs
  /// or internal nodes will be used for the i-th hash.
  /// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's
  /// preimage should match LEAF_DOMAIN_SEPARATOR.
  /// @param proofs The hashes to be used instead of a leaf hash when the proofFlagBits
  ///  indicates a proof should be used.
  /// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or
  ///  a proof needs to be used in a hash operation.
  /// @dev the maximum number of hash operations it set to 256. Any input that would require
  ///  more than 256 hashes to get to a root will revert.
  /// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5
  ///     totalHashes = 3 + 1 - 1 = 3
  ///  ** round 1 **
  ///    proofFlagBits = (5 >> 0) & 1 = true
  ///    hashes[0] = hashPair(a, b)
  ///    (leafPos, hashPos, proofPos) = (2, 0, 0);
  ///
  ///  ** round 2 **
  ///    proofFlagBits = (5 >> 1) & 1 = false
  ///    hashes[1] = hashPair(D, c)
  ///    (leafPos, hashPos, proofPos) = (3, 0, 1);
  ///
  ///  ** round 3 **
  ///    proofFlagBits = (5 >> 2) & 1 = true
  ///    hashes[2] = hashPair(hashes[0], hashes[1])
  ///    (leafPos, hashPos, proofPos) = (3, 2, 1);
  ///
  ///    i = 3 and no longer < totalHashes. The algorithm is done
  ///    return hashes[totalHashes - 1] = hashes[2]; the last hash we computed.
  // We mark this function as internal to force it to be inlined in contracts
  // that use it, but semantically it is public.
  // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
  function merkleRoot(
    bytes32[] memory leaves,
    bytes32[] memory proofs,
    uint256 proofFlagBits
  ) internal pure returns (bytes32) {
    unchecked {
      uint256 leavesLen = leaves.length;
      uint256 proofsLen = proofs.length;
      if (leavesLen == 0) revert LeavesCannotBeEmpty();
      if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof();
      uint256 totalHashes = leavesLen + proofsLen - 1;
      if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof();
      if (totalHashes == 0) {
        return leaves[0];
      }
      bytes32[] memory hashes = new bytes32[](totalHashes);
      (uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0);

      for (uint256 i = 0; i < totalHashes; ++i) {
        // Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash.
        bytes32 a;
        if (proofFlagBits & (1 << i) == (1 << i)) {
          // Use a leaf or a previously computed hash.
          if (leafPos < leavesLen) {
            a = leaves[leafPos++];
          } else {
            a = hashes[hashPos++];
          }
        } else {
          // Use a supplied proof.
          a = proofs[proofPos++];
        }

        // The second part of the hashed pair is never a proof as hashing two proofs would result in a
        // hash that can already be computed offchain.
        bytes32 b;
        if (leafPos < leavesLen) {
          b = leaves[leafPos++];
        } else {
          b = hashes[hashPos++];
        }

        if (!(hashPos <= i)) revert InvalidProof();

        hashes[i] = _hashPair(a, b);
      }
      if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof();
      // Return the last hash.
      return hashes[totalHashes - 1];
    }
  }

  /// @notice Hashes two bytes32 objects in their given order, prepended by the
  /// INTERNAL_DOMAIN_SEPARATOR.
  function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) {
    return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right));
  }

  /// @notice Hashes two bytes32 objects. The order is taken into account,
  /// using the lower value first.
  function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
    return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a);
  }
}

File 8 of 14 : OCR2Base.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol";
import {OCR2Abstract} from "./OCR2Abstract.sol";

/// @notice Onchain verification of reports from the offchain reporting protocol
/// @dev For details on its operation, see the offchain reporting protocol design
/// doc, which refers to this contract as simply the "contract".
abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract {
  error InvalidConfig(InvalidConfigErrorType errorType);
  error WrongMessageLength(uint256 expected, uint256 actual);
  error ConfigDigestMismatch(bytes32 expected, bytes32 actual);
  error ForkedChain(uint256 expected, uint256 actual);
  error WrongNumberOfSignatures();
  error SignaturesOutOfRegistration();
  error UnauthorizedTransmitter();
  error UnauthorizedSigner();
  error NonUniqueSignatures();
  error OracleCannotBeZeroAddress();

  enum InvalidConfigErrorType {
    F_MUST_BE_POSITIVE,
    TOO_MANY_SIGNERS,
    F_TOO_HIGH,
    REPEATED_ORACLE_ADDRESS,
    NUM_SIGNERS_NOT_NUM_TRANSMITTERS
  }

  // Packing these fields used on the hot path in a ConfigInfo variable reduces the
  // retrieval of all of them to a minimum number of SLOADs.
  struct ConfigInfo {
    bytes32 latestConfigDigest;
    uint8 f;
    uint8 n;
  }

  // Used for s_oracles[a].role, where a is an address, to track the purpose
  // of the address, or to indicate that the address is unset.
  enum Role {
    // No oracle role has been set for address a
    Unset,
    // Signing address for the s_oracles[a].index'th oracle. I.e., report
    // signatures from this oracle should ecrecover back to address a.
    Signer,
    // Transmission address for the s_oracles[a].index'th oracle. I.e., if a
    // report is received by OCR2Aggregator.transmit in which msg.sender is
    // a, it is attributed to the s_oracles[a].index'th oracle.
    Transmitter
  }

  struct Oracle {
    uint8 index; // Index of oracle in s_signers/s_transmitters
    Role role; // Role of the address which mapped to this struct
  }

  // The current config
  ConfigInfo internal s_configInfo;

  // incremented each time a new config is posted. This count is incorporated
  // into the config digest, to prevent replay attacks.
  uint32 internal s_configCount;
  // makes it easier for offchain systems to extract config from logs.
  uint32 internal s_latestConfigBlockNumber;

  // signer OR transmitter address
  mapping(address signerOrTransmitter => Oracle oracle) internal s_oracles;

  // s_signers contains the signing address of each oracle
  address[] internal s_signers;

  // s_transmitters contains the transmission address of each oracle,
  // i.e. the address the oracle actually sends transactions to the contract from
  address[] internal s_transmitters;

  // The constant-length components of the msg.data sent to transmit.
  // See the "If we wanted to call sam" example on for example reasoning
  // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html
  uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = 4 // function selector
    + 32 * 3 // 3 words containing reportContext
    + 32 // word containing start location of abiencoded report value
    + 32 // word containing location start of abiencoded rs value
    + 32 // word containing start location of abiencoded ss value
    + 32 // rawVs value
    + 32 // word containing length of report
    + 32 // word containing length rs
    + 32; // word containing length of ss

  bool internal immutable i_uniqueReports;
  uint256 internal immutable i_chainID;

  constructor(bool uniqueReports) {
    i_uniqueReports = uniqueReports;
    i_chainID = block.chainid;
  }

  // Reverts transaction if config args are invalid
  modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) {
    if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS);
    if (f == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE);
    if (numSigners != numTransmitters) revert InvalidConfig(InvalidConfigErrorType.NUM_SIGNERS_NOT_NUM_TRANSMITTERS);
    if (numSigners <= 3 * f) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH);
    _;
  }

  /// @notice sets offchain reporting protocol configuration incl. participating oracles
  /// @param signers addresses with which oracles sign the reports
  /// @param transmitters addresses oracles use to transmit the reports
  /// @param f number of faulty oracles the system can tolerate
  /// @param onchainConfig encoded on-chain contract configuration
  /// @param offchainConfigVersion version number for offchainEncoding schema
  /// @param offchainConfig encoded off-chain oracle configuration
  function setOCR2Config(
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  ) external override checkConfigValid(signers.length, transmitters.length, f) onlyOwner {
    _beforeSetConfig(onchainConfig);
    uint256 oldSignerLength = s_signers.length;
    for (uint256 i = 0; i < oldSignerLength; ++i) {
      delete s_oracles[s_signers[i]];
      delete s_oracles[s_transmitters[i]];
    }

    uint256 newSignersLength = signers.length;
    for (uint256 i = 0; i < newSignersLength; ++i) {
      // add new signer/transmitter addresses
      address signer = signers[i];
      if (s_oracles[signer].role != Role.Unset) revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS);
      if (signer == address(0)) revert OracleCannotBeZeroAddress();
      s_oracles[signer] = Oracle(uint8(i), Role.Signer);

      address transmitter = transmitters[i];
      if (s_oracles[transmitter].role != Role.Unset) {
        revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS);
      }
      if (transmitter == address(0)) revert OracleCannotBeZeroAddress();
      s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter);
    }

    s_signers = signers;
    s_transmitters = transmitters;

    s_configInfo.f = f;
    s_configInfo.n = uint8(newSignersLength);
    s_configInfo.latestConfigDigest = _configDigestFromConfigData(
      block.chainid,
      address(this),
      ++s_configCount,
      signers,
      transmitters,
      f,
      onchainConfig,
      offchainConfigVersion,
      offchainConfig
    );

    uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
    s_latestConfigBlockNumber = uint32(block.number);

    emit ConfigSet(
      previousConfigBlockNumber,
      s_configInfo.latestConfigDigest,
      s_configCount,
      signers,
      transmitters,
      f,
      onchainConfig,
      offchainConfigVersion,
      offchainConfig
    );
  }

  /// @dev Hook that is run from setOCR2Config() right after validating configuration.
  /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing
  function _beforeSetConfig(bytes memory _onchainConfig) internal virtual;

  /// @return list of addresses permitted to transmit reports to this contract
  /// @dev The list will match the order used to specify the transmitter during setConfig
  function getTransmitters() external view returns (address[] memory) {
    return s_transmitters;
  }

  /// @notice transmit is called to post a new report to the contract
  /// @param report serialized report, which the signatures are signing.
  /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
  /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
  /// @param rawVs ith element is the the V component of the ith signature
  function transmit(
    // NOTE: If these parameters are changed, expectedMsgDataLength and/or
    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
    bytes32[3] calldata reportContext,
    bytes calldata report,
    bytes32[] calldata rs,
    bytes32[] calldata ss,
    bytes32 rawVs // signatures
  ) external override {
    // Scoping this reduces stack pressure and gas usage
    {
      // report and epochAndRound
      _report(report, uint40(uint256(reportContext[1])));
    }

    // reportContext consists of:
    // reportContext[0]: ConfigDigest
    // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round
    // reportContext[2]: ExtraHash
    bytes32 configDigest = reportContext[0];
    ConfigInfo memory configInfo = s_configInfo;

    if (configInfo.latestConfigDigest != configDigest) {
      revert ConfigDigestMismatch(configInfo.latestConfigDigest, configDigest);
    }
    // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports.
    // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest
    // calculated from chain A and so OCR reports will be valid on both forks.
    if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid);

    emit Transmitted(configDigest, uint32(uint256(reportContext[1]) >> 8));

    uint256 expectedNumSignatures;
    if (i_uniqueReports) {
      expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1;
    } else {
      expectedNumSignatures = configInfo.f + 1;
    }
    if (rs.length != expectedNumSignatures) revert WrongNumberOfSignatures();
    if (rs.length != ss.length) revert SignaturesOutOfRegistration();

    // Scoping this reduces stack pressure and gas usage
    {
      Oracle memory transmitter = s_oracles[msg.sender];
      // Check that sender is authorized to report
      if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index])) {
        revert UnauthorizedTransmitter();
      }
    }
    // Scoping this reduces stack pressure and gas usage
    {
      uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + report.length // one byte pure entry in _report
        + rs.length * 32 // 32 bytes per entry in _rs
        + ss.length * 32; // 32 bytes per entry in _ss)
      if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length);
    }

    // Verify signatures attached to report
    bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext));
    bool[MAX_NUM_ORACLES] memory signed;

    uint256 numberOfSignatures = rs.length;
    for (uint256 i = 0; i < numberOfSignatures; ++i) {
      // Safe from ECDSA malleability here since we check for duplicate signers.
      address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]);
      // Since we disallow address(0) as a valid signer address, it can
      // never have a signer role.
      Oracle memory oracle = s_oracles[signer];
      if (oracle.role != Role.Signer) revert UnauthorizedSigner();
      if (signed[oracle.index]) revert NonUniqueSignatures();
      signed[oracle.index] = true;
    }
  }

  /// @notice information about current offchain reporting protocol configuration
  /// @return configCount ordinal number of current config, out of all configs applied to this contract so far
  /// @return blockNumber block at which this config was set
  /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)
  function latestConfigDetails()
    external
    view
    override
    returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest)
  {
    return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest);
  }

  /// @inheritdoc OCR2Abstract
  function latestConfigDigestAndEpoch()
    external
    view
    virtual
    override
    returns (bool scanLogs, bytes32 configDigest, uint32 epoch)
  {
    return (true, bytes32(0), uint32(0));
  }

  function _report(bytes calldata report, uint40 epochAndRound) internal virtual;
}

File 9 of 14 : Client.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// End consumer library.
library Client {
  /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
  struct EVMTokenAmount {
    address token; // token address on the local chain.
    uint256 amount; // Amount of tokens.
  }

  struct Any2EVMMessage {
    bytes32 messageId; // MessageId corresponding to ccipSend on source.
    uint64 sourceChainSelector; // Source chain selector.
    bytes sender; // abi.decode(sender) if coming from an EVM chain.
    bytes data; // payload sent in original message.
    EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.
  }

  // If extraArgs is empty bytes, the default is 200k gas limit.
  struct EVM2AnyMessage {
    bytes receiver; // abi.encode(receiver address) for dest EVM chains
    bytes data; // Data payload
    EVMTokenAmount[] tokenAmounts; // Token transfers
    address feeToken; // Address of feeToken. address(0) means you will send msg.value.
    bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV2)
  }

  // bytes4(keccak256("CCIP EVMExtraArgsV1"));
  bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;

  struct EVMExtraArgsV1 {
    uint256 gasLimit;
  }

  function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
  }

  // bytes4(keccak256("CCIP EVMExtraArgsV2"));
  bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10;

  /// @param gasLimit: gas limit for the callback on the destination chain.
  /// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to other messages from the same sender.
  /// This value's default varies by chain. On some chains, a particular value is enforced, meaning if the expected value
  /// is not set, the message request will revert.
  struct EVMExtraArgsV2 {
    uint256 gasLimit;
    bool allowOutOfOrderExecution;
  }

  function _argsToBytes(EVMExtraArgsV2 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs);
  }
}

File 10 of 14 : OwnerIsCreator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ConfirmedOwner} from "./ConfirmedOwner.sol";

/// @title The OwnerIsCreator contract
/// @notice A contract with helpers for basic contract ownership.
contract OwnerIsCreator is ConfirmedOwner {
  constructor() ConfirmedOwner(msg.sender) {}
}

File 11 of 14 : OCR2Abstract.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";

abstract contract OCR2Abstract is ITypeAndVersion {
  // Maximum number of oracles the offchain reporting protocol is designed for
  uint256 internal constant MAX_NUM_ORACLES = 31;

  /// @notice triggers a new run of the offchain reporting protocol
  /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis
  /// @param configDigest configDigest of this configuration
  /// @param configCount ordinal number of this config setting among all config settings over the life of this contract
  /// @param signers ith element is address ith oracle uses to sign a report
  /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method
  /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
  /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)
  /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter
  /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
  event ConfigSet(
    uint32 previousConfigBlockNumber,
    bytes32 configDigest,
    uint64 configCount,
    address[] signers,
    address[] transmitters,
    uint8 f,
    bytes onchainConfig,
    uint64 offchainConfigVersion,
    bytes offchainConfig
  );

  /// @notice sets offchain reporting protocol configuration incl. participating oracles
  /// @param signers addresses with which oracles sign the reports
  /// @param transmitters addresses oracles use to transmit the reports
  /// @param f number of faulty oracles the system can tolerate
  /// @param onchainConfig serialized configuration used by the contract (and possibly oracles)
  /// @param offchainConfigVersion version number for offchainEncoding schema
  /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
  function setOCR2Config(
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  ) external virtual;

  /// @notice information about current offchain reporting protocol configuration
  /// @return configCount ordinal number of current config, out of all configs applied to this contract so far
  /// @return blockNumber block at which this config was set
  /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)
  function latestConfigDetails()
    external
    view
    virtual
    returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest);

  function _configDigestFromConfigData(
    uint256 chainId,
    address contractAddress,
    uint64 configCount,
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  ) internal pure returns (bytes32) {
    uint256 h = uint256(
      keccak256(
        abi.encode(
          chainId,
          contractAddress,
          configCount,
          signers,
          transmitters,
          f,
          onchainConfig,
          offchainConfigVersion,
          offchainConfig
        )
      )
    );
    uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00
    uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00
    return bytes32((prefix & prefixMask) | (h & ~prefixMask));
  }

  /// @notice optionally emitted to indicate the latest configDigest and epoch for
  /// which a report was successfully transmitted. Alternatively, the contract may
  /// use latestConfigDigestAndEpoch with scanLogs set to false.
  event Transmitted(bytes32 configDigest, uint32 epoch);

  /// @notice optionally returns the latest configDigest and epoch for which a
  /// report was successfully transmitted. Alternatively, the contract may return
  /// scanLogs set to true and use Transmitted events to provide this information
  /// to offchain watchers.
  /// @return scanLogs indicates whether to rely on the configDigest and epoch
  /// returned or whether to scan logs for the Transmitted event instead.
  /// @return configDigest
  /// @return epoch
  function latestConfigDigestAndEpoch()
    external
    view
    virtual
    returns (bool scanLogs, bytes32 configDigest, uint32 epoch);

  /// @notice transmit is called to post a new report to the contract
  /// @param report serialized report, which the signatures are signing.
  /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
  /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
  /// @param rawVs ith element is the the V component of the ith signature
  function transmit(
    // NOTE: If these parameters are changed, expectedMsgDataLength and/or
    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
    bytes32[3] calldata reportContext,
    bytes calldata report,
    bytes32[] calldata rs,
    bytes32[] calldata ss,
    bytes32 rawVs // signatures
  ) external virtual;
}

File 12 of 14 : ConfirmedOwner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol";

/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
  constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}

File 13 of 14 : ConfirmedOwnerWithProposal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IOwnable} from "../interfaces/IOwnable.sol";

/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwnerWithProposal is IOwnable {
  address private s_owner;
  address private s_pendingOwner;

  event OwnershipTransferRequested(address indexed from, address indexed to);
  event OwnershipTransferred(address indexed from, address indexed to);

  constructor(address newOwner, address pendingOwner) {
    // solhint-disable-next-line gas-custom-errors
    require(newOwner != address(0), "Cannot set owner to zero");

    s_owner = newOwner;
    if (pendingOwner != address(0)) {
      _transferOwnership(pendingOwner);
    }
  }

  /// @notice Allows an owner to begin transferring ownership to a new address.
  function transferOwnership(address to) public override onlyOwner {
    _transferOwnership(to);
  }

  /// @notice Allows an ownership transfer to be completed by the recipient.
  function acceptOwnership() external override {
    // solhint-disable-next-line gas-custom-errors
    require(msg.sender == s_pendingOwner, "Must be proposed owner");

    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /// @notice Get the current owner
  function owner() public view override returns (address) {
    return s_owner;
  }

  /// @notice validate, transfer ownership, and emit relevant events
  function _transferOwnership(address to) private {
    // solhint-disable-next-line gas-custom-errors
    require(to != msg.sender, "Cannot transfer to self");

    s_pendingOwner = to;

    emit OwnershipTransferRequested(s_owner, to);
  }

  /// @notice validate access
  function _validateOwnership() internal view {
    // solhint-disable-next-line gas-custom-errors
    require(msg.sender == s_owner, "Only callable by owner");
  }

  /// @notice Reverts if called by anyone other than the contract owner.
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }
}

File 14 of 14 : IOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOwnable {
  function owner() external returns (address);

  function transferOwnership(address recipient) external;

  function acceptOwnership() external;
}

Settings
{
  "remappings": [
    "forge-std/=src/v0.8/vendor/forge-std/src/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@arbitrum/=node_modules/@arbitrum/",
    "hardhat/=node_modules/hardhat/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "@scroll-tech/=node_modules/@scroll-tech/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 26000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

[{"inputs":[{"components":[{"internalType":"uint64","name":"chainSelector","type":"uint64"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"address","name":"onRamp","type":"address"},{"internalType":"address","name":"rmnProxy","type":"address"}],"internalType":"struct CommitStore.StaticConfig","name":"staticConfig","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"CursedByRMN","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"ForkedChain","type":"error"},{"inputs":[],"name":"InvalidCommitStoreConfig","type":"error"},{"inputs":[{"internalType":"enum OCR2Base.InvalidConfigErrorType","name":"errorType","type":"uint8"}],"name":"InvalidConfig","type":"error"},{"inputs":[{"components":[{"internalType":"uint64","name":"min","type":"uint64"},{"internalType":"uint64","name":"max","type":"uint64"}],"internalType":"struct CommitStore.Interval","name":"interval","type":"tuple"}],"name":"InvalidInterval","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidRoot","type":"error"},{"inputs":[],"name":"LeavesCannotBeEmpty","type":"error"},{"inputs":[],"name":"NonUniqueSignatures","type":"error"},{"inputs":[],"name":"OracleCannotBeZeroAddress","type":"error"},{"inputs":[],"name":"PausedError","type":"error"},{"inputs":[],"name":"RootAlreadyCommitted","type":"error"},{"inputs":[],"name":"SignaturesOutOfRegistration","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[],"name":"UnauthorizedSigner","type":"error"},{"inputs":[],"name":"UnauthorizedTransmitter","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"WrongMessageLength","type":"error"},{"inputs":[],"name":"WrongNumberOfSignatures","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"chainSelector","type":"uint64"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"address","name":"onRamp","type":"address"},{"internalType":"address","name":"rmnProxy","type":"address"}],"indexed":false,"internalType":"struct CommitStore.StaticConfig","name":"staticConfig","type":"tuple"},{"components":[{"internalType":"address","name":"priceRegistry","type":"address"}],"indexed":false,"internalType":"struct CommitStore.DynamicConfig","name":"dynamicConfig","type":"tuple"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"oldEpochAndRound","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"newEpochAndRound","type":"uint40"}],"name":"LatestPriceEpochAndRoundSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"sourceToken","type":"address"},{"internalType":"uint224","name":"usdPerToken","type":"uint224"}],"internalType":"struct Internal.TokenPriceUpdate[]","name":"tokenPriceUpdates","type":"tuple[]"},{"components":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"uint224","name":"usdPerUnitGas","type":"uint224"}],"internalType":"struct Internal.GasPriceUpdate[]","name":"gasPriceUpdates","type":"tuple[]"}],"internalType":"struct Internal.PriceUpdates","name":"priceUpdates","type":"tuple"},{"components":[{"internalType":"uint64","name":"min","type":"uint64"},{"internalType":"uint64","name":"max","type":"uint64"}],"internalType":"struct CommitStore.Interval","name":"interval","type":"tuple"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"indexed":false,"internalType":"struct CommitStore.CommitReport","name":"report","type":"tuple"}],"name":"ReportAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"RootRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"oldSeqNum","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newSeqNum","type":"uint64"}],"name":"SequenceNumberSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getDynamicConfig","outputs":[{"components":[{"internalType":"address","name":"priceRegistry","type":"address"}],"internalType":"struct CommitStore.DynamicConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExpectedNextSequenceNumber","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestPriceEpochAndRound","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"getMerkleRoot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStaticConfig","outputs":[{"components":[{"internalType":"uint64","name":"chainSelector","type":"uint64"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"address","name":"onRamp","type":"address"},{"internalType":"address","name":"rmnProxy","type":"address"}],"internalType":"struct CommitStore.StaticConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"isBlessed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isUnpausedAndNotCursed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"rootToReset","type":"bytes32[]"}],"name":"resetUnblessedRoots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"latestPriceEpochAndRound","type":"uint40"}],"name":"setLatestPriceEpochAndRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"minSeqNr","type":"uint64"}],"name":"setMinSeqNr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setOCR2Config","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"report","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"hashedLeaves","type":"bytes32[]"},{"internalType":"bytes32[]","name":"proofs","type":"bytes32[]"},{"internalType":"uint256","name":"proofFlagBits","type":"uint256"}],"name":"verify","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061018d5760003560e01c806379ba5097116100e3578063afcb95d71161008c578063f2fde38b11610066578063f2fde38b146104e3578063f47a8690146104f6578063ff888fb11461050957600080fd5b8063afcb95d7146104a8578063b1dc65a4146104c8578063e89d039f146104db57600080fd5b80638da5cb5b116100bd5780638da5cb5b1461044d578063a7206cd614610475578063ad7a22f81461049557600080fd5b806379ba50971461040d57806381ff7048146104155780638456cb591461044557600080fd5b806332048875116101455780635c975abb1161011f5780635c975abb14610391578063666cab8d146103b95780637437ff9f146103ce57600080fd5b806332048875146103565780633f4ba83a146103775780634120fccd1461037f57600080fd5b8063181f5a7711610176578063181f5a77146102e55780631ef381741461032e57806329b980e41461034357600080fd5b806306285c691461019257806310c374ed146102b5575b600080fd5b61029f60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000de41ba4fc9d91ad967ffffffffffffffff1681526020017f0000000000000000000000000000000000000000000000001fa3b5d5b7cd348b67ffffffffffffffff1681526020017f0000000000000000000000003279a265dc108a588263c7a81114226d460d3e3d73ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000ba3f6251de62ded61ff98590cb2fdf6871fbb99173ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102ac9190612583565b60405180910390f35b60095468010000000000000000900464ffffffffff165b60405167ffffffffffffffff90911681526020016102ac565b6103216040518060400160405280601181526020017f436f6d6d697453746f726520312e352e3000000000000000000000000000000081525081565b6040516102ac9190612640565b61034161033c366004612897565b61051c565b005b610341610351366004612964565b610c00565b6103696103643660046129d7565b610c90565b6040519081526020016102ac565b610341610d86565b60095467ffffffffffffffff166102cc565b6009546d0100000000000000000000000000900460ff165b60405190151581526020016102ac565b6103c1610dec565b6040516102ac9190612a9d565b604080516020808201835260009091528151808201835260085473ffffffffffffffffffffffffffffffffffffffff16908190529151918252016102ac565b610341610e5b565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016102ac565b610341610f58565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ac565b610369610483366004612ab0565b6000908152600a602052604090205490565b6103416104a3366004612ac9565b610fc8565b6040805160018152600060208201819052918101919091526060016102ac565b6103416104d6366004612ae4565b611043565b6103a961165a565b6103416104f1366004612bc9565b61176e565b610341610504366004612be6565b611782565b6103a9610517366004612ab0565b611819565b855185518560ff16601f83111561056b5760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b60405180910390fd5b806000036105a85760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b8183146105e45760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6105ef816003612cc7565b831161062a5760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b6106326118ed565b61063b86611970565b60065460005b8181101561072f57600560006006838154811061066057610660612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600780546005929190849081106106d0576106d0612cde565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101610641565b50895160005b81811015610aa85760008c828151811061075157610751612cde565b602002602001015190506000600281111561076e5761076e612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff1660028111156107ad576107ad612c28565b146107e75760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff8116610834576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016001905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156108e4576108e4612c28565b021790555090505060008c838151811061090057610900612cde565b602002602001015190506000600281111561091d5761091d612c28565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561095c5761095c612c28565b146109965760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016105629190612c57565b73ffffffffffffffffffffffffffffffffffffffff81166109e3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff84168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610a9357610a93612c28565b02179055509050505050806001019050610735565b508a51610abc9060069060208e01906124c5565b508951610ad09060079060208d01906124c5565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908c161717905560048054610b56914691309190600090610b289063ffffffff16612d0d565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168e8e8e8e8e8e611b20565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168f8f8f8f8f8f604051610bea99989796959493929190612d30565b60405180910390a1505050505050505050505050565b610c086118ed565b6009805464ffffffffff838116680100000000000000008181027fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff85161790945560408051949093049091168084526020840191909152917ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf56545644491015b60405180910390a15050565b6009546000906d0100000000000000000000000000900460ff1615610ce1576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d5287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250611bcb915050565b9050610d5d81611819565b610d6b576000915050610d7d565b6000908152600a602052604090205490505b95945050505050565b610d8e6118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60606007805480602002602001604051908101604052809291908181526020018280548015610e5157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e26575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610562565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f606118ed565b600980547fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff166d01000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610de2565b610fd06118ed565b6009805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000083168117909355604080519190921680825260208201939093527fea59e8027e41fda1525220008cf2416797405065eb21b0ebd417bfc6d361b8de9101610c84565b611052878760208b0135611eec565b6040805160608101825260025480825260035460ff8082166020850152610100909104169282019290925289359182146110c55780516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101839052604401610562565b467f0000000000000000000000000000000000000000000000000000000000aa36a714611146576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000aa36a76004820152466024820152604401610562565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a160007f0000000000000000000000000000000000000000000000000000000000000000156111e8576002826020015183604001516111c99190612dc6565b6111d39190612ddf565b6111de906001612dc6565b60ff1690506111fe565b60208201516111f8906001612dc6565b60ff1690505b868114611237576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b868514611270576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156112b3576112b3612c28565b60028111156112c4576112c4612c28565b90525090506002816020015160028111156112e1576112e1612c28565b14801561132857506007816000015160ff168154811061130357611303612cde565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61135e576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600061136c866020612cc7565b611377896020612cc7565b6113838c610144612e28565b61138d9190612e28565b6113979190612e28565b90503681146113db576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610562565b5060008a8a6040516113ee929190612e3b565b604051908190038120611405918e90602001612e4b565b60405160208183030381529060405280519060200120905061142561254f565b8860005b818110156116495760006001858a846020811061144857611448612cde565b61145591901a601b612dc6565b8f8f8681811061146757611467612cde565b905060200201358e8e8781811061148057611480612cde565b90506020020135604051600081526020016040526040516114bd949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156114df573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152848220848601909552845460ff808216865293975091955092939284019161010090910416600281111561156257611562612c28565b600281111561157357611573612c28565b905250905060018160200151600281111561159057611590612c28565b146115c7576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106115de576115de612cde565b60200201511561161a576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061163557611635612cde565b911515602090920201525050600101611429565b505050505050505050505050505050565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000001fa3b5d5b7cd348b60801b77ffffffffffffffff000000000000000000000000000000001660048201526000907f000000000000000000000000ba3f6251de62ded61ff98590cb2fdf6871fbb99173ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117489190612e5f565b15801561176957506009546d0100000000000000000000000000900460ff16155b905090565b6117766118ed565b61177f81612355565b50565b61178a6118ed565b60005b818110156118145760008383838181106117a9576117a9612cde565b9050602002013590506117bb81611819565b61180b576000818152600a602052604080822091909155517f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12906118029083815260200190565b60405180910390a15b5060010161178d565b505050565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f000000000000000000000000ba3f6251de62ded61ff98590cb2fdf6871fbb9911690634d61677190604401602060405180830381865afa1580156118c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e79190612e5f565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461196e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610562565b565b6000818060200190518101906119869190612e81565b805190915073ffffffffffffffffffffffffffffffffffffffff166119d7576040517f3f8be2be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff928316179055600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff169055604080516080810182527f000000000000000000000000000000000000000000000000de41ba4fc9d91ad967ffffffffffffffff90811682527f0000000000000000000000000000000000000000000000001fa3b5d5b7cd348b1660208201527f0000000000000000000000003279a265dc108a588263c7a81114226d460d3e3d8316818301527f000000000000000000000000ba3f6251de62ded61ff98590cb2fdf6871fbb9919092166060830152517fc9d7123efd4203e60b0f0a4b1dbc4800fc97ce63679f71c3a27279b24a7ddec391610c84918490612ecd565b6000808a8a8a8a8a8a8a8a8a604051602001611b4499989796959493929190612f4a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b8251825160009190818303611c0c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590611c2057506101018111155b611c56576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115611cb7576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003611ce45786600081518110611cd257611cd2612cde565b60200260200101519350505050611ee5565b60008167ffffffffffffffff811115611cff57611cff612653565b604051908082528060200260200182016040528015611d28578160200160208202803683370190505b50905060008080805b85811015611e6b5760006001821b8b811603611d8c5788851015611d75578c5160018601958e918110611d6657611d66612cde565b60200260200101519050611dae565b8551600185019487918110611d6657611d66612cde565b8b5160018401938d918110611da357611da3612cde565b602002602001015190505b600089861015611dde578d5160018701968f918110611dcf57611dcf612cde565b60200260200101519050611e00565b8651600186019588918110611df557611df5612cde565b602002602001015190505b82851115611e3a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e44828261244a565b878481518110611e5657611e56612cde565b60209081029190910101525050600101611d31565b506001850382148015611e7d57508683145b8015611e8857508581145b611ebe576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001860381518110611ed357611ed3612cde565b60200260200101519750505050505050505b9392505050565b6009546d0100000000000000000000000000900460ff1615611f3a576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000001fa3b5d5b7cd348b60801b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000ba3f6251de62ded61ff98590cb2fdf6871fbb99173ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120259190612e5f565b1561205c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061206a838501856130d6565b8051515190915015158061208357508051602001515115155b156121bb5760095464ffffffffff8084166801000000000000000090920416101561218057600980547fffffffffffffffffffffffffffffffffffffff0000000000ffffffffffffffff166801000000000000000064ffffffffff85160217905560085481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f9161213a91600401613329565b600060405180830381600087803b15801561215457600080fd5b505af1158015612168573d6000803e3d6000fd5b50505050604081015161217b5750505050565b6121bb565b60408101516121bb576040517ff803a2ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101515160095467ffffffffffffffff90811691161415806121f6575060208082015190810151905167ffffffffffffffff9182169116115b156122335780602001516040517fbb1ae18d000000000000000000000000000000000000000000000000000000008152600401610562919061333c565b604081015161226e576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000908152600a6020522054156122b7576040517fa0bce24f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015101516122ca906001613361565b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169190911790556040818101516000908152600a602052819020429055517f291698c01aa71f912280535d88a00d2c59fb63530a3f5d0098560468acb9ebf590612347908390613389565b60405180910390a150505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036123d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610562565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081831061248c5760408051600160208083019190915281830185905260608083018790528351808403909101815260809092019092528051910120611ee5565b60408051600160208083019190915281830186905260608083018690528351808403909101815260809092019092528051910120611ee5565b82805482825590600052602060002090810192821561253f579160200282015b8281111561253f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906124e5565b5061254b92915061256e565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b8082111561254b576000815560010161256f565b608081016118e7828467ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b6000815180845260005b81811015612602576020818501810151868301820152016125e6565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611ee560208301846125dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156126a5576126a5612653565b60405290565b6040516060810167ffffffffffffffff811182821017156126a5576126a5612653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561271557612715612653565b604052919050565b600067ffffffffffffffff82111561273757612737612653565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461177f57600080fd5b600082601f83011261277457600080fd5b813560206127896127848361271d565b6126ce565b8083825260208201915060208460051b8701019350868411156127ab57600080fd5b602086015b848110156127d05780356127c381612741565b83529183019183016127b0565b509695505050505050565b803560ff811681146127ec57600080fd5b919050565b600082601f83011261280257600080fd5b813567ffffffffffffffff81111561281c5761281c612653565b61284d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016126ce565b81815284602083860101111561286257600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff811681146127ec57600080fd5b60008060008060008060c087890312156128b057600080fd5b863567ffffffffffffffff808211156128c857600080fd5b6128d48a838b01612763565b975060208901359150808211156128ea57600080fd5b6128f68a838b01612763565b965061290460408a016127db565b9550606089013591508082111561291a57600080fd5b6129268a838b016127f1565b945061293460808a0161287f565b935060a089013591508082111561294a57600080fd5b5061295789828a016127f1565b9150509295509295509295565b60006020828403121561297657600080fd5b813564ffffffffff81168114611ee557600080fd5b60008083601f84011261299d57600080fd5b50813567ffffffffffffffff8111156129b557600080fd5b6020830191508360208260051b85010111156129d057600080fd5b9250929050565b6000806000806000606086880312156129ef57600080fd5b853567ffffffffffffffff80821115612a0757600080fd5b612a1389838a0161298b565b90975095506020880135915080821115612a2c57600080fd5b50612a398882890161298b565b96999598509660400135949350505050565b60008151808452602080850194506020840160005b83811015612a9257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612a60565b509495945050505050565b602081526000611ee56020830184612a4b565b600060208284031215612ac257600080fd5b5035919050565b600060208284031215612adb57600080fd5b611ee58261287f565b60008060008060008060008060e0898b031215612b0057600080fd5b606089018a811115612b1157600080fd5b8998503567ffffffffffffffff80821115612b2b57600080fd5b818b0191508b601f830112612b3f57600080fd5b813581811115612b4e57600080fd5b8c6020828501011115612b6057600080fd5b6020830199508098505060808b0135915080821115612b7e57600080fd5b612b8a8c838d0161298b565b909750955060a08b0135915080821115612ba357600080fd5b50612bb08b828c0161298b565b999c989b50969995989497949560c00135949350505050565b600060208284031215612bdb57600080fd5b8135611ee581612741565b60008060208385031215612bf957600080fd5b823567ffffffffffffffff811115612c1057600080fd5b612c1c8582860161298b565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310612c92577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176118e7576118e7612c98565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103612d2657612d26612c98565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152612d608184018a612a4b565b90508281036080840152612d748189612a4b565b905060ff871660a084015282810360c0840152612d9181876125dc565b905067ffffffffffffffff851660e0840152828103610100840152612db681856125dc565b9c9b505050505050505050505050565b60ff81811683821601908111156118e7576118e7612c98565b600060ff831680612e19577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b808201808211156118e7576118e7612c98565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612e7157600080fd5b81518015158114611ee557600080fd5b600060208284031215612e9357600080fd5b6040516020810181811067ffffffffffffffff82111715612eb657612eb6612653565b6040528251612ec481612741565b81529392505050565b60a08101612f26828567ffffffffffffffff80825116835280602083015116602084015250604081015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606084015116606085015250505050565b73ffffffffffffffffffffffffffffffffffffffff83511660808301529392505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152612f918285018b612a4b565b91508382036080850152612fa5828a612a4b565b915060ff881660a085015283820360c0850152612fc282886125dc565b90861660e08501528381036101008501529050612db681856125dc565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146127ec57600080fd5b600082601f83011261301c57600080fd5b8135602061302c6127848361271d565b82815260069290921b8401810191818101908684111561304b57600080fd5b8286015b848110156127d057604081890312156130685760008081fd5b613070612682565b6130798261287f565b8152613086858301612fdf565b8186015283529183019160400161304f565b6000604082840312156130aa57600080fd5b6130b2612682565b90506130bd8261287f565b81526130cb6020830161287f565b602082015292915050565b600060208083850312156130e957600080fd5b823567ffffffffffffffff8082111561310157600080fd5b908401906080828703121561311557600080fd5b61311d6126ab565b82358281111561312c57600080fd5b8301604081890381131561313f57600080fd5b613147612682565b82358581111561315657600080fd5b8301601f81018b1361316757600080fd5b80356131756127848261271d565b81815260069190911b8201890190898101908d83111561319457600080fd5b928a01925b828410156131e45785848f0312156131b15760008081fd5b6131b9612682565b84356131c481612741565b81526131d1858d01612fdf565b818d0152825292850192908a0190613199565b8452505050828701359150848211156131fc57600080fd5b6132088a83850161300b565b8188015283525061321d905087848601613098565b93810193909352506060013560408201529392505050565b805160408084528151848201819052600092602091908201906060870190855b818110156132ae578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101613255565b50508583015187820388850152805180835290840192506000918401905b8083101561331d578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906132cc565b50979650505050505050565b602081526000611ee56020830184613235565b604081016118e78284805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff81811683821601908082111561338257613382612c98565b5092915050565b6020815260008251608060208401526133a560a0840182613235565b905060208401516133d06040850182805167ffffffffffffffff908116835260209182015116910152565b5060408401516080840152809150509291505056fea164736f6c6343000818000a

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.