ETH Price: $2,092.45 (+3.34%)
Gas: 0.12 Gwei

Transaction Decoder

Block:
20265606 at Jul-09-2024 01:18:23 AM +UTC
Transaction Fee:
0.001560616464505605 ETH $3.27
Gas Used:
436,735 Gas / 3.573371643 Gwei

Emitted Events:

31 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x0C46Dc0B...324dA687B, previous=0x00000000...000000000, current=0x9D219125...475f172f1 )
32 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x6D53d5E3...7387aC6B5, previous=0x00000000...000000000, current=0x7CC60c9C...5c87a7550 )
33 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x5C026B71...252B0788d, previous=0x00000000...000000000, current=0x21F1dB6E...42Ed4737D )
34 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x8AaDF849...E0cc0134E, previous=0x00000000...000000000, current=0x6eF38c3d...b8CAc2589 )
35 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0xC0C7eB4A...6Df85E489, previous=0x00000000...000000000, current=0x0921E157...3964F6776 )
36 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x97360A89...a48D550E6, previous=0x00000000...000000000, current=0xba8Bcb4E...49f909cB2 )
37 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x30d87235...9b0816f04, previous=0x00000000...000000000, current=0x59eCf483...d0A94E2A5 )
38 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x7B740d24...Fbb5C73c8, previous=0x00000000...000000000, current=0x9efa0A61...68b3e709C )
39 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x5fdf4ABa...0d8108e96, previous=0x00000000...000000000, current=0x47044eE2...5aDA4D12A )
40 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0xC917E3BF...7682095CA, previous=0x00000000...000000000, current=0x14f94049...36bC4393B )
41 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x1d5804aE...230F11895, previous=0x00000000...000000000, current=0xDF812B91...79Ba63420 )
42 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x65a43936...49cAb32c8, previous=0x00000000...000000000, current=0x183A9662...7EB40A59A )
43 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0xE62Efa54...545E4d273, previous=0x00000000...000000000, current=0x7D0f8dd2...957dd52c3 )
44 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0xBa4555a8...10eb65dFa, previous=0x00000000...000000000, current=0xA68F8E34...81eCf486c )
45 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x87B331d3...0bd61c772, previous=0x00000000...000000000, current=0x5823D12a...D87CF507A )
46 AccessControlledOCR2Aggregator.PayeeshipTransferred( transmitter=0x522bB49b...57E6Fc3e2, previous=0x00000000...000000000, current=0xDA80050E...3Ab91dF55 )

Account State Difference:

  Address   Before After State Difference Code
(Lido: Execution Layer Rewards Vault)
79.381160680508042446 Eth79.381597415508042446 Eth0.000436735
0xc77904CD...3e2f6093d
0xD436f206...9C14C8e8f
7.026745298900661658 Eth
Nonce: 1235
7.025184682436156053 Eth
Nonce: 1236
0.001560616464505605

Execution Trace

AccessControlledOCR2Aggregator.setPayees( transmitters=[0x0C46Dc0BA85eAb5A515f819F1a705eD324dA687B, 0x6D53d5E35F5226a1613877e071b81217387aC6B5, 0x5C026B7107f1F92a9768CF64f8B2a22252B0788d, 0x8AaDF849561DcCeC75DA44d1147E736E0cc0134E, 0xC0C7eB4A39BAa77fD52715BD1dcE2246Df85E489, 0x97360A89B5adb7D82Dbde6C66A49de8a48D550E6, 0x30d872350Fe74f47C85847D6784B42f9b0816f04, 0x7B740d24396B09F992B655A590139D7Fbb5C73c8, 0x5fdf4ABaF24d8229deFBD28890cb01E0d8108e96, 0xC917E3BF6c211b326ffD4ed13E7D9a67682095CA, 0x1d5804aE896c64ECc88E15379061CE6230F11895, 0x65a43936d7e1295CcA6f30F6a0B25fe49cAb32c8, 0xE62Efa5462961055757C63931a15601545E4d273, 0xBa4555a80E47477BBf23B721563D38B10eb65dFa, 0x87B331d3bb9Cf70Dd85c3dc606B684a0bd61c772, 0x522bB49bE4fB6E3ceC18df911C2A66457E6Fc3e2], payees=[0x9D219125a0CE10241b4eC1280c2F880475f172f1, 0x7CC60c9C24E9A290Db55b1017AF477E5c87a7550, 0x21F1dB6E4B5e1dF5c68bC1dfB58c28942Ed4737D, 0x6eF38c3d1D85B710A9e160aD41B912Cb8CAc2589, 0x0921E157b690c4F89F7C2a210cFd8bF3964F6776, 0xba8Bcb4EB9a90D5A0eAe0098496703b49f909cB2, 0x59eCf48345A221E0731E785ED79eD40d0A94E2A5, 0x9efa0A617C0552F1558c95993aA8b8A68b3e709C, 0x47044eE2F23001F8a03FB2f7d2ce6645aDA4D12A, 0x14f94049397C3F1807c45B6f854Cb5F36bC4393B, 0xDF812B91D8bf6DF698BFD1D8047839479Ba63420, 0x183A96629fF566e7AA8AfA38980Cd037EB40A59A, 0x7D0f8dd25135047967bA6C50309b567957dd52c3, 0xA68F8E34B775aA1f0c0E9028b13BdB481eCf486c, 0x5823D12aD85Ef11f4e5508AB3559a37D87CF507A, 0xDA80050Ed4F50033949608208f79EE43Ab91dF55] )
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;
import "./OCR2Aggregator.sol";
import "./SimpleReadAccessController.sol";
/**
 * @notice Wrapper of OCR2Aggregator which checks read access on Aggregator-interface methods
 */
contract AccessControlledOCR2Aggregator is OCR2Aggregator, SimpleReadAccessController {
  constructor(
    LinkTokenInterface _link,
    int192 _minAnswer,
    int192 _maxAnswer,
    AccessControllerInterface _billingAccessController,
    AccessControllerInterface _requesterAccessController,
    uint8 _decimals,
    string memory description
  )
    OCR2Aggregator(
      _link,
      _minAnswer,
      _maxAnswer,
      _billingAccessController,
      _requesterAccessController,
      _decimals,
      description
    ) {
    }
  /*
   * Versioning
   */
  function typeAndVersion()
    external
    override
    pure
    virtual
    returns (string memory)
  {
    return "AccessControlledOCR2Aggregator 1.0.0";
  }
  /*
   * v2 Aggregator interface
   */
  /// @inheritdoc OCR2Aggregator
  function latestAnswer()
    public
    override
    view
    checkAccess()
    returns (int256)
  {
    return super.latestAnswer();
  }
  /// @inheritdoc OCR2Aggregator
  function latestTimestamp()
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.latestTimestamp();
  }
  /// @inheritdoc OCR2Aggregator
  function latestRound()
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.latestRound();
  }
  /// @inheritdoc OCR2Aggregator
  function getAnswer(uint256 _roundId)
    public
    override
    view
    checkAccess()
    returns (int256)
  {
    return super.getAnswer(_roundId);
  }
  /// @inheritdoc OCR2Aggregator
  function getTimestamp(uint256 _roundId)
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.getTimestamp(_roundId);
  }
  /*
   * v3 Aggregator interface
   */
  /// @inheritdoc OCR2Aggregator
  function description()
    public
    override
    view
    checkAccess()
    returns (string memory)
  {
    return super.description();
  }
  /// @inheritdoc OCR2Aggregator
  function getRoundData(uint80 _roundId)
    public
    override
    view
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.getRoundData(_roundId);
  }
  /// @inheritdoc OCR2Aggregator
  function latestRoundData()
    public
    override
    view
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.latestRoundData();
  }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./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)
    )
  {
  }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/OwnableInterface.sol";
