ETH Price: $2,576.59 (-3.31%)

Transaction Decoder

Block:
13650509 at Nov-20-2021 07:17:02 AM +UTC
Transaction Fee:
0.011135787504393824 ETH $28.69
Gas Used:
93,131 Gas / 119.571222304 Gwei

Emitted Events:

35 BaseRegistrarImplementation.NameRenewed( id=106030805661672287403280037114175019832484666799368440341387782759361000707697, expires=1981698697 )
36 ETHRegistrarController.NameRenewed( name=blank, label=EA6B4F2D39E69CB00345AE42B7CCCD50EA2E6B3098AD8F1BC3FAB201685B1671, cost=11652026497313212, expires=1981698697 )

Account State Difference:

  Address   Before After State Difference Code
0x283Af0B2...A627EB7F5
(ENS: Old ETH Registrar Controller)
4,346.433884499061938355 Eth4,346.445536525559251567 Eth0.011652026497313212
0x57f1887a...Af147eA85
0xD1898665...6df34AC33
0.518095084860890414 Eth
Nonce: 300
0.495307270859183378 Eth
Nonce: 301
0.022787814001707036
(Ethermine)
2,353.284872115820757826 Eth2,353.28734808276555864 Eth0.002475966944800814

Execution Trace

ETH 0.012817229147044533 ETHRegistrarController.renew( name=blank, duration=315569520 )
  • BaseRegistrarImplementation.nameExpires( id=106030805661672287403280037114175019832484666799368440341387782759361000707697 ) => ( 1666129177 )
  • LinearPremiumPriceOracle.price( name=blank, expires=1666129177, duration=315569520 ) => ( 11652026497313212 )
    • EACAggregatorProxy.STATICCALL( )
      • AccessControlledOffchainAggregator.STATICCALL( )
      • BaseRegistrarImplementation.renew( id=106030805661672287403280037114175019832484666799368440341387782759361000707697, duration=315569520 ) => ( 1981698697 )
        • ENSRegistryWithFallback.owner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE ) => ( 0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85 )
        • ETH 0.001165202649731321 0xd1898665a01a91ac10bd2c6cb1899336df34ac33.CALL( )
          File 1 of 6: ETHRegistrarController
          // File: @ensdomains/ethregistrar/contracts/PriceOracle.sol
          
          pragma solidity >=0.4.24;
          
          interface PriceOracle {
              /**
               * @dev Returns the price to register or renew a name.
               * @param name The name being registered or renewed.
               * @param expires When the name presently expires (0 if this is a new registration).
               * @param duration How long the name is being registered or extended for, in seconds.
               * @return The price of this renewal or registration, in wei.
               */
              function price(string calldata name, uint expires, uint duration) external view returns(uint);
          }
          
          // File: @ensdomains/ens/contracts/ENS.sol
          
          pragma solidity >=0.4.24;
          
          interface ENS {
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          
              // Logged when an operator is added or removed.
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external;
              function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external;
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns(bytes32);
              function setResolver(bytes32 node, address resolver) external;
              function setOwner(bytes32 node, address owner) external;
              function setTTL(bytes32 node, uint64 ttl) external;
              function setApprovalForAll(address operator, bool approved) external;
              function owner(bytes32 node) external view returns (address);
              function resolver(bytes32 node) external view returns (address);
              function ttl(bytes32 node) external view returns (uint64);
              function recordExists(bytes32 node) external view returns (bool);
              function isApprovedForAll(address owner, address operator) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title IERC165
           * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
           */
          interface IERC165 {
              /**
               * @notice Query if a contract implements an interface
               * @param interfaceId The interface identifier, as specified in ERC-165
               * @dev Interface identification is specified in ERC-165. This function
               * uses less than 30,000 gas.
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic interface
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract IERC721 is IERC165 {
              event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
              event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function balanceOf(address owner) public view returns (uint256 balance);
              function ownerOf(uint256 tokenId) public view returns (address owner);
          
              function approve(address to, uint256 tokenId) public;
              function getApproved(uint256 tokenId) public view returns (address operator);
          
              function setApprovalForAll(address operator, bool _approved) public;
              function isApprovedForAll(address owner, address operator) public view returns (bool);
          
              function transferFrom(address from, address to, uint256 tokenId) public;
              function safeTransferFrom(address from, address to, uint256 tokenId) public;
          
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: @ensdomains/ethregistrar/contracts/BaseRegistrar.sol
          
          pragma solidity >=0.4.24;
          
          
          
          
          contract BaseRegistrar is IERC721, Ownable {
              uint constant public GRACE_PERIOD = 90 days;
          
              event ControllerAdded(address indexed controller);
              event ControllerRemoved(address indexed controller);
              event NameMigrated(uint256 indexed id, address indexed owner, uint expires);
              event NameRegistered(uint256 indexed id, address indexed owner, uint expires);
              event NameRenewed(uint256 indexed id, uint expires);
          
              // The ENS registry
              ENS public ens;
          
              // The namehash of the TLD this registrar owns (eg, .eth)
              bytes32 public baseNode;
          
              // A map of addresses that are authorised to register and renew names.
              mapping(address=>bool) public controllers;
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external;
          
              // Revoke controller permission for an address.
              function removeController(address controller) external;
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external;
          
              // Returns the expiration timestamp of the specified label hash.
              function nameExpires(uint256 id) external view returns(uint);
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool);
          
              /**
               * @dev Register a name.
               */
              function register(uint256 id, address owner, uint duration) external returns(uint);
          
              function renew(uint256 id, uint duration) external returns(uint);
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external;
          }
          
          // File: @ensdomains/ethregistrar/contracts/StringUtils.sol
          
          pragma solidity >=0.4.24;
          
          library StringUtils {
              /**
               * @dev Returns the length of a given string
               *
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string memory s) internal pure returns (uint) {
                  uint len;
                  uint i = 0;
                  uint bytelength = bytes(s).length;
                  for(len = 0; i < bytelength; len++) {
                      byte b = bytes(s)[i];
                      if(b < 0x80) {
                          i += 1;
                      } else if (b < 0xE0) {
                          i += 2;
                      } else if (b < 0xF0) {
                          i += 3;
                      } else if (b < 0xF8) {
                          i += 4;
                      } else if (b < 0xFC) {
                          i += 5;
                      } else {
                          i += 6;
                      }
                  }
                  return len;
              }
          }
          
          // File: @ensdomains/resolver/contracts/Resolver.sol
          
          pragma solidity >=0.4.25;
          
          /**
           * A generic resolver interface which includes all the functions including the ones deprecated
           */
          interface Resolver{
              event AddrChanged(bytes32 indexed node, address a);
              event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);
              event NameChanged(bytes32 indexed node, string name);
              event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
              event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
              event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
              event ContenthashChanged(bytes32 indexed node, bytes hash);
              /* Deprecated events */
              event ContentChanged(bytes32 indexed node, bytes32 hash);
          
              function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);
              function addr(bytes32 node) external view returns (address);
              function addr(bytes32 node, uint coinType) external view returns(bytes memory);
              function contenthash(bytes32 node) external view returns (bytes memory);
              function dnsrr(bytes32 node) external view returns (bytes memory);
              function name(bytes32 node) external view returns (string memory);
              function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
              function text(bytes32 node, string calldata key) external view returns (string memory);
              function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
          
              function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;
              function setAddr(bytes32 node, address addr) external;
              function setAddr(bytes32 node, uint coinType, bytes calldata a) external;
              function setContenthash(bytes32 node, bytes calldata hash) external;
              function setDnsrr(bytes32 node, bytes calldata data) external;
              function setName(bytes32 node, string calldata _name) external;
              function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;
              function setText(bytes32 node, string calldata key, string calldata value) external;
              function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;
          
              function supportsInterface(bytes4 interfaceID) external pure returns (bool);
          
              /* Deprecated functions */
              function content(bytes32 node) external view returns (bytes32);
              function multihash(bytes32 node) external view returns (bytes memory);
              function setContent(bytes32 node, bytes32 hash) external;
              function setMultihash(bytes32 node, bytes calldata hash) external;
          }
          
          // File: @ensdomains/ethregistrar/contracts/ETHRegistrarController.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          
          /**
           * @dev A registrar controller for registering and renewing names at fixed cost.
           */
          contract ETHRegistrarController is Ownable {
              using StringUtils for *;
          
              uint constant public MIN_REGISTRATION_DURATION = 28 days;
          
              bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
              bytes4 constant private COMMITMENT_CONTROLLER_ID = bytes4(
                  keccak256("rentPrice(string,uint256)") ^
                  keccak256("available(string)") ^
                  keccak256("makeCommitment(string,address,bytes32)") ^
                  keccak256("commit(bytes32)") ^
                  keccak256("register(string,address,uint256,bytes32)") ^
                  keccak256("renew(string,uint256)")
              );
          
              bytes4 constant private COMMITMENT_WITH_CONFIG_CONTROLLER_ID = bytes4(
                  keccak256("registerWithConfig(string,address,uint256,bytes32,address,address)") ^
                  keccak256("makeCommitmentWithConfig(string,address,bytes32,address,address)")
              );
          
              BaseRegistrar base;
              PriceOracle prices;
              uint public minCommitmentAge;
              uint public maxCommitmentAge;
          
              mapping(bytes32=>uint) public commitments;
          
              event NameRegistered(string name, bytes32 indexed label, address indexed owner, uint cost, uint expires);
              event NameRenewed(string name, bytes32 indexed label, uint cost, uint expires);
              event NewPriceOracle(address indexed oracle);
          
              constructor(BaseRegistrar _base, PriceOracle _prices, uint _minCommitmentAge, uint _maxCommitmentAge) public {
                  require(_maxCommitmentAge > _minCommitmentAge);
          
                  base = _base;
                  prices = _prices;
                  minCommitmentAge = _minCommitmentAge;
                  maxCommitmentAge = _maxCommitmentAge;
              }
          
              function rentPrice(string memory name, uint duration) view public returns(uint) {
                  bytes32 hash = keccak256(bytes(name));
                  return prices.price(name, base.nameExpires(uint256(hash)), duration);
              }
          
              function valid(string memory name) public pure returns(bool) {
                  return name.strlen() >= 3;
              }
          
              function available(string memory name) public view returns(bool) {
                  bytes32 label = keccak256(bytes(name));
                  return valid(name) && base.available(uint256(label));
              }
          
              function makeCommitment(string memory name, address owner, bytes32 secret) pure public returns(bytes32) {
                  return makeCommitmentWithConfig(name, owner, secret, address(0), address(0));
              }
          
              function makeCommitmentWithConfig(string memory name, address owner, bytes32 secret, address resolver, address addr) pure public returns(bytes32) {
                  bytes32 label = keccak256(bytes(name));
                  if (resolver == address(0) && addr == address(0)) {
                      return keccak256(abi.encodePacked(label, owner, secret));
                  }
                  require(resolver != address(0));
                  return keccak256(abi.encodePacked(label, owner, resolver, addr, secret));
              }
          
              function commit(bytes32 commitment) public {
                  require(commitments[commitment] + maxCommitmentAge < now);
                  commitments[commitment] = now;
              }
          
              function register(string calldata name, address owner, uint duration, bytes32 secret) external payable {
                registerWithConfig(name, owner, duration, secret, address(0), address(0));
              }
          
              function registerWithConfig(string memory name, address owner, uint duration, bytes32 secret, address resolver, address addr) public payable {
                  bytes32 commitment = makeCommitmentWithConfig(name, owner, secret, resolver, addr);
                  uint cost = _consumeCommitment(name, duration, commitment);
          
                  bytes32 label = keccak256(bytes(name));
                  uint256 tokenId = uint256(label);
          
                  uint expires;
                  if(resolver != address(0)) {
                      // Set this contract as the (temporary) owner, giving it
                      // permission to set up the resolver.
                      expires = base.register(tokenId, address(this), duration);
          
                      // The nodehash of this label
                      bytes32 nodehash = keccak256(abi.encodePacked(base.baseNode(), label));
          
                      // Set the resolver
                      base.ens().setResolver(nodehash, resolver);
          
                      // Configure the resolver
                      if (addr != address(0)) {
                          Resolver(resolver).setAddr(nodehash, addr);
                      }
          
                      // Now transfer full ownership to the expeceted owner
                      base.reclaim(tokenId, owner);
                      base.transferFrom(address(this), owner, tokenId);
                  } else {
                      require(addr == address(0));
                      expires = base.register(tokenId, owner, duration);
                  }
          
                  emit NameRegistered(name, label, owner, cost, expires);
          
                  // Refund any extra payment
                  if(msg.value > cost) {
                      msg.sender.transfer(msg.value - cost);
                  }
              }
          
              function renew(string calldata name, uint duration) external payable {
                  uint cost = rentPrice(name, duration);
                  require(msg.value >= cost);
          
                  bytes32 label = keccak256(bytes(name));
                  uint expires = base.renew(uint256(label), duration);
          
                  if(msg.value > cost) {
                      msg.sender.transfer(msg.value - cost);
                  }
          
                  emit NameRenewed(name, label, cost, expires);
              }
          
              function setPriceOracle(PriceOracle _prices) public onlyOwner {
                  prices = _prices;
                  emit NewPriceOracle(address(prices));
              }
          
              function setCommitmentAges(uint _minCommitmentAge, uint _maxCommitmentAge) public onlyOwner {
                  minCommitmentAge = _minCommitmentAge;
                  maxCommitmentAge = _maxCommitmentAge;
              }
          
              function withdraw() public onlyOwner {
                  msg.sender.transfer(address(this).balance);
              }
          
              function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
                  return interfaceID == INTERFACE_META_ID ||
                         interfaceID == COMMITMENT_CONTROLLER_ID ||
                         interfaceID == COMMITMENT_WITH_CONFIG_CONTROLLER_ID;
              }
          
              function _consumeCommitment(string memory name, uint duration, bytes32 commitment) internal returns (uint256) {
                  // Require a valid commitment
                  require(commitments[commitment] + minCommitmentAge <= now);
          
                  // If the commitment is too old, or the name is registered, stop
                  require(commitments[commitment] + maxCommitmentAge > now);
                  require(available(name));
          
                  delete(commitments[commitment]);
          
                  uint cost = rentPrice(name, duration);
                  require(duration >= MIN_REGISTRATION_DURATION);
                  require(msg.value >= cost);
          
                  return cost;
              }
          }

          File 2 of 6: BaseRegistrarImplementation
          // File: @ensdomains/ens/contracts/ENS.sol
          
          pragma solidity >=0.4.24;
          
          interface ENS {
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          
              // Logged when an operator is added or removed.
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external;
              function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external;
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns(bytes32);
              function setResolver(bytes32 node, address resolver) external;
              function setOwner(bytes32 node, address owner) external;
              function setTTL(bytes32 node, uint64 ttl) external;
              function setApprovalForAll(address operator, bool approved) external;
              function owner(bytes32 node) external view returns (address);
              function resolver(bytes32 node) external view returns (address);
              function ttl(bytes32 node) external view returns (uint64);
              function recordExists(bytes32 node) external view returns (bool);
              function isApprovedForAll(address owner, address operator) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title IERC165
           * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
           */
          interface IERC165 {
              /**
               * @notice Query if a contract implements an interface
               * @param interfaceId The interface identifier, as specified in ERC-165
               * @dev Interface identification is specified in ERC-165. This function
               * uses less than 30,000 gas.
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic interface
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract IERC721 is IERC165 {
              event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
              event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function balanceOf(address owner) public view returns (uint256 balance);
              function ownerOf(uint256 tokenId) public view returns (address owner);
          
              function approve(address to, uint256 tokenId) public;
              function getApproved(uint256 tokenId) public view returns (address operator);
          
              function setApprovalForAll(address operator, bool _approved) public;
              function isApprovedForAll(address owner, address operator) public view returns (bool);
          
              function transferFrom(address from, address to, uint256 tokenId) public;
              function safeTransferFrom(address from, address to, uint256 tokenId) public;
          
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title ERC721 token receiver interface
           * @dev Interface for any contract that wants to support safeTransfers
           * from ERC721 asset contracts.
           */
          contract IERC721Receiver {
              /**
               * @notice Handle the receipt of an NFT
               * @dev The ERC721 smart contract calls this function on the recipient
               * after a `safeTransfer`. This function MUST return the function selector,
               * otherwise the caller will revert the transaction. The selector to be
               * returned can be obtained as `this.onERC721Received.selector`. This
               * function MAY throw to revert and reject the transfer.
               * Note: the ERC721 contract address is always the message sender.
               * @param operator The address which called `safeTransferFrom` function
               * @param from The address which previously owned the token
               * @param tokenId The NFT identifier which is being transferred
               * @param data Additional data with no specified format
               * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
               */
              function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
              public returns (bytes4);
          }
          
          // File: openzeppelin-solidity/contracts/math/SafeMath.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title SafeMath
           * @dev Unsigned math operations with safety checks that revert on error
           */
          library SafeMath {
              /**
              * @dev Multiplies two unsigned integers, reverts on overflow.
              */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
          
                  uint256 c = a * b;
                  require(c / a == b);
          
                  return c;
              }
          
              /**
              * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
              */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Solidity only automatically asserts when dividing by 0
                  require(b > 0);
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
              * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
          
                  return c;
              }
          
              /**
              * @dev Adds two unsigned integers, reverts on overflow.
              */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
          
                  return c;
              }
          
              /**
              * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
              * reverts when dividing by zero.
              */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0);
                  return a % b;
              }
          }
          
          // File: openzeppelin-solidity/contracts/utils/Address.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * Utility library of inline functions on addresses
           */
          library Address {
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               * as the code is not actually created until after the constructor finishes.
               * @param account address of the account to check
               * @return whether the target address is a contract
               */
              function isContract(address account) internal view returns (bool) {
                  uint256 size;
                  // XXX Currently there is no better way to check if there is a contract in an address
                  // than to check the size of the code at that address.
                  // See https://ethereum.stackexchange.com/a/14016/36603
                  // for more details about how this works.
                  // TODO Check this again before the Serenity release, because all addresses will be
                  // contracts then.
                  // solhint-disable-next-line no-inline-assembly
                  assembly { size := extcodesize(account) }
                  return size > 0;
              }
          }
          
          // File: openzeppelin-solidity/contracts/introspection/ERC165.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC165
           * @author Matt Condon (@shrugs)
           * @dev Implements ERC165 using a lookup table.
           */
          contract ERC165 is IERC165 {
              bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
              /**
               * 0x01ffc9a7 ===
               *     bytes4(keccak256('supportsInterface(bytes4)'))
               */
          
              /**
               * @dev a mapping of interface id to whether or not it's supported
               */
              mapping(bytes4 => bool) private _supportedInterfaces;
          
              /**
               * @dev A contract implementing SupportsInterfaceWithLookup
               * implement ERC165 itself
               */
              constructor () internal {
                  _registerInterface(_INTERFACE_ID_ERC165);
              }
          
              /**
               * @dev implement supportsInterface(bytes4) using a lookup table
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool) {
                  return _supportedInterfaces[interfaceId];
              }
          
              /**
               * @dev internal method for registering an interface
               */
              function _registerInterface(bytes4 interfaceId) internal {
                  require(interfaceId != 0xffffffff);
                  _supportedInterfaces[interfaceId] = true;
              }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/ERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic implementation
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract ERC721 is ERC165, IERC721 {
              using SafeMath for uint256;
              using Address for address;
          
              // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
              // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
              bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
          
              // Mapping from token ID to owner
              mapping (uint256 => address) private _tokenOwner;
          
              // Mapping from token ID to approved address
              mapping (uint256 => address) private _tokenApprovals;
          
              // Mapping from owner to number of owned token
              mapping (address => uint256) private _ownedTokensCount;
          
              // Mapping from owner to operator approvals
              mapping (address => mapping (address => bool)) private _operatorApprovals;
          
              bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
              /*
               * 0x80ac58cd ===
               *     bytes4(keccak256('balanceOf(address)')) ^
               *     bytes4(keccak256('ownerOf(uint256)')) ^
               *     bytes4(keccak256('approve(address,uint256)')) ^
               *     bytes4(keccak256('getApproved(uint256)')) ^
               *     bytes4(keccak256('setApprovalForAll(address,bool)')) ^
               *     bytes4(keccak256('isApprovedForAll(address,address)')) ^
               *     bytes4(keccak256('transferFrom(address,address,uint256)')) ^
               *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
               *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
               */
          
              constructor () public {
                  // register the supported interfaces to conform to ERC721 via ERC165
                  _registerInterface(_INTERFACE_ID_ERC721);
              }
          
              /**
               * @dev Gets the balance of the specified address
               * @param owner address to query the balance of
               * @return uint256 representing the amount owned by the passed address
               */
              function balanceOf(address owner) public view returns (uint256) {
                  require(owner != address(0));
                  return _ownedTokensCount[owner];
              }
          
              /**
               * @dev Gets the owner of the specified token ID
               * @param tokenId uint256 ID of the token to query the owner of
               * @return owner address currently marked as the owner of the given token ID
               */
              function ownerOf(uint256 tokenId) public view returns (address) {
                  address owner = _tokenOwner[tokenId];
                  require(owner != address(0));
                  return owner;
              }
          
              /**
               * @dev Approves another address to transfer the given token ID
               * The zero address indicates there is no approved address.
               * There can only be one approved address per token at a given time.
               * Can only be called by the token owner or an approved operator.
               * @param to address to be approved for the given token ID
               * @param tokenId uint256 ID of the token to be approved
               */
              function approve(address to, uint256 tokenId) public {
                  address owner = ownerOf(tokenId);
                  require(to != owner);
                  require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
          
                  _tokenApprovals[tokenId] = to;
                  emit Approval(owner, to, tokenId);
              }
          
              /**
               * @dev Gets the approved address for a token ID, or zero if no address set
               * Reverts if the token ID does not exist.
               * @param tokenId uint256 ID of the token to query the approval of
               * @return address currently approved for the given token ID
               */
              function getApproved(uint256 tokenId) public view returns (address) {
                  require(_exists(tokenId));
                  return _tokenApprovals[tokenId];
              }
          
              /**
               * @dev Sets or unsets the approval of a given operator
               * An operator is allowed to transfer all tokens of the sender on their behalf
               * @param to operator address to set the approval
               * @param approved representing the status of the approval to be set
               */
              function setApprovalForAll(address to, bool approved) public {
                  require(to != msg.sender);
                  _operatorApprovals[msg.sender][to] = approved;
                  emit ApprovalForAll(msg.sender, to, approved);
              }
          
              /**
               * @dev Tells whether an operator is approved by a given owner
               * @param owner owner address which you want to query the approval of
               * @param operator operator address which you want to query the approval of
               * @return bool whether the given operator is approved by the given owner
               */
              function isApprovedForAll(address owner, address operator) public view returns (bool) {
                  return _operatorApprovals[owner][operator];
              }
          
              /**
               * @dev Transfers the ownership of a given token ID to another address
               * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function transferFrom(address from, address to, uint256 tokenId) public {
                  require(_isApprovedOrOwner(msg.sender, tokenId));
          
                  _transferFrom(from, to, tokenId);
              }
          
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               *
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function safeTransferFrom(address from, address to, uint256 tokenId) public {
                  safeTransferFrom(from, to, tokenId, "");
              }
          
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
               * @param _data bytes data to send along with a safe transfer check
               */
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
                  transferFrom(from, to, tokenId);
                  require(_checkOnERC721Received(from, to, tokenId, _data));
              }
          
              /**
               * @dev Returns whether the specified token exists
               * @param tokenId uint256 ID of the token to query the existence of
               * @return whether the token exists
               */
              function _exists(uint256 tokenId) internal view returns (bool) {
                  address owner = _tokenOwner[tokenId];
                  return owner != address(0);
              }
          
              /**
               * @dev Returns whether the given spender can transfer a given token ID
               * @param spender address of the spender to query
               * @param tokenId uint256 ID of the token to be transferred
               * @return bool whether the msg.sender is approved for the given token ID,
               *    is an operator of the owner, or is the owner of the token
               */
              function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
                  address owner = ownerOf(tokenId);
                  return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
              }
          
              /**
               * @dev Internal function to mint a new token
               * Reverts if the given token ID already exists
               * @param to The address that will own the minted token
               * @param tokenId uint256 ID of the token to be minted
               */
              function _mint(address to, uint256 tokenId) internal {
                  require(to != address(0));
                  require(!_exists(tokenId));
          
                  _tokenOwner[tokenId] = to;
                  _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
          
                  emit Transfer(address(0), to, tokenId);
              }
          
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * Deprecated, use _burn(uint256) instead.
               * @param owner owner of the token to burn
               * @param tokenId uint256 ID of the token being burned
               */
              function _burn(address owner, uint256 tokenId) internal {
                  require(ownerOf(tokenId) == owner);
          
                  _clearApproval(tokenId);
          
                  _ownedTokensCount[owner] = _ownedTokensCount[owner].sub(1);
                  _tokenOwner[tokenId] = address(0);
          
                  emit Transfer(owner, address(0), tokenId);
              }
          
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * @param tokenId uint256 ID of the token being burned
               */
              function _burn(uint256 tokenId) internal {
                  _burn(ownerOf(tokenId), tokenId);
              }
          
              /**
               * @dev Internal function to transfer ownership of a given token ID to another address.
               * As opposed to transferFrom, this imposes no restrictions on msg.sender.
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function _transferFrom(address from, address to, uint256 tokenId) internal {
                  require(ownerOf(tokenId) == from);
                  require(to != address(0));
          
                  _clearApproval(tokenId);
          
                  _ownedTokensCount[from] = _ownedTokensCount[from].sub(1);
                  _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
          
                  _tokenOwner[tokenId] = to;
          
                  emit Transfer(from, to, tokenId);
              }
          
              /**
               * @dev Internal function to invoke `onERC721Received` on a target address
               * The call is not executed if the target address is not a contract
               * @param from address representing the previous owner of the given token ID
               * @param to target address that will receive the tokens
               * @param tokenId uint256 ID of the token to be transferred
               * @param _data bytes optional data to send along with the call
               * @return whether the call correctly returned the expected magic value
               */
              function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
                  internal returns (bool)
              {
                  if (!to.isContract()) {
                      return true;
                  }
          
                  bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
                  return (retval == _ERC721_RECEIVED);
              }
          
              /**
               * @dev Private function to clear current approval of a given token ID
               * @param tokenId uint256 ID of the token to be transferred
               */
              function _clearApproval(uint256 tokenId) private {
                  if (_tokenApprovals[tokenId] != address(0)) {
                      _tokenApprovals[tokenId] = address(0);
                  }
              }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: @ensdomains/ethregistrar/contracts/BaseRegistrar.sol
          
          pragma solidity >=0.4.24;
          
          
          
          
          contract BaseRegistrar is IERC721, Ownable {
              uint constant public GRACE_PERIOD = 90 days;
          
              event ControllerAdded(address indexed controller);
              event ControllerRemoved(address indexed controller);
              event NameMigrated(uint256 indexed id, address indexed owner, uint expires);
              event NameRegistered(uint256 indexed id, address indexed owner, uint expires);
              event NameRenewed(uint256 indexed id, uint expires);
          
              // The ENS registry
              ENS public ens;
          
              // The namehash of the TLD this registrar owns (eg, .eth)
              bytes32 public baseNode;
          
              // A map of addresses that are authorised to register and renew names.
              mapping(address=>bool) public controllers;
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external;
          
              // Revoke controller permission for an address.
              function removeController(address controller) external;
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external;
          
              // Returns the expiration timestamp of the specified label hash.
              function nameExpires(uint256 id) external view returns(uint);
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool);
          
              /**
               * @dev Register a name.
               */
              function register(uint256 id, address owner, uint duration) external returns(uint);
          
              function renew(uint256 id, uint duration) external returns(uint);
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external;
          }
          
          // File: @ensdomains/ethregistrar/contracts/BaseRegistrarImplementation.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          contract BaseRegistrarImplementation is BaseRegistrar, ERC721 {
              // A map of expiry times
              mapping(uint256=>uint) expiries;
          
              bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
              bytes4 constant private ERC721_ID = bytes4(
                  keccak256("balanceOf(address)") ^
                  keccak256("ownerOf(uint256)") ^
                  keccak256("approve(address,uint256)") ^
                  keccak256("getApproved(uint256)") ^
                  keccak256("setApprovalForAll(address,bool)") ^
                  keccak256("isApprovedForAll(address,address)") ^
                  keccak256("transferFrom(address,address,uint256)") ^
                  keccak256("safeTransferFrom(address,address,uint256)") ^
                  keccak256("safeTransferFrom(address,address,uint256,bytes)")
              );
              bytes4 constant private RECLAIM_ID = bytes4(keccak256("reclaim(uint256,address)"));
          
              constructor(ENS _ens, bytes32 _baseNode) public {
                  ens = _ens;
                  baseNode = _baseNode;
              }
          
              modifier live {
                  require(ens.owner(baseNode) == address(this));
                  _;
              }
          
              modifier onlyController {
                  require(controllers[msg.sender]);
                  _;
              }
          
              /**
               * @dev Gets the owner of the specified token ID. Names become unowned
               *      when their registration expires.
               * @param tokenId uint256 ID of the token to query the owner of
               * @return address currently marked as the owner of the given token ID
               */
              function ownerOf(uint256 tokenId) public view returns (address) {
                  require(expiries[tokenId] > now);
                  return super.ownerOf(tokenId);
              }
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external onlyOwner {
                  controllers[controller] = true;
                  emit ControllerAdded(controller);
              }
          
              // Revoke controller permission for an address.
              function removeController(address controller) external onlyOwner {
                  controllers[controller] = false;
                  emit ControllerRemoved(controller);
              }
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external onlyOwner {
                  ens.setResolver(baseNode, resolver);
              }
          
              // Returns the expiration timestamp of the specified id.
              function nameExpires(uint256 id) external view returns(uint) {
                  return expiries[id];
              }
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool) {
                  // Not available if it's registered here or in its grace period.
                  return expiries[id] + GRACE_PERIOD < now;
              }
          
              /**
               * @dev Register a name.
               * @param id The token ID (keccak256 of the label).
               * @param owner The address that should own the registration.
               * @param duration Duration in seconds for the registration.
               */
              function register(uint256 id, address owner, uint duration) external returns(uint) {
                return _register(id, owner, duration, true);
              }
          
              /**
               * @dev Register a name, without modifying the registry.
               * @param id The token ID (keccak256 of the label).
               * @param owner The address that should own the registration.
               * @param duration Duration in seconds for the registration.
               */
              function registerOnly(uint256 id, address owner, uint duration) external returns(uint) {
                return _register(id, owner, duration, false);
              }
          
              function _register(uint256 id, address owner, uint duration, bool updateRegistry) internal live onlyController returns(uint) {
                  require(available(id));
                  require(now + duration + GRACE_PERIOD > now + GRACE_PERIOD); // Prevent future overflow
          
                  expiries[id] = now + duration;
                  if(_exists(id)) {
                      // Name was previously owned, and expired
                      _burn(id);
                  }
                  _mint(owner, id);
                  if(updateRegistry) {
                      ens.setSubnodeOwner(baseNode, bytes32(id), owner);
                  }
          
                  emit NameRegistered(id, owner, now + duration);
          
                  return now + duration;
              }
          
              function renew(uint256 id, uint duration) external live onlyController returns(uint) {
                  require(expiries[id] + GRACE_PERIOD >= now); // Name must be registered here or in grace period
                  require(expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD); // Prevent future overflow
          
                  expiries[id] += duration;
                  emit NameRenewed(id, expiries[id]);
                  return expiries[id];
              }
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external live {
                  require(_isApprovedOrOwner(msg.sender, id));
                  ens.setSubnodeOwner(baseNode, bytes32(id), owner);
              }
          
              function supportsInterface(bytes4 interfaceID) external view returns (bool) {
                  return interfaceID == INTERFACE_META_ID ||
                         interfaceID == ERC721_ID ||
                         interfaceID == RECLAIM_ID;
              }
          }

          File 3 of 6: LinearPremiumPriceOracle
          // File: contracts/SafeMath.sol
          
          pragma solidity >=0.4.24;
          
          /**
           * @title SafeMath
           * @dev Unsigned math operations with safety checks that revert on error
           */
          library SafeMath {
              /**
              * @dev Multiplies two unsigned integers, reverts on overflow.
              */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
          
                  uint256 c = a * b;
                  require(c / a == b);
          
                  return c;
              }
          
              /**
              * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
              */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Solidity only automatically asserts when dividing by 0
                  require(b > 0);
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
              * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
          
                  return c;
              }
          
              /**
              * @dev Adds two unsigned integers, reverts on overflow.
              */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
          
                  return c;
              }
          
              /**
              * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
              * reverts when dividing by zero.
              */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0);
                  return a % b;
              }
          }
          
          // File: contracts/PriceOracle.sol
          
          pragma solidity >=0.4.24;
          
          interface PriceOracle {
              /**
               * @dev Returns the price to register or renew a name.
               * @param name The name being registered or renewed.
               * @param expires When the name presently expires (0 if this is a new registration).
               * @param duration How long the name is being registered or extended for, in seconds.
               * @return The price of this renewal or registration, in wei.
               */
              function price(string calldata name, uint expires, uint duration) external view returns(uint);
          }
          
          // File: contracts/StringUtils.sol
          
          pragma solidity >=0.4.24;
          
          library StringUtils {
              /**
               * @dev Returns the length of a given string
               *
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string memory s) internal pure returns (uint) {
                  uint len;
                  uint i = 0;
                  uint bytelength = bytes(s).length;
                  for(len = 0; i < bytelength; len++) {
                      byte b = bytes(s)[i];
                      if(b < 0x80) {
                          i += 1;
                      } else if (b < 0xE0) {
                          i += 2;
                      } else if (b < 0xF0) {
                          i += 3;
                      } else if (b < 0xF8) {
                          i += 4;
                      } else if (b < 0xFC) {
                          i += 5;
                      } else {
                          i += 6;
                      }
                  }
                  return len;
              }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: contracts/StablePriceOracle.sol
          
          pragma solidity >=0.5.0;
          
          
          
          
          
          interface AggregatorInterface {
            function latestAnswer() external view returns (int256);
          }
          
          
          // StablePriceOracle sets a price in USD, based on an oracle.
          contract StablePriceOracle is Ownable, PriceOracle {
              using SafeMath for *;
              using StringUtils for *;
          
              // Rent in base price units by length. Element 0 is for 1-length names, and so on.
              uint[] public rentPrices;
          
              // Oracle address
              AggregatorInterface public usdOracle;
          
              event OracleChanged(address oracle);
          
              event RentPriceChanged(uint[] prices);
          
              bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
              bytes4 constant private ORACLE_ID = bytes4(keccak256("price(string,uint256,uint256)") ^ keccak256("premium(string,uint256,uint256)"));
          
              constructor(AggregatorInterface _usdOracle, uint[] memory _rentPrices) public {
                  usdOracle = _usdOracle;
                  setPrices(_rentPrices);
              }
          
              function price(string calldata name, uint expires, uint duration) external view returns(uint) {
                  uint len = name.strlen();
                  if(len > rentPrices.length) {
                      len = rentPrices.length;
                  }
                  require(len > 0);
                  
                  uint basePrice = rentPrices[len - 1].mul(duration);
                  basePrice = basePrice.add(_premium(name, expires, duration));
          
                  return attoUSDToWei(basePrice);
              }
          
              /**
               * @dev Sets rent prices.
               * @param _rentPrices The price array. Each element corresponds to a specific
               *                    name length; names longer than the length of the array
               *                    default to the price of the last element. Values are
               *                    in base price units, equal to one attodollar (1e-18
               *                    dollar) each.
               */
              function setPrices(uint[] memory _rentPrices) public onlyOwner {
                  rentPrices = _rentPrices;
                  emit RentPriceChanged(_rentPrices);
              }
          
              /**
               * @dev Sets the price oracle address
               * @param _usdOracle The address of the price oracle to use.
               */
              function setOracle(AggregatorInterface _usdOracle) public onlyOwner {
                  usdOracle = _usdOracle;
                  emit OracleChanged(address(_usdOracle));
              }
          
              /**
               * @dev Returns the pricing premium in wei.
               */
              function premium(string calldata name, uint expires, uint duration) external view returns(uint) {
                  return attoUSDToWei(_premium(name, expires, duration));
              }
          
              /**
               * @dev Returns the pricing premium in internal base units.
               */
              function _premium(string memory name, uint expires, uint duration) internal view returns(uint) {
                  return 0;
              }
          
              function attoUSDToWei(uint amount) internal view returns(uint) {
                  uint ethPrice = uint(usdOracle.latestAnswer());
                  return amount.mul(1e8).div(ethPrice);
              }
          
              function weiToAttoUSD(uint amount) internal view returns(uint) {
                  uint ethPrice = uint(usdOracle.latestAnswer());
                  return amount.mul(ethPrice).div(1e8);
              }
          
              function supportsInterface(bytes4 interfaceID) public view returns (bool) {
                  return interfaceID == INTERFACE_META_ID || interfaceID == ORACLE_ID;
              }
          }
          
          // File: contracts/LinearPremiumPriceOracle.sol
          
          pragma solidity >=0.5.0;
          
          
          
          contract LinearPremiumPriceOracle is StablePriceOracle {
              using SafeMath for *;
          
              uint GRACE_PERIOD = 90 days;
          
              uint public initialPremium;
              uint public premiumDecreaseRate;
          
              bytes4 constant private TIME_UNTIL_PREMIUM_ID = bytes4(keccak256("timeUntilPremium(uint,uint"));
          
              constructor(AggregatorInterface _usdOracle, uint[] memory _rentPrices, uint _initialPremium, uint _premiumDecreaseRate) public
                  StablePriceOracle(_usdOracle, _rentPrices)
              {
                  initialPremium = _initialPremium;
                  premiumDecreaseRate = _premiumDecreaseRate;
              }
          
              function _premium(string memory name, uint expires, uint /*duration*/) internal view returns(uint) {
                  expires = expires.add(GRACE_PERIOD);
                  if(expires > now) {
                      // No premium for renewals
                      return 0;
                  }
          
                  // Calculate the discount off the maximum premium
                  uint discount = premiumDecreaseRate.mul(now.sub(expires));
          
                  // If we've run out the premium period, return 0.
                  if(discount > initialPremium) {
                      return 0;
                  }
                  
                  return initialPremium - discount;
              }
          
              /**
               * @dev Returns the timestamp at which a name with the specified expiry date will have
               *      the specified re-registration price premium.
               * @param expires The timestamp at which the name expires.
               * @param amount The amount, in wei, the caller is willing to pay
               * @return The timestamp at which the premium for this domain will be `amount`.
               */
              function timeUntilPremium(uint expires, uint amount) external view returns(uint) {
                  amount = weiToAttoUSD(amount);
                  require(amount <= initialPremium);
          
                  expires = expires.add(GRACE_PERIOD);
          
                  uint discount = initialPremium.sub(amount);
                  uint duration = discount.div(premiumDecreaseRate);
                  return expires.add(duration);
              }
          
              function supportsInterface(bytes4 interfaceID) public view returns (bool) {
                  return (interfaceID == TIME_UNTIL_PREMIUM_ID) || super.supportsInterface(interfaceID);
              }
          }

          File 4 of 6: 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 5 of 6: AccessControlledOffchainAggregator
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.1;
          import "./OffchainAggregator.sol";
          import "./SimpleReadAccessController.sol";
          /**
           * @notice Wrapper of OffchainAggregator which checks read access on Aggregator-interface methods
           */
          contract AccessControlledOffchainAggregator is OffchainAggregator, SimpleReadAccessController {
            constructor(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission,
              address _link,
              int192 _minAnswer,
              int192 _maxAnswer,
              AccessControllerInterface _billingAccessController,
              AccessControllerInterface _requesterAccessController,
              uint8 _decimals,
              string memory description
            )
              OffchainAggregator(
                _maximumGasPrice,
                _reasonableGasPrice,
                _microLinkPerEth,
                _linkGweiPerObservation,
                _linkGweiPerTransmission,
                _link,
                _minAnswer,
                _maxAnswer,
                _billingAccessController,
                _requesterAccessController,
                _decimals,
                description
              ) {
              }
            /*
             * Versioning
             */
            function typeAndVersion()
              external
              override
              pure
              virtual
              returns (string memory)
            {
              return "AccessControlledOffchainAggregator 2.0.0";
            }
            /*
             * v2 Aggregator interface
             */
            /// @inheritdoc OffchainAggregator
            function latestAnswer()
              public
              override
              view
              checkAccess()
              returns (int256)
            {
              return super.latestAnswer();
            }
            /// @inheritdoc OffchainAggregator
            function latestTimestamp()
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.latestTimestamp();
            }
            /// @inheritdoc OffchainAggregator
            function latestRound()
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.latestRound();
            }
            /// @inheritdoc OffchainAggregator
            function getAnswer(uint256 _roundId)
              public
              override
              view
              checkAccess()
              returns (int256)
            {
              return super.getAnswer(_roundId);
            }
            /// @inheritdoc OffchainAggregator
            function getTimestamp(uint256 _roundId)
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.getTimestamp(_roundId);
            }
            /*
             * v3 Aggregator interface
             */
            /// @inheritdoc OffchainAggregator
            function description()
              public
              override
              view
              checkAccess()
              returns (string memory)
            {
              return super.description();
            }
            /// @inheritdoc OffchainAggregator
            function getRoundData(uint80 _roundId)
              public
              override
              view
              checkAccess()
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              )
            {
              return super.getRoundData(_roundId);
            }
            /// @inheritdoc OffchainAggregator
            function latestRoundData()
              public
              override
              view
              checkAccess()
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              )
            {
              return super.latestRoundData();
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./AccessControllerInterface.sol";
          import "./AggregatorV2V3Interface.sol";
          import "./AggregatorValidatorInterface.sol";
          import "./LinkTokenInterface.sol";
          import "./Owned.sol";
          import "./OffchainAggregatorBilling.sol";
          import "./TypeAndVersionInterface.sol";
          /**
            * @notice Onchain verification of reports from the offchain reporting protocol
            * @dev For details on its operation, see the offchain reporting protocol design
            * @dev doc, which refers to this contract as simply the "contract".
          */
          contract OffchainAggregator is Owned, OffchainAggregatorBilling, AggregatorV2V3Interface, TypeAndVersionInterface {
            uint256 constant private maxUint32 = (1 << 32) - 1;
            // Storing these fields used on the hot path in a HotVars variable reduces the
            // retrieval of all of them to a single SLOAD. If any further fields are
            // added, make sure that storage of the struct still takes at most 32 bytes.
            struct HotVars {
              // Provides 128 bits of security against 2nd pre-image attacks, but only
              // 64 bits against collisions. This is acceptable, since a malicious owner has
              // easier way of messing up the protocol than to find hash collisions.
              bytes16 latestConfigDigest;
              uint40 latestEpochAndRound; // 32 most sig bits for epoch, 8 least sig bits for round
              // Current bound assumed on number of faulty/dishonest oracles participating
              // in the protocol, this value is referred to as f in the design
              uint8 threshold;
              // Chainlink Aggregators expose a roundId to consumers. The offchain reporting
              // protocol does not use this id anywhere. We increment it whenever a new
              // transmission is made to provide callers with contiguous ids for successive
              // reports.
              uint32 latestAggregatorRoundId;
            }
            HotVars internal s_hotVars;
            // Transmission records the median answer from the transmit transaction at
            // time timestamp
            struct Transmission {
              int192 answer; // 192 bits ought to be enough for anyone
              uint64 timestamp;
            }
            mapping(uint32 /* aggregator round ID */ => Transmission) internal s_transmissions;
            // incremented each time a new config is posted. This count is incorporated
            // into the config digest, to prevent replay attacks.
            uint32 internal s_configCount;
            uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems
                                                       // to extract config from logs.
            // Lowest answer the system is allowed to report in response to transmissions
            int192 immutable public minAnswer;
            // Highest answer the system is allowed to report in response to transmissions
            int192 immutable public maxAnswer;
            /*
             * @param _maximumGasPrice highest gas price for which transmitter will be compensated
             * @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
             * @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
             * @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
             * @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
             * @param _link address of the LINK contract
             * @param _minAnswer lowest answer the median of a report is allowed to be
             * @param _maxAnswer highest answer the median of a report is allowed to be
             * @param _billingAccessController access controller for billing admin functions
             * @param _requesterAccessController access controller for requesting new rounds
             * @param _decimals answers are stored in fixed-point format, with this many digits of precision
             * @param _description short human-readable description of observable this contract's answers pertain to
             */
            constructor(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission,
              address _link,
              int192 _minAnswer,
              int192 _maxAnswer,
              AccessControllerInterface _billingAccessController,
              AccessControllerInterface _requesterAccessController,
              uint8 _decimals,
              string memory _description
            )
              OffchainAggregatorBilling(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission, _link,
                _billingAccessController
              )
            {
              decimals = _decimals;
              s_description = _description;
              setRequesterAccessController(_requesterAccessController);
              setValidatorConfig(AggregatorValidatorInterface(0x0), 0);
              minAnswer = _minAnswer;
              maxAnswer = _maxAnswer;
            }
            /*
             * Versioning
             */
            function typeAndVersion()
              external
              override
              pure
              virtual
              returns (string memory)
            {
              return "OffchainAggregator 2.0.0";
            }
            /*
             * Config logic
             */
            /**
             * @notice triggers a new run of the offchain reporting protocol
             * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis
             * @param configCount ordinal number of this config setting among all config settings over the life of this contract
             * @param signers ith element is address ith oracle uses to sign a report
             * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method
             * @param threshold maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
             * @param encodedConfigVersion version of the serialization format used for "encoded" parameter
             * @param encoded serialized data used by oracles to configure their offchain operation
             */
            event ConfigSet(
              uint32 previousConfigBlockNumber,
              uint64 configCount,
              address[] signers,
              address[] transmitters,
              uint8 threshold,
              uint64 encodedConfigVersion,
              bytes encoded
            );
            // Reverts transaction if config args are invalid
            modifier checkConfigValid (
              uint256 _numSigners, uint256 _numTransmitters, uint256 _threshold
            ) {
              require(_numSigners <= maxNumOracles, "too many signers");
              require(_threshold > 0, "threshold must be positive");
              require(
                _numSigners == _numTransmitters,
                "oracle addresses out of registration"
              );
              require(_numSigners > 3*_threshold, "faulty-oracle threshold too high");
              _;
            }
            /**
             * @notice sets offchain reporting protocol configuration incl. participating oracles
             * @param _signers addresses with which oracles sign the reports
             * @param _transmitters addresses oracles use to transmit the reports
             * @param _threshold number of faulty oracles the system can tolerate
             * @param _encodedConfigVersion version number for offchainEncoding schema
             * @param _encoded encoded off-chain oracle configuration
             */
            function setConfig(
              address[] calldata _signers,
              address[] calldata _transmitters,
              uint8 _threshold,
              uint64 _encodedConfigVersion,
              bytes calldata _encoded
            )
              external
              checkConfigValid(_signers.length, _transmitters.length, _threshold)
              onlyOwner()
            {
              while (s_signers.length != 0) { // remove any old signer/transmitter addresses
                uint lastIdx = s_signers.length - 1;
                address signer = s_signers[lastIdx];
                address transmitter = s_transmitters[lastIdx];
                payOracle(transmitter);
                delete s_oracles[signer];
                delete s_oracles[transmitter];
                s_signers.pop();
                s_transmitters.pop();
              }
              for (uint i = 0; i < _signers.length; i++) { // add new signer/transmitter addresses
                require(
                  s_oracles[_signers[i]].role == Role.Unset,
                  "repeated signer address"
                );
                s_oracles[_signers[i]] = Oracle(uint8(i), Role.Signer);
                require(s_payees[_transmitters[i]] != address(0), "payee must be set");
                require(
                  s_oracles[_transmitters[i]].role == Role.Unset,
                  "repeated transmitter address"
                );
                s_oracles[_transmitters[i]] = Oracle(uint8(i), Role.Transmitter);
                s_signers.push(_signers[i]);
                s_transmitters.push(_transmitters[i]);
              }
              s_hotVars.threshold = _threshold;
              uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
              s_latestConfigBlockNumber = uint32(block.number);
              s_configCount += 1;
              uint64 configCount = s_configCount;
              {
                s_hotVars.latestConfigDigest = configDigestFromConfigData(
                  address(this),
                  configCount,
                  _signers,
                  _transmitters,
                  _threshold,
                  _encodedConfigVersion,
                  _encoded
                );
                s_hotVars.latestEpochAndRound = 0;
              }
              emit ConfigSet(
                previousConfigBlockNumber,
                configCount,
                _signers,
                _transmitters,
                _threshold,
                _encodedConfigVersion,
                _encoded
              );
            }
            function configDigestFromConfigData(
              address _contractAddress,
              uint64 _configCount,
              address[] calldata _signers,
              address[] calldata _transmitters,
              uint8 _threshold,
              uint64 _encodedConfigVersion,
              bytes calldata _encodedConfig
            ) internal pure returns (bytes16) {
              return bytes16(keccak256(abi.encode(_contractAddress, _configCount,
                _signers, _transmitters, _threshold, _encodedConfigVersion, _encodedConfig
              )));
            }
            /**
             * @notice information about current offchain reporting protocol configuration
             * @return configCount ordinal number of current config, out of all configs applied to this contract so far
             * @return blockNumber block at which this config was set
             * @return configDigest domain-separation tag for current config (see configDigestFromConfigData)
             */
            function latestConfigDetails()
              external
              view
              returns (
                uint32 configCount,
                uint32 blockNumber,
                bytes16 configDigest
              )
            {
              return (s_configCount, s_latestConfigBlockNumber, s_hotVars.latestConfigDigest);
            }
            /**
             * @return list of addresses permitted to transmit reports to this contract
             * @dev The list will match the order used to specify the transmitter during setConfig
             */
            function transmitters()
              external
              view
              returns(address[] memory)
            {
                return s_transmitters;
            }
            /*
             * On-chain validation logc
             */
            // Configuration for validator
            struct ValidatorConfig {
              AggregatorValidatorInterface validator;
              uint32 gasLimit;
            }
            ValidatorConfig private s_validatorConfig;
            /**
             * @notice indicates that the validator configuration has been set
             * @param previousValidator previous validator contract
             * @param previousGasLimit previous gas limit for validate calls
             * @param currentValidator current validator contract
             * @param currentGasLimit current gas limit for validate calls
             */
            event ValidatorConfigSet(
              AggregatorValidatorInterface indexed previousValidator,
              uint32 previousGasLimit,
              AggregatorValidatorInterface indexed currentValidator,
              uint32 currentGasLimit
            );
            /**
             * @notice validator configuration
             * @return validator validator contract
             * @return gasLimit gas limit for validate calls
             */
            function validatorConfig()
              external
              view
              returns (AggregatorValidatorInterface validator, uint32 gasLimit)
            {
              ValidatorConfig memory vc = s_validatorConfig;
              return (vc.validator, vc.gasLimit);
            }
            /**
             * @notice sets validator configuration
             * @dev set _newValidator to 0x0 to disable validate calls
             * @param _newValidator address of the new validator contract
             * @param _newGasLimit new gas limit for validate calls
             */
            function setValidatorConfig(AggregatorValidatorInterface _newValidator, uint32 _newGasLimit)
              public
              onlyOwner()
            {
              ValidatorConfig memory previous = s_validatorConfig;
              if (previous.validator != _newValidator || previous.gasLimit != _newGasLimit) {
                s_validatorConfig = ValidatorConfig({
                  validator: _newValidator,
                  gasLimit: _newGasLimit
                });
                emit ValidatorConfigSet(previous.validator, previous.gasLimit, _newValidator, _newGasLimit);
              }
            }
            function validateAnswer(
              uint32 _aggregatorRoundId,
              int256 _answer
            )
              private
            {
              ValidatorConfig memory vc = s_validatorConfig;
              if (address(vc.validator) == address(0)) {
                return;
              }
              uint32 prevAggregatorRoundId = _aggregatorRoundId - 1;
              int256 prevAggregatorRoundAnswer = s_transmissions[prevAggregatorRoundId].answer;
              // We do not want the validator to ever prevent reporting, so we limit its
              // gas usage and catch any errors that may arise.
              try vc.validator.validate{gas: vc.gasLimit}(
                prevAggregatorRoundId,
                prevAggregatorRoundAnswer,
                _aggregatorRoundId,
                _answer
              ) {} catch {}
            }
            /*
             * requestNewRound logic
             */
            AccessControllerInterface internal s_requesterAccessController;
            /**
             * @notice emitted when a new requester access controller contract is set
             * @param old the address prior to the current setting
             * @param current the address of the new access controller contract
             */
            event RequesterAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
            /**
             * @notice emitted to immediately request a new round
             * @param requester the address of the requester
             * @param configDigest the latest transmission's configDigest
             * @param epoch the latest transmission's epoch
             * @param round the latest transmission's round
             */
            event RoundRequested(address indexed requester, bytes16 configDigest, uint32 epoch, uint8 round);
            /**
             * @notice address of the requester access controller contract
             * @return requester access controller address
             */
            function requesterAccessController()
              external
              view
              returns (AccessControllerInterface)
            {
              return s_requesterAccessController;
            }
            /**
             * @notice sets the requester access controller
             * @param _requesterAccessController designates the address of the new requester access controller
             */
            function setRequesterAccessController(AccessControllerInterface _requesterAccessController)
              public
              onlyOwner()
            {
              AccessControllerInterface oldController = s_requesterAccessController;
              if (_requesterAccessController != oldController) {
                s_requesterAccessController = AccessControllerInterface(_requesterAccessController);
                emit RequesterAccessControllerSet(oldController, _requesterAccessController);
              }
            }
            /**
             * @notice immediately requests a new round
             * @return the aggregatorRoundId of the next round. Note: The report for this round may have been
             * transmitted (but not yet mined) *before* requestNewRound() was even called. There is *no*
             * guarantee of causality between the request and the report at aggregatorRoundId.
             */
            function requestNewRound() external returns (uint80) {
              require(msg.sender == owner || s_requesterAccessController.hasAccess(msg.sender, msg.data),
                "Only owner&requester can call");
              HotVars memory hotVars = s_hotVars;
              emit RoundRequested(
                msg.sender,
                hotVars.latestConfigDigest,
                uint32(s_hotVars.latestEpochAndRound >> 8),
                uint8(s_hotVars.latestEpochAndRound)
              );
              return hotVars.latestAggregatorRoundId + 1;
            }
            /*
             * Transmission logic
             */
            /**
             * @notice indicates that a new report was transmitted
             * @param aggregatorRoundId the round to which this report was assigned
             * @param answer median of the observations attached this report
             * @param transmitter address from which the report was transmitted
             * @param observations observations transmitted with this report
             * @param rawReportContext signature-replay-prevention domain-separation tag
             */
            event NewTransmission(
              uint32 indexed aggregatorRoundId,
              int192 answer,
              address transmitter,
              int192[] observations,
              bytes observers,
              bytes32 rawReportContext
            );
            // decodeReport is used to check that the solidity and go code are using the
            // same format. See TestOffchainAggregator.testDecodeReport and TestReportParsing
            function decodeReport(bytes memory _report)
              internal
              pure
              returns (
                bytes32 rawReportContext,
                bytes32 rawObservers,
                int192[] memory observations
              )
            {
              (rawReportContext, rawObservers, observations) = abi.decode(_report,
                (bytes32, bytes32, int192[]));
            }
            // Used to relieve stack pressure in transmit
            struct ReportData {
              HotVars hotVars; // Only read from storage once
              bytes observers; // ith element is the index of the ith observer
              int192[] observations; // ith element is the ith observation
              bytes vs; // jth element is the v component of the jth signature
              bytes32 rawReportContext;
            }
            /*
             * @notice details about the most recent report
             * @return configDigest domain separation tag for the latest report
             * @return epoch epoch in which the latest report was generated
             * @return round OCR round in which the latest report was generated
             * @return latestAnswer median value from latest report
             * @return latestTimestamp when the latest report was transmitted
             */
            function latestTransmissionDetails()
              external
              view
              returns (
                bytes16 configDigest,
                uint32 epoch,
                uint8 round,
                int192 latestAnswer,
                uint64 latestTimestamp
              )
            {
              require(msg.sender == tx.origin, "Only callable by EOA");
              return (
                s_hotVars.latestConfigDigest,
                uint32(s_hotVars.latestEpochAndRound >> 8),
                uint8(s_hotVars.latestEpochAndRound),
                s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
                s_transmissions[s_hotVars.latestAggregatorRoundId].timestamp
              );
            }
            // The constant-length components of the msg.data sent to transmit.
            // See the "If we wanted to call sam" example on for example reasoning
            // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html
            uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT =
              4 + // function selector
              32 + // word containing start location of abiencoded _report value
              32 + // word containing location start of abiencoded  _rs value
              32 + // word containing start location of abiencoded _ss value
              32 + // _rawVs value
              32 + // word containing length of _report
              32 + // word containing length _rs
              32 + // word containing length of _ss
              0; // placeholder
            function expectedMsgDataLength(
              bytes calldata _report, bytes32[] calldata _rs, bytes32[] calldata _ss
            ) private pure returns (uint256 length)
            {
              // calldata will never be big enough to make this overflow
              return uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) +
                _report.length + // one byte pure entry in _report
                _rs.length * 32 + // 32 bytes per entry in _rs
                _ss.length * 32 + // 32 bytes per entry in _ss
                0; // placeholder
            }
            /**
             * @notice transmit is called to post a new report to the contract
             * @param _report serialized report, which the signatures are signing. See parsing code below for format. The ith element of the observers component must be the index in s_signers of the address for the ith signature
             * @param _rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
             * @param _ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
             * @param _rawVs ith element is the the V component of the ith signature
             */
            function transmit(
              // NOTE: If these parameters are changed, expectedMsgDataLength and/or
              // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
              bytes calldata _report,
              bytes32[] calldata _rs, bytes32[] calldata _ss, bytes32 _rawVs // signatures
            )
              external
            {
              uint256 initialGas = gasleft(); // This line must come first
              // Make sure the transmit message-length matches the inputs. Otherwise, the
              // transmitter could append an arbitrarily long (up to gas-block limit)
              // string of 0 bytes, which we would reimburse at a rate of 16 gas/byte, but
              // which would only cost the transmitter 4 gas/byte. (Appendix G of the
              // yellow paper, p. 25, for G_txdatazero and EIP 2028 for G_txdatanonzero.)
              // This could amount to reimbursement profit of 36 million gas, given a 3MB
              // zero tail.
              require(msg.data.length == expectedMsgDataLength(_report, _rs, _ss),
                "transmit message too long");
              ReportData memory r; // Relieves stack pressure
              {
                r.hotVars = s_hotVars; // cache read from storage
                bytes32 rawObservers;
                (r.rawReportContext, rawObservers, r.observations) = abi.decode(
                  _report, (bytes32, bytes32, int192[])
                );
                // rawReportContext consists of:
                // 11-byte zero padding
                // 16-byte configDigest
                // 4-byte epoch
                // 1-byte round
                bytes16 configDigest = bytes16(r.rawReportContext << 88);
                require(
                  r.hotVars.latestConfigDigest == configDigest,
                  "configDigest mismatch"
                );
                uint40 epochAndRound = uint40(uint256(r.rawReportContext));
                // direct numerical comparison works here, because
                //
                //   ((e,r) <= (e',r')) implies (epochAndRound <= epochAndRound')
                //
                // because alphabetic ordering implies e <= e', and if e = e', then r<=r',
                // so e*256+r <= e'*256+r', because r, r' < 256
                require(r.hotVars.latestEpochAndRound < epochAndRound, "stale report");
                require(_rs.length > r.hotVars.threshold, "not enough signatures");
                require(_rs.length <= maxNumOracles, "too many signatures");
                require(_ss.length == _rs.length, "signatures out of registration");
                require(r.observations.length <= maxNumOracles,
                        "num observations out of bounds");
                require(r.observations.length > 2 * r.hotVars.threshold,
                        "too few values to trust median");
                // Copy signature parities in bytes32 _rawVs to bytes r.v
                r.vs = new bytes(_rs.length);
                for (uint8 i = 0; i < _rs.length; i++) {
                  r.vs[i] = _rawVs[i];
                }
                // Copy observer identities in bytes32 rawObservers to bytes r.observers
                r.observers = new bytes(r.observations.length);
                bool[maxNumOracles] memory seen;
                for (uint8 i = 0; i < r.observations.length; i++) {
                  uint8 observerIdx = uint8(rawObservers[i]);
                  require(!seen[observerIdx], "observer index repeated");
                  seen[observerIdx] = true;
                  r.observers[i] = rawObservers[i];
                }
                Oracle memory transmitter = s_oracles[msg.sender];
                require( // Check that sender is authorized to report
                  transmitter.role == Role.Transmitter &&
                  msg.sender == s_transmitters[transmitter.index],
                  "unauthorized transmitter"
                );
                // record epochAndRound here, so that we don't have to carry the local
                // variable in transmit. The change is reverted if something fails later.
                r.hotVars.latestEpochAndRound = epochAndRound;
              }
              { // Verify signatures attached to report
                bytes32 h = keccak256(_report);
                bool[maxNumOracles] memory signed;
                Oracle memory o;
                for (uint i = 0; i < _rs.length; i++) {
                  address signer = ecrecover(h, uint8(r.vs[i])+27, _rs[i], _ss[i]);
                  o = s_oracles[signer];
                  require(o.role == Role.Signer, "address not authorized to sign");
                  require(!signed[o.index], "non-unique signature");
                  signed[o.index] = true;
                }
              }
              { // Check the report contents, and record the result
                for (uint i = 0; i < r.observations.length - 1; i++) {
                  bool inOrder = r.observations[i] <= r.observations[i+1];
                  require(inOrder, "observations not sorted");
                }
                int192 median = r.observations[r.observations.length/2];
                require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
                r.hotVars.latestAggregatorRoundId++;
                s_transmissions[r.hotVars.latestAggregatorRoundId] =
                  Transmission(median, uint64(block.timestamp));
                emit NewTransmission(
                  r.hotVars.latestAggregatorRoundId,
                  median,
                  msg.sender,
                  r.observations,
                  r.observers,
                  r.rawReportContext
                );
                // Emit these for backwards compatability with offchain consumers
                // that only support legacy events
                emit NewRound(
                  r.hotVars.latestAggregatorRoundId,
                  address(0x0), // use zero address since we don't have anybody "starting" the round here
                  block.timestamp
                );
                emit AnswerUpdated(
                  median,
                  r.hotVars.latestAggregatorRoundId,
                  block.timestamp
                );
                validateAnswer(r.hotVars.latestAggregatorRoundId, median);
              }
              s_hotVars = r.hotVars;
              assert(initialGas < maxUint32);
              reimburseAndRewardOracles(uint32(initialGas), r.observers);
            }
            /*
             * v2 Aggregator interface
             */
            /**
             * @notice median from the most recent report
             */
            function latestAnswer()
              public
              override
              view
              virtual
              returns (int256)
            {
              return s_transmissions[s_hotVars.latestAggregatorRoundId].answer;
            }
            /**
             * @notice timestamp of block in which last report was transmitted
             */
            function latestTimestamp()
              public
              override
              view
              virtual
              returns (uint256)
            {
              return s_transmissions[s_hotVars.latestAggregatorRoundId].timestamp;
            }
            /**
             * @notice Aggregator round (NOT OCR round) in which last report was transmitted
             */
            function latestRound()
              public
              override
              view
              virtual
              returns (uint256)
            {
              return s_hotVars.latestAggregatorRoundId;
            }
            /**
             * @notice median of report from given aggregator round (NOT OCR round)
             * @param _roundId the aggregator round of the target report
             */
            function getAnswer(uint256 _roundId)
              public
              override
              view
              virtual
              returns (int256)
            {
              if (_roundId > 0xFFFFFFFF) { return 0; }
              return s_transmissions[uint32(_roundId)].answer;
            }
            /**
             * @notice timestamp of block in which report from given aggregator round was transmitted
             * @param _roundId aggregator round (NOT OCR round) of target report
             */
            function getTimestamp(uint256 _roundId)
              public
              override
              view
              virtual
              returns (uint256)
            {
              if (_roundId > 0xFFFFFFFF) { return 0; }
              return s_transmissions[uint32(_roundId)].timestamp;
            }
            /*
             * v3 Aggregator interface
             */
            string constant private V3_NO_DATA_ERROR = "No data present";
            /**
             * @return answers are stored in fixed-point format, with this many digits of precision
             */
            uint8 immutable public override decimals;
            /**
             * @notice aggregator contract version
             */
            uint256 constant public override version = 4;
            string internal s_description;
            /**
             * @notice human-readable description of observable this contract is reporting on
             */
            function description()
              public
              override
              view
              virtual
              returns (string memory)
            {
              return s_description;
            }
            /**
             * @notice details for the given aggregator round
             * @param _roundId target aggregator round (NOT OCR round). Must fit in uint32
             * @return roundId _roundId
             * @return answer median of report from given _roundId
             * @return startedAt timestamp of block in which report from given _roundId was transmitted
             * @return updatedAt timestamp of block in which report from given _roundId was transmitted
             * @return answeredInRound _roundId
             */
            function getRoundData(uint80 _roundId)
              public
              override
              view
              virtual
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              )
            {
              require(_roundId <= 0xFFFFFFFF, V3_NO_DATA_ERROR);
              Transmission memory transmission = s_transmissions[uint32(_roundId)];
              return (
                _roundId,
                transmission.answer,
                transmission.timestamp,
                transmission.timestamp,
                _roundId
              );
            }
            /**
             * @notice aggregator details for the most recently transmitted report
             * @return roundId aggregator round of latest report (NOT OCR round)
             * @return answer median of latest report
             * @return startedAt timestamp of block containing latest report
             * @return updatedAt timestamp of block containing latest report
             * @return answeredInRound aggregator round of latest report
             */
            function latestRoundData()
              public
              override
              view
              virtual
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              )
            {
              roundId = s_hotVars.latestAggregatorRoundId;
              // Skipped for compatability with existing FluxAggregator in which latestRoundData never reverts.
              // require(roundId != 0, V3_NO_DATA_ERROR);
              Transmission memory transmission = s_transmissions[uint32(roundId)];
              return (
                roundId,
                transmission.answer,
                transmission.timestamp,
                transmission.timestamp,
                roundId
              );
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.1;
          import "./SimpleWriteAccessController.sol";
          /**
           * @title SimpleReadAccessController
           * @notice Gives access to:
           * - any externally owned account (note that offchain actors can always read
           * any contract storage regardless of onchain access control measures, so this
           * does not weaken the access control while improving usability)
           * - accounts explicitly added to an access list
           * @dev SimpleReadAccessController is not suitable for access controlling writes
           * since it grants any externally owned account access! See
           * SimpleWriteAccessController for that.
           */
          contract SimpleReadAccessController is SimpleWriteAccessController {
            /**
             * @notice Returns the access of an address
             * @param _user The address to query
             */
            function hasAccess(
              address _user,
              bytes memory _calldata
            )
              public
              view
              virtual
              override
              returns (bool)
            {
              return super.hasAccess(_user, _calldata) || _user == tx.origin;
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AccessControllerInterface {
            function hasAccess(address user, bytes calldata data) external view returns (bool);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./AggregatorInterface.sol";
          import "./AggregatorV3Interface.sol";
          interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
          {
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AggregatorValidatorInterface {
            function validate(
              uint256 previousRoundId,
              int256 previousAnswer,
              uint256 currentRoundId,
              int256 currentAnswer
            ) external returns (bool);
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.7.1;
          interface LinkTokenInterface {
            function allowance(address owner, address spender) external view returns (uint256 remaining);
            function approve(address spender, uint256 value) external returns (bool success);
            function balanceOf(address owner) external view returns (uint256 balance);
            function decimals() external view returns (uint8 decimalPlaces);
            function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
            function increaseApproval(address spender, uint256 subtractedValue) external;
            function name() external view returns (string memory tokenName);
            function symbol() external view returns (string memory tokenSymbol);
            function totalSupply() external view returns (uint256 totalTokensIssued);
            function transfer(address to, uint256 value) external returns (bool success);
            function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
            function transferFrom(address from, address to, uint256 value) external returns (bool success);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          /**
           * @title The Owned contract
           * @notice A contract with helpers for basic contract ownership.
           */
          contract Owned {
            address payable public owner;
            address private pendingOwner;
            event OwnershipTransferRequested(
              address indexed from,
              address indexed to
            );
            event OwnershipTransferred(
              address indexed from,
              address indexed to
            );
            constructor() {
              owner = msg.sender;
            }
            /**
             * @dev Allows an owner to begin transferring ownership to a new address,
             * pending.
             */
            function transferOwnership(address _to)
              external
              onlyOwner()
            {
              pendingOwner = _to;
              emit OwnershipTransferRequested(owner, _to);
            }
            /**
             * @dev Allows an ownership transfer to be completed by the recipient.
             */
            function acceptOwnership()
              external
            {
              require(msg.sender == pendingOwner, "Must be proposed owner");
              address oldOwner = owner;
              owner = msg.sender;
              pendingOwner = address(0);
              emit OwnershipTransferred(oldOwner, msg.sender);
            }
            /**
             * @dev Reverts if called by anyone other than the contract owner.
             */
            modifier onlyOwner() {
              require(msg.sender == owner, "Only callable by owner");
              _;
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./AccessControllerInterface.sol";
          import "./LinkTokenInterface.sol";
          import "./Owned.sol";
          /**
           * @notice tracks administration of oracle-reward and gas-reimbursement parameters.
           * @dev
           * If you read or change this, be sure to read or adjust the comments. They
           * track the units of the values under consideration, and are crucial to
           * the readability of the operations it specifies.
           * @notice
           * Trust Model:
           * Nothing in this contract prevents a billing admin from setting insane
           * values for the billing parameters in setBilling. Oracles
           * participating in this contract should regularly check that the
           * parameters make sense. Similarly, the outstanding obligations of this
           * contract to the oracles can exceed the funds held by the contract.
           * Oracles participating in this contract should regularly check that it
           * holds sufficient funds and stop interacting with it if funding runs
           * out.
           * This still leaves oracles with some risk due to TOCTOU issues.
           * However, since the sums involved are pretty small (Ethereum
           * transactions aren't that expensive in the end) and an oracle would
           * likely stop participating in a contract it repeatedly lost money on,
           * this risk is deemed acceptable. Oracles should also regularly
           * withdraw any funds in the contract to prevent issues where the
           * contract becomes underfunded at a later time, and different oracles
           * are competing for the left-over funds.
           * Finally, note that any change to the set of oracles or to the billing
           * parameters will trigger payout of all oracles first (using the old
           * parameters), a billing admin cannot take away funds that are already
           * marked for payment.
          */
          contract OffchainAggregatorBilling is Owned {
            // Maximum number of oracles the offchain reporting protocol is designed for
            uint256 constant internal maxNumOracles = 31;
            // Parameters for oracle payments
            struct Billing {
              // Highest compensated gas price, in ETH-gwei uints
              uint32 maximumGasPrice;
              // If gas price is less (in ETH-gwei units), transmitter gets half the savings
              uint32 reasonableGasPrice;
              // Pay transmitter back this much LINK per unit eth spent on gas
              // (1e-6LINK/ETH units)
              uint32 microLinkPerEth;
              // Fixed LINK reward for each observer, in LINK-gwei units
              uint32 linkGweiPerObservation;
              // Fixed reward for transmitter, in linkGweiPerObservation units
              uint32 linkGweiPerTransmission;
            }
            Billing internal s_billing;
            /**
            * @return LINK token contract used for billing
            */
            LinkTokenInterface immutable public LINK;
            AccessControllerInterface internal s_billingAccessController;
            // ith element is number of observation rewards due to ith process, plus one.
            // This is expected to saturate after an oracle has submitted 65,535
            // observations, or about 65535/(3*24*20) = 45 days, given a transmission
            // every 3 minutes.
            //
            // This is always one greater than the actual value, so that when the value is
            // reset to zero, we don't end up with a zero value in storage (which would
            // result in a higher gas cost, the next time the value is incremented.)
            // Calculations using this variable need to take that offset into account.
            uint16[maxNumOracles] internal s_oracleObservationsCounts;
            // Addresses at which oracles want to receive payments, by transmitter address
            mapping (address /* transmitter */ => address /* payment address */)
              internal
              s_payees;
            // Payee addresses which must be approved by the owner
            mapping (address /* transmitter */ => address /* payment address */)
              internal
              s_proposedPayees;
            // LINK-wei-denominated reimbursements for gas used by transmitters.
            //
            // This is always one greater than the actual value, so that when the value is
            // reset to zero, we don't end up with a zero value in storage (which would
            // result in a higher gas cost, the next time the value is incremented.)
            // Calculations using this variable need to take that offset into account.
            //
            // Argument for overflow safety:
            // We have the following maximum intermediate values:
            // - 2**40 additions to this variable (epochAndRound is a uint40)
            // - 2**32 gas price in ethgwei/gas
            // - 1e9 ethwei/ethgwei
            // - 2**32 gas since the block gas limit is at ~20 million
            // - 2**32 (microlink/eth)
            // And we have 2**40 * 2**32 * 1e9 * 2**32 * 2**32 < 2**166
            // (we also divide in some places, but that only makes the value smaller)
            // We can thus safely use uint256 intermediate values for the computation
            // updating this variable.
            uint256[maxNumOracles] internal s_gasReimbursementsLinkWei;
            // Used for s_oracles[a].role, where a is an address, to track the purpose
            // of the address, or to indicate that the address is unset.
            enum Role {
              // No oracle role has been set for address a
              Unset,
              // Signing address for the s_oracles[a].index'th oracle. I.e., report
              // signatures from this oracle should ecrecover back to address a.
              Signer,
              // Transmission address for the s_oracles[a].index'th oracle. I.e., if a
              // report is received by OffchainAggregator.transmit in which msg.sender is
              // a, it is attributed to the s_oracles[a].index'th oracle.
              Transmitter
            }
            struct Oracle {
              uint8 index; // Index of oracle in s_signers/s_transmitters
              Role role;   // Role of the address which mapped to this struct
            }
            mapping (address /* signer OR transmitter address */ => Oracle)
              internal s_oracles;
            // s_signers contains the signing address of each oracle
            address[] internal s_signers;
            // s_transmitters contains the transmission address of each oracle,
            // i.e. the address the oracle actually sends transactions to the contract from
            address[] internal s_transmitters;
            uint256 constant private  maxUint16 = (1 << 16) - 1;
            uint256 constant internal maxUint128 = (1 << 128) - 1;
            constructor(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission,
              address _link,
              AccessControllerInterface _billingAccessController
            )
            {
              setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission);
              setBillingAccessControllerInternal(_billingAccessController);
              LINK = LinkTokenInterface(_link);
              uint16[maxNumOracles] memory counts; // See s_oracleObservationsCounts docstring
              uint256[maxNumOracles] memory gas; // see s_gasReimbursementsLinkWei docstring
              for (uint8 i = 0; i < maxNumOracles; i++) {
                counts[i] = 1;
                gas[i] = 1;
              }
              s_oracleObservationsCounts = counts;
              s_gasReimbursementsLinkWei = gas;
            }
            /**
             * @notice emitted when billing parameters are set
             * @param maximumGasPrice highest gas price for which transmitter will be compensated
             * @param reasonableGasPrice transmitter will receive reward for gas prices under this value
             * @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
             * @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
             * @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
             */
            event BillingSet(
              uint32 maximumGasPrice,
              uint32 reasonableGasPrice,
              uint32 microLinkPerEth,
              uint32 linkGweiPerObservation,
              uint32 linkGweiPerTransmission
            );
            function setBillingInternal(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission
            )
              internal
            {
              s_billing = Billing(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission);
              emit BillingSet(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission);
            }
            /**
             * @notice sets billing parameters
             * @param _maximumGasPrice highest gas price for which transmitter will be compensated
             * @param _reasonableGasPrice transmitter will receive reward for gas prices under this value
             * @param _microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
             * @param _linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
             * @param _linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
             * @dev access control provided by billingAccessController
             */
            function setBilling(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission
            )
              external
            {
              AccessControllerInterface access = s_billingAccessController;
              require(msg.sender == owner || access.hasAccess(msg.sender, msg.data),
                "Only owner&billingAdmin can call");
              payOracles();
              setBillingInternal(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission);
            }
            /**
             * @notice gets billing parameters
             * @param maximumGasPrice highest gas price for which transmitter will be compensated
             * @param reasonableGasPrice transmitter will receive reward for gas prices under this value
             * @param microLinkPerEth reimbursement per ETH of gas cost, in 1e-6LINK units
             * @param linkGweiPerObservation reward to oracle for contributing an observation to a successfully transmitted report, in 1e-9LINK units
             * @param linkGweiPerTransmission reward to transmitter of a successful report, in 1e-9LINK units
             */
            function getBilling()
              external
              view
              returns (
                uint32 maximumGasPrice,
                uint32 reasonableGasPrice,
                uint32 microLinkPerEth,
                uint32 linkGweiPerObservation,
                uint32 linkGweiPerTransmission
              )
            {
              Billing memory billing = s_billing;
              return (
                billing.maximumGasPrice,
                billing.reasonableGasPrice,
                billing.microLinkPerEth,
                billing.linkGweiPerObservation,
                billing.linkGweiPerTransmission
              );
            }
            /**
             * @notice emitted when a new access-control contract is set
             * @param old the address prior to the current setting
             * @param current the address of the new access-control contract
             */
            event BillingAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);
            function setBillingAccessControllerInternal(AccessControllerInterface _billingAccessController)
              internal
            {
              AccessControllerInterface oldController = s_billingAccessController;
              if (_billingAccessController != oldController) {
                s_billingAccessController = _billingAccessController;
                emit BillingAccessControllerSet(
                  oldController,
                  _billingAccessController
                );
              }
            }
            /**
             * @notice sets billingAccessController
             * @param _billingAccessController new billingAccessController contract address
             * @dev only owner can call this
             */
            function setBillingAccessController(AccessControllerInterface _billingAccessController)
              external
              onlyOwner
            {
              setBillingAccessControllerInternal(_billingAccessController);
            }
            /**
             * @notice gets billingAccessController
             * @return address of billingAccessController contract
             */
            function billingAccessController()
              external
              view
              returns (AccessControllerInterface)
            {
              return s_billingAccessController;
            }
            /**
             * @notice withdraws an oracle's payment from the contract
             * @param _transmitter the transmitter address of the oracle
             * @dev must be called by oracle's payee address
             */
            function withdrawPayment(address _transmitter)
              external
            {
              require(msg.sender == s_payees[_transmitter], "Only payee can withdraw");
              payOracle(_transmitter);
            }
            /**
             * @notice query an oracle's payment amount
             * @param _transmitter the transmitter address of the oracle
             */
            function owedPayment(address _transmitter)
              public
              view
              returns (uint256)
            {
              Oracle memory oracle = s_oracles[_transmitter];
              if (oracle.role == Role.Unset) { return 0; }
              Billing memory billing = s_billing;
              uint256 linkWeiAmount =
                uint256(s_oracleObservationsCounts[oracle.index] - 1) *
                uint256(billing.linkGweiPerObservation) *
                (1 gwei);
              linkWeiAmount += s_gasReimbursementsLinkWei[oracle.index] - 1;
              return linkWeiAmount;
            }
            /**
             * @notice emitted when an oracle has been paid LINK
             * @param transmitter address from which the oracle sends reports to the transmit method
             * @param payee address to which the payment is sent
             * @param amount amount of LINK sent
             */
            event OraclePaid(address transmitter, address payee, uint256 amount);
            // payOracle pays out _transmitter's balance to the corresponding payee, and zeros it out
            function payOracle(address _transmitter)
              internal
            {
              Oracle memory oracle = s_oracles[_transmitter];
              uint256 linkWeiAmount = owedPayment(_transmitter);
              if (linkWeiAmount > 0) {
                address payee = s_payees[_transmitter];
                // Poses no re-entrancy issues, because LINK.transfer does not yield
                // control flow.
                require(LINK.transfer(payee, linkWeiAmount), "insufficient funds");
                s_oracleObservationsCounts[oracle.index] = 1; // "zero" the counts. see var's docstring
                s_gasReimbursementsLinkWei[oracle.index] = 1; // "zero" the counts. see var's docstring
                emit OraclePaid(_transmitter, payee, linkWeiAmount);
              }
            }
            // payOracles pays out all transmitters, and zeros out their balances.
            //
            // It's much more gas-efficient to do this as a single operation, to avoid
            // hitting storage too much.
            function payOracles()
              internal
            {
              Billing memory billing = s_billing;
              uint16[maxNumOracles] memory observationsCounts = s_oracleObservationsCounts;
              uint256[maxNumOracles] memory gasReimbursementsLinkWei =
                s_gasReimbursementsLinkWei;
              address[] memory transmitters = s_transmitters;
              for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
                uint256 reimbursementAmountLinkWei = gasReimbursementsLinkWei[transmitteridx] - 1;
                uint256 obsCount = observationsCounts[transmitteridx] - 1;
                uint256 linkWeiAmount =
                  obsCount * uint256(billing.linkGweiPerObservation) * (1 gwei) + reimbursementAmountLinkWei;
                if (linkWeiAmount > 0) {
                    address payee = s_payees[transmitters[transmitteridx]];
                    // Poses no re-entrancy issues, because LINK.transfer does not yield
                    // control flow.
                    require(LINK.transfer(payee, linkWeiAmount), "insufficient funds");
                    observationsCounts[transmitteridx] = 1;       // "zero" the counts.
                    gasReimbursementsLinkWei[transmitteridx] = 1; // "zero" the counts.
                    emit OraclePaid(transmitters[transmitteridx], payee, linkWeiAmount);
                  }
              }
              // "Zero" the accounting storage variables
              s_oracleObservationsCounts = observationsCounts;
              s_gasReimbursementsLinkWei = gasReimbursementsLinkWei;
            }
            function oracleRewards(
              bytes memory observers,
              uint16[maxNumOracles] memory observations
            )
              internal
              pure
              returns (uint16[maxNumOracles] memory)
            {
              // reward each observer-participant with the observer reward
              for (uint obsIdx = 0; obsIdx < observers.length; obsIdx++) {
                uint8 observer = uint8(observers[obsIdx]);
                observations[observer] = saturatingAddUint16(observations[observer], 1);
              }
              return observations;
            }
            // This value needs to change if maxNumOracles is increased, or the accounting
            // calculations at the bottom of reimburseAndRewardOracles change.
            //
            // To recalculate it, run the profiler as described in
            // ../../profile/README.md, and add up the gas-usage values reported for the
            // lines in reimburseAndRewardOracles following the "gasLeft = gasleft()"
            // line. E.g., you will see output like this:
            //
            //      7        uint256 gasLeft = gasleft();
            //     29        uint256 gasCostEthWei = transmitterGasCostEthWei(
            //      9          uint256(initialGas),
            //      3          gasPrice,
            //      3          callDataGasCost,
            //      3          gasLeft
            //      .
            //      .
            //      .
            //     59        uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
            //      .
            //      .
            //      .
            //   5047        s_gasReimbursementsLinkWei[txOracle.index] =
            //    856          s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
            //     26          uint256(billing.linkGweiPerTransmission) * (1 gwei);
            //
            // If those were the only lines to be accounted for, you would add up
            // 29+9+3+3+3+59+5047+856+26=6035.
            uint256 internal constant accountingGasCost = 6035;
            // Uncomment the following declaration to compute the remaining gas cost after
            // above gasleft(). (This must exist in a base class to OffchainAggregator, so
            // it can't go in TestOffchainAggregator.)
            //
            // uint256 public gasUsedInAccounting;
            // Gas price at which the transmitter should be reimbursed, in ETH-gwei/gas
            function impliedGasPrice(
              uint256 txGasPrice,         // ETH-gwei/gas units
              uint256 reasonableGasPrice, // ETH-gwei/gas units
              uint256 maximumGasPrice     // ETH-gwei/gas units
            )
              internal
              pure
              returns (uint256)
            {
              // Reward the transmitter for choosing an efficient gas price: if they manage
              // to come in lower than considered reasonable, give them half the savings.
              //
              // The following calculations are all in units of gwei/gas, i.e. 1e-9ETH/gas
              uint256 gasPrice = txGasPrice;
              if (txGasPrice < reasonableGasPrice) {
                // Give transmitter half the savings for coming in under the reasonable gas price
                gasPrice += (reasonableGasPrice - txGasPrice) / 2;
              }
              // Don't reimburse a gas price higher than maximumGasPrice
              return min(gasPrice, maximumGasPrice);
            }
            // gas reimbursement due the transmitter, in ETH-wei
            //
            // If this function is changed, accountingGasCost needs to change, too. See
            // its docstring
            function transmitterGasCostEthWei(
              uint256 initialGas,
              uint256 gasPrice, // ETH-gwei/gas units
              uint256 callDataCost, // gas units
              uint256 gasLeft
            )
              internal
              pure
              returns (uint128 gasCostEthWei)
            {
              require(initialGas >= gasLeft, "gasLeft cannot exceed initialGas");
              uint256 gasUsed = // gas units
                initialGas - gasLeft + // observed gas usage
                callDataCost + accountingGasCost; // estimated gas usage
              // gasUsed is in gas units, gasPrice is in ETH-gwei/gas units; convert to ETH-wei
              uint256 fullGasCostEthWei = gasUsed * gasPrice * (1 gwei);
              assert(fullGasCostEthWei < maxUint128); // the entire ETH supply fits in a uint128...
              return uint128(fullGasCostEthWei);
            }
            /**
             * @notice withdraw any available funds left in the contract, up to _amount, after accounting for the funds due to participants in past reports
             * @param _recipient address to send funds to
             * @param _amount maximum amount to withdraw, denominated in LINK-wei.
             * @dev access control provided by billingAccessController
             */
            function withdrawFunds(address _recipient, uint256 _amount)
              external
            {
              require(msg.sender == owner || s_billingAccessController.hasAccess(msg.sender, msg.data),
                "Only owner&billingAdmin can call");
              uint256 linkDue = totalLINKDue();
              uint256 linkBalance = LINK.balanceOf(address(this));
              require(linkBalance >= linkDue, "insufficient balance");
              require(LINK.transfer(_recipient, min(linkBalance - linkDue, _amount)), "insufficient funds");
            }
            // Total LINK due to participants in past reports.
            function totalLINKDue()
              internal
              view
              returns (uint256 linkDue)
            {
              // Argument for overflow safety: We do all computations in
              // uint256s. The inputs to linkDue are:
              // - the <= 31 observation rewards each of which has less than
              //   64 bits (32 bits for billing.linkGweiPerObservation, 32 bits
              //   for wei/gwei conversion). Hence 69 bits are sufficient for this part.
              // - the <= 31 gas reimbursements, each of which consists of at most 166
              //   bits (see s_gasReimbursementsLinkWei docstring). Hence 171 bits are
              //   sufficient for this part
              // In total, 172 bits are enough.
              uint16[maxNumOracles] memory observationCounts = s_oracleObservationsCounts;
              for (uint i = 0; i < maxNumOracles; i++) {
                linkDue += observationCounts[i] - 1; // Stored value is one greater than actual value
              }
              Billing memory billing = s_billing;
              // Convert linkGweiPerObservation to uint256, or this overflows!
              linkDue *= uint256(billing.linkGweiPerObservation) * (1 gwei);
              address[] memory transmitters = s_transmitters;
              uint256[maxNumOracles] memory gasReimbursementsLinkWei =
                s_gasReimbursementsLinkWei;
              for (uint i = 0; i < transmitters.length; i++) {
                linkDue += uint256(gasReimbursementsLinkWei[i]-1); // Stored value is one greater than actual value
              }
            }
            /**
             * @notice allows oracles to check that sufficient LINK balance is available
             * @return availableBalance LINK available on this contract, after accounting for outstanding obligations. can become negative
             */
            function linkAvailableForPayment()
              external
              view
              returns (int256 availableBalance)
            {
              // there are at most one billion LINK, so this cast is safe
              int256 balance = int256(LINK.balanceOf(address(this)));
              // according to the argument in the definition of totalLINKDue,
              // totalLINKDue is never greater than 2**172, so this cast is safe
              int256 due = int256(totalLINKDue());
              // safe from overflow according to above sizes
              return int256(balance) - int256(due);
            }
            /**
             * @notice number of observations oracle is due to be reimbursed for
             * @param _signerOrTransmitter address used by oracle for signing or transmitting reports
             */
            function oracleObservationCount(address _signerOrTransmitter)
              external
              view
              returns (uint16)
            {
              Oracle memory oracle = s_oracles[_signerOrTransmitter];
              if (oracle.role == Role.Unset) { return 0; }
              return s_oracleObservationsCounts[oracle.index] - 1;
            }
            function reimburseAndRewardOracles(
              uint32 initialGas,
              bytes memory observers
            )
              internal
            {
              Oracle memory txOracle = s_oracles[msg.sender];
              Billing memory billing = s_billing;
              // Reward oracles for providing observations. Oracles are not rewarded
              // for providing signatures, because signing is essentially free.
              s_oracleObservationsCounts =
                oracleRewards(observers, s_oracleObservationsCounts);
              // Reimburse transmitter of the report for gas usage
              require(txOracle.role == Role.Transmitter,
                "sent by undesignated transmitter"
              );
              uint256 gasPrice = impliedGasPrice(
                tx.gasprice / (1 gwei), // convert to ETH-gwei units
                billing.reasonableGasPrice,
                billing.maximumGasPrice
              );
              // The following is only an upper bound, as it ignores the cheaper cost for
              // 0 bytes. Safe from overflow, because calldata just isn't that long.
              uint256 callDataGasCost = 16 * msg.data.length;
              // If any changes are made to subsequent calculations, accountingGasCost
              // needs to change, too.
              uint256 gasLeft = gasleft();
              uint256 gasCostEthWei = transmitterGasCostEthWei(
                uint256(initialGas),
                gasPrice,
                callDataGasCost,
                gasLeft
              );
              // microLinkPerEth is 1e-6LINK/ETH units, gasCostEthWei is 1e-18ETH units
              // (ETH-wei), product is 1e-24LINK-wei units, dividing by 1e6 gives
              // 1e-18LINK units, i.e. LINK-wei units
              // Safe from over/underflow, since all components are non-negative,
              // gasCostEthWei will always fit into uint128 and microLinkPerEth is a
              // uint32 (128+32 < 256!).
              uint256 gasCostLinkWei = (gasCostEthWei * billing.microLinkPerEth)/ 1e6;
              // Safe from overflow, because gasCostLinkWei < 2**160 and
              // billing.linkGweiPerTransmission * (1 gwei) < 2**64 and we increment
              // s_gasReimbursementsLinkWei[txOracle.index] at most 2**40 times.
              s_gasReimbursementsLinkWei[txOracle.index] =
                s_gasReimbursementsLinkWei[txOracle.index] + gasCostLinkWei +
                uint256(billing.linkGweiPerTransmission) * (1 gwei); // convert from linkGwei to linkWei
              // Uncomment next line to compute the remaining gas cost after above gasleft().
              // See OffchainAggregatorBilling.accountingGasCost docstring for more information.
              //
              // gasUsedInAccounting = gasLeft - gasleft();
            }
            /*
             * Payee management
             */
            /**
             * @notice emitted when a transfer of an oracle's payee address has been initiated
             * @param transmitter address from which the oracle sends reports to the transmit method
             * @param current the payeee address for the oracle, prior to this setting
             * @param proposed the proposed new payee address for the oracle
             */
            event PayeeshipTransferRequested(
              address indexed transmitter,
              address indexed current,
              address indexed proposed
            );
            /**
             * @notice emitted when a transfer of an oracle's payee address has been completed
             * @param transmitter address from which the oracle sends reports to the transmit method
             * @param current the payeee address for the oracle, prior to this setting
             */
            event PayeeshipTransferred(
              address indexed transmitter,
              address indexed previous,
              address indexed current
            );
            /**
             * @notice sets the payees for transmitting addresses
             * @param _transmitters addresses oracles use to transmit the reports
             * @param _payees addresses of payees corresponding to list of transmitters
             * @dev must be called by owner
             * @dev cannot be used to change payee addresses, only to initially populate them
             */
            function setPayees(
              address[] calldata _transmitters,
              address[] calldata _payees
            )
              external
              onlyOwner()
            {
              require(_transmitters.length == _payees.length, "transmitters.size != payees.size");
              for (uint i = 0; i < _transmitters.length; i++) {
                address transmitter = _transmitters[i];
                address payee = _payees[i];
                address currentPayee = s_payees[transmitter];
                bool zeroedOut = currentPayee == address(0);
                require(zeroedOut || currentPayee == payee, "payee already set");
                s_payees[transmitter] = payee;
                if (currentPayee != payee) {
                  emit PayeeshipTransferred(transmitter, currentPayee, payee);
                }
              }
            }
            /**
             * @notice first step of payeeship transfer (safe transfer pattern)
             * @param _transmitter transmitter address of oracle whose payee is changing
             * @param _proposed new payee address
             * @dev can only be called by payee address
             */
            function transferPayeeship(
              address _transmitter,
              address _proposed
            )
              external
            {
                require(msg.sender == s_payees[_transmitter], "only current payee can update");
                require(msg.sender != _proposed, "cannot transfer to self");
                address previousProposed = s_proposedPayees[_transmitter];
                s_proposedPayees[_transmitter] = _proposed;
                if (previousProposed != _proposed) {
                  emit PayeeshipTransferRequested(_transmitter, msg.sender, _proposed);
                }
            }
            /**
             * @notice second step of payeeship transfer (safe transfer pattern)
             * @param _transmitter transmitter address of oracle whose payee is changing
             * @dev can only be called by proposed new payee address
             */
            function acceptPayeeship(
              address _transmitter
            )
              external
            {
              require(msg.sender == s_proposedPayees[_transmitter], "only proposed payees can accept");
              address currentPayee = s_payees[_transmitter];
              s_payees[_transmitter] = msg.sender;
              s_proposedPayees[_transmitter] = address(0);
              emit PayeeshipTransferred(_transmitter, currentPayee, msg.sender);
            }
            /*
             * Helper functions
             */
            function saturatingAddUint16(uint16 _x, uint16 _y)
              internal
              pure
              returns (uint16)
            {
              return uint16(min(uint256(_x)+uint256(_y), maxUint16));
            }
            function min(uint256 a, uint256 b)
              internal
              pure
              returns (uint256)
            {
              if (a < b) { return a; }
              return b;
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          abstract contract TypeAndVersionInterface{
            function typeAndVersion()
              external
              pure
              virtual
              returns (string memory);
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AggregatorInterface {
            function latestAnswer() external view returns (int256);
            function latestTimestamp() external view returns (uint256);
            function latestRound() external view returns (uint256);
            function getAnswer(uint256 roundId) external view returns (int256);
            function getTimestamp(uint256 roundId) external view returns (uint256);
            event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
            event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          interface AggregatorV3Interface {
            function decimals() external view returns (uint8);
            function description() external view returns (string memory);
            function version() external view returns (uint256);
            // getRoundData and latestRoundData should both raise "No data present"
            // if they do not have data to report, instead of returning unset values
            // which could be misinterpreted as actual reported values.
            function getRoundData(uint80 _roundId)
              external
              view
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              );
            function latestRoundData()
              external
              view
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              );
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./Owned.sol";
          import "./AccessControllerInterface.sol";
          /**
           * @title SimpleWriteAccessController
           * @notice Gives access to accounts explicitly added to an access list by the
           * controller's owner.
           * @dev does not make any special permissions for externally, see
           * SimpleReadAccessController for that.
           */
          contract SimpleWriteAccessController is AccessControllerInterface, Owned {
            bool public checkEnabled;
            mapping(address => bool) internal accessList;
            event AddedAccess(address user);
            event RemovedAccess(address user);
            event CheckAccessEnabled();
            event CheckAccessDisabled();
            constructor()
            {
              checkEnabled = true;
            }
            /**
             * @notice Returns the access of an address
             * @param _user The address to query
             */
            function hasAccess(
              address _user,
              bytes memory
            )
              public
              view
              virtual
              override
              returns (bool)
            {
              return accessList[_user] || !checkEnabled;
            }
            /**
             * @notice Adds an address to the access list
             * @param _user The address to add
             */
            function addAccess(address _user) external onlyOwner() {
              addAccessInternal(_user);
            }
            function addAccessInternal(address _user) internal {
              if (!accessList[_user]) {
                accessList[_user] = true;
                emit AddedAccess(_user);
              }
            }
            /**
             * @notice Removes an address from the access list
             * @param _user The address to remove
             */
            function removeAccess(address _user)
              external
              onlyOwner()
            {
              if (accessList[_user]) {
                accessList[_user] = false;
                emit RemovedAccess(_user);
              }
            }
            /**
             * @notice makes the access check enforced
             */
            function enableAccessCheck()
              external
              onlyOwner()
            {
              if (!checkEnabled) {
                checkEnabled = true;
                emit CheckAccessEnabled();
              }
            }
            /**
             * @notice makes the access check unenforced
             */
            function disableAccessCheck()
              external
              onlyOwner()
            {
              if (checkEnabled) {
                checkEnabled = false;
                emit CheckAccessDisabled();
              }
            }
            /**
             * @dev reverts if the caller does not have access
             */
            modifier checkAccess() {
              require(hasAccess(msg.sender, msg.data), "No access");
              _;
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./AccessControlledOffchainAggregator.sol";
          import "./AccessControlTestHelper.sol";
          contract TestOffchainAggregator is AccessControlledOffchainAggregator {
            function testDecodeReport(
              bytes memory report
            ) public pure returns (bytes32, bytes32, int192[] memory)
            {
              return decodeReport(report);
            }
            constructor(
              uint32 _maximumGasPrice,
              uint32 _reasonableGasPrice,
              uint32 _microLinkPerEth,
              uint32 _linkGweiPerObservation,
              uint32 _linkGweiPerTransmission,
              address _link,
              int192 _minAnswer, int192 _maxAnswer,
              AccessControllerInterface _billingAccessController,
              AccessControllerInterface _requesterAdminAccessController
            )
              AccessControlledOffchainAggregator(_maximumGasPrice, _reasonableGasPrice, _microLinkPerEth,
                _linkGweiPerObservation, _linkGweiPerTransmission, _link,
                _minAnswer, _maxAnswer, _billingAccessController, _requesterAdminAccessController, 0, "TEST"
              )
            {}
            function testPayee(
              address _transmitter
            )
              external
              view
              returns (address)
            {
              return s_payees[_transmitter];
            }
            function getConfigDigest() public view returns (bytes16) {
              return s_hotVars.latestConfigDigest;
            }
            function testSaturatingAddUint16(uint16 _x, uint16 _y)
              external pure returns (uint16)
            {
              return saturatingAddUint16(_x, _y);
            }
            function testImpliedGasPrice(uint256 txGasPrice, uint256 reasonableGasPrice,
              uint256 maximumGasPrice
            ) external pure returns (uint256) {
              return impliedGasPrice(txGasPrice, reasonableGasPrice, maximumGasPrice);
            }
            function testTransmitterGasCostEthWei(uint256 initialGas, uint256 gasPrice,
              uint256 callDataCost, uint256 gasLeft
            ) external pure returns (uint128) {
              return transmitterGasCostEthWei(
                initialGas, gasPrice, callDataCost, gasLeft
              );
            }
            function testSetOracleObservationCount(address _oracle, uint16 _amount) external {
              s_oracleObservationsCounts[s_oracles[_oracle].index] = _amount + 1;
            }
            function testTotalLinkDue()
              external view returns (uint256 linkDue)
            {
              return totalLINKDue();
            }
            function billingData() external view returns (
              uint16[maxNumOracles] memory observationsCounts,
              uint256[maxNumOracles] memory gasReimbursements,
              uint32 maximumGasPrice,
              uint32 reasonableGasPrice,
              uint32 microLinkPerEth,
              uint32 linkGweiPerObservation,
              uint32 linkGweiPerTransmission
            ) {
              Billing memory b = s_billing;
              return (s_oracleObservationsCounts, s_gasReimbursementsLinkWei,
                b.maximumGasPrice, b.reasonableGasPrice, b.microLinkPerEth,
                b.linkGweiPerObservation, b.linkGweiPerTransmission);
            }
            function testSetGasReimbursements(address _transmitterOrSigner, uint256 _amountLinkWei)
              external
            {
              require(s_oracles[_transmitterOrSigner].role != Role.Unset, "address unknown");
              s_gasReimbursementsLinkWei[s_oracles[_transmitterOrSigner].index] = _amountLinkWei + 1;
            }
            function testAccountingGasCost() public pure returns (uint256) {
              return accountingGasCost;
            }
            function testBurnLINK(uint256 amount) public {
                LINK.transfer(address(1), amount);
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.1;
          import "./AccessControlledOffchainAggregator.sol";
          contract AccessControlTestHelper {
            event Dummy(); // Used to silence warning that these methods are pure
            function readGetRoundData(address _aggregator, uint80 _roundID)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).getRoundData(_roundID);
              emit Dummy();
            }
            function readLatestRoundData(address _aggregator)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).latestRoundData();
              emit Dummy();
            }
            function readLatestAnswer(address _aggregator)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).latestAnswer();
              emit Dummy();
            }
            function readLatestTimestamp(address _aggregator)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).latestTimestamp();
              emit Dummy();
            }
            function readLatestRound(address _aggregator)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).latestRound();
              emit Dummy();
            }
            function readGetAnswer(address _aggregator, uint256 _roundID)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).getAnswer(_roundID);
              emit Dummy();
            }
            function readGetTimestamp(address _aggregator, uint256 _roundID)
              external
            {
              AccessControlledOffchainAggregator(_aggregator).getTimestamp(_roundID);
              emit Dummy();
            }
            function testLatestTransmissionDetails(address _aggregator) external view {
                OffchainAggregator(_aggregator).latestTransmissionDetails();
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./OffchainAggregator.sol";
          // ExposedOffchainAggregator exposes certain internal OffchainAggregator
          // methods/structures so that golang code can access them, and we get
          // reliable type checking on their usage
          contract ExposedOffchainAggregator is OffchainAggregator {
            constructor()
              OffchainAggregator(
                0, 0, 0, 0, 0, address(0), 0, 0, AccessControllerInterface(address(0)), AccessControllerInterface(address(0)), 0, ""
              )
              {}
            function exposedConfigDigestFromConfigData(
              address _contractAddress,
              uint64 _configCount,
              address[] calldata _signers,
              address[] calldata _transmitters,
              uint8 _threshold,
              uint64 _encodedConfigVersion,
              bytes calldata _encodedConfig
            ) external pure returns (bytes16) {
              return configDigestFromConfigData(_contractAddress, _configCount,
                _signers, _transmitters, _threshold, _encodedConfigVersion,
                _encodedConfig);
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.7.0;
          import "./AggregatorValidatorInterface.sol";
          contract TestValidator is AggregatorValidatorInterface {
            uint32 s_minGasUse;
            uint256 s_latestRoundId;
            event Validated(
              uint256 previousRoundId,
              int256 previousAnswer,
              uint256 currentRoundId,
              int256 currentAnswer,
              uint256 initialGas
            );
            function validate(
              uint256 previousRoundId,
              int256 previousAnswer,
              uint256 currentRoundId,
              int256 currentAnswer
            ) external override returns (bool) {
              uint256 initialGas = gasleft();
              emit Validated(
                previousRoundId,
                previousAnswer,
                currentRoundId,
                currentAnswer,
                initialGas
              );
              s_latestRoundId = currentRoundId;
              uint256 minGasUse = s_minGasUse;
              while (initialGas - gasleft() < minGasUse) {}
              return true;
            }
            function setMinGasUse(uint32 minGasUse) external {
              s_minGasUse = minGasUse;
            }
            function latestRoundId() external view returns (uint256) {
              return s_latestRoundId;
            }
          }
          

          File 6 of 6: ENSRegistryWithFallback
          // File: @ensdomains/ens/contracts/ENS.sol
          
          pragma solidity >=0.4.24;
          
          interface ENS {
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          
              // Logged when an operator is added or removed.
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external;
              function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external;
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns(bytes32);
              function setResolver(bytes32 node, address resolver) external;
              function setOwner(bytes32 node, address owner) external;
              function setTTL(bytes32 node, uint64 ttl) external;
              function setApprovalForAll(address operator, bool approved) external;
              function owner(bytes32 node) external view returns (address);
              function resolver(bytes32 node) external view returns (address);
              function ttl(bytes32 node) external view returns (uint64);
              function recordExists(bytes32 node) external view returns (bool);
              function isApprovedForAll(address owner, address operator) external view returns (bool);
          }
          
          // File: @ensdomains/ens/contracts/ENSRegistry.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * The ENS registry contract.
           */
          contract ENSRegistry is ENS {
          
              struct Record {
                  address owner;
                  address resolver;
                  uint64 ttl;
              }
          
              mapping (bytes32 => Record) records;
              mapping (address => mapping(address => bool)) operators;
          
              // Permits modifications only by the owner of the specified node.
              modifier authorised(bytes32 node) {
                  address owner = records[node].owner;
                  require(owner == msg.sender || operators[owner][msg.sender]);
                  _;
              }
          
              /**
               * @dev Constructs a new ENS registrar.
               */
              constructor() public {
                  records[0x0].owner = msg.sender;
              }
          
              /**
               * @dev Sets the record for a node.
               * @param node The node to update.
               * @param owner The address of the new owner.
               * @param resolver The address of the resolver.
               * @param ttl The TTL in seconds.
               */
              function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external {
                  setOwner(node, owner);
                  _setResolverAndTTL(node, resolver, ttl);
              }
          
              /**
               * @dev Sets the record for a subnode.
               * @param node The parent node.
               * @param label The hash of the label specifying the subnode.
               * @param owner The address of the new owner.
               * @param resolver The address of the resolver.
               * @param ttl The TTL in seconds.
               */
              function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external {
                  bytes32 subnode = setSubnodeOwner(node, label, owner);
                  _setResolverAndTTL(subnode, resolver, ttl);
              }
          
              /**
               * @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.
               * @param node The node to transfer ownership of.
               * @param owner The address of the new owner.
               */
              function setOwner(bytes32 node, address owner) public authorised(node) {
                  _setOwner(node, owner);
                  emit Transfer(node, owner);
              }
          
              /**
               * @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.
               * @param node The parent node.
               * @param label The hash of the label specifying the subnode.
               * @param owner The address of the new owner.
               */
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public authorised(node) returns(bytes32) {
                  bytes32 subnode = keccak256(abi.encodePacked(node, label));
                  _setOwner(subnode, owner);
                  emit NewOwner(node, label, owner);
                  return subnode;
              }
          
              /**
               * @dev Sets the resolver address for the specified node.
               * @param node The node to update.
               * @param resolver The address of the resolver.
               */
              function setResolver(bytes32 node, address resolver) public authorised(node) {
                  emit NewResolver(node, resolver);
                  records[node].resolver = resolver;
              }
          
              /**
               * @dev Sets the TTL for the specified node.
               * @param node The node to update.
               * @param ttl The TTL in seconds.
               */
              function setTTL(bytes32 node, uint64 ttl) public authorised(node) {
                  emit NewTTL(node, ttl);
                  records[node].ttl = ttl;
              }
          
              /**
               * @dev Enable or disable approval for a third party ("operator") to manage
               *  all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.
               * @param operator Address to add to the set of authorized operators.
               * @param approved True if the operator is approved, false to revoke approval.
               */
              function setApprovalForAll(address operator, bool approved) external {
                  operators[msg.sender][operator] = approved;
                  emit ApprovalForAll(msg.sender, operator, approved);
              }
          
              /**
               * @dev Returns the address that owns the specified node.
               * @param node The specified node.
               * @return address of the owner.
               */
              function owner(bytes32 node) public view returns (address) {
                  address addr = records[node].owner;
                  if (addr == address(this)) {
                      return address(0x0);
                  }
          
                  return addr;
              }
          
              /**
               * @dev Returns the address of the resolver for the specified node.
               * @param node The specified node.
               * @return address of the resolver.
               */
              function resolver(bytes32 node) public view returns (address) {
                  return records[node].resolver;
              }
          
              /**
               * @dev Returns the TTL of a node, and any records associated with it.
               * @param node The specified node.
               * @return ttl of the node.
               */
              function ttl(bytes32 node) public view returns (uint64) {
                  return records[node].ttl;
              }
          
              /**
               * @dev Returns whether a record has been imported to the registry.
               * @param node The specified node.
               * @return Bool if record exists
               */
              function recordExists(bytes32 node) public view returns (bool) {
                  return records[node].owner != address(0x0);
              }
          
              /**
               * @dev Query if an address is an authorized operator for another address.
               * @param owner The address that owns the records.
               * @param operator The address that acts on behalf of the owner.
               * @return True if `operator` is an approved operator for `owner`, false otherwise.
               */
              function isApprovedForAll(address owner, address operator) external view returns (bool) {
                  return operators[owner][operator];
              }
          
              function _setOwner(bytes32 node, address owner) internal {
                  records[node].owner = owner;
              }
          
              function _setResolverAndTTL(bytes32 node, address resolver, uint64 ttl) internal {
                  if(resolver != records[node].resolver) {
                      records[node].resolver = resolver;
                      emit NewResolver(node, resolver);
                  }
          
                  if(ttl != records[node].ttl) {
                      records[node].ttl = ttl;
                      emit NewTTL(node, ttl);
                  }
              }
          }
          
          // File: @ensdomains/ens/contracts/ENSRegistryWithFallback.sol
          
          pragma solidity ^0.5.0;
          
          
          
          /**
           * The ENS registry contract.
           */
          contract ENSRegistryWithFallback is ENSRegistry {
          
              ENS public old;
          
              /**
               * @dev Constructs a new ENS registrar.
               */
              constructor(ENS _old) public ENSRegistry() {
                  old = _old;
              }
          
              /**
               * @dev Returns the address of the resolver for the specified node.
               * @param node The specified node.
               * @return address of the resolver.
               */
              function resolver(bytes32 node) public view returns (address) {
                  if (!recordExists(node)) {
                      return old.resolver(node);
                  }
          
                  return super.resolver(node);
              }
          
              /**
               * @dev Returns the address that owns the specified node.
               * @param node The specified node.
               * @return address of the owner.
               */
              function owner(bytes32 node) public view returns (address) {
                  if (!recordExists(node)) {
                      return old.owner(node);
                  }
          
                  return super.owner(node);
              }
          
              /**
               * @dev Returns the TTL of a node, and any records associated with it.
               * @param node The specified node.
               * @return ttl of the node.
               */
              function ttl(bytes32 node) public view returns (uint64) {
                  if (!recordExists(node)) {
                      return old.ttl(node);
                  }
          
                  return super.ttl(node);
              }
          
              function _setOwner(bytes32 node, address owner) internal {
                  address addr = owner;
                  if (addr == address(0x0)) {
                      addr = address(this);
                  }
          
                  super._setOwner(node, addr);
              }
          }