ETH Price: $2,441.30 (+8.51%)

Transaction Decoder

Block:
15288143 at Aug-06-2022 10:19:14 AM +UTC
Transaction Fee:
0.00072776103365787 ETH $1.78
Gas Used:
125,655 Gas / 5.791739554 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x55dBfaF8...FD9Fc6f24
0x7162FF5f...08aD32434
0.558071049577442707 Eth
Nonce: 240
0.553263850742838758 Eth
Nonce: 241
0.004807198834603949
0xa1ed9309...3054c4a82 0.726402539402184265 Eth0.730481977203130344 Eth0.004079437800946079
(Ethermine)
982.466500193679840663 Eth982.466814331179840663 Eth0.0003141375

Execution Trace

ETH 0.004079437800946079 0x55dbfaf811f15bc790c52168d278cfcfd9fc6f24.c8a3bb7b( )
  • EACAggregatorProxy.STATICCALL( )
    • AccessControlledOffchainAggregator.STATICCALL( )
    • ETH 0.004079437800946079 0xa1ed930901534a5eeccc37fe131362e3054c4a82.CALL( )
      File 1 of 2: EACAggregatorProxy
      pragma solidity 0.6.6;
      
      
      /**
       * @title The Owned contract
       * @notice A contract with helpers for basic contract ownership.
       */
      contract Owned {
      
        address payable public owner;
        address private pendingOwner;
      
        event OwnershipTransferRequested(
          address indexed from,
          address indexed to
        );
        event OwnershipTransferred(
          address indexed from,
          address indexed to
        );
      
        constructor() public {
          owner = msg.sender;
        }
      
        /**
         * @dev Allows an owner to begin transferring ownership to a new address,
         * pending.
         */
        function transferOwnership(address _to)
          external
          onlyOwner()
        {
          pendingOwner = _to;
      
          emit OwnershipTransferRequested(owner, _to);
        }
      
        /**
         * @dev Allows an ownership transfer to be completed by the recipient.
         */
        function acceptOwnership()
          external
        {
          require(msg.sender == pendingOwner, "Must be proposed owner");
      
          address oldOwner = owner;
          owner = msg.sender;
          pendingOwner = address(0);
      
          emit OwnershipTransferred(oldOwner, msg.sender);
        }
      
        /**
         * @dev Reverts if called by anyone other than the contract owner.
         */
        modifier onlyOwner() {
          require(msg.sender == owner, "Only callable by owner");
          _;
        }
      
      }
      
      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);
      }
      
      interface AggregatorV3Interface {
      
        function decimals() external view returns (uint8);
        function description() external view returns (string memory);
        function version() external view returns (uint256);
      
        // getRoundData and latestRoundData should both raise "No data present"
        // if they do not have data to report, instead of returning unset values
        // which could be misinterpreted as actual reported values.
        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
          );
      
      }
      
      interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
      {
      }
      
      /**
       * @title A trusted proxy for updating where current answers are read from
       * @notice This contract provides a consistent address for the
       * CurrentAnwerInterface but delegates where it reads from to the owner, who is
       * trusted to update it.
       */
      contract AggregatorProxy is AggregatorV2V3Interface, Owned {
      
        struct Phase {
          uint16 id;
          AggregatorV2V3Interface aggregator;
        }
        Phase private currentPhase;
        AggregatorV2V3Interface public proposedAggregator;
        mapping(uint16 => AggregatorV2V3Interface) public phaseAggregators;
      
        uint256 constant private PHASE_OFFSET = 64;
        uint256 constant private PHASE_SIZE = 16;
        uint256 constant private MAX_ID = 2**(PHASE_OFFSET+PHASE_SIZE) - 1;
      
        constructor(address _aggregator) public Owned() {
          setAggregator(_aggregator);
        }
      
        /**
         * @notice Reads the current answer from aggregator delegated to.
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestAnswer()
          public
          view
          virtual
          override
          returns (int256 answer)
        {
          return currentPhase.aggregator.latestAnswer();
        }
      
        /**
         * @notice Reads the last updated height from aggregator delegated to.
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestTimestamp()
          public
          view
          virtual
          override
          returns (uint256 updatedAt)
        {
          return currentPhase.aggregator.latestTimestamp();
        }
      
        /**
         * @notice get past rounds answers
         * @param _roundId the answer number to retrieve the answer for
         *
         * @dev #[deprecated] Use getRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended getRoundData
         * instead which includes better verification information.
         */
        function getAnswer(uint256 _roundId)
          public
          view
          virtual
          override
          returns (int256 answer)
        {
          if (_roundId > MAX_ID) return 0;
      
          (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);
          AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];
          if (address(aggregator) == address(0)) return 0;
      
          return aggregator.getAnswer(aggregatorRoundId);
        }
      
        /**
         * @notice get block timestamp when an answer was last updated
         * @param _roundId the answer number to retrieve the updated timestamp for
         *
         * @dev #[deprecated] Use getRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended getRoundData
         * instead which includes better verification information.
         */
        function getTimestamp(uint256 _roundId)
          public
          view
          virtual
          override
          returns (uint256 updatedAt)
        {
          if (_roundId > MAX_ID) return 0;
      
          (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);
          AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];
          if (address(aggregator) == address(0)) return 0;
      
          return aggregator.getTimestamp(aggregatorRoundId);
        }
      
        /**
         * @notice get the latest completed round where the answer was updated. This
         * ID includes the proxy's phase, to make sure round IDs increase even when
         * switching to a newly deployed aggregator.
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestRound()
          public
          view
          virtual
          override
          returns (uint256 roundId)
        {
          Phase memory phase = currentPhase; // cache storage reads
          return addPhase(phase.id, uint64(phase.aggregator.latestRound()));
        }
      
        /**
         * @notice get data about a round. Consumers are encouraged to check
         * that they're receiving fresh data by inspecting the updatedAt and
         * answeredInRound return values.
         * Note that different underlying implementations of AggregatorV3Interface
         * have slightly different semantics for some of the return values. Consumers
         * should determine what implementations they expect to receive
         * data from and validate that they can properly handle return data from all
         * of them.
         * @param _roundId the requested round ID as presented through the proxy, this
         * is made up of the aggregator's round ID with the phase ID encoded in the
         * two highest order bytes
         * @return roundId is the round ID from the aggregator for which the data was
         * retrieved combined with an phase to ensure that round IDs get larger as
         * time moves forward.
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @dev Note that answer and updatedAt may change between queries.
         */
        function getRoundData(uint80 _roundId)
          public
          view
          virtual
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);
      
          (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 ansIn
          ) = phaseAggregators[phaseId].getRoundData(aggregatorRoundId);
      
          return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, phaseId);
        }
      
        /**
         * @notice get data about the latest round. Consumers are encouraged to check
         * that they're receiving fresh data by inspecting the updatedAt and
         * answeredInRound return values.
         * Note that different underlying implementations of AggregatorV3Interface
         * have slightly different semantics for some of the return values. Consumers
         * should determine what implementations they expect to receive
         * data from and validate that they can properly handle return data from all
         * of them.
         * @return roundId is the round ID from the aggregator for which the data was
         * retrieved combined with an phase to ensure that round IDs get larger as
         * time moves forward.
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @dev Note that answer and updatedAt may change between queries.
         */
        function latestRoundData()
          public
          view
          virtual
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          Phase memory current = currentPhase; // cache storage reads
      
          (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 ansIn
          ) = current.aggregator.latestRoundData();
      
          return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, current.id);
        }
      
        /**
         * @notice Used if an aggregator contract has been proposed.
         * @param _roundId the round ID to retrieve the round data for
         * @return roundId is the round ID for which data was retrieved
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
        */
        function proposedGetRoundData(uint80 _roundId)
          public
          view
          virtual
          hasProposal()
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return proposedAggregator.getRoundData(_roundId);
        }
      
        /**
         * @notice Used if an aggregator contract has been proposed.
         * @return roundId is the round ID for which data was retrieved
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
        */
        function proposedLatestRoundData()
          public
          view
          virtual
          hasProposal()
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return proposedAggregator.latestRoundData();
        }
      
        /**
         * @notice returns the current phase's aggregator address.
         */
        function aggregator()
          external
          view
          returns (address)
        {
          return address(currentPhase.aggregator);
        }
      
        /**
         * @notice returns the current phase's ID.
         */
        function phaseId()
          external
          view
          returns (uint16)
        {
          return currentPhase.id;
        }
      
        /**
         * @notice represents the number of decimals the aggregator responses represent.
         */
        function decimals()
          external
          view
          override
          returns (uint8)
        {
          return currentPhase.aggregator.decimals();
        }
      
        /**
         * @notice the version number representing the type of aggregator the proxy
         * points to.
         */
        function version()
          external
          view
          override
          returns (uint256)
        {
          return currentPhase.aggregator.version();
        }
      
        /**
         * @notice returns the description of the aggregator the proxy points to.
         */
        function description()
          external
          view
          override
          returns (string memory)
        {
          return currentPhase.aggregator.description();
        }
      
        /**
         * @notice Allows the owner to propose a new address for the aggregator
         * @param _aggregator The new address for the aggregator contract
         */
        function proposeAggregator(address _aggregator)
          external
          onlyOwner()
        {
          proposedAggregator = AggregatorV2V3Interface(_aggregator);
        }
      
        /**
         * @notice Allows the owner to confirm and change the address
         * to the proposed aggregator
         * @dev Reverts if the given address doesn't match what was previously
         * proposed
         * @param _aggregator The new address for the aggregator contract
         */
        function confirmAggregator(address _aggregator)
          external
          onlyOwner()
        {
          require(_aggregator == address(proposedAggregator), "Invalid proposed aggregator");
          delete proposedAggregator;
          setAggregator(_aggregator);
        }
      
      
        /*
         * Internal
         */
      
        function setAggregator(address _aggregator)
          internal
        {
          uint16 id = currentPhase.id + 1;
          currentPhase = Phase(id, AggregatorV2V3Interface(_aggregator));
          phaseAggregators[id] = AggregatorV2V3Interface(_aggregator);
        }
      
        function addPhase(
          uint16 _phase,
          uint64 _originalId
        )
          internal
          view
          returns (uint80)
        {
          return uint80(uint256(_phase) << PHASE_OFFSET | _originalId);
        }
      
        function parseIds(
          uint256 _roundId
        )
          internal
          view
          returns (uint16, uint64)
        {
          uint16 phaseId = uint16(_roundId >> PHASE_OFFSET);
          uint64 aggregatorRoundId = uint64(_roundId);
      
          return (phaseId, aggregatorRoundId);
        }
      
        function addPhaseIds(
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound,
            uint16 phaseId
        )
          internal
          view
          returns (uint80, int256, uint256, uint256, uint80)
        {
          return (
            addPhase(phaseId, uint64(roundId)),
            answer,
            startedAt,
            updatedAt,
            addPhase(phaseId, uint64(answeredInRound))
          );
        }
      
        /*
         * Modifiers
         */
      
        modifier hasProposal() {
          require(address(proposedAggregator) != address(0), "No proposed aggregator present");
          _;
        }
      
      }
      
      interface AccessControllerInterface {
        function hasAccess(address user, bytes calldata data) external view returns (bool);
      }
      
      /**
       * @title External Access Controlled Aggregator Proxy
       * @notice A trusted proxy for updating where current answers are read from
       * @notice This contract provides a consistent address for the
       * Aggregator and AggregatorV3Interface but delegates where it reads from to the owner, who is
       * trusted to update it.
       * @notice Only access enabled addresses are allowed to access getters for
       * aggregated answers and round information.
       */
      contract EACAggregatorProxy is AggregatorProxy {
      
        AccessControllerInterface public accessController;
      
        constructor(
          address _aggregator,
          address _accessController
        )
          public
          AggregatorProxy(_aggregator)
        {
          setController(_accessController);
        }
      
        /**
         * @notice Allows the owner to update the accessController contract address.
         * @param _accessController The new address for the accessController contract
         */
        function setController(address _accessController)
          public
          onlyOwner()
        {
          accessController = AccessControllerInterface(_accessController);
        }
      
        /**
         * @notice Reads the current answer from aggregator delegated to.
         * @dev overridden function to add the checkAccess() modifier
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestAnswer()
          public
          view
          override
          checkAccess()
          returns (int256)
        {
          return super.latestAnswer();
        }
      
        /**
         * @notice get the latest completed round where the answer was updated. This
         * ID includes the proxy's phase, to make sure round IDs increase even when
         * switching to a newly deployed aggregator.
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestTimestamp()
          public
          view
          override
          checkAccess()
          returns (uint256)
        {
          return super.latestTimestamp();
        }
      
        /**
         * @notice get past rounds answers
         * @param _roundId the answer number to retrieve the answer for
         * @dev overridden function to add the checkAccess() modifier
         *
         * @dev #[deprecated] Use getRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended getRoundData
         * instead which includes better verification information.
         */
        function getAnswer(uint256 _roundId)
          public
          view
          override
          checkAccess()
          returns (int256)
        {
          return super.getAnswer(_roundId);
        }
      
        /**
         * @notice get block timestamp when an answer was last updated
         * @param _roundId the answer number to retrieve the updated timestamp for
         * @dev overridden function to add the checkAccess() modifier
         *
         * @dev #[deprecated] Use getRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended getRoundData
         * instead which includes better verification information.
         */
        function getTimestamp(uint256 _roundId)
          public
          view
          override
          checkAccess()
          returns (uint256)
        {
          return super.getTimestamp(_roundId);
        }
      
        /**
         * @notice get the latest completed round where the answer was updated
         * @dev overridden function to add the checkAccess() modifier
         *
         * @dev #[deprecated] Use latestRoundData instead. This does not error if no
         * answer has been reached, it will simply return 0. Either wait to point to
         * an already answered Aggregator or use the recommended latestRoundData
         * instead which includes better verification information.
         */
        function latestRound()
          public
          view
          override
          checkAccess()
          returns (uint256)
        {
          return super.latestRound();
        }
      
        /**
         * @notice get data about a round. Consumers are encouraged to check
         * that they're receiving fresh data by inspecting the updatedAt and
         * answeredInRound return values.
         * Note that different underlying implementations of AggregatorV3Interface
         * have slightly different semantics for some of the return values. Consumers
         * should determine what implementations they expect to receive
         * data from and validate that they can properly handle return data from all
         * of them.
         * @param _roundId the round ID to retrieve the round data for
         * @return roundId is the round ID from the aggregator for which the data was
         * retrieved combined with a phase to ensure that round IDs get larger as
         * time moves forward.
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @dev Note that answer and updatedAt may change between queries.
         */
        function getRoundData(uint80 _roundId)
          public
          view
          checkAccess()
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return super.getRoundData(_roundId);
        }
      
        /**
         * @notice get data about the latest round. Consumers are encouraged to check
         * that they're receiving fresh data by inspecting the updatedAt and
         * answeredInRound return values.
         * Note that different underlying implementations of AggregatorV3Interface
         * have slightly different semantics for some of the return values. Consumers
         * should determine what implementations they expect to receive
         * data from and validate that they can properly handle return data from all
         * of them.
         * @return roundId is the round ID from the aggregator for which the data was
         * retrieved combined with a phase to ensure that round IDs get larger as
         * time moves forward.
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @dev Note that answer and updatedAt may change between queries.
         */
        function latestRoundData()
          public
          view
          checkAccess()
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return super.latestRoundData();
        }
      
        /**
         * @notice Used if an aggregator contract has been proposed.
         * @param _roundId the round ID to retrieve the round data for
         * @return roundId is the round ID for which data was retrieved
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
        */
        function proposedGetRoundData(uint80 _roundId)
          public
          view
          checkAccess()
          hasProposal()
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return super.proposedGetRoundData(_roundId);
        }
      
        /**
         * @notice Used if an aggregator contract has been proposed.
         * @return roundId is the round ID for which data was retrieved
         * @return answer is the answer for the given round
         * @return startedAt is the timestamp when the round was started.
         * (Only some AggregatorV3Interface implementations return meaningful values)
         * @return updatedAt is the timestamp when the round last was updated (i.e.
         * answer was last computed)
         * @return answeredInRound is the round ID of the round in which the answer
         * was computed.
        */
        function proposedLatestRoundData()
          public
          view
          checkAccess()
          hasProposal()
          override
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return super.proposedLatestRoundData();
        }
      
        /**
         * @dev reverts if the caller does not have access by the accessController
         * contract or is the contract itself.
         */
        modifier checkAccess() {
          AccessControllerInterface ac = accessController;
          require(address(ac) == address(0) || ac.hasAccess(msg.sender, msg.data), "No access");
          _;
        }
      }

      File 2 of 2: AccessControlledOffchainAggregator
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.1;
      import "./OffchainAggregator.sol";
      import "./SimpleReadAccessController.sol";
      /**
       * @notice Wrapper of OffchainAggregator which checks read access on Aggregator-interface methods
       */
      contract AccessControlledOffchainAggregator is OffchainAggregator, SimpleReadAccessController {
        constructor(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission,
          address _link,
          int192 _minAnswer,
          int192 _maxAnswer,
          AccessControllerInterface _billingAccessController,
          AccessControllerInterface _requesterAccessController,
          uint8 _decimals,
          string memory description
        )
          OffchainAggregator(
            _maximumGasPrice,
            _reasonableGasPrice,
            _microLinkPerEth,
            _linkGweiPerObservation,
            _linkGweiPerTransmission,
            _link,
            _minAnswer,
            _maxAnswer,
            _billingAccessController,
            _requesterAccessController,
            _decimals,
            description
          ) {
          }
        /*
         * Versioning
         */
        function typeAndVersion()
          external
          override
          pure
          virtual
          returns (string memory)
        {
          return "AccessControlledOffchainAggregator 2.0.0";
        }
        /*
         * v2 Aggregator interface
         */
        /// @inheritdoc OffchainAggregator
        function latestAnswer()
          public
          override
          view
          checkAccess()
          returns (int256)
        {
          return super.latestAnswer();
        }
        /// @inheritdoc OffchainAggregator
        function latestTimestamp()
          public
          override
          view
          checkAccess()
          returns (uint256)
        {
          return super.latestTimestamp();
        }
        /// @inheritdoc OffchainAggregator
        function latestRound()
          public
          override
          view
          checkAccess()
          returns (uint256)
        {
          return super.latestRound();
        }
        /// @inheritdoc OffchainAggregator
        function getAnswer(uint256 _roundId)
          public
          override
          view
          checkAccess()
          returns (int256)
        {
          return super.getAnswer(_roundId);
        }
        /// @inheritdoc OffchainAggregator
        function getTimestamp(uint256 _roundId)
          public
          override
          view
          checkAccess()
          returns (uint256)
        {
          return super.getTimestamp(_roundId);
        }
        /*
         * v3 Aggregator interface
         */
        /// @inheritdoc OffchainAggregator
        function description()
          public
          override
          view
          checkAccess()
          returns (string memory)
        {
          return super.description();
        }
        /// @inheritdoc OffchainAggregator
        function getRoundData(uint80 _roundId)
          public
          override
          view
          checkAccess()
          returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
          )
        {
          return super.getRoundData(_roundId);
        }
        /// @inheritdoc OffchainAggregator
        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.7.0;
      import "./AccessControllerInterface.sol";
      import "./AggregatorV2V3Interface.sol";
      import "./AggregatorValidatorInterface.sol";
      import "./LinkTokenInterface.sol";
      import "./Owned.sol";
      import "./OffchainAggregatorBilling.sol";
      import "./TypeAndVersionInterface.sol";
      /**
        * @notice Onchain verification of reports from the offchain reporting protocol
        * @dev For details on its operation, see the offchain reporting protocol design
        * @dev doc, which refers to this contract as simply the "contract".
      */
      contract OffchainAggregator is Owned, OffchainAggregatorBilling, AggregatorV2V3Interface, TypeAndVersionInterface {
        uint256 constant private maxUint32 = (1 << 32) - 1;
        // Storing these fields used on the hot path in a HotVars variable reduces the
        // retrieval of all of them to a single SLOAD. If any further fields are
        // added, make sure that storage of the struct still takes at most 32 bytes.
        struct HotVars {
          // Provides 128 bits of security against 2nd pre-image attacks, but only
          // 64 bits against collisions. This is acceptable, since a malicious owner has
          // easier way of messing up the protocol than to find hash collisions.
          bytes16 latestConfigDigest;
          uint40 latestEpochAndRound; // 32 most sig bits for epoch, 8 least sig bits for round
          // Current bound assumed on number of faulty/dishonest oracles participating
          // in the protocol, this value is referred to as f in the design
          uint8 threshold;
          // 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;
        }
        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
          uint64 timestamp;
        }
        mapping(uint32 /* aggregator round ID */ => Transmission) internal s_transmissions;
        // incremented each time a new config is posted. This count is incorporated
        // into the config digest, to prevent replay attacks.
        uint32 internal s_configCount;
        uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems
                                                   // to extract config from logs.
        // 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;
        /*
         * @param _maximumGasPrice highest gas price for which transmitter will be compensated
         * @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
         * @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
         * @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
         * @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
         * @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 _billingAccessController access controller for billing admin functions
         * @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(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission,
          address _link,
          int192 _minAnswer,
          int192 _maxAnswer,
          AccessControllerInterface _billingAccessController,
          AccessControllerInterface _requesterAccessController,
          uint8 _decimals,
          string memory _description
        )
          OffchainAggregatorBilling(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission, _link,
            _billingAccessController
          )
        {
          decimals = _decimals;
          s_description = _description;
          setRequesterAccessController(_requesterAccessController);
          setValidatorConfig(AggregatorValidatorInterface(0x0), 0);
          minAnswer = _minAnswer;
          maxAnswer = _maxAnswer;
        }
        /*
         * Versioning
         */
        function typeAndVersion()
          external
          override
          pure
          virtual
          returns (string memory)
        {
          return "OffchainAggregator 2.0.0";
        }
        /*
         * Config logic
         */
        /**
         * @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 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 threshold maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
         * @param encodedConfigVersion version of the serialization format used for "encoded" parameter
         * @param encoded serialized data used by oracles to configure their offchain operation
         */
        event ConfigSet(
          uint32 previousConfigBlockNumber,
          uint64 configCount,
          address[] signers,
          address[] transmitters,
          uint8 threshold,
          uint64 encodedConfigVersion,
          bytes encoded
        );
        // Reverts transaction if config args are invalid
        modifier checkConfigValid (
          uint256 _numSigners, uint256 _numTransmitters, uint256 _threshold
        ) {
          require(_numSigners <= maxNumOracles, "too many signers");
          require(_threshold > 0, "threshold must be positive");
          require(
            _numSigners == _numTransmitters,
            "oracle addresses out of registration"
          );
          require(_numSigners > 3*_threshold, "faulty-oracle threshold 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 _threshold number of faulty oracles the system can tolerate
         * @param _encodedConfigVersion version number for offchainEncoding schema
         * @param _encoded encoded off-chain oracle configuration
         */
        function setConfig(
          address[] calldata _signers,
          address[] calldata _transmitters,
          uint8 _threshold,
          uint64 _encodedConfigVersion,
          bytes calldata _encoded
        )
          external
          checkConfigValid(_signers.length, _transmitters.length, _threshold)
          onlyOwner()
        {
          while (s_signers.length != 0) { // remove any old signer/transmitter addresses
            uint lastIdx = s_signers.length - 1;
            address signer = s_signers[lastIdx];
            address transmitter = s_transmitters[lastIdx];
            payOracle(transmitter);
            delete s_oracles[signer];
            delete s_oracles[transmitter];
            s_signers.pop();
            s_transmitters.pop();
          }
          for (uint i = 0; i < _signers.length; i++) { // add new signer/transmitter addresses
            require(
              s_oracles[_signers[i]].role == Role.Unset,
              "repeated signer address"
            );
            s_oracles[_signers[i]] = Oracle(uint8(i), Role.Signer);
            require(s_payees[_transmitters[i]] != address(0), "payee must be set");
            require(
              s_oracles[_transmitters[i]].role == Role.Unset,
              "repeated transmitter address"
            );
            s_oracles[_transmitters[i]] = Oracle(uint8(i), Role.Transmitter);
            s_signers.push(_signers[i]);
            s_transmitters.push(_transmitters[i]);
          }
          s_hotVars.threshold = _threshold;
          uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
          s_latestConfigBlockNumber = uint32(block.number);
          s_configCount += 1;
          uint64 configCount = s_configCount;
          {
            s_hotVars.latestConfigDigest = configDigestFromConfigData(
              address(this),
              configCount,
              _signers,
              _transmitters,
              _threshold,
              _encodedConfigVersion,
              _encoded
            );
            s_hotVars.latestEpochAndRound = 0;
          }
          emit ConfigSet(
            previousConfigBlockNumber,
            configCount,
            _signers,
            _transmitters,
            _threshold,
            _encodedConfigVersion,
            _encoded
          );
        }
        function configDigestFromConfigData(
          address _contractAddress,
          uint64 _configCount,
          address[] calldata _signers,
          address[] calldata _transmitters,
          uint8 _threshold,
          uint64 _encodedConfigVersion,
          bytes calldata _encodedConfig
        ) internal pure returns (bytes16) {
          return bytes16(keccak256(abi.encode(_contractAddress, _configCount,
            _signers, _transmitters, _threshold, _encodedConfigVersion, _encodedConfig
          )));
        }
        /**
         * @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
          returns (
            uint32 configCount,
            uint32 blockNumber,
            bytes16 configDigest
          )
        {
          return (s_configCount, s_latestConfigBlockNumber, s_hotVars.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 transmitters()
          external
          view
          returns(address[] memory)
        {
            return s_transmitters;
        }
        /*
         * On-chain validation logc
         */
        // 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 validatorConfig()
          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;
          // We do not want the validator to ever prevent reporting, so we limit its
          // gas usage and catch any errors that may arise.
          try vc.validator.validate{gas: vc.gasLimit}(
            prevAggregatorRoundId,
            prevAggregatorRoundAnswer,
            _aggregatorRoundId,
            _answer
          ) {} catch {}
        }
        /*
         * requestNewRound logic
         */
        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, bytes16 configDigest, uint32 epoch, uint8 round);
        /**
         * @notice address of the requester access controller contract
         * @return requester access controller address
         */
        function requesterAccessController()
          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");
          HotVars memory hotVars = s_hotVars;
          emit RoundRequested(
            msg.sender,
            hotVars.latestConfigDigest,
            uint32(s_hotVars.latestEpochAndRound >> 8),
            uint8(s_hotVars.latestEpochAndRound)
          );
          return hotVars.latestAggregatorRoundId + 1;
        }
        /*
         * Transmission logic
         */
        /**
         * @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 this report
         * @param transmitter address from which the report was transmitted
         * @param observations observations transmitted with this report
         * @param rawReportContext signature-replay-prevention domain-separation tag
         */
        event NewTransmission(
          uint32 indexed aggregatorRoundId,
          int192 answer,
          address transmitter,
          int192[] observations,
          bytes observers,
          bytes32 rawReportContext
        );
        // decodeReport is used to check that the solidity and go code are using the
        // same format. See TestOffchainAggregator.testDecodeReport and TestReportParsing
        function decodeReport(bytes memory _report)
          internal
          pure
          returns (
            bytes32 rawReportContext,
            bytes32 rawObservers,
            int192[] memory observations
          )
        {
          (rawReportContext, rawObservers, observations) = abi.decode(_report,
            (bytes32, bytes32, int192[]));
        }
        // Used to relieve stack pressure in transmit
        struct ReportData {
          HotVars hotVars; // Only read from storage once
          bytes observers; // ith element is the index of the ith observer
          int192[] observations; // ith element is the ith observation
          bytes vs; // jth element is the v component of the jth signature
          bytes32 rawReportContext;
        }
        /*
         * @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 (
            bytes16 configDigest,
            uint32 epoch,
            uint8 round,
            int192 latestAnswer,
            uint64 latestTimestamp
          )
        {
          require(msg.sender == tx.origin, "Only callable by EOA");
          return (
            s_hotVars.latestConfigDigest,
            uint32(s_hotVars.latestEpochAndRound >> 8),
            uint8(s_hotVars.latestEpochAndRound),
            s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
            s_transmissions[s_hotVars.latestAggregatorRoundId].timestamp
          );
        }
        // 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 + // 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
          0; // placeholder
        function expectedMsgDataLength(
          bytes calldata _report, bytes32[] calldata _rs, bytes32[] calldata _ss
        ) private pure returns (uint256 length)
        {
          // calldata will never be big enough to make this overflow
          return 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
            0; // placeholder
        }
        /**
         * @notice transmit is called to post a new report to the contract
         * @param _report serialized report, which the signatures are signing. See parsing code below for format. The ith element of the observers component must be the index in s_signers of the address for the ith signature
         * @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
          bytes calldata _report,
          bytes32[] calldata _rs, bytes32[] calldata _ss, bytes32 _rawVs // signatures
        )
          external
        {
          uint256 initialGas = gasleft(); // This line must come first
          // Make sure the transmit message-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. (Appendix G of the
          // yellow paper, p. 25, for G_txdatazero and EIP 2028 for G_txdatanonzero.)
          // This could amount to reimbursement profit of 36 million gas, given a 3MB
          // zero tail.
          require(msg.data.length == expectedMsgDataLength(_report, _rs, _ss),
            "transmit message too long");
          ReportData memory r; // Relieves stack pressure
          {
            r.hotVars = s_hotVars; // cache read from storage
            bytes32 rawObservers;
            (r.rawReportContext, rawObservers, r.observations) = abi.decode(
              _report, (bytes32, bytes32, int192[])
            );
            // rawReportContext consists of:
            // 11-byte zero padding
            // 16-byte configDigest
            // 4-byte epoch
            // 1-byte round
            bytes16 configDigest = bytes16(r.rawReportContext << 88);
            require(
              r.hotVars.latestConfigDigest == configDigest,
              "configDigest mismatch"
            );
            uint40 epochAndRound = uint40(uint256(r.rawReportContext));
            // direct numerical comparison works here, because
            //
            //   ((e,r) <= (e',r')) implies (epochAndRound <= epochAndRound')
            //
            // because alphabetic ordering implies e <= e', and if e = e', then r<=r',
            // so e*256+r <= e'*256+r', because r, r' < 256
            require(r.hotVars.latestEpochAndRound < epochAndRound, "stale report");
            require(_rs.length > r.hotVars.threshold, "not enough signatures");
            require(_rs.length <= maxNumOracles, "too many signatures");
            require(_ss.length == _rs.length, "signatures out of registration");
            require(r.observations.length <= maxNumOracles,
                    "num observations out of bounds");
            require(r.observations.length > 2 * r.hotVars.threshold,
                    "too few values to trust median");
            // Copy signature parities in bytes32 _rawVs to bytes r.v
            r.vs = new bytes(_rs.length);
            for (uint8 i = 0; i < _rs.length; i++) {
              r.vs[i] = _rawVs[i];
            }
            // Copy observer identities in bytes32 rawObservers to bytes r.observers
            r.observers = new bytes(r.observations.length);
            bool[maxNumOracles] memory seen;
            for (uint8 i = 0; i < r.observations.length; i++) {
              uint8 observerIdx = uint8(rawObservers[i]);
              require(!seen[observerIdx], "observer index repeated");
              seen[observerIdx] = true;
              r.observers[i] = rawObservers[i];
            }
            Oracle memory transmitter = s_oracles[msg.sender];
            require( // Check that sender is authorized to report
              transmitter.role == Role.Transmitter &&
              msg.sender == s_transmitters[transmitter.index],
              "unauthorized transmitter"
            );
            // record epochAndRound here, so that we don't have to carry the local
            // variable in transmit. The change is reverted if something fails later.
            r.hotVars.latestEpochAndRound = epochAndRound;
          }
          { // Verify signatures attached to report
            bytes32 h = keccak256(_report);
            bool[maxNumOracles] memory signed;
            Oracle memory o;
            for (uint i = 0; i < _rs.length; i++) {
              address signer = ecrecover(h, uint8(r.vs[i])+27, _rs[i], _ss[i]);
              o = s_oracles[signer];
              require(o.role == Role.Signer, "address not authorized to sign");
              require(!signed[o.index], "non-unique signature");
              signed[o.index] = true;
            }
          }
          { // Check the report contents, and record the result
            for (uint i = 0; i < r.observations.length - 1; i++) {
              bool inOrder = r.observations[i] <= r.observations[i+1];
              require(inOrder, "observations not sorted");
            }
            int192 median = r.observations[r.observations.length/2];
            require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
            r.hotVars.latestAggregatorRoundId++;
            s_transmissions[r.hotVars.latestAggregatorRoundId] =
              Transmission(median, uint64(block.timestamp));
            emit NewTransmission(
              r.hotVars.latestAggregatorRoundId,
              median,
              msg.sender,
              r.observations,
              r.observers,
              r.rawReportContext
            );
            // Emit these for backwards compatability with offchain consumers
            // that only support legacy events
            emit NewRound(
              r.hotVars.latestAggregatorRoundId,
              address(0x0), // use zero address since we don't have anybody "starting" the round here
              block.timestamp
            );
            emit AnswerUpdated(
              median,
              r.hotVars.latestAggregatorRoundId,
              block.timestamp
            );
            validateAnswer(r.hotVars.latestAggregatorRoundId, median);
          }
          s_hotVars = r.hotVars;
          assert(initialGas < maxUint32);
          reimburseAndRewardOracles(uint32(initialGas), r.observers);
        }
        /*
         * v2 Aggregator interface
         */
        /**
         * @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].timestamp;
        }
        /**
         * @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)].timestamp;
        }
        /*
         * v3 Aggregator interface
         */
        string constant private V3_NO_DATA_ERROR = "No data present";
        /**
         * @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 = 4;
        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 block in which report from given _roundId was transmitted
         * @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
          )
        {
          require(_roundId <= 0xFFFFFFFF, V3_NO_DATA_ERROR);
          Transmission memory transmission = s_transmissions[uint32(_roundId)];
          return (
            _roundId,
            transmission.answer,
            transmission.timestamp,
            transmission.timestamp,
            _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 block containing latest report
         * @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
          )
        {
          roundId = s_hotVars.latestAggregatorRoundId;
          // Skipped for compatability with existing FluxAggregator in which latestRoundData never reverts.
          // require(roundId != 0, V3_NO_DATA_ERROR);
          Transmission memory transmission = s_transmissions[uint32(roundId)];
          return (
            roundId,
            transmission.answer,
            transmission.timestamp,
            transmission.timestamp,
            roundId
          );
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.1;
      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.7.0;
      interface AccessControllerInterface {
        function hasAccess(address user, bytes calldata data) external view returns (bool);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      import "./AggregatorInterface.sol";
      import "./AggregatorV3Interface.sol";
      interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
      {
      }// SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      interface AggregatorValidatorInterface {
        function validate(
          uint256 previousRoundId,
          int256 previousAnswer,
          uint256 currentRoundId,
          int256 currentAnswer
        ) external returns (bool);
      }// SPDX-License-Identifier: MIT
      pragma solidity ^0.7.1;
      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.7.0;
      /**
       * @title The Owned contract
       * @notice A contract with helpers for basic contract ownership.
       */
      contract Owned {
        address payable public owner;
        address private pendingOwner;
        event OwnershipTransferRequested(
          address indexed from,
          address indexed to
        );
        event OwnershipTransferred(
          address indexed from,
          address indexed to
        );
        constructor() {
          owner = msg.sender;
        }
        /**
         * @dev Allows an owner to begin transferring ownership to a new address,
         * pending.
         */
        function transferOwnership(address _to)
          external
          onlyOwner()
        {
          pendingOwner = _to;
          emit OwnershipTransferRequested(owner, _to);
        }
        /**
         * @dev Allows an ownership transfer to be completed by the recipient.
         */
        function acceptOwnership()
          external
        {
          require(msg.sender == pendingOwner, "Must be proposed owner");
          address oldOwner = owner;
          owner = msg.sender;
          pendingOwner = address(0);
          emit OwnershipTransferred(oldOwner, msg.sender);
        }
        /**
         * @dev Reverts if called by anyone other than the contract owner.
         */
        modifier onlyOwner() {
          require(msg.sender == owner, "Only callable by owner");
          _;
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      import "./AccessControllerInterface.sol";
      import "./LinkTokenInterface.sol";
      import "./Owned.sol";
      /**
       * @notice tracks administration of oracle-reward and gas-reimbursement parameters.
       * @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
       * 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 OffchainAggregatorBilling is Owned {
        // Maximum number of oracles the offchain reporting protocol is designed for
        uint256 constant internal maxNumOracles = 31;
        // Parameters for oracle payments
        struct Billing {
          // Highest compensated gas price, in ETH-gwei uints
          uint32 maximumGasPrice;
          // If gas price is less (in ETH-gwei units), transmitter gets half the savings
          uint32 reasonableGasPrice;
          // Pay transmitter back this much LINK per unit eth spent on gas
          // (1e-6LINK/ETH units)
          uint32 microLinkPerEth;
          // Fixed LINK reward for each observer, in LINK-gwei units
          uint32 linkGweiPerObservation;
          // Fixed reward for transmitter, in linkGweiPerObservation units
          uint32 linkGweiPerTransmission;
        }
        Billing internal s_billing;
        /**
        * @return LINK token contract used for billing
        */
        LinkTokenInterface immutable public LINK;
        AccessControllerInterface internal s_billingAccessController;
        // ith element is number of observation rewards due to ith process, plus one.
        // This is expected to saturate after an oracle has submitted 65,535
        // observations, or about 65535/(3*24*20) = 45 days, given a transmission
        // every 3 minutes.
        //
        // This is always one greater than the actual value, so that when the value is
        // reset to zero, we don't end up with a zero value in storage (which would
        // result in a higher gas cost, the next time the value is incremented.)
        // Calculations using this variable need to take that offset into account.
        uint16[maxNumOracles] internal s_oracleObservationsCounts;
        // 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;
        // LINK-wei-denominated reimbursements for gas used by transmitters.
        //
        // This is always one greater than the actual value, so that when the value is
        // reset to zero, we don't end up with a zero value in storage (which would
        // result in a higher gas cost, the next time the value is incremented.)
        // Calculations using this variable need to take that offset into account.
        //
        // Argument for overflow safety:
        // We have the following maximum intermediate values:
        // - 2**40 additions to this variable (epochAndRound is a uint40)
        // - 2**32 gas price in ethgwei/gas
        // - 1e9 ethwei/ethgwei
        // - 2**32 gas since the block gas limit is at ~20 million
        // - 2**32 (microlink/eth)
        // And we have 2**40 * 2**32 * 1e9 * 2**32 * 2**32 < 2**166
        // (we also divide in some places, but that only makes the value smaller)
        // We can thus safely use uint256 intermediate values for the computation
        // updating this variable.
        uint256[maxNumOracles] internal s_gasReimbursementsLinkWei;
        // 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 OffchainAggregator.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
        }
        mapping (address /* signer OR transmitter address */ => 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;
        uint256 constant private  maxUint16 = (1 << 16) - 1;
        uint256 constant internal maxUint128 = (1 << 128) - 1;
        constructor(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission,
          address _link,
          AccessControllerInterface _billingAccessController
        )
        {
          setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission);
          setBillingAccessControllerInternal(_billingAccessController);
          LINK = LinkTokenInterface(_link);
          uint16[maxNumOracles] memory counts; // See s_oracleObservationsCounts docstring
          uint256[maxNumOracles] memory gas; // see s_gasReimbursementsLinkWei docstring
          for (uint8 i = 0; i < maxNumOracles; i++) {
            counts[i] = 1;
            gas[i] = 1;
          }
          s_oracleObservationsCounts = counts;
          s_gasReimbursementsLinkWei = gas;
        }
        /**
         * @notice emitted when billing parameters are set
         * @param maximumGasPrice highest gas price for which transmitter will be compensated
         * @param reasonableGasPrice transmitter will receive reward for gas prices under this value
         * @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
         * @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
         * @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
         */
        event BillingSet(
          uint32 maximumGasPrice,
          uint32 reasonableGasPrice,
          uint32 microLinkPerEth,
          uint32 linkGweiPerObservation,
          uint32 linkGweiPerTransmission
        );
        function setBillingInternal(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission
        )
          internal
        {
          s_billing = Billing(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission);
          emit BillingSet(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission);
        }
        /**
         * @notice sets billing parameters
         * @param _maximumGasPrice highest gas price for which transmitter will be compensated
         * @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
         * @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
         * @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
         * @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
         * @dev access control provided by billingAccessController
         */
        function setBilling(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission
        )
          external
        {
          AccessControllerInterface access = s_billingAccessController;
          require(msg.sender == owner || access.hasAccess(msg.sender, msg.data),
            "Only owner&billingAdmin can call");
          payOracles();
          setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission);
        }
        /**
         * @notice gets billing parameters
         * @param maximumGasPrice highest gas price for which transmitter will be compensated
         * @param reasonableGasPrice transmitter will receive reward for gas prices under this value
         * @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
         * @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
         * @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
         */
        function getBilling()
          external
          view
          returns (
            uint32 maximumGasPrice,
            uint32 reasonableGasPrice,
            uint32 microLinkPerEth,
            uint32 linkGweiPerObservation,
            uint32 linkGweiPerTransmission
          )
        {
          Billing memory billing = s_billing;
          return (
            billing.maximumGasPrice,
            billing.reasonableGasPrice,
            billing.microLinkPerEth,
            billing.linkGweiPerObservation,
            billing.linkGweiPerTransmission
          );
        }
        /**
         * @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 setBillingAccessControllerInternal(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
        {
          setBillingAccessControllerInternal(_billingAccessController);
        }
        /**
         * @notice gets billingAccessController
         * @return address of billingAccessController contract
         */
        function billingAccessController()
          external
          view
          returns (AccessControllerInterface)
        {
          return s_billingAccessController;
        }
        /**
         * @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
         * @param _transmitter the transmitter address of the oracle
         */
        function owedPayment(address _transmitter)
          public
          view
          returns (uint256)
        {
          Oracle memory oracle = s_oracles[_transmitter];
          if (oracle.role == Role.Unset) { return 0; }
          Billing memory billing = s_billing;
          uint256 linkWeiAmount =
            uint256(s_oracleObservationsCounts[oracle.index] - 1) *
            uint256(billing.linkGweiPerObservation) *
            (1 gwei);
          linkWeiAmount += s_gasReimbursementsLinkWei[oracle.index] - 1;
          return linkWeiAmount;
        }
        /**
         * @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
         */
        event OraclePaid(address transmitter, address payee, uint256 amount);
        // payOracle pays out _transmitter's balance to the corresponding payee, and zeros it out
        function payOracle(address _transmitter)
          internal
        {
          Oracle memory oracle = s_oracles[_transmitter];
          uint256 linkWeiAmount = owedPayment(_transmitter);
          if (linkWeiAmount > 0) {
            address payee = s_payees[_transmitter];
            // Poses no re-entrancy issues, because LINK.transfer does not yield
            // control flow.
            require(LINK.transfer(payee, linkWeiAmount), "insufficient funds");
            s_oracleObservationsCounts[oracle.index] = 1; // "zero" the counts. see var's docstring
            s_gasReimbursementsLinkWei[oracle.index] = 1; // "zero" the counts. see var's docstring
            emit OraclePaid(_transmitter, payee, linkWeiAmount);
          }
        }
        // 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
        {
          Billing memory billing = s_billing;
          uint16[maxNumOracles] memory observationsCounts = s_oracleObservationsCounts;
          uint256[maxNumOracles] memory gasReimbursementsLinkWei =
            s_gasReimbursementsLinkWei;
          address[] memory transmitters = s_transmitters;
          for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
            uint256 reimbursementAmountLinkWei = gasReimbursementsLinkWei[transmitteridx] - 1;
            uint256 obsCount = observationsCounts[transmitteridx] - 1;
            uint256 linkWeiAmount =
              obsCount * uint256(billing.linkGweiPerObservation) * (1 gwei) + reimbursementAmountLinkWei;
            if (linkWeiAmount > 0) {
                address payee = s_payees[transmitters[transmitteridx]];
                // Poses no re-entrancy issues, because LINK.transfer does not yield
                // control flow.
                require(LINK.transfer(payee, linkWeiAmount), "insufficient funds");
                observationsCounts[transmitteridx] = 1;       // "zero" the counts.
                gasReimbursementsLinkWei[transmitteridx] = 1; // "zero" the counts.
                emit OraclePaid(transmitters[transmitteridx], payee, linkWeiAmount);
              }
          }
          // "Zero" the accounting storage variables
          s_oracleObservationsCounts = observationsCounts;
          s_gasReimbursementsLinkWei = gasReimbursementsLinkWei;
        }
        function oracleRewards(
          bytes memory observers,
          uint16[maxNumOracles] memory observations
        )
          internal
          pure
          returns (uint16[maxNumOracles] memory)
        {
          // reward each observer-participant with the observer reward
          for (uint obsIdx = 0; obsIdx < observers.length; obsIdx++) {
            uint8 observer = uint8(observers[obsIdx]);
            observations[observer] = saturatingAddUint16(observations[observer], 1);
          }
          return observations;
        }
        // This value needs to change if maxNumOracles is increased, or the accounting
        // calculations at the bottom of reimburseAndRewardOracles change.
        //
        // To recalculate it, run the profiler as described in
        // ../../profile/README.md, and add up the gas-usage values reported for the
        // lines in reimburseAndRewardOracles following the "gasLeft = gasleft()"
        // line. E.g., you will see output like this:
        //
        //      7        uint256 gasLeft = gasleft();
        //     29        uint256 gasCostEthWei = transmitterGasCostEthWei(
        //      9          uint256(initialGas),
        //      3          gasPrice,
        //      3          callDataGasCost,
        //      3          gasLeft
        //      .
        //      .
        //      .
        //     59        uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
        //      .
        //      .
        //      .
        //   5047        s_gasReimbursementsLinkWei[txOracle.index] =
        //    856          s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
        //     26          uint256(billing.linkGweiPerTransmission) * (1 gwei);
        //
        // If those were the only lines to be accounted for, you would add up
        // 29+9+3+3+3+59+5047+856+26=6035.
        uint256 internal constant accountingGasCost = 6035;
        // Uncomment the following declaration to compute the remaining gas cost after
        // above gasleft(). (This must exist in a base class to OffchainAggregator, so
        // it can't go in TestOffchainAggregator.)
        //
        // uint256 public gasUsedInAccounting;
        // Gas price at which the transmitter should be reimbursed, in ETH-gwei/gas
        function impliedGasPrice(
          uint256 txGasPrice,         // ETH-gwei/gas units
          uint256 reasonableGasPrice, // ETH-gwei/gas units
          uint256 maximumGasPrice     // ETH-gwei/gas units
        )
          internal
          pure
          returns (uint256)
        {
          // Reward the transmitter for choosing an efficient gas price: if they manage
          // to come in lower than considered reasonable, give them half the savings.
          //
          // The following calculations are all in units of gwei/gas, i.e. 1e-9ETH/gas
          uint256 gasPrice = txGasPrice;
          if (txGasPrice < reasonableGasPrice) {
            // Give transmitter half the savings for coming in under the reasonable gas price
            gasPrice += (reasonableGasPrice - txGasPrice) / 2;
          }
          // Don't reimburse a gas price higher than maximumGasPrice
          return min(gasPrice, maximumGasPrice);
        }
        // gas reimbursement due the transmitter, in ETH-wei
        //
        // If this function is changed, accountingGasCost needs to change, too. See
        // its docstring
        function transmitterGasCostEthWei(
          uint256 initialGas,
          uint256 gasPrice, // ETH-gwei/gas units
          uint256 callDataCost, // gas units
          uint256 gasLeft
        )
          internal
          pure
          returns (uint128 gasCostEthWei)
        {
          require(initialGas >= gasLeft, "gasLeft cannot exceed initialGas");
          uint256 gasUsed = // gas units
            initialGas - gasLeft + // observed gas usage
            callDataCost + accountingGasCost; // estimated gas usage
          // gasUsed is in gas units, gasPrice is in ETH-gwei/gas units; convert to ETH-wei
          uint256 fullGasCostEthWei = gasUsed * gasPrice * (1 gwei);
          assert(fullGasCostEthWei < maxUint128); // the entire ETH supply fits in a uint128...
          return uint128(fullGasCostEthWei);
        }
        /**
         * @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 = LINK.balanceOf(address(this));
          require(linkBalance >= linkDue, "insufficient balance");
          require(LINK.transfer(_recipient, min(linkBalance - linkDue, _amount)), "insufficient funds");
        }
        // Total LINK due to participants in past reports.
        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 billing.linkGweiPerObservation, 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 166
          //   bits (see s_gasReimbursementsLinkWei docstring). Hence 171 bits are
          //   sufficient for this part
          // In total, 172 bits are enough.
          uint16[maxNumOracles] memory observationCounts = s_oracleObservationsCounts;
          for (uint i = 0; i < maxNumOracles; i++) {
            linkDue += observationCounts[i] - 1; // Stored value is one greater than actual value
          }
          Billing memory billing = s_billing;
          // Convert linkGweiPerObservation to uint256, or this overflows!
          linkDue *= uint256(billing.linkGweiPerObservation) * (1 gwei);
          address[] memory transmitters = s_transmitters;
          uint256[maxNumOracles] memory gasReimbursementsLinkWei =
            s_gasReimbursementsLinkWei;
          for (uint i = 0; i < transmitters.length; i++) {
            linkDue += uint256(gasReimbursementsLinkWei[i]-1); // Stored value is one greater than actual value
          }
        }
        /**
         * @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(LINK.balanceOf(address(this)));
          // according to the argument in the definition of totalLINKDue,
          // totalLINKDue is never greater than 2**172, 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 _signerOrTransmitter address used by oracle for signing or transmitting reports
         */
        function oracleObservationCount(address _signerOrTransmitter)
          external
          view
          returns (uint16)
        {
          Oracle memory oracle = s_oracles[_signerOrTransmitter];
          if (oracle.role == Role.Unset) { return 0; }
          return s_oracleObservationsCounts[oracle.index] - 1;
        }
        function reimburseAndRewardOracles(
          uint32 initialGas,
          bytes memory observers
        )
          internal
        {
          Oracle memory txOracle = s_oracles[msg.sender];
          Billing memory billing = s_billing;
          // Reward oracles for providing observations. Oracles are not rewarded
          // for providing signatures, because signing is essentially free.
          s_oracleObservationsCounts =
            oracleRewards(observers, s_oracleObservationsCounts);
          // Reimburse transmitter of the report for gas usage
          require(txOracle.role == Role.Transmitter,
            "sent by undesignated transmitter"
          );
          uint256 gasPrice = impliedGasPrice(
            tx.gasprice / (1 gwei), // convert to ETH-gwei units
            billing.reasonableGasPrice,
            billing.maximumGasPrice
          );
          // 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;
          // If any changes are made to subsequent calculations, accountingGasCost
          // needs to change, too.
          uint256 gasLeft = gasleft();
          uint256 gasCostEthWei = transmitterGasCostEthWei(
            uint256(initialGas),
            gasPrice,
            callDataGasCost,
            gasLeft
          );
          // microLinkPerEth is 1e-6LINK/ETH units, gasCostEthWei is 1e-18ETH units
          // (ETH-wei), product is 1e-24LINK-wei units, dividing by 1e6 gives
          // 1e-18LINK units, i.e. LINK-wei units
          // Safe from over/underflow, since all components are non-negative,
          // gasCostEthWei will always fit into uint128 and microLinkPerEth is a
          // uint32 (128+32 < 256!).
          uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
          // Safe from overflow, because gasCostLinkWei < 2**160 and
          // billing.linkGweiPerTransmission * (1 gwei) < 2**64 and we increment
          // s_gasReimbursementsLinkWei[txOracle.index] at most 2**40 times.
          s_gasReimbursementsLinkWei[txOracle.index] =
            s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
            uint256(billing.linkGweiPerTransmission) * (1 gwei); // convert from linkGwei to linkWei
          // Uncomment next line to compute the remaining gas cost after above gasleft().
          // See OffchainAggregatorBilling.accountingGasCost docstring for more information.
          //
          // gasUsedInAccounting = gasLeft - gasleft();
        }
        /*
         * Payee management
         */
        /**
         * @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 payeee 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 payeee 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);
        }
        /*
         * Helper functions
         */
        function saturatingAddUint16(uint16 _x, uint16 _y)
          internal
          pure
          returns (uint16)
        {
          return uint16(min(uint256(_x)+uint256(_y), maxUint16));
        }
        function min(uint256 a, uint256 b)
          internal
          pure
          returns (uint256)
        {
          if (a < b) { return a; }
          return b;
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      abstract contract TypeAndVersionInterface{
        function typeAndVersion()
          external
          pure
          virtual
          returns (string memory);
      }// SPDX-License-Identifier: MIT
      pragma solidity ^0.7.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.7.0;
      interface AggregatorV3Interface {
        function decimals() external view returns (uint8);
        function description() external view returns (string memory);
        function version() external view returns (uint256);
        // getRoundData and latestRoundData should both raise "No data present"
        // if they do not have data to report, instead of returning unset values
        // which could be misinterpreted as actual reported values.
        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.7.0;
      import "./Owned.sol";
      import "./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, Owned {
        bool public checkEnabled;
        mapping(address => bool) internal accessList;
        event AddedAccess(address user);
        event RemovedAccess(address user);
        event CheckAccessEnabled();
        event CheckAccessDisabled();
        constructor()
        {
          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() {
          addAccessInternal(_user);
        }
        function addAccessInternal(address _user) internal {
          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.7.0;
      import "./AccessControlledOffchainAggregator.sol";
      import "./AccessControlTestHelper.sol";
      contract TestOffchainAggregator is AccessControlledOffchainAggregator {
        function testDecodeReport(
          bytes memory report
        ) public pure returns (bytes32, bytes32, int192[] memory)
        {
          return decodeReport(report);
        }
        constructor(
          uint32 _maximumGasPrice,
          uint32 _reasonableGasPrice,
          uint32 _microLinkPerEth,
          uint32 _linkGweiPerObservation,
          uint32 _linkGweiPerTransmission,
          address _link,
          int192 _minAnswer, int192 _maxAnswer,
          AccessControllerInterface _billingAccessController,
          AccessControllerInterface _requesterAdminAccessController
        )
          AccessControlledOffchainAggregator(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission, _link,
            _minAnswer, _maxAnswer, _billingAccessController, _requesterAdminAccessController, 0, "TEST"
          )
        {}
        function testPayee(
          address _transmitter
        )
          external
          view
          returns (address)
        {
          return s_payees[_transmitter];
        }
        function getConfigDigest() public view returns (bytes16) {
          return s_hotVars.latestConfigDigest;
        }
        function testSaturatingAddUint16(uint16 _x, uint16 _y)
          external pure returns (uint16)
        {
          return saturatingAddUint16(_x, _y);
        }
        function testImpliedGasPrice(uint256 txGasPrice, uint256 reasonableGasPrice,
          uint256 maximumGasPrice
        ) external pure returns (uint256) {
          return impliedGasPrice(txGasPrice, reasonableGasPrice, maximumGasPrice);
        }
        function testTransmitterGasCostEthWei(uint256 initialGas, uint256 gasPrice,
          uint256 callDataCost, uint256 gasLeft
        ) external pure returns (uint128) {
          return transmitterGasCostEthWei(
            initialGas, gasPrice, callDataCost, gasLeft
          );
        }
        function testSetOracleObservationCount(address _oracle, uint16 _amount) external {
          s_oracleObservationsCounts[s_oracles[_oracle].index] = _amount + 1;
        }
        function testTotalLinkDue()
          external view returns (uint256 linkDue)
        {
          return totalLINKDue();
        }
        function billingData() external view returns (
          uint16[maxNumOracles] memory observationsCounts,
          uint256[maxNumOracles] memory gasReimbursements,
          uint32 maximumGasPrice,
          uint32 reasonableGasPrice,
          uint32 microLinkPerEth,
          uint32 linkGweiPerObservation,
          uint32 linkGweiPerTransmission
        ) {
          Billing memory b = s_billing;
          return (s_oracleObservationsCounts, s_gasReimbursementsLinkWei,
            b.maximumGasPrice, b.reasonableGasPrice, b.microLinkPerEth,
            b.linkGweiPerObservation, b.linkGweiPerTransmission);
        }
        function testSetGasReimbursements(address _transmitterOrSigner, uint256 _amountLinkWei)
          external
        {
          require(s_oracles[_transmitterOrSigner].role != Role.Unset, "address unknown");
          s_gasReimbursementsLinkWei[s_oracles[_transmitterOrSigner].index] = _amountLinkWei + 1;
        }
        function testAccountingGasCost() public pure returns (uint256) {
          return accountingGasCost;
        }
        function testBurnLINK(uint256 amount) public {
            LINK.transfer(address(1), amount);
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.1;
      import "./AccessControlledOffchainAggregator.sol";
      contract AccessControlTestHelper {
        event Dummy(); // Used to silence warning that these methods are pure
        function readGetRoundData(address _aggregator, uint80 _roundID)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).getRoundData(_roundID);
          emit Dummy();
        }
        function readLatestRoundData(address _aggregator)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).latestRoundData();
          emit Dummy();
        }
        function readLatestAnswer(address _aggregator)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).latestAnswer();
          emit Dummy();
        }
        function readLatestTimestamp(address _aggregator)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).latestTimestamp();
          emit Dummy();
        }
        function readLatestRound(address _aggregator)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).latestRound();
          emit Dummy();
        }
        function readGetAnswer(address _aggregator, uint256 _roundID)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).getAnswer(_roundID);
          emit Dummy();
        }
        function readGetTimestamp(address _aggregator, uint256 _roundID)
          external
        {
          AccessControlledOffchainAggregator(_aggregator).getTimestamp(_roundID);
          emit Dummy();
        }
        function testLatestTransmissionDetails(address _aggregator) external view {
            OffchainAggregator(_aggregator).latestTransmissionDetails();
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      import "./OffchainAggregator.sol";
      // ExposedOffchainAggregator exposes certain internal OffchainAggregator
      // methods/structures so that golang code can access them, and we get
      // reliable type checking on their usage
      contract ExposedOffchainAggregator is OffchainAggregator {
        constructor()
          OffchainAggregator(
            0, 0, 0, 0, 0, address(0), 0, 0, AccessControllerInterface(address(0)), AccessControllerInterface(address(0)), 0, ""
          )
          {}
        function exposedConfigDigestFromConfigData(
          address _contractAddress,
          uint64 _configCount,
          address[] calldata _signers,
          address[] calldata _transmitters,
          uint8 _threshold,
          uint64 _encodedConfigVersion,
          bytes calldata _encodedConfig
        ) external pure returns (bytes16) {
          return configDigestFromConfigData(_contractAddress, _configCount,
            _signers, _transmitters, _threshold, _encodedConfigVersion,
            _encodedConfig);
        }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      import "./AggregatorValidatorInterface.sol";
      contract TestValidator is AggregatorValidatorInterface {
        uint32 s_minGasUse;
        uint256 s_latestRoundId;
        event Validated(
          uint256 previousRoundId,
          int256 previousAnswer,
          uint256 currentRoundId,
          int256 currentAnswer,
          uint256 initialGas
        );
        function validate(
          uint256 previousRoundId,
          int256 previousAnswer,
          uint256 currentRoundId,
          int256 currentAnswer
        ) external override returns (bool) {
          uint256 initialGas = gasleft();
          emit Validated(
            previousRoundId,
            previousAnswer,
            currentRoundId,
            currentAnswer,
            initialGas
          );
          s_latestRoundId = currentRoundId;
          uint256 minGasUse = s_minGasUse;
          while (initialGas - gasleft() < minGasUse) {}
          return true;
        }
        function setMinGasUse(uint32 minGasUse) external {
          s_minGasUse = minGasUse;
        }
        function latestRoundId() external view returns (uint256) {
          return s_latestRoundId;
        }
      }