ETH Price: $2,644.65 (+3.89%)

Transaction Decoder

Block:
19683688 at Apr-18-2024 04:59:47 PM +UTC
Transaction Fee:
0.000766414146173091 ETH $2.03
Gas Used:
63,219 Gas / 12.123161489 Gwei

Emitted Events:

287 PresaleRegistry.TokensBoughtWithEth( buyer=[Sender] 0x38ded5db21cd0c6cd85816c5b3138bdeba1c9b84, ethAmount=50000000000000000, ethPrice=3063643246800000000000, tokenPrice=69000, timestamp=1713459587 )

Account State Difference:

  Address   Before After State Difference Code
4.325127542818302039 Eth4.325127981458528895 Eth0.000000438640226856
0x38Ded5db...eBa1C9b84
0.052885416464501495 Eth
Nonce: 24
0.002119002318328404 Eth
Nonce: 25
0.050766414146173091
0xF8ba9371...4eE85F046 44.300456429225248553 Eth44.350456429225248553 Eth0.05

Execution Trace

ETH 0.05 PresaleRegistry.CALL( )
  • ETH 0.05 0xf8ba937177ee910b1f3afa43a0bc2d94ee85f046.CALL( )
  • EACAggregatorProxy.STATICCALL( )
    • AccessControlledOffchainAggregator.STATICCALL( )
      File 1 of 3: PresaleRegistry
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which allows children to implement an emergency stop
       * mechanism that can be triggered by an authorized account.
       *
       * This module is used through inheritance. It will make available the
       * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
       * the functions of your contract. Note that they will not be pausable by
       * simply including this module, only once the modifiers are put in place.
       */
      abstract contract Pausable is Context {
          /**
           * @dev Emitted when the pause is triggered by `account`.
           */
          event Paused(address account);
          /**
           * @dev Emitted when the pause is lifted by `account`.
           */
          event Unpaused(address account);
          bool private _paused;
          /**
           * @dev Initializes the contract in unpaused state.
           */
          constructor() {
              _paused = false;
          }
          /**
           * @dev Returns true if the contract is paused, and false otherwise.
           */
          function paused() public view virtual returns (bool) {
              return _paused;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is not paused.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          modifier whenNotPaused() {
              require(!paused(), "Pausable: paused");
              _;
          }
          /**
           * @dev Modifier to make a function callable only when the contract is paused.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          modifier whenPaused() {
              require(paused(), "Pausable: not paused");
              _;
          }
          /**
           * @dev Triggers stopped state.
           *
           * Requirements:
           *
           * - The contract must not be paused.
           */
          function _pause() internal virtual whenNotPaused {
              _paused = true;
              emit Paused(_msgSender());
          }
          /**
           * @dev Returns to normal state.
           *
           * Requirements:
           *
           * - The contract must be paused.
           */
          function _unpause() internal virtual whenPaused {
              _paused = false;
              emit Unpaused(_msgSender());
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant _NOT_ENTERED = 1;
          uint256 private constant _ENTERED = 2;
          uint256 private _status;
          constructor() {
              _status = _NOT_ENTERED;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and making it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              // On the first call to nonReentrant, _notEntered will be true
              require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
              // Any calls to nonReentrant after this point will fail
              _status = _ENTERED;
              _;
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = _NOT_ENTERED;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * @dev Moves `amount` tokens from the caller's account to `to`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address to, uint256 amount) external returns (bool);
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
          /**
           * @dev Moves `amount` tokens from `from` to `to` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(
              address from,
              address to,
              uint256 amount
          ) external returns (bool);
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
      pragma solidity ^0.8.0;
      import "../IERC20.sol";
      import "../../../utils/Address.sol";
      /**
       * @title SafeERC20
       * @dev Wrappers around ERC20 operations that throw on failure (when the token
       * contract returns false). Tokens that return no value (and instead revert or
       * throw on failure) are also supported, non-reverting calls are assumed to be
       * successful.
       * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
       * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
       */
      library SafeERC20 {
          using Address for address;
          function safeTransfer(
              IERC20 token,
              address to,
              uint256 value
          ) internal {
              _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
          }
          function safeTransferFrom(
              IERC20 token,
              address from,
              address to,
              uint256 value
          ) internal {
              _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
          }
          /**
           * @dev Deprecated. This function has issues similar to the ones found in
           * {IERC20-approve}, and its usage is discouraged.
           *
           * Whenever possible, use {safeIncreaseAllowance} and
           * {safeDecreaseAllowance} instead.
           */
          function safeApprove(
              IERC20 token,
              address spender,
              uint256 value
          ) internal {
              // safeApprove should only be called when setting an initial allowance,
              // or when resetting it to zero. To increase and decrease it, use
              // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
              require(
                  (value == 0) || (token.allowance(address(this), spender) == 0),
                  "SafeERC20: approve from non-zero to non-zero allowance"
              );
              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
          }
          function safeIncreaseAllowance(
              IERC20 token,
              address spender,
              uint256 value
          ) internal {
              uint256 newAllowance = token.allowance(address(this), spender) + value;
              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
          }
          function safeDecreaseAllowance(
              IERC20 token,
              address spender,
              uint256 value
          ) internal {
              unchecked {
                  uint256 oldAllowance = token.allowance(address(this), spender);
                  require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                  uint256 newAllowance = oldAllowance - value;
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
              }
          }
          /**
           * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
           * on the return value: the return value is optional (but if data is returned, it must not be false).
           * @param token The token targeted by the call.
           * @param data The call data (encoded using abi.encode or one of its variants).
           */
          function _callOptionalReturn(IERC20 token, bytes memory data) private {
              // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
              // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
              // the target address contains contract code and also asserts for success in the low-level call.
              bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
              if (returndata.length > 0) {
                  // Return data is optional
                  require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
      pragma solidity ^0.8.1;
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           * ====
           *
           * [IMPORTANT]
           * ====
           * You shouldn't rely on `isContract` to protect against flash loan attacks!
           *
           * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
           * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
           * constructor.
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize/address.code.length, which returns 0
              // for contracts in construction, since the code is only stored at the end
              // of the constructor execution.
              return account.code.length > 0;
          }
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain `call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              require(isContract(target), "Address: call to non-contract");
              (bool success, bytes memory returndata) = target.call{value: value}(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              require(isContract(target), "Address: static call to non-contract");
              (bool success, bytes memory returndata) = target.staticcall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(isContract(target), "Address: delegate call to non-contract");
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
          /**
           * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
           * revert reason using the provided one.
           *
           * _Available since v4.3._
           */
          function verifyCallResult(
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal pure returns (bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  // Look for revert reason and bubble it up if present
                  if (returndata.length > 0) {
                      // The easiest way to bubble the revert reason is using memory via assembly
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
      import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
      import "@openzeppelin/contracts/utils/Address.sol";
      import "@openzeppelin/contracts/utils/Context.sol";
      import "@openzeppelin/contracts/security/Pausable.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
      interface Aggregator {
          function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
      }
      contract PresaleRegistry is ReentrancyGuard, Ownable, Pausable {
          uint256 public currentPrice = 69000;
          address public paymentWallet = 0xF8ba937177EE910B1f3aFA43A0bC2d94eE85F046; // Actual
          IERC20 public USDTInterface = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); // USDT on Ethereum
          Aggregator public aggregatorInterface = Aggregator(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); // Chainlink on Ethereum
          event TokensBoughtWithEth(address indexed buyer, uint256 ethAmount, uint256 ethPrice, uint256 tokenPrice, uint256 timestamp);
          event TokensBoughtWithUsdt(address indexed buyer, uint256 usdtAmount, uint256 tokenPrice, uint256 timestamp);
          function pause() external onlyOwner {
              _pause();
          }
          function unpause() external onlyOwner {
              _unpause();
          }
          function buyWithUSDT(uint256 usdtAmount) external whenNotPaused returns (bool) {
              uint256 ourAllowance = USDTInterface.allowance(_msgSender(), address(this));
              require(usdtAmount <= ourAllowance, "Make sure to add enough allowance");
              (bool success, ) = address(USDTInterface).call(
                  abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), paymentWallet, usdtAmount)
              );
              require(success, "Token payment failed");
              emit TokensBoughtWithUsdt(_msgSender(), usdtAmount, currentPrice, block.timestamp);
              return true;
          }
          function buyWithEth() external payable whenNotPaused nonReentrant returns (bool) {
              require(msg.value > 0, "No ETH sent");
              sendValue(payable(paymentWallet), msg.value);
              emit TokensBoughtWithEth(_msgSender(), msg.value, getLatestEthPrice(), currentPrice, block.timestamp);
              return true;
          }
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Low balance");
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "ETH Payment failed");
          }
          function changePrice(uint256 _currentPrice) external onlyOwner {
              currentPrice = _currentPrice;
          }
          function changePaymentWallet(address _newPaymentWallet) external onlyOwner {
              paymentWallet = _newPaymentWallet;
          }
          function getLatestEthPrice() public view returns (uint256) {
              (, int256 price, , , ) = aggregatorInterface.latestRoundData();
              price = (price * (10 ** 10));
              return uint256(price);
          }
          function withdrawToken(address tokenContractAddress, uint256 amount) external onlyOwner {
              IERC20 tokenContract = IERC20(tokenContractAddress);
              SafeERC20.safeTransfer(tokenContract, msg.sender, amount);
          }
          function withdrawNative(uint256 amount) external onlyOwner {
              payable(msg.sender).transfer(amount);
          }
          // solhint-disable-next-line no-empty-blocks
          receive() external payable {}
      }
      

      File 2 of 3: 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 3 of 3: AccessControlledOffchainAggregator
      // SPDX-License-Identifier: MIT
      pragma solidity 0.7.6;
      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,
          LinkTokenInterface _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 4.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;
      interface AccessControllerInterface {
        function hasAccess(address user, bytes calldata data) external view returns (bool);
      }
      // 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;
      import "./AggregatorInterface.sol";
      import "./AggregatorV3Interface.sol";
      interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
      {
      }// 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);
        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;
      interface AggregatorValidatorInterface {
        function validate(
          uint256 previousRoundId,
          int256 previousAnswer,
          uint256 currentRoundId,
          int256 currentAnswer
        ) external returns (bool);
      }// SPDX-License-Identifier: MIT
      pragma solidity ^0.7.0;
      interface LinkTokenInterface {
        function allowance(address owner, address spender) external view returns (uint256 remaining);
        function approve(address spender, uint256 value) external returns (bool success);
        function balanceOf(address owner) external view returns (uint256 balance);
        function decimals() external view returns (uint8 decimalPlaces);
        function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
        function increaseApproval(address spender, uint256 subtractedValue) external;
        function name() external view returns (string memory tokenName);
        function symbol() external view returns (string memory tokenSymbol);
        function totalSupply() external view returns (uint256 totalTokensIssued);
        function transfer(address to, uint256 value) external returns (bool success);
        function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
        function transferFrom(address from, address to, uint256 value) external returns (bool success);
      }
      // SPDX-License-Identifier: MIT
      pragma solidity 0.7.6;
      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,
          LinkTokenInterface _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 4.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;
          require(
            callWithExactGasEvenIfTargetIsNoContract(
              vc.gasLimit,
              address(vc.validator),
              abi.encodeWithSignature(
                "validate(uint256,int256,uint256,int256)",
                uint256(prevAggregatorRoundId),
                prevAggregatorRoundAnswer,
                uint256(_aggregatorRoundId),
                _answer
              )
            ),
            "insufficient gas"
          );
        }
        uint256 private constant CALL_WITH_EXACT_GAS_CUSHION = 5_000;
        /**
         * @dev calls target address with exactly gasAmount gas and data as calldata
         * or reverts if at least gasAmount gas is not available.
         */
        function callWithExactGasEvenIfTargetIsNoContract(
          uint256 _gasAmount,
          address _target,
          bytes memory _data
        )
          private
          returns (bool sufficientGas)
        {
          // solhint-disable-next-line no-inline-assembly
          assembly {
            let g := gas()
            // Compute g -= CALL_WITH_EXACT_GAS_CUSHION and check for underflow. We
            // need the cushion since the logic following the above call to gas also
            // costs gas which we cannot account for exactly. So cushion is a
            // conservative upper bound for the cost of this logic.
            if iszero(lt(g, CALL_WITH_EXACT_GAS_CUSHION)) {
              g := sub(g, CALL_WITH_EXACT_GAS_CUSHION)
              // If g - g//64 <= _gasAmount, we don't have enough gas. (We subtract g//64
              // because of EIP-150.)
              if gt(sub(g, div(g, 64)), _gasAmount) {
                // Call and ignore success/return data. Note that we did not check
                // whether a contract actually exists at the _target address.
                pop(call(_gasAmount, _target, 0, add(_data, 0x20), mload(_data), 0, 0))
                sufficientGas := true
              }
            }
          }
        }
        /*
         * 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.6;
      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;
        // We assume that the token contract is correct. This contract is not written
        // to handle misbehaving ERC20 tokens!
        LinkTokenInterface internal s_linkToken;
        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,
          LinkTokenInterface _link,
          AccessControllerInterface _billingAccessController
        )
        {
          setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
            _linkGweiPerObservation, _linkGweiPerTransmission);
          s_linkToken = _link;
          emit LinkTokenSet(LinkTokenInterface(address(0)), _link);
          setBillingAccessControllerInternal(_billingAccessController);
          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 the LINK token contract is set
         * @param _oldLinkToken the address of the old LINK token contract
         * @param _newLinkToken the address of the new LINK token contract
         */
        event LinkTokenSet(
          LinkTokenInterface indexed _oldLinkToken,
          LinkTokenInterface indexed _newLinkToken
        );
        /*
         * @notice sets the LINK token contract used for paying oracles
         * @param _linkToken the address of the LINK token contract
         * @param _recipient remaining funds from the previous token contract are transfered
         * here
         * @dev this function will return early (without an error) without changing any state
         * if _linkToken equals getLinkToken().
         * @dev this will trigger a payout so that a malicious owner cannot take from oracles
         * what is already owed to them.
         * @dev we assume that the token contract is correct. This contract is not written
         * to handle misbehaving ERC20 tokens!
         */
        function setLinkToken(
          LinkTokenInterface _linkToken,
          address _recipient
        ) external
          onlyOwner()
        {
          LinkTokenInterface oldLinkToken = s_linkToken;
          if (_linkToken == oldLinkToken) {
            // No change, nothing to be done
            return;
          }
          // call balanceOf as a sanity check on whether we're talking to a token
          // contract
          _linkToken.balanceOf(address(this));
          // we break CEI here, but that's okay because we're dealing with a correct
          // token contract (by assumption).
          payOracles();
          uint256 remainingBalance = oldLinkToken.balanceOf(address(this));
          require(oldLinkToken.transfer(_recipient, remainingBalance), "transfer remaining funds failed");
          s_linkToken = _linkToken;
          emit LinkTokenSet(oldLinkToken, _linkToken);
        }
        /*
         * @notice gets the LINK token contract used for paying oracles
         * @return linkToken the address of the LINK token contract
         */
        function getLinkToken()
          external
          view
          returns(LinkTokenInterface linkToken)
        {
          return s_linkToken;
        }
        /**
         * @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
         * @param linkToken address of the LINK token contract
         */
        event OraclePaid(
          address indexed transmitter,
          address indexed payee,
          uint256 amount,
          LinkTokenInterface indexed linkToken
        );
        // payOracle pays out _transmitter's balance to the corresponding payee, and zeros it out
        function payOracle(address _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(s_linkToken.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, s_linkToken);
          }
        }
        // payOracles pays out all transmitters, and zeros out their balances.
        //
        // It's much more gas-efficient to do this as a single operation, to avoid
        // hitting storage too much.
        function payOracles()
          internal
        {
          Billing memory billing = s_billing;
          LinkTokenInterface linkToken = s_linkToken;
          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(linkToken.transfer(payee, linkWeiAmount), "insufficient funds");
                observationsCounts[transmitteridx] = 1;       // "zero" the counts.
                gasReimbursementsLinkWei[transmitteridx] = 1; // "zero" the counts.
                emit OraclePaid(transmitters[transmitteridx], payee, linkWeiAmount, linkToken);
              }
          }
          // "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 = s_linkToken.balanceOf(address(this));
          require(linkBalance >= linkDue, "insufficient balance");
          require(s_linkToken.transfer(_recipient, min(linkBalance - linkDue, _amount)), "insufficient funds");
        }
        // Total LINK due to participants in past reports.
        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(s_linkToken.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.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() {
          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.6;
      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.6;
      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;
      abstract contract TypeAndVersionInterface{
        function typeAndVersion()
          external
          pure
          virtual
          returns (string memory);
      }