/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwnerWithProposal is OwnableInterface {
  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
  ) {
    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,
   * pending.
   */
  function transferOwnership(
    address to
  )
    public
    override
    onlyOwner()
  {
    _transferOwnership(to);
  }
  /**
   * @notice Allows an ownership transfer to be completed by the recipient.
   */
  function acceptOwnership()
    external
    override
  {
    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
  {
    require(to != msg.sender, "Cannot transfer to self");
    s_pendingOwner = to;
    emit OwnershipTransferRequested(s_owner, to);
  }
  /**
   * @notice validate access
   */
  function _validateOwnership()
    internal
    view
  {
    require(msg.sender == s_owner, "Only callable by owner");
  }
  /**
   * @notice Reverts if called by anyone other than the contract owner.
   */
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/TypeAndVersionInterface.sol";
abstract contract OCR2Abstract is TypeAndVersionInterface {
  // Maximum number of oracles the offchain reporting protocol is designed for
  uint256 constant internal maxNumOracles = 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 setConfig(
    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 reportContext serialized report context containing configDigest, epoch, round, extraHash
   * @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 maxNumOracles entries
   * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles 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;
}
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;
import "./interfaces/AccessControllerInterface.sol";
import "./interfaces/AggregatorV2V3Interface.sol";
import "./interfaces/AggregatorValidatorInterface.sol";
import "./interfaces/LinkTokenInterface.sol";
import "./interfaces/TypeAndVersionInterface.sol";
import "./OCR2Abstract.sol";
import "./OwnerIsCreator.sol";
/**
 * @notice OCR2Aggregator for numerical data with billing support.
 * @dev
 * If you read or change this, be sure to read or adjust the comments. They
 * track the units of the values under consideration, and are crucial to
 * the readability of the operations it specifies.
 * @notice
 * Billing Trust Model:
 * Nothing in this contract prevents a billing admin from setting insane
 * values for the billing parameters in setBilling. Oracles
 * participating in this contract should regularly check that the
 * parameters make sense. Similarly, the outstanding obligations of this
 * contract to the oracles can exceed the funds held by the contract.
 * Oracles participating in this contract should regularly check that it
 * holds sufficient funds and stop interacting with it if funding runs
 * out.
 * This still leaves oracles with some risk due to TOCTOU issues.
 * However, since the sums involved are pretty small (Ethereum
 * transactions aren't that expensive in the end) and an oracle would
 * likely stop participating in a contract it repeatedly lost money on,
 * this risk is deemed acceptable. Oracles should also regularly
 * withdraw any funds in the contract to prevent issues where the
 * contract becomes underfunded at a later time, and different oracles
 * are competing for the left-over funds.
 * Finally, note that any change to the set of oracles or to the billing
 * parameters will trigger payout of all oracles first (using the old
 * parameters), a billing admin cannot take away funds that are already
 * marked for payment.
 */
contract OCR2Aggregator is OCR2Abstract, OwnerIsCreator, AggregatorV2V3Interface {
  // This contract is divided into sections. Each section defines a set of
  // variables, events, and functions that belong together.
  /***************************************************************************
   * Section: Variables used in multiple other sections
   **************************************************************************/
  struct Transmitter {
    bool active;
    // Index of oracle in s_signersList/s_transmittersList
    uint8 index;
    // juels-denominated payment for transmitters, covering gas costs incurred
    // by the transmitter plus additional rewards. The entire LINK supply (1e9
    // LINK = 1e27 Juels) will always fit into a uint96.
    uint96 paymentJuels;
  }
  mapping (address /* transmitter address */ => Transmitter) internal s_transmitters;
  struct Signer {
    bool active;
    // Index of oracle in s_signersList/s_transmittersList
    uint8 index;
  }
  mapping (address /* signer address */ => Signer) internal s_signers;
  // s_signersList contains the signing address of each oracle
  address[] internal s_signersList;
  // s_transmittersList contains the transmission address of each oracle,
  // i.e. the address the oracle actually sends transactions to the contract from
  address[] internal s_transmittersList;
  // We assume that all oracles contribute observations to all rounds. this
  // variable tracks (per-oracle) from what round an oracle should be rewarded,
  // i.e. the oracle gets (latestAggregatorRoundId -
  // rewardFromAggregatorRoundId) * reward
  uint32[maxNumOracles] internal s_rewardFromAggregatorRoundId;
  bytes32 s_latestConfigDigest;
  // Storing these fields used on the hot path in a HotVars variable reduces the
  // retrieval of all of them to a single SLOAD.
  struct HotVars {
    // maximum number of faulty oracles
    uint8 f;
    // epoch and round from OCR protocol.
    // 32 most sig bits for epoch, 8 least sig bits for round
    uint40 latestEpochAndRound;
    // Chainlink Aggregators expose a roundId to consumers. The offchain reporting
    // protocol does not use this id anywhere. We increment it whenever a new
    // transmission is made to provide callers with contiguous ids for successive
    // reports.
    uint32 latestAggregatorRoundId;
    // Highest compensated gas price, in gwei uints
    uint32 maximumGasPriceGwei;
    // If gas price is less (in gwei units), transmitter gets half the savings
    uint32 reasonableGasPriceGwei;
    // Fixed LINK reward for each observer
    uint32 observationPaymentGjuels;
    // Fixed reward for transmitter
    uint32 transmissionPaymentGjuels;
    // Overhead incurred by accounting logic
    uint24 accountingGas;
  }
  HotVars internal s_hotVars;
  // Transmission records the median answer from the transmit transaction at
  // time timestamp
  struct Transmission {
    int192 answer; // 192 bits ought to be enough for anyone
    uint32 observationsTimestamp; // when were observations made offchain
    uint32 transmissionTimestamp; // when was report received onchain
  }
  mapping(uint32 /* aggregator round ID */ => Transmission) internal s_transmissions;
  // Lowest answer the system is allowed to report in response to transmissions
  int192 immutable public minAnswer;
  // Highest answer the system is allowed to report in response to transmissions
  int192 immutable public maxAnswer;
  /***************************************************************************
   * Section: Constructor
   **************************************************************************/
  /**
   * @param link address of the LINK contract
   * @param minAnswer_ lowest answer the median of a report is allowed to be
   * @param maxAnswer_ highest answer the median of a report is allowed to be
   * @param requesterAccessController access controller for requesting new rounds
   * @param decimals_ answers are stored in fixed-point format, with this many digits of precision
   * @param description_ short human-readable description of observable this contract's answers pertain to
   */
  constructor(
    LinkTokenInterface link,
    int192 minAnswer_,
    int192 maxAnswer_,
    AccessControllerInterface billingAccessController,
    AccessControllerInterface requesterAccessController,
    uint8 decimals_,
    string memory description_
  ) {
    s_linkToken = link;
    emit LinkTokenSet(LinkTokenInterface(address(0)), link);
    _setBillingAccessController(billingAccessController);
    decimals = decimals_;
    s_description = description_;
    setRequesterAccessController(requesterAccessController);
    setValidatorConfig(AggregatorValidatorInterface(address(0x0)), 0);
    minAnswer = minAnswer_;
    maxAnswer = maxAnswer_;
  }
  /***************************************************************************
   * Section: OCR2Abstract Configuration
   **************************************************************************/
  // 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;
  // left as a function so this check can be disabled in derived contracts
  function _requirePositiveF (
    uint256 f
  )
    internal
    pure
    virtual
  {
    require(0 < f, "f must be positive");
  }
  struct SetConfigArgs {
    address[] signers;
    address[] transmitters;
    uint8 f;
    bytes onchainConfig;
    uint64 offchainConfigVersion;
    bytes offchainConfig;
  }
  /// @inheritdoc OCR2Abstract
  function setConfig(
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  )
    external
    override
    onlyOwner()
  {
    require(signers.length <= maxNumOracles, "too many oracles");
    require(signers.length == transmitters.length, "oracle length mismatch");
    require(3*f < signers.length, "faulty-oracle f too high");
    _requirePositiveF(f);
    require(keccak256(onchainConfig) == keccak256(abi.encodePacked(uint8(1) /*version*/, minAnswer, maxAnswer)), "invalid onchainConfig");
    SetConfigArgs memory args = SetConfigArgs({
      signers: signers,
      transmitters: transmitters,
      f: f,
      onchainConfig: onchainConfig,
      offchainConfigVersion: offchainConfigVersion,
      offchainConfig: offchainConfig
    });
    s_hotVars.latestEpochAndRound = 0;
    _payOracles();
    // remove any old signer/transmitter addresses
    uint256 oldLength = s_signersList.length;
    for (uint256 i = 0; i < oldLength; i++) {
      address signer = s_signersList[i];
      address transmitter = s_transmittersList[i];
      delete s_signers[signer];
      delete s_transmitters[transmitter];
    }
    delete s_signersList;
    delete s_transmittersList;
    // add new signer/transmitter addresses
    for (uint i = 0; i < args.signers.length; i++) {
      require(
        !s_signers[args.signers[i]].active,
        "repeated signer address"
      );
      s_signers[args.signers[i]] = Signer({
        active: true,
        index: uint8(i)
      });
      require(
        !s_transmitters[args.transmitters[i]].active,
        "repeated transmitter address"
      );
      s_transmitters[args.transmitters[i]] = Transmitter({
        active: true,
        index: uint8(i),
        paymentJuels: 0
      });
    }
    s_signersList = args.signers;
    s_transmittersList = args.transmitters;
    s_hotVars.f = args.f;
    uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
    s_latestConfigBlockNumber = uint32(block.number);
    s_configCount += 1;
    s_latestConfigDigest = _configDigestFromConfigData(
      block.chainid,
      address(this),
      s_configCount,
      args.signers,
      args.transmitters,
      args.f,
      args.onchainConfig,
      args.offchainConfigVersion,
      args.offchainConfig
    );
    emit ConfigSet(
      previousConfigBlockNumber,
      s_latestConfigDigest,
      s_configCount,
      args.signers,
      args.transmitters,
      args.f,
      args.onchainConfig,
      args.offchainConfigVersion,
      args.offchainConfig
    );
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    for (uint256 i = 0; i < args.signers.length; i++) {
      s_rewardFromAggregatorRoundId[i] = latestAggregatorRoundId;
    }
  }
  /// @inheritdoc OCR2Abstract
  function latestConfigDetails()
    external
    override
    view
    returns (
      uint32 configCount,
      uint32 blockNumber,
      bytes32 configDigest
    )
  {
    return (s_configCount, s_latestConfigBlockNumber, s_latestConfigDigest);
  }
  /**
   * @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_transmittersList;
  }
  /***************************************************************************
   * Section: Onchain Validation
   **************************************************************************/
  // Configuration for validator
  struct ValidatorConfig {
    AggregatorValidatorInterface validator;
    uint32 gasLimit;
  }
  ValidatorConfig private s_validatorConfig;
  /**
   * @notice indicates that the validator configuration has been set
   * @param previousValidator previous validator contract
   * @param previousGasLimit previous gas limit for validate calls
   * @param currentValidator current validator contract
   * @param currentGasLimit current gas limit for validate calls
   */
  event ValidatorConfigSet(
    AggregatorValidatorInterface indexed previousValidator,
    uint32 previousGasLimit,
    AggregatorValidatorInterface indexed currentValidator,
    uint32 currentGasLimit
  );
  /**
   * @notice validator configuration
   * @return validator validator contract
   * @return gasLimit gas limit for validate calls
   */
  function getValidatorConfig()
    external
    view
    returns (AggregatorValidatorInterface validator, uint32 gasLimit)
  {
    ValidatorConfig memory vc = s_validatorConfig;
    return (vc.validator, vc.gasLimit);
  }
  /**
   * @notice sets validator configuration
   * @dev set newValidator to 0x0 to disable validate calls
   * @param newValidator address of the new validator contract
   * @param newGasLimit new gas limit for validate calls
   */
  function setValidatorConfig(
    AggregatorValidatorInterface newValidator,
    uint32 newGasLimit
  )
    public
    onlyOwner()
  {
    ValidatorConfig memory previous = s_validatorConfig;
    if (previous.validator != newValidator || previous.gasLimit != newGasLimit) {
      s_validatorConfig = ValidatorConfig({
        validator: newValidator,
        gasLimit: newGasLimit
      });
      emit ValidatorConfigSet(previous.validator, previous.gasLimit, newValidator, newGasLimit);
    }
  }
  function _validateAnswer(
    uint32 aggregatorRoundId,
    int256 answer
  )
    private
  {
    ValidatorConfig memory vc = s_validatorConfig;
    if (address(vc.validator) == address(0)) {
      return;
    }
    uint32 prevAggregatorRoundId = aggregatorRoundId - 1;
    int256 prevAggregatorRoundAnswer = s_transmissions[prevAggregatorRoundId].answer;
    require(
      _callWithExactGasEvenIfTargetIsNoContract(
        vc.gasLimit,
        address(vc.validator),
        abi.encodeWithSignature(
          "validate(uint256,int256,uint256,int256)",
          uint256(prevAggregatorRoundId),
          prevAggregatorRoundAnswer,
          uint256(aggregatorRoundId),
          answer
        )
      ),
      "insufficient gas"
    );
  }
  uint256 private constant CALL_WITH_EXACT_GAS_CUSHION = 5_000;
  /**
   * @dev calls target address with exactly gasAmount gas and data as calldata
   * or reverts if at least gasAmount gas is not available.
   */
  function _callWithExactGasEvenIfTargetIsNoContract(
    uint256 gasAmount,
    address target,
    bytes memory data
  )
    private
    returns (bool sufficientGas)
  {
    // solhint-disable-next-line no-inline-assembly
    assembly {
      let g := gas()
      // Compute g -= CALL_WITH_EXACT_GAS_CUSHION and check for underflow. We
      // need the cushion since the logic following the above call to gas also
      // costs gas which we cannot account for exactly. So cushion is a
      // conservative upper bound for the cost of this logic.
      if iszero(lt(g, CALL_WITH_EXACT_GAS_CUSHION)) {
        g := sub(g, CALL_WITH_EXACT_GAS_CUSHION)
        // If g - g//64 <= gasAmount, we don't have enough gas. (We subtract g//64
        // because of EIP-150.)
        if gt(sub(g, div(g, 64)), gasAmount) {
          // Call and ignore success/return data. Note that we did not check
          // whether a contract actually exists at the target address.
          pop(call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0))
          sufficientGas := true
        }
      }
    }
  }
  /***************************************************************************
   * Section: RequestNewRound
   **************************************************************************/
  AccessControllerInterface internal s_requesterAccessController;
  /**
   * @notice emitted when a new requester access controller contract is set
   * @param old the address prior to the current setting
   * @param current the address of the new access controller contract
   */
  event RequesterAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
  /**
   * @notice emitted to immediately request a new round
   * @param requester the address of the requester
   * @param configDigest the latest transmission's configDigest
   * @param epoch the latest transmission's epoch
   * @param round the latest transmission's round
   */
  event RoundRequested(address indexed requester, bytes32 configDigest, uint32 epoch, uint8 round);
  /**
   * @notice address of the requester access controller contract
   * @return requester access controller address
   */
  function getRequesterAccessController()
    external
    view
    returns (AccessControllerInterface)
  {
    return s_requesterAccessController;
  }
  /**
   * @notice sets the requester access controller
   * @param requesterAccessController designates the address of the new requester access controller
   */
  function setRequesterAccessController(AccessControllerInterface requesterAccessController)
    public
    onlyOwner()
  {
    AccessControllerInterface oldController = s_requesterAccessController;
    if (requesterAccessController != oldController) {
      s_requesterAccessController = AccessControllerInterface(requesterAccessController);
      emit RequesterAccessControllerSet(oldController, requesterAccessController);
    }
  }
  /**
   * @notice immediately requests a new round
   * @return the aggregatorRoundId of the next round. Note: The report for this round may have been
   * transmitted (but not yet mined) *before* requestNewRound() was even called. There is *no*
   * guarantee of causality between the request and the report at aggregatorRoundId.
   */
  function requestNewRound() external returns (uint80) {
    require(msg.sender == owner() || s_requesterAccessController.hasAccess(msg.sender, msg.data),
      "Only owner&requester can call");
    uint40 latestEpochAndRound = s_hotVars.latestEpochAndRound;
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    emit RoundRequested(
      msg.sender,
      s_latestConfigDigest,
      uint32(latestEpochAndRound >> 8),
      uint8(latestEpochAndRound)
    );
    return latestAggregatorRoundId + 1;
  }
  /***************************************************************************
   * Section: Transmission
   **************************************************************************/
  /**
   * @notice indicates that a new report was transmitted
   * @param aggregatorRoundId the round to which this report was assigned
   * @param answer median of the observations attached to this report
   * @param transmitter address from which the report was transmitted
   * @param observationsTimestamp when were observations made offchain
   * @param observations observations transmitted with this report
   * @param observers i-th element is the oracle id of the oracle that made the i-th observation
   * @param juelsPerFeeCoin exchange rate between feeCoin (e.g. ETH on Ethereum) and LINK, denominated in juels
   * @param configDigest configDigest of transmission
   * @param epochAndRound least-significant byte is the OCR protocol round number, the other bytes give the big-endian OCR protocol epoch number
   */
  event NewTransmission(
    uint32 indexed aggregatorRoundId,
    int192 answer,
    address transmitter,
    uint32 observationsTimestamp,
    int192[] observations,
    bytes observers,
    int192 juelsPerFeeCoin,
    bytes32 configDigest,
    uint40 epochAndRound
  );
  // Used to relieve stack pressure in transmit
  struct Report {
    uint32 observationsTimestamp;
    bytes observers; // ith element is the index of the ith observer
    int192[] observations; // ith element is the ith observation
    int192 juelsPerFeeCoin;
  }
  // _decodeReport decodes a serialized report into a Report struct
  function _decodeReport(bytes memory rawReport)
    internal
    pure
    returns (
      Report memory
    )
  {
    uint32 observationsTimestamp;
    bytes32 rawObservers;
    int192[] memory observations;
    int192 juelsPerFeeCoin;
    (observationsTimestamp, rawObservers, observations, juelsPerFeeCoin) = abi.decode(rawReport, (uint32, bytes32, int192[], int192));
    _requireExpectedReportLength(rawReport, observations);
    uint256 numObservations = observations.length;
    bytes memory observers = abi.encodePacked(rawObservers);
    assembly {
      // we truncate observers from length 32 to the number of observations
      mstore(observers, numObservations)
    }
    return Report({
      observationsTimestamp: observationsTimestamp,
      observers: observers,
      observations: observations,
      juelsPerFeeCoin: juelsPerFeeCoin
    });
  }
  // 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
  uint256 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 start location 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
    0; // placeholder
  // Make sure the calldata length matches the inputs. Otherwise, the
  // transmitter could append an arbitrarily long (up to gas-block limit)
  // string of 0 bytes, which we would reimburse at a rate of 16 gas/byte, but
  // which would only cost the transmitter 4 gas/byte.
  function _requireExpectedMsgDataLength(
    bytes calldata report,
    bytes32[] calldata rs,
    bytes32[] calldata ss
  )
    private
    pure
  {
    // calldata will never be big enough to make this overflow
    uint256 expected = TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT +
      report.length + // one byte per entry in report
      rs.length * 32 + // 32 bytes per entry in rs
      ss.length * 32 + // 32 bytes per entry in ss
      0; // placeholder
    require(msg.data.length == expected, "calldata length mismatch");
  }
  /// @inheritdoc OCR2Abstract
  function transmit(
    // reportContext consists of:
    // reportContext[0]: ConfigDigest
    // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round
    // reportContext[2]: ExtraHash
    bytes32[3] calldata reportContext,
    bytes calldata report,
    // ECDSA signatures
    bytes32[] calldata rs,
    bytes32[] calldata ss,
    bytes32 rawVs
  )
    external
    override
  {
    // NOTE: If the arguments to this function are changed, _requireExpectedMsgDataLength and/or
    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
    uint256 initialGas = gasleft(); // This line must come first
    HotVars memory hotVars = s_hotVars;
    uint40 epochAndRound = uint40(uint256(reportContext[1]));
    require(hotVars.latestEpochAndRound < epochAndRound, "stale report");
    require(s_transmitters[msg.sender].active, "unauthorized transmitter");
    require(s_latestConfigDigest == reportContext[0], "configDigest mismatch");
    _requireExpectedMsgDataLength(report, rs, ss);
    require(rs.length == hotVars.f + 1, "wrong number of signatures");
    require(rs.length == ss.length, "signatures out of registration");
    // Verify signatures attached to report
    {
      bytes32 h = keccak256(abi.encode(keccak256(report), reportContext));
      // i-th byte counts number of sigs made by i-th signer
      uint256 signedCount = 0;
      Signer memory signer;
      for (uint i = 0; i < rs.length; i++) {
        address signerAddress = ecrecover(h, uint8(rawVs[i])+27, rs[i], ss[i]);
        signer = s_signers[signerAddress];
        require(signer.active, "signature error");
        unchecked{
          signedCount += 1 << (8 * signer.index);
        }
      }
      // The first byte of the mask can be 0, because we only ever have 31 oracles
      require(signedCount & 0x0001010101010101010101010101010101010101010101010101010101010101 == signedCount, "duplicate signer");
    }
    int192 juelsPerFeeCoin = _report(hotVars, reportContext[0], epochAndRound, report);
    _payTransmitter(hotVars, juelsPerFeeCoin, uint32(initialGas), msg.sender);
  }
  /**
   * @notice details about the most recent report
   * @return configDigest domain separation tag for the latest report
   * @return epoch epoch in which the latest report was generated
   * @return round OCR round in which the latest report was generated
   * @return latestAnswer_ median value from latest report
   * @return latestTimestamp_ when the latest report was transmitted
   */
  function latestTransmissionDetails()
    external
    view
    returns (
      bytes32 configDigest,
      uint32 epoch,
      uint8 round,
      int192 latestAnswer_,
      uint64 latestTimestamp_
    )
  {
    require(msg.sender == tx.origin, "Only callable by EOA");
    return (
      s_latestConfigDigest,
      uint32(s_hotVars.latestEpochAndRound >> 8),
      uint8(s_hotVars.latestEpochAndRound),
      s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
      s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp
    );
  }
  /// @inheritdoc OCR2Abstract
  function latestConfigDigestAndEpoch()
    external
    override
    view
    virtual
    returns(
      bool scanLogs,
      bytes32 configDigest,
      uint32 epoch
    )
  {
    return (false, s_latestConfigDigest, uint32(s_hotVars.latestEpochAndRound >> 8));
  }
  function _requireExpectedReportLength(
    bytes memory report,
    int192[] memory observations
  )
    private
    pure
  {
    uint256 expected =
      32 + // observationsTimestamp
      32 + // rawObservers
      32 + // observations offset
      32 + // juelsPerFeeCoin
      32 + // observations length
      32 * observations.length + // observations payload
      0;
    require(report.length == expected, "report length mismatch");
  }
  function _report(
    HotVars memory hotVars,
    bytes32 configDigest,
    uint40 epochAndRound,
    bytes memory rawReport
  )
    internal
    returns (int192 juelsPerFeeCoin)
  {
    Report memory report = _decodeReport(rawReport);
    require(report.observations.length <= maxNumOracles, "num observations out of bounds");
    // Offchain logic ensures that a quorum of oracles is operating on a matching set of at least
    // 2f+1 observations. By assumption, up to f of those can be faulty, which includes being
    // malformed. Conversely, more than f observations have to be well-formed and sent on chain.
    require(hotVars.f < report.observations.length, "too few values to trust median");
    hotVars.latestEpochAndRound = epochAndRound;
    // get median, validate its range, store it in new aggregator round
    int192 median = report.observations[report.observations.length/2];
    require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
    hotVars.latestAggregatorRoundId++;
    s_transmissions[hotVars.latestAggregatorRoundId] =
      Transmission({
        answer: median,
        observationsTimestamp: report.observationsTimestamp,
        transmissionTimestamp: uint32(block.timestamp)
      });
    // persist updates to hotVars
    s_hotVars = hotVars;
    emit NewTransmission(
      hotVars.latestAggregatorRoundId,
      median,
      msg.sender,
      report.observationsTimestamp,
      report.observations,
      report.observers,
      report.juelsPerFeeCoin,
      configDigest,
      epochAndRound
    );
    // Emit these for backwards compatibility with offchain consumers
    // that only support legacy events
    emit NewRound(
      hotVars.latestAggregatorRoundId,
      address(0x0), // use zero address since we don't have anybody "starting" the round here
      report.observationsTimestamp
    );
    emit AnswerUpdated(
      median,
      hotVars.latestAggregatorRoundId,
      block.timestamp
    );
    _validateAnswer(hotVars.latestAggregatorRoundId, median);
    return report.juelsPerFeeCoin;
  }
  /***************************************************************************
   * Section: v2 AggregatorInterface
   **************************************************************************/
  /**
   * @notice median from the most recent report
   */
  function latestAnswer()
    public
    override
    view
    virtual
    returns (int256)
  {
    return s_transmissions[s_hotVars.latestAggregatorRoundId].answer;
  }
  /**
   * @notice timestamp of block in which last report was transmitted
   */
  function latestTimestamp()
    public
    override
    view
    virtual
    returns (uint256)
  {
    return s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp;
  }
  /**
   * @notice Aggregator round (NOT OCR round) in which last report was transmitted
   */
  function latestRound()
    public
    override
    view
    virtual
    returns (uint256)
  {
    return s_hotVars.latestAggregatorRoundId;
  }
  /**
   * @notice median of report from given aggregator round (NOT OCR round)
   * @param roundId the aggregator round of the target report
   */
  function getAnswer(uint256 roundId)
    public
    override
    view
    virtual
    returns (int256)
  {
    if (roundId > 0xFFFFFFFF) { return 0; }
    return s_transmissions[uint32(roundId)].answer;
  }
  /**
   * @notice timestamp of block in which report from given aggregator round was transmitted
   * @param roundId aggregator round (NOT OCR round) of target report
   */
  function getTimestamp(uint256 roundId)
    public
    override
    view
    virtual
    returns (uint256)
  {
    if (roundId > 0xFFFFFFFF) { return 0; }
    return s_transmissions[uint32(roundId)].transmissionTimestamp;
  }
  /***************************************************************************
   * Section: v3 AggregatorInterface
   **************************************************************************/
  /**
   * @return answers are stored in fixed-point format, with this many digits of precision
   */
  uint8 immutable public override decimals;
  /**
   * @notice aggregator contract version
   */
  uint256 constant public override version = 6;
  string internal s_description;
  /**
   * @notice human-readable description of observable this contract is reporting on
   */
  function description()
    public
    override
    view
    virtual
    returns (string memory)
  {
    return s_description;
  }
  /**
   * @notice details for the given aggregator round
   * @param roundId target aggregator round (NOT OCR round). Must fit in uint32
   * @return roundId_ roundId
   * @return answer median of report from given roundId
   * @return startedAt timestamp of when observations were made offchain
   * @return updatedAt timestamp of block in which report from given roundId was transmitted
   * @return answeredInRound roundId
   */
  function getRoundData(uint80 roundId)
    public
    override
    view
    virtual
    returns (
      uint80 roundId_,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    if(roundId > type(uint32).max) { return (0, 0, 0, 0, 0); }
    Transmission memory transmission = s_transmissions[uint32(roundId)];
    return (
      roundId,
      transmission.answer,
      transmission.observationsTimestamp,
      transmission.transmissionTimestamp,
      roundId
    );
  }
  /**
   * @notice aggregator details for the most recently transmitted report
   * @return roundId aggregator round of latest report (NOT OCR round)
   * @return answer median of latest report
   * @return startedAt timestamp of when observations were made offchain
   * @return updatedAt timestamp of block containing latest report
   * @return answeredInRound aggregator round of latest report
   */
  function latestRoundData()
    public
    override
    view
    virtual
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    Transmission memory transmission = s_transmissions[latestAggregatorRoundId];
    return (
      latestAggregatorRoundId,
      transmission.answer,
      transmission.observationsTimestamp,
      transmission.transmissionTimestamp,
      latestAggregatorRoundId
    );
  }
  /***************************************************************************
   * Section: Configurable LINK Token
   **************************************************************************/
  // We assume that the token contract is correct. This contract is not written
  // to handle misbehaving ERC20 tokens!
  LinkTokenInterface internal s_linkToken;
  /*
   * @notice emitted when the LINK token contract is set
   * @param oldLinkToken the address of the old LINK token contract
   * @param newLinkToken the address of the new LINK token contract
   */
  event LinkTokenSet(
    LinkTokenInterface indexed oldLinkToken,
    LinkTokenInterface indexed newLinkToken
  );
  /**
   * @notice sets the LINK token contract used for paying oracles
   * @param linkToken the address of the LINK token contract
   * @param recipient remaining funds from the previous token contract are transferred
   * here
   * @dev this function will return early (without an error) without changing any state
   * if linkToken equals getLinkToken().
   * @dev this will trigger a payout so that a malicious owner cannot take from oracles
   * what is already owed to them.
   * @dev we assume that the token contract is correct. This contract is not written
   * to handle misbehaving ERC20 tokens!
   */
  function setLinkToken(
    LinkTokenInterface linkToken,
    address recipient
  ) external
    onlyOwner()
  {
    LinkTokenInterface oldLinkToken = s_linkToken;
    if (linkToken == oldLinkToken) {
      // No change, nothing to be done
      return;
    }
    // call balanceOf as a sanity check on whether we're talking to a token
    // contract
    linkToken.balanceOf(address(this));
    // we break CEI here, but that's okay because we're dealing with a correct
    // token contract (by assumption).
    _payOracles();
    uint256 remainingBalance = oldLinkToken.balanceOf(address(this));
    require(oldLinkToken.transfer(recipient, remainingBalance), "transfer remaining funds failed");
    s_linkToken = linkToken;
    emit LinkTokenSet(oldLinkToken, linkToken);
  }
  /*
   * @notice gets the LINK token contract used for paying oracles
   * @return linkToken the address of the LINK token contract
   */
  function getLinkToken()
    external
    view
    returns(LinkTokenInterface linkToken)
  {
    return s_linkToken;
  }
  /***************************************************************************
   * Section: BillingAccessController Management
   **************************************************************************/
  // Controls who can change billing parameters. A billingAdmin is not able to
  // affect any OCR protocol settings and therefore cannot tamper with the
  // liveness or integrity of a data feed. However, a billingAdmin can set
  // faulty billing parameters causing oracles to be underpaid, or causing them
  // to be paid so much that further calls to setConfig, setBilling,
  // setLinkToken will always fail due to the contract being underfunded.
  AccessControllerInterface internal s_billingAccessController;
  /**
   * @notice emitted when a new access-control contract is set
   * @param old the address prior to the current setting
   * @param current the address of the new access-control contract
   */
  event BillingAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
  function _setBillingAccessController(AccessControllerInterface billingAccessController)
    internal
  {
    AccessControllerInterface oldController = s_billingAccessController;
    if (billingAccessController != oldController) {
      s_billingAccessController = billingAccessController;
      emit BillingAccessControllerSet(
        oldController,
        billingAccessController
      );
    }
  }
  /**
   * @notice sets billingAccessController
   * @param _billingAccessController new billingAccessController contract address
   * @dev only owner can call this
   */
  function setBillingAccessController(AccessControllerInterface _billingAccessController)
    external
    onlyOwner
  {
    _setBillingAccessController(_billingAccessController);
  }
  /**
   * @notice gets billingAccessController
   * @return address of billingAccessController contract
   */
  function getBillingAccessController()
    external
    view
    returns (AccessControllerInterface)
  {
    return s_billingAccessController;
  }
  /***************************************************************************
   * Section: Billing Configuration
   **************************************************************************/
  /**
   * @notice emitted when billing parameters are set
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead incurred by accounting logic
   */
  event BillingSet(
    uint32 maximumGasPriceGwei,
    uint32 reasonableGasPriceGwei,
    uint32 observationPaymentGjuels,
    uint32 transmissionPaymentGjuels,
    uint24 accountingGas
  );
  /**
   * @notice sets billing parameters
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead incurred by accounting logic
   * @dev access control provided by billingAccessController
   */
  function setBilling(
    uint32 maximumGasPriceGwei,
    uint32 reasonableGasPriceGwei,
    uint32 observationPaymentGjuels,
    uint32 transmissionPaymentGjuels,
    uint24 accountingGas
  )
    external
  {
    AccessControllerInterface access = s_billingAccessController;
    require(msg.sender == owner() || access.hasAccess(msg.sender, msg.data),
      "Only owner&billingAdmin can call");
    _payOracles();
    s_hotVars.maximumGasPriceGwei = maximumGasPriceGwei;
    s_hotVars.reasonableGasPriceGwei = reasonableGasPriceGwei;
    s_hotVars.observationPaymentGjuels = observationPaymentGjuels;
    s_hotVars.transmissionPaymentGjuels = transmissionPaymentGjuels;
    s_hotVars.accountingGas = accountingGas;
    emit BillingSet(maximumGasPriceGwei, reasonableGasPriceGwei,
      observationPaymentGjuels, transmissionPaymentGjuels, accountingGas);
  }
  /**
   * @notice gets billing parameters
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead of the accounting logic
   */
  function getBilling()
    external
    view
    returns (
      uint32 maximumGasPriceGwei,
      uint32 reasonableGasPriceGwei,
      uint32 observationPaymentGjuels,
      uint32 transmissionPaymentGjuels,
      uint24 accountingGas
    )
  {
    return (
      s_hotVars.maximumGasPriceGwei,
      s_hotVars.reasonableGasPriceGwei,
      s_hotVars.observationPaymentGjuels,
      s_hotVars.transmissionPaymentGjuels,
      s_hotVars.accountingGas
    );
  }
  /***************************************************************************
   * Section: Payments and Withdrawals
   **************************************************************************/
  /**
   * @notice withdraws an oracle's payment from the contract
   * @param transmitter the transmitter address of the oracle
   * @dev must be called by oracle's payee address
   */
  function withdrawPayment(address transmitter)
    external
  {
    require(msg.sender == s_payees[transmitter], "Only payee can withdraw");
    _payOracle(transmitter);
  }
  /**
   * @notice query an oracle's payment amount, denominated in juels
   * @param transmitterAddress the transmitter address of the oracle
   */
  function owedPayment(address transmitterAddress)
    public
    view
    returns (uint256)
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return 0; }
    // safe from overflow:
    // s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index] <= 2**32
    // s_hotVars.observationPaymentGjuels <= 2**32
    // 1 gwei <= 2**32
    // hence juelsAmount <= 2**96
    uint256 juelsAmount =
      uint256(s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index]) *
      uint256(s_hotVars.observationPaymentGjuels) *
      (1 gwei);
    juelsAmount += transmitter.paymentJuels;
    return juelsAmount;
  }
  /**
   * @notice emitted when an oracle has been paid LINK
   * @param transmitter address from which the oracle sends reports to the transmit method
   * @param payee address to which the payment is sent
   * @param amount amount of LINK sent
   * @param linkToken address of the LINK token contract
   */
  event OraclePaid(
    address indexed transmitter,
    address indexed payee,
    uint256 amount,
    LinkTokenInterface indexed linkToken
  );
  // _payOracle pays out transmitter's balance to the corresponding payee, and zeros it out
  function _payOracle(address transmitterAddress)
    internal
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return; }
    uint256 juelsAmount = owedPayment(transmitterAddress);
    if (juelsAmount > 0) {
      address payee = s_payees[transmitterAddress];
      // Poses no re-entrancy issues, because LINK.transfer does not yield
      // control flow.
      require(s_linkToken.transfer(payee, juelsAmount), "insufficient funds");
      s_rewardFromAggregatorRoundId[transmitter.index] = s_hotVars.latestAggregatorRoundId;
      s_transmitters[transmitterAddress].paymentJuels = 0;
      emit OraclePaid(transmitterAddress, payee, juelsAmount, s_linkToken);
    }
  }
  // _payOracles pays out all transmitters, and zeros out their balances.
  //
  // It's much more gas-efficient to do this as a single operation, to avoid
  // hitting storage too much.
  function _payOracles()
    internal
  {
    unchecked {
      LinkTokenInterface linkToken = s_linkToken;
      uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
      uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
      address[] memory transmitters = s_transmittersList;
      for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
        uint256 reimbursementAmountJuels = s_transmitters[transmitters[transmitteridx]].paymentJuels;
        s_transmitters[transmitters[transmitteridx]].paymentJuels = 0;
        uint256 obsCount = latestAggregatorRoundId - rewardFromAggregatorRoundId[transmitteridx];
        uint256 juelsAmount =
          obsCount * uint256(s_hotVars.observationPaymentGjuels) * (1 gwei) + reimbursementAmountJuels;
        if (juelsAmount > 0) {
            address payee = s_payees[transmitters[transmitteridx]];
            // Poses no re-entrancy issues, because LINK.transfer does not yield
            // control flow.
            require(linkToken.transfer(payee, juelsAmount), "insufficient funds");
            rewardFromAggregatorRoundId[transmitteridx] = latestAggregatorRoundId;
            emit OraclePaid(transmitters[transmitteridx], payee, juelsAmount, linkToken);
          }
      }
      // "Zero" the accounting storage variables
      s_rewardFromAggregatorRoundId = rewardFromAggregatorRoundId;
    }
  }
  /**
   * @notice withdraw any available funds left in the contract, up to amount, after accounting for the funds due to participants in past reports
   * @param recipient address to send funds to
   * @param amount maximum amount to withdraw, denominated in LINK-wei.
   * @dev access control provided by billingAccessController
   */
  function withdrawFunds(
    address recipient,
    uint256 amount
  )
    external
  {
    require(msg.sender == owner() || s_billingAccessController.hasAccess(msg.sender, msg.data),
      "Only owner&billingAdmin can call");
    uint256 linkDue = _totalLinkDue();
    uint256 linkBalance = s_linkToken.balanceOf(address(this));
    require(linkBalance >= linkDue, "insufficient balance");
    require(s_linkToken.transfer(recipient, _min(linkBalance - linkDue, amount)), "insufficient funds");
  }
  // Total LINK due to participants in past reports (denominated in Juels).
  function _totalLinkDue()
    internal
    view
    returns (uint256 linkDue)
  {
    // Argument for overflow safety: We do all computations in
    // uint256s. The inputs to linkDue are:
    // - the <= 31 observation rewards each of which has less than
    //   64 bits (32 bits for observationPaymentGjuels, 32 bits
    //   for wei/gwei conversion). Hence 69 bits are sufficient for this part.
    // - the <= 31 gas reimbursements, each of which consists of at most 96
    //   bits. Hence 101 bits are sufficient for this part.
    // So we never need more than 102 bits.
    address[] memory transmitters = s_transmittersList;
    uint256 n = transmitters.length;
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
    for (uint i = 0; i < n; i++) {
      linkDue += latestAggregatorRoundId - rewardFromAggregatorRoundId[i];
    }
    // Convert observationPaymentGjuels to uint256, or this overflows!
    linkDue *= uint256(s_hotVars.observationPaymentGjuels) * (1 gwei);
    for (uint i = 0; i < n; i++) {
      linkDue += uint256(s_transmitters[transmitters[i]].paymentJuels);
    }
  }
  /**
   * @notice allows oracles to check that sufficient LINK balance is available
   * @return availableBalance LINK available on this contract, after accounting for outstanding obligations. can become negative
   */
  function linkAvailableForPayment()
    external
    view
    returns (int256 availableBalance)
  {
    // there are at most one billion LINK, so this cast is safe
    int256 balance = int256(s_linkToken.balanceOf(address(this)));
    // according to the argument in the definition of _totalLinkDue,
    // _totalLinkDue is never greater than 2**102, so this cast is safe
    int256 due = int256(_totalLinkDue());
    // safe from overflow according to above sizes
    return int256(balance) - int256(due);
  }
  /**
   * @notice number of observations oracle is due to be reimbursed for
   * @param transmitterAddress address used by oracle for signing or transmitting reports
   */
  function oracleObservationCount(address transmitterAddress)
    external
    view
    returns (uint32)
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return 0; }
    return s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index];
  }
  /***************************************************************************
   * Section: Transmitter Payment
   **************************************************************************/
  // Gas price at which the transmitter should be reimbursed, in gwei/gas
  function _reimbursementGasPriceGwei(
    uint256 txGasPriceGwei,
    uint256 reasonableGasPriceGwei,
    uint256 maximumGasPriceGwei
  )
    internal
    pure
    returns (uint256)
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      // Reward the transmitter for choosing an efficient gas price: if they manage
      // to come in lower than considered reasonable, give them half the savings.
      uint256 gasPriceGwei = txGasPriceGwei;
      if (txGasPriceGwei < reasonableGasPriceGwei) {
        // Give transmitter half the savings for coming in under the reasonable gas price
        gasPriceGwei += (reasonableGasPriceGwei - txGasPriceGwei) / 2;
      }
      // Don't reimburse a gas price higher than maximumGasPriceGwei
      return _min(gasPriceGwei, maximumGasPriceGwei);
    }
  }
  // gas reimbursement due the transmitter, in wei
  function _transmitterGasCostWei(
    uint256 initialGas,
    uint256 gasPriceGwei,
    uint256 callDataGas,
    uint256 accountingGas,
    uint256 leftGas
  )
    internal
    pure
    returns (uint256)
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      require(initialGas >= leftGas, "leftGas cannot exceed initialGas");
      uint256 usedGas =
        initialGas - leftGas + // observed gas usage
        callDataGas + accountingGas; // estimated gas usage
      uint256 fullGasCostWei = usedGas * gasPriceGwei * (1 gwei);
      return fullGasCostWei;
    }
  }
  function _payTransmitter(
    HotVars memory hotVars,
    int192 juelsPerFeeCoin,
    uint32 initialGas,
    address transmitter
  )
    internal
    virtual
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      // we can't deal with negative juelsPerFeeCoin, better to just not pay
      if (juelsPerFeeCoin < 0) {
        return;
      }
      // Reimburse transmitter of the report for gas usage
      uint256 gasPriceGwei = _reimbursementGasPriceGwei(
        tx.gasprice / (1 gwei), // convert to ETH-gwei units
        hotVars.reasonableGasPriceGwei,
        hotVars.maximumGasPriceGwei
      );
      // The following is only an upper bound, as it ignores the cheaper cost for
      // 0 bytes. Safe from overflow, because calldata just isn't that long.
      uint256 callDataGasCost = 16 * msg.data.length;
      uint256 gasLeft = gasleft();
      uint256 gasCostEthWei = _transmitterGasCostWei(
        uint256(initialGas),
        gasPriceGwei,
        callDataGasCost,
        hotVars.accountingGas,
        gasLeft
      );
      // Even if we assume absurdly large values, this still does not overflow. With
      // - usedGas <= 1'000'000 gas <= 2**20 gas
      // - weiPerGas <= 1'000'000 gwei <= 2**50 wei
      // - hence gasCostEthWei <= 2**70
      // - juelsPerFeeCoin <= 2**96 (more than the entire supply)
      // we still fit into 166 bits
      uint256 gasCostJuels = (gasCostEthWei * uint192(juelsPerFeeCoin))/1e18;
      uint96 oldTransmitterPaymentJuels = s_transmitters[transmitter].paymentJuels;
      uint96 newTransmitterPaymentJuels = uint96(uint256(oldTransmitterPaymentJuels) +
        gasCostJuels + uint256(hotVars.transmissionPaymentGjuels) * (1 gwei));
      // overflow *should* never happen, but if it does, let's not persist it.
      if (newTransmitterPaymentJuels < oldTransmitterPaymentJuels) {
        return;
      }
      s_transmitters[transmitter].paymentJuels = newTransmitterPaymentJuels;
    }
  }
  /***************************************************************************
   * Section: Payee Management
   **************************************************************************/
  // Addresses at which oracles want to receive payments, by transmitter address
  mapping (address /* transmitter */ => address /* payment address */)
    internal
    s_payees;
  // Payee addresses which must be approved by the owner
  mapping (address /* transmitter */ => address /* payment address */)
    internal
    s_proposedPayees;
  /**
   * @notice emitted when a transfer of an oracle's payee address has been initiated
   * @param transmitter address from which the oracle sends reports to the transmit method
   * @param current the payee address for the oracle, prior to this setting
   * @param proposed the proposed new payee address for the oracle
   */
  event PayeeshipTransferRequested(
    address indexed transmitter,
    address indexed current,
    address indexed proposed
  );
  /**
   * @notice emitted when a transfer of an oracle's payee address has been completed
   * @param transmitter address from which the oracle sends reports to the transmit method
   * @param current the payee address for the oracle, prior to this setting
   */
  event PayeeshipTransferred(
    address indexed transmitter,
    address indexed previous,
    address indexed current
  );
  /**
   * @notice sets the payees for transmitting addresses
   * @param transmitters addresses oracles use to transmit the reports
   * @param payees addresses of payees corresponding to list of transmitters
   * @dev must be called by owner
   * @dev cannot be used to change payee addresses, only to initially populate them
   */
  function setPayees(
    address[] calldata transmitters,
    address[] calldata payees
  )
    external
    onlyOwner()
  {
    require(transmitters.length == payees.length, "transmitters.size != payees.size");
    for (uint i = 0; i < transmitters.length; i++) {
      address transmitter = transmitters[i];
      address payee = payees[i];
      address currentPayee = s_payees[transmitter];
      bool zeroedOut = currentPayee == address(0);
      require(zeroedOut || currentPayee == payee, "payee already set");
      s_payees[transmitter] = payee;
      if (currentPayee != payee) {
        emit PayeeshipTransferred(transmitter, currentPayee, payee);
      }
    }
  }
  /**
   * @notice first step of payeeship transfer (safe transfer pattern)
   * @param transmitter transmitter address of oracle whose payee is changing
   * @param proposed new payee address
   * @dev can only be called by payee address
   */
  function transferPayeeship(
    address transmitter,
    address proposed
  )
    external
  {
    require(msg.sender == s_payees[transmitter], "only current payee can update");
    require(msg.sender != proposed, "cannot transfer to self");
    address previousProposed = s_proposedPayees[transmitter];
    s_proposedPayees[transmitter] = proposed;
    if (previousProposed != proposed) {
      emit PayeeshipTransferRequested(transmitter, msg.sender, proposed);
    }
  }
  /**
   * @notice second step of payeeship transfer (safe transfer pattern)
   * @param transmitter transmitter address of oracle whose payee is changing
   * @dev can only be called by proposed new payee address
   */
  function acceptPayeeship(
    address transmitter
  )
    external
  {
    require(msg.sender == s_proposedPayees[transmitter], "only proposed payees can accept");
    address currentPayee = s_payees[transmitter];
    s_payees[transmitter] = msg.sender;
    s_proposedPayees[transmitter] = address(0);
    emit PayeeshipTransferred(transmitter, currentPayee, msg.sender);
  }
  /***************************************************************************
   * Section: TypeAndVersionInterface
   **************************************************************************/
  function typeAndVersion()
    external
    override
    pure
    virtual
    returns (string memory)
  {
    return "OCR2Aggregator 1.0.0";
  }
  /***************************************************************************
   * Section: Helper Functions
   **************************************************************************/
  function _min(
    uint256 a,
    uint256 b
  )
    internal
    pure
    returns (uint256)
  {
    unchecked {
      if (a < b) { return a; }
      return b;
    }
  }
}
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;
import "./interfaces/TypeAndVersionInterface.sol";
import "./lib/ConfigDigestUtilEVMSimple.sol";
import "./OwnerIsCreator.sol";
import "./OCR2Abstract.sol";
/// @title OCRConfigurationStoreEVMSimple
/// @notice This contract stores configurations for protocol versions OCR2 and
/// above in contract storage. It uses the "EVMSimple" config digester.
contract OCRConfigurationStoreEVMSimple is TypeAndVersionInterface {
    struct ConfigurationEVMSimple {
        address[] signers;
        address[] transmitters;
        bytes onchainConfig;
        bytes offchainConfig;
        address contractAddress;
        uint64 offchainConfigVersion;
        uint32 configCount;
        uint8 f;
    }
    /// @notice a list of configurations keyed by their digest
    mapping(bytes32 => ConfigurationEVMSimple) internal s_configurations;
    /// @notice emitted when a new configuration is added
    event NewConfiguration(bytes32 indexed configDigest);
    /// @notice adds a new configuration to the store
    function addConfig(ConfigurationEVMSimple calldata configuration) external returns (bytes32) {
        bytes32 configDigest = ConfigDigestUtilEVMSimple.configDigestFromConfigData(
            block.chainid,
            configuration.contractAddress,
            configuration.configCount,
            configuration.signers,
            configuration.transmitters,
            configuration.f,
            configuration.onchainConfig,
            configuration.offchainConfigVersion,
            configuration.offchainConfig
        );
        s_configurations[configDigest] = configuration;
        emit NewConfiguration(configDigest);
        return configDigest;
    }
    /// @notice reads a configuration from the store
    function readConfig(bytes32 configDigest) external view returns (ConfigurationEVMSimple memory) {
        return s_configurations[configDigest];
    }
    /// @inheritdoc TypeAndVersionInterface
    function typeAndVersion() external override pure virtual returns (string memory)
    {
        return "OCRConfigurationStoreEVMSimple 1.0.0";
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ConfirmedOwner.sol";
/**
 * @title The OwnerIsCreator contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract OwnerIsCreator is ConfirmedOwner {
  constructor(
  )
    ConfirmedOwner(
      msg.sender
    )
  {
  }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./SimpleWriteAccessController.sol";
/**
 * @title SimpleReadAccessController
 * @notice Gives access to:
 * - any externally owned account (note that offchain actors can always read
 * any contract storage regardless of onchain access control measures, so this
 * does not weaken the access control while improving usability)
 * - accounts explicitly added to an access list
 * @dev SimpleReadAccessController is not suitable for access controlling writes
 * since it grants any externally owned account access! See
 * SimpleWriteAccessController for that.
 */
contract SimpleReadAccessController is SimpleWriteAccessController {
  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory _calldata
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return super.hasAccess(_user, _calldata) || _user == tx.origin;
  }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OwnerIsCreator.sol";
import "./interfaces/AccessControllerInterface.sol";
/**
 * @title SimpleWriteAccessController
 * @notice Gives access to accounts explicitly added to an access list by the
 * controller's owner.
 * @dev does not make any special permissions for externally, see
 * SimpleReadAccessController for that.
 */
contract SimpleWriteAccessController is AccessControllerInterface, OwnerIsCreator {
  bool public checkEnabled;
  mapping(address => bool) internal accessList;
  event AddedAccess(address user);
  event RemovedAccess(address user);
  event CheckAccessEnabled();
  event CheckAccessDisabled();
  constructor()
  // TODO
  // this is modified from the version in the Chainlink monorepo
  //  OwnerIsCreator()
  {
    checkEnabled = true;
  }
  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return accessList[_user] || !checkEnabled;
  }
  /**
   * @notice Adds an address to the access list
   * @param _user The address to add
   */
  function addAccess(address _user)
    external
    onlyOwner()
  {
    if (!accessList[_user]) {
      accessList[_user] = true;
      emit AddedAccess(_user);
    }
  }
  /**
   * @notice Removes an address from the access list
   * @param _user The address to remove
   */
  function removeAccess(address _user)
    external
    onlyOwner()
  {
    if (accessList[_user]) {
      accessList[_user] = false;
      emit RemovedAccess(_user);
    }
  }
  /**
   * @notice makes the access check enforced
   */
  function enableAccessCheck()
    external
    onlyOwner()
  {
    if (!checkEnabled) {
      checkEnabled = true;
      emit CheckAccessEnabled();
    }
  }
  /**
   * @notice makes the access check unenforced
   */
  function disableAccessCheck()
    external
    onlyOwner()
  {
    if (checkEnabled) {
      checkEnabled = false;
      emit CheckAccessDisabled();
    }
  }
  /**
   * @dev reverts if the caller does not have access
   */
  modifier checkAccess() {
    require(hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AccessControllerInterface {
  function hasAccess(address user, bytes calldata data) external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorInterface {
  function latestAnswer() external view returns (int256);
  function latestTimestamp() external view returns (uint256);
  function latestRound() external view returns (uint256);
  function getAnswer(uint256 roundId) external view returns (int256);
  function getTimestamp(uint256 roundId) external view returns (uint256);
  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
  event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./AggregatorInterface.sol";
import "./AggregatorV3Interface.sol";
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorValidatorInterface {
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  ) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);
  function approve(address spender, uint256 value) external returns (bool success);
  function balanceOf(address owner) external view returns (uint256 balance);
  function decimals() external view returns (uint8 decimalPlaces);
  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
  function increaseApproval(address spender, uint256 subtractedValue) external;
  function name() external view returns (string memory tokenName);
  function symbol() external view returns (string memory tokenSymbol);
  function totalSupply() external view returns (uint256 totalTokensIssued);
  function transfer(address to, uint256 value) external returns (bool success);
  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
  function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface OwnableInterface {
  function owner()
    external
    returns (
      address
    );
  function transferOwnership(
    address recipient
  )
    external;
  function acceptOwnership()
    external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface TypeAndVersionInterface{
  function typeAndVersion()
    external
    pure
    returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ConfigDigestUtilEVMSimple
/// @notice ConfigDigest related utility functions for "EVMSimple" config
/// digester
library ConfigDigestUtilEVMSimple {
    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 hash = 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) | (hash & ~prefixMask));
    }
}