ETH Price: $2,639.76 (+4.04%)

Transaction Decoder

Block:
16020335 at Nov-21-2022 06:59:35 PM +UTC
Transaction Fee:
0.00349750809672822 ETH $9.23
Gas Used:
244,380 Gas / 14.311760769 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
0x45704eda...511e452cF 16.808587063838925448 Eth16.813122005564924268 Eth0.00453494172599882
(builder0x69)
2.488482072040954948 Eth2.489198650684015588 Eth0.00071657864306064
0xb681e94c...8e6C8eA32
0.011001726049327558 Eth
Nonce: 185
0.002969276226600518 Eth
Nonce: 186
0.00803244982272704

Execution Trace

ETH 0.00453494172599882 lzCore.register( domainName=zk6356, year=1 )
  • EACAggregatorProxy.STATICCALL( )
    • AccessControlledOffchainAggregator.STATICCALL( )
      File 1 of 3: lzCore
      // File: @openzeppelin/contracts/utils/Strings.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev String operations.
       */
      library Strings {
          bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
          uint8 private constant _ADDRESS_LENGTH = 20;
      
          /**
           * @dev Converts a `uint256` to its ASCII `string` decimal representation.
           */
          function toString(uint256 value) internal pure returns (string memory) {
              // Inspired by OraclizeAPI's implementation - MIT licence
              // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
      
              if (value == 0) {
                  return "0";
              }
              uint256 temp = value;
              uint256 digits;
              while (temp != 0) {
                  digits++;
                  temp /= 10;
              }
              bytes memory buffer = new bytes(digits);
              while (value != 0) {
                  digits -= 1;
                  buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
                  value /= 10;
              }
              return string(buffer);
          }
      
          /**
           * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
           */
          function toHexString(uint256 value) internal pure returns (string memory) {
              if (value == 0) {
                  return "0x00";
              }
              uint256 temp = value;
              uint256 length = 0;
              while (temp != 0) {
                  length++;
                  temp >>= 8;
              }
              return toHexString(value, length);
          }
      
          /**
           * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
           */
          function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
              bytes memory buffer = new bytes(2 * length + 2);
              buffer[0] = "0";
              buffer[1] = "x";
              for (uint256 i = 2 * length + 1; i > 1; --i) {
                  buffer[i] = _HEX_SYMBOLS[value & 0xf];
                  value >>= 4;
              }
              require(value == 0, "Strings: hex length insufficient");
              return string(buffer);
          }
      
          /**
           * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
           */
          function toHexString(address addr) internal pure returns (string memory) {
              return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
          }
      }
      
      // File: @openzeppelin/contracts/utils/Context.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
      
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      
      // File: @openzeppelin/contracts/utils/Address.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
      
      pragma solidity ^0.8.1;
      
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           * ====
           *
           * [IMPORTANT]
           * ====
           * You shouldn't rely on `isContract` to protect against flash loan attacks!
           *
           * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
           * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
           * constructor.
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize/address.code.length, which returns 0
              // for contracts in construction, since the code is only stored at the end
              // of the constructor execution.
      
              return account.code.length > 0;
          }
      
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
      
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
      
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain `call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              require(isContract(target), "Address: call to non-contract");
      
              (bool success, bytes memory returndata) = target.call{value: value}(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              require(isContract(target), "Address: static call to non-contract");
      
              (bool success, bytes memory returndata) = target.staticcall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(isContract(target), "Address: delegate call to non-contract");
      
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return verifyCallResult(success, returndata, errorMessage);
          }
      
          /**
           * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
           * revert reason using the provided one.
           *
           * _Available since v4.3._
           */
          function verifyCallResult(
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal pure returns (bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  // Look for revert reason and bubble it up if present
                  if (returndata.length > 0) {
                      // The easiest way to bubble the revert reason is using memory via assembly
                      /// @solidity memory-safe-assembly
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      
      // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
      
      
      // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @title ERC721 token receiver interface
       * @dev Interface for any contract that wants to support safeTransfers
       * from ERC721 asset contracts.
       */
      interface IERC721Receiver {
          /**
           * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
           * by `operator` from `from`, this function is called.
           *
           * It must return its Solidity selector to confirm the token transfer.
           * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
           *
           * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
           */
          function onERC721Received(
              address operator,
              address from,
              uint256 tokenId,
              bytes calldata data
          ) external returns (bytes4);
      }
      
      // File: @openzeppelin/contracts/utils/introspection/IERC165.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Interface of the ERC165 standard, as defined in the
       * https://eips.ethereum.org/EIPS/eip-165[EIP].
       *
       * Implementers can declare support of contract interfaces, which can then be
       * queried by others ({ERC165Checker}).
       *
       * For an implementation, see {ERC165}.
       */
      interface IERC165 {
          /**
           * @dev Returns true if this contract implements the interface defined by
           * `interfaceId`. See the corresponding
           * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
           * to learn more about how these ids are created.
           *
           * This function call must use less than 30 000 gas.
           */
          function supportsInterface(bytes4 interfaceId) external view returns (bool);
      }
      
      // File: @openzeppelin/contracts/utils/introspection/ERC165.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
      
      pragma solidity ^0.8.0;
      
      
      /**
       * @dev Implementation of the {IERC165} interface.
       *
       * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
       * for the additional interface id that will be supported. For example:
       *
       * ```solidity
       * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
       *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
       * }
       * ```
       *
       * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
       */
      abstract contract ERC165 is IERC165 {
          /**
           * @dev See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
              return interfaceId == type(IERC165).interfaceId;
          }
      }
      
      // File: @openzeppelin/contracts/token/ERC721/IERC721.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
      
      pragma solidity ^0.8.0;
      
      
      /**
       * @dev Required interface of an ERC721 compliant contract.
       */
      interface IERC721 is IERC165 {
          /**
           * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
           */
          event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
      
          /**
           * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
           */
          event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
      
          /**
           * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
           */
          event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
      
          /**
           * @dev Returns the number of tokens in ``owner``'s account.
           */
          function balanceOf(address owner) external view returns (uint256 balance);
      
          /**
           * @dev Returns the owner of the `tokenId` token.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           */
          function ownerOf(uint256 tokenId) external view returns (address owner);
      
          /**
           * @dev Safely transfers `tokenId` token from `from` to `to`.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must exist and be owned by `from`.
           * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId,
              bytes calldata data
          ) external;
      
          /**
           * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
           * are aware of the ERC721 protocol to prevent tokens from being forever locked.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must exist and be owned by `from`.
           * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId
          ) external;
      
          /**
           * @dev Transfers `tokenId` token from `from` to `to`.
           *
           * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must be owned by `from`.
           * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(
              address from,
              address to,
              uint256 tokenId
          ) external;
      
          /**
           * @dev Gives permission to `to` to transfer `tokenId` token to another account.
           * The approval is cleared when the token is transferred.
           *
           * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
           *
           * Requirements:
           *
           * - The caller must own the token or be an approved operator.
           * - `tokenId` must exist.
           *
           * Emits an {Approval} event.
           */
          function approve(address to, uint256 tokenId) external;
      
          /**
           * @dev Approve or remove `operator` as an operator for the caller.
           * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
           *
           * Requirements:
           *
           * - The `operator` cannot be the caller.
           *
           * Emits an {ApprovalForAll} event.
           */
          function setApprovalForAll(address operator, bool _approved) external;
      
          /**
           * @dev Returns the account approved for `tokenId` token.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           */
          function getApproved(uint256 tokenId) external view returns (address operator);
      
          /**
           * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
           *
           * See {setApprovalForAll}
           */
          function isApprovedForAll(address owner, address operator) external view returns (bool);
      }
      
      // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
      
      
      // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
      
      pragma solidity ^0.8.0;
      
      
      /**
       * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
       * @dev See https://eips.ethereum.org/EIPS/eip-721
       */
      interface IERC721Enumerable is IERC721 {
          /**
           * @dev Returns the total amount of tokens stored by the contract.
           */
          function totalSupply() external view returns (uint256);
      
          /**
           * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
           * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
           */
          function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
      
          /**
           * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
           * Use along with {totalSupply} to enumerate all tokens.
           */
          function tokenByIndex(uint256 index) external view returns (uint256);
      }
      
      // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
      
      pragma solidity ^0.8.0;
      
      
      /**
       * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
       * @dev See https://eips.ethereum.org/EIPS/eip-721
       */
      interface IERC721Metadata is IERC721 {
          /**
           * @dev Returns the token collection name.
           */
          function name() external view returns (string memory);
      
          /**
           * @dev Returns the token collection symbol.
           */
          function symbol() external view returns (string memory);
      
          /**
           * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
           */
          function tokenURI(uint256 tokenId) external view returns (string memory);
      }
      
      // File: @openzeppelin/contracts/token/ERC721/ERC721.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)
      
      pragma solidity ^0.8.0;
      
      
      
      
      
      
      
      
      /**
       * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
       * the Metadata extension, but not including the Enumerable extension, which is available separately as
       * {ERC721Enumerable}.
       */
      contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
          using Address for address;
          using Strings for uint256;
      
          // Token name
          string private _name;
      
          // Token symbol
          string private _symbol;
      
          // Mapping from token ID to owner address
          mapping(uint256 => address) private _owners;
      
          // Mapping owner address to token count
          mapping(address => uint256) private _balances;
      
          // Mapping from token ID to approved address
          mapping(uint256 => address) private _tokenApprovals;
      
          // Mapping from owner to operator approvals
          mapping(address => mapping(address => bool)) private _operatorApprovals;
      
          /**
           * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
           */
          constructor(string memory name_, string memory symbol_) {
              _name = name_;
              _symbol = symbol_;
          }
      
          /**
           * @dev See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
              return
                  interfaceId == type(IERC721).interfaceId ||
                  interfaceId == type(IERC721Metadata).interfaceId ||
                  super.supportsInterface(interfaceId);
          }
      
          /**
           * @dev See {IERC721-balanceOf}.
           */
          function balanceOf(address owner) public view virtual override returns (uint256) {
              require(owner != address(0), "ERC721: address zero is not a valid owner");
              return _balances[owner];
          }
      
          /**
           * @dev See {IERC721-ownerOf}.
           */
          function ownerOf(uint256 tokenId) public view virtual override returns (address) {
              address owner = _owners[tokenId];
              require(owner != address(0), "ERC721: invalid token ID");
              return owner;
          }
      
          /**
           * @dev See {IERC721Metadata-name}.
           */
          function name() public view virtual override returns (string memory) {
              return _name;
          }
      
          /**
           * @dev See {IERC721Metadata-symbol}.
           */
          function symbol() public view virtual override returns (string memory) {
              return _symbol;
          }
      
          /**
           * @dev See {IERC721Metadata-tokenURI}.
           */
          function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
              _requireMinted(tokenId);
      
              string memory baseURI = _baseURI();
              return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
          }
      
          /**
           * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
           * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
           * by default, can be overridden in child contracts.
           */
          function _baseURI() internal view virtual returns (string memory) {
              return "";
          }
      
          /**
           * @dev See {IERC721-approve}.
           */
          function approve(address to, uint256 tokenId) public virtual override {
              address owner = ERC721.ownerOf(tokenId);
              require(to != owner, "ERC721: approval to current owner");
      
              require(
                  _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
                  "ERC721: approve caller is not token owner nor approved for all"
              );
      
              _approve(to, tokenId);
          }
      
          /**
           * @dev See {IERC721-getApproved}.
           */
          function getApproved(uint256 tokenId) public view virtual override returns (address) {
              _requireMinted(tokenId);
      
              return _tokenApprovals[tokenId];
          }
      
          /**
           * @dev See {IERC721-setApprovalForAll}.
           */
          function setApprovalForAll(address operator, bool approved) public virtual override {
              _setApprovalForAll(_msgSender(), operator, approved);
          }
      
          /**
           * @dev See {IERC721-isApprovedForAll}.
           */
          function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
              return _operatorApprovals[owner][operator];
          }
      
          /**
           * @dev See {IERC721-transferFrom}.
           */
          function transferFrom(
              address from,
              address to,
              uint256 tokenId
          ) public virtual override {
              //solhint-disable-next-line max-line-length
              require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
      
              _transfer(from, to, tokenId);
          }
      
          /**
           * @dev See {IERC721-safeTransferFrom}.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId
          ) public virtual override {
              safeTransferFrom(from, to, tokenId, "");
          }
      
          /**
           * @dev See {IERC721-safeTransferFrom}.
           */
          function safeTransferFrom(
              address from,
              address to,
              uint256 tokenId,
              bytes memory data
          ) public virtual override {
              require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
              _safeTransfer(from, to, tokenId, data);
          }
      
          /**
           * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
           * are aware of the ERC721 protocol to prevent tokens from being forever locked.
           *
           * `data` is additional data, it has no specified format and it is sent in call to `to`.
           *
           * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
           * implement alternative mechanisms to perform token transfer, such as signature-based.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `tokenId` token must exist and be owned by `from`.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function _safeTransfer(
              address from,
              address to,
              uint256 tokenId,
              bytes memory data
          ) internal virtual {
              _transfer(from, to, tokenId);
              require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
          }
      
          /**
           * @dev Returns whether `tokenId` exists.
           *
           * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
           *
           * Tokens start existing when they are minted (`_mint`),
           * and stop existing when they are burned (`_burn`).
           */
          function _exists(uint256 tokenId) internal view virtual returns (bool) {
              return _owners[tokenId] != address(0);
          }
      
          /**
           * @dev Returns whether `spender` is allowed to manage `tokenId`.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           */
          function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
              address owner = ERC721.ownerOf(tokenId);
              return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
          }
      
          /**
           * @dev Safely mints `tokenId` and transfers it to `to`.
           *
           * Requirements:
           *
           * - `tokenId` must not exist.
           * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
           *
           * Emits a {Transfer} event.
           */
          function _safeMint(address to, uint256 tokenId) internal virtual {
              _safeMint(to, tokenId, "");
          }
      
          /**
           * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
           * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
           */
          function _safeMint(
              address to,
              uint256 tokenId,
              bytes memory data
          ) internal virtual {
              _mint(to, tokenId);
              require(
                  _checkOnERC721Received(address(0), to, tokenId, data),
                  "ERC721: transfer to non ERC721Receiver implementer"
              );
          }
      
          /**
           * @dev Mints `tokenId` and transfers it to `to`.
           *
           * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
           *
           * Requirements:
           *
           * - `tokenId` must not exist.
           * - `to` cannot be the zero address.
           *
           * Emits a {Transfer} event.
           */
          function _mint(address to, uint256 tokenId) internal virtual {
              require(to != address(0), "ERC721: mint to the zero address");
              require(!_exists(tokenId), "ERC721: token already minted");
      
              _beforeTokenTransfer(address(0), to, tokenId);
      
              _balances[to] += 1;
              _owners[tokenId] = to;
      
              emit Transfer(address(0), to, tokenId);
      
              _afterTokenTransfer(address(0), to, tokenId);
          }
      
          /**
           * @dev Destroys `tokenId`.
           * The approval is cleared when the token is burned.
           *
           * Requirements:
           *
           * - `tokenId` must exist.
           *
           * Emits a {Transfer} event.
           */
          function _burn(uint256 tokenId) internal virtual {
              address owner = ERC721.ownerOf(tokenId);
      
              _beforeTokenTransfer(owner, address(0), tokenId);
      
              // Clear approvals
              _approve(address(0), tokenId);
      
              _balances[owner] -= 1;
              delete _owners[tokenId];
      
              emit Transfer(owner, address(0), tokenId);
      
              _afterTokenTransfer(owner, address(0), tokenId);
          }
      
          /**
           * @dev Transfers `tokenId` from `from` to `to`.
           *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
           *
           * Requirements:
           *
           * - `to` cannot be the zero address.
           * - `tokenId` token must be owned by `from`.
           *
           * Emits a {Transfer} event.
           */
          function _transfer(
              address from,
              address to,
              uint256 tokenId
          ) internal virtual {
              require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
              require(to != address(0), "ERC721: transfer to the zero address");
      
              _beforeTokenTransfer(from, to, tokenId);
      
              // Clear approvals from the previous owner
              _approve(address(0), tokenId);
      
              _balances[from] -= 1;
              _balances[to] += 1;
              _owners[tokenId] = to;
      
              emit Transfer(from, to, tokenId);
      
              _afterTokenTransfer(from, to, tokenId);
          }
      
          /**
           * @dev Approve `to` to operate on `tokenId`
           *
           * Emits an {Approval} event.
           */
          function _approve(address to, uint256 tokenId) internal virtual {
              _tokenApprovals[tokenId] = to;
              emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
          }
      
          /**
           * @dev Approve `operator` to operate on all of `owner` tokens
           *
           * Emits an {ApprovalForAll} event.
           */
          function _setApprovalForAll(
              address owner,
              address operator,
              bool approved
          ) internal virtual {
              require(owner != operator, "ERC721: approve to caller");
              _operatorApprovals[owner][operator] = approved;
              emit ApprovalForAll(owner, operator, approved);
          }
      
          /**
           * @dev Reverts if the `tokenId` has not been minted yet.
           */
          function _requireMinted(uint256 tokenId) internal view virtual {
              require(_exists(tokenId), "ERC721: invalid token ID");
          }
      
          /**
           * @dev Internal function to invoke {IERC721Receiver-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 bool whether the call correctly returned the expected magic value
           */
          function _checkOnERC721Received(
              address from,
              address to,
              uint256 tokenId,
              bytes memory data
          ) private returns (bool) {
              if (to.isContract()) {
                  try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                      return retval == IERC721Receiver.onERC721Received.selector;
                  } catch (bytes memory reason) {
                      if (reason.length == 0) {
                          revert("ERC721: transfer to non ERC721Receiver implementer");
                      } else {
                          /// @solidity memory-safe-assembly
                          assembly {
                              revert(add(32, reason), mload(reason))
                          }
                      }
                  }
              } else {
                  return true;
              }
          }
      
          /**
           * @dev Hook that is called before any token transfer. This includes minting
           * and burning.
           *
           * Calling conditions:
           *
           * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
           * transferred to `to`.
           * - When `from` is zero, `tokenId` will be minted for `to`.
           * - When `to` is zero, ``from``'s `tokenId` will be burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 tokenId
          ) internal virtual {}
      
          /**
           * @dev Hook that is called after any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _afterTokenTransfer(
              address from,
              address to,
              uint256 tokenId
          ) internal virtual {}
      }
      
      // File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
      
      pragma solidity ^0.8.0;
      
      
      
      /**
       * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
       * enumerability of all the token ids in the contract as well as all token ids owned by each
       * account.
       */
      abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
          // Mapping from owner to list of owned token IDs
          mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
      
          // Mapping from token ID to index of the owner tokens list
          mapping(uint256 => uint256) private _ownedTokensIndex;
      
          // Array with all token ids, used for enumeration
          uint256[] private _allTokens;
      
          // Mapping from token id to position in the allTokens array
          mapping(uint256 => uint256) private _allTokensIndex;
      
          /**
           * @dev See {IERC165-supportsInterface}.
           */
          function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
              return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
          }
      
          /**
           * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
           */
          function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
              require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
              return _ownedTokens[owner][index];
          }
      
          /**
           * @dev See {IERC721Enumerable-totalSupply}.
           */
          function totalSupply() public view virtual override returns (uint256) {
              return _allTokens.length;
          }
      
          /**
           * @dev See {IERC721Enumerable-tokenByIndex}.
           */
          function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
              require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
              return _allTokens[index];
          }
      
          /**
           * @dev Hook that is called before any token transfer. This includes minting
           * and burning.
           *
           * Calling conditions:
           *
           * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
           * transferred to `to`.
           * - When `from` is zero, `tokenId` will be minted for `to`.
           * - When `to` is zero, ``from``'s `tokenId` will be burned.
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 tokenId
          ) internal virtual override {
              super._beforeTokenTransfer(from, to, tokenId);
      
              if (from == address(0)) {
                  _addTokenToAllTokensEnumeration(tokenId);
              } else if (from != to) {
                  _removeTokenFromOwnerEnumeration(from, tokenId);
              }
              if (to == address(0)) {
                  _removeTokenFromAllTokensEnumeration(tokenId);
              } else if (to != from) {
                  _addTokenToOwnerEnumeration(to, tokenId);
              }
          }
      
          /**
           * @dev Private function to add a token to this extension's ownership-tracking data structures.
           * @param to address representing the new owner of the given token ID
           * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
           */
          function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
              uint256 length = ERC721.balanceOf(to);
              _ownedTokens[to][length] = tokenId;
              _ownedTokensIndex[tokenId] = length;
          }
      
          /**
           * @dev Private function to add a token to this extension's token tracking data structures.
           * @param tokenId uint256 ID of the token to be added to the tokens list
           */
          function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
              _allTokensIndex[tokenId] = _allTokens.length;
              _allTokens.push(tokenId);
          }
      
          /**
           * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
           * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
           * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
           * This has O(1) time complexity, but alters the order of the _ownedTokens array.
           * @param from address representing the previous owner of the given token ID
           * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
           */
          function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
              // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
              // then delete the last slot (swap and pop).
      
              uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
              uint256 tokenIndex = _ownedTokensIndex[tokenId];
      
              // When the token to delete is the last token, the swap operation is unnecessary
              if (tokenIndex != lastTokenIndex) {
                  uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
      
                  _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
                  _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
              }
      
              // This also deletes the contents at the last position of the array
              delete _ownedTokensIndex[tokenId];
              delete _ownedTokens[from][lastTokenIndex];
          }
      
          /**
           * @dev Private function to remove a token from this extension's token tracking data structures.
           * This has O(1) time complexity, but alters the order of the _allTokens array.
           * @param tokenId uint256 ID of the token to be removed from the tokens list
           */
          function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
              // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
              // then delete the last slot (swap and pop).
      
              uint256 lastTokenIndex = _allTokens.length - 1;
              uint256 tokenIndex = _allTokensIndex[tokenId];
      
              // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
              // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
              // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
              uint256 lastTokenId = _allTokens[lastTokenIndex];
      
              _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
              _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
      
              // This also deletes the contents at the last position of the array
              delete _allTokensIndex[tokenId];
              _allTokens.pop();
          }
      }
      
      // File: @openzeppelin/contracts/utils/math/SafeMath.sol
      
      
      // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)
      
      pragma solidity ^0.8.0;
      
      // CAUTION
      // This version of SafeMath should only be used with Solidity 0.8 or later,
      // because it relies on the compiler's built in overflow checks.
      
      /**
       * @dev Wrappers over Solidity's arithmetic operations.
       *
       * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
       * now has built in overflow checking.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
          }
      
          /**
           * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
          }
      
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  // 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-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
          }
      
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
          }
      
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              return a + b;
          }
      
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return a - b;
          }
      
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              return a * b;
          }
      
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator.
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return a / b;
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return a % b;
          }
      
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(
              uint256 a,
              uint256 b,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b <= a, errorMessage);
                  return a - b;
              }
          }
      
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(
              uint256 a,
              uint256 b,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b > 0, errorMessage);
                  return a / b;
              }
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(
              uint256 a,
              uint256 b,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
      }
      
      // File: @openzeppelin/contracts/utils/math/SafeCast.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
       * checks.
       *
       * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
       * easily result in undesired exploitation or bugs, since developers usually
       * assume that overflows raise errors. `SafeCast` restores this intuition by
       * reverting the transaction when such an operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       *
       * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
       * all math on `uint256` and `int256` and then downcasting.
       */
      library SafeCast {
          /**
           * @dev Returns the downcasted uint248 from uint256, reverting on
           * overflow (when the input is greater than largest uint248).
           *
           * Counterpart to Solidity's `uint248` operator.
           *
           * Requirements:
           *
           * - input must fit into 248 bits
           *
           * _Available since v4.7._
           */
          function toUint248(uint256 value) internal pure returns (uint248) {
              require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
              return uint248(value);
          }
      
          /**
           * @dev Returns the downcasted uint240 from uint256, reverting on
           * overflow (when the input is greater than largest uint240).
           *
           * Counterpart to Solidity's `uint240` operator.
           *
           * Requirements:
           *
           * - input must fit into 240 bits
           *
           * _Available since v4.7._
           */
          function toUint240(uint256 value) internal pure returns (uint240) {
              require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
              return uint240(value);
          }
      
          /**
           * @dev Returns the downcasted uint232 from uint256, reverting on
           * overflow (when the input is greater than largest uint232).
           *
           * Counterpart to Solidity's `uint232` operator.
           *
           * Requirements:
           *
           * - input must fit into 232 bits
           *
           * _Available since v4.7._
           */
          function toUint232(uint256 value) internal pure returns (uint232) {
              require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
              return uint232(value);
          }
      
          /**
           * @dev Returns the downcasted uint224 from uint256, reverting on
           * overflow (when the input is greater than largest uint224).
           *
           * Counterpart to Solidity's `uint224` operator.
           *
           * Requirements:
           *
           * - input must fit into 224 bits
           *
           * _Available since v4.2._
           */
          function toUint224(uint256 value) internal pure returns (uint224) {
              require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
              return uint224(value);
          }
      
          /**
           * @dev Returns the downcasted uint216 from uint256, reverting on
           * overflow (when the input is greater than largest uint216).
           *
           * Counterpart to Solidity's `uint216` operator.
           *
           * Requirements:
           *
           * - input must fit into 216 bits
           *
           * _Available since v4.7._
           */
          function toUint216(uint256 value) internal pure returns (uint216) {
              require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
              return uint216(value);
          }
      
          /**
           * @dev Returns the downcasted uint208 from uint256, reverting on
           * overflow (when the input is greater than largest uint208).
           *
           * Counterpart to Solidity's `uint208` operator.
           *
           * Requirements:
           *
           * - input must fit into 208 bits
           *
           * _Available since v4.7._
           */
          function toUint208(uint256 value) internal pure returns (uint208) {
              require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
              return uint208(value);
          }
      
          /**
           * @dev Returns the downcasted uint200 from uint256, reverting on
           * overflow (when the input is greater than largest uint200).
           *
           * Counterpart to Solidity's `uint200` operator.
           *
           * Requirements:
           *
           * - input must fit into 200 bits
           *
           * _Available since v4.7._
           */
          function toUint200(uint256 value) internal pure returns (uint200) {
              require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
              return uint200(value);
          }
      
          /**
           * @dev Returns the downcasted uint192 from uint256, reverting on
           * overflow (when the input is greater than largest uint192).
           *
           * Counterpart to Solidity's `uint192` operator.
           *
           * Requirements:
           *
           * - input must fit into 192 bits
           *
           * _Available since v4.7._
           */
          function toUint192(uint256 value) internal pure returns (uint192) {
              require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
              return uint192(value);
          }
      
          /**
           * @dev Returns the downcasted uint184 from uint256, reverting on
           * overflow (when the input is greater than largest uint184).
           *
           * Counterpart to Solidity's `uint184` operator.
           *
           * Requirements:
           *
           * - input must fit into 184 bits
           *
           * _Available since v4.7._
           */
          function toUint184(uint256 value) internal pure returns (uint184) {
              require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
              return uint184(value);
          }
      
          /**
           * @dev Returns the downcasted uint176 from uint256, reverting on
           * overflow (when the input is greater than largest uint176).
           *
           * Counterpart to Solidity's `uint176` operator.
           *
           * Requirements:
           *
           * - input must fit into 176 bits
           *
           * _Available since v4.7._
           */
          function toUint176(uint256 value) internal pure returns (uint176) {
              require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
              return uint176(value);
          }
      
          /**
           * @dev Returns the downcasted uint168 from uint256, reverting on
           * overflow (when the input is greater than largest uint168).
           *
           * Counterpart to Solidity's `uint168` operator.
           *
           * Requirements:
           *
           * - input must fit into 168 bits
           *
           * _Available since v4.7._
           */
          function toUint168(uint256 value) internal pure returns (uint168) {
              require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
              return uint168(value);
          }
      
          /**
           * @dev Returns the downcasted uint160 from uint256, reverting on
           * overflow (when the input is greater than largest uint160).
           *
           * Counterpart to Solidity's `uint160` operator.
           *
           * Requirements:
           *
           * - input must fit into 160 bits
           *
           * _Available since v4.7._
           */
          function toUint160(uint256 value) internal pure returns (uint160) {
              require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
              return uint160(value);
          }
      
          /**
           * @dev Returns the downcasted uint152 from uint256, reverting on
           * overflow (when the input is greater than largest uint152).
           *
           * Counterpart to Solidity's `uint152` operator.
           *
           * Requirements:
           *
           * - input must fit into 152 bits
           *
           * _Available since v4.7._
           */
          function toUint152(uint256 value) internal pure returns (uint152) {
              require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
              return uint152(value);
          }
      
          /**
           * @dev Returns the downcasted uint144 from uint256, reverting on
           * overflow (when the input is greater than largest uint144).
           *
           * Counterpart to Solidity's `uint144` operator.
           *
           * Requirements:
           *
           * - input must fit into 144 bits
           *
           * _Available since v4.7._
           */
          function toUint144(uint256 value) internal pure returns (uint144) {
              require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
              return uint144(value);
          }
      
          /**
           * @dev Returns the downcasted uint136 from uint256, reverting on
           * overflow (when the input is greater than largest uint136).
           *
           * Counterpart to Solidity's `uint136` operator.
           *
           * Requirements:
           *
           * - input must fit into 136 bits
           *
           * _Available since v4.7._
           */
          function toUint136(uint256 value) internal pure returns (uint136) {
              require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
              return uint136(value);
          }
      
          /**
           * @dev Returns the downcasted uint128 from uint256, reverting on
           * overflow (when the input is greater than largest uint128).
           *
           * Counterpart to Solidity's `uint128` operator.
           *
           * Requirements:
           *
           * - input must fit into 128 bits
           *
           * _Available since v2.5._
           */
          function toUint128(uint256 value) internal pure returns (uint128) {
              require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
              return uint128(value);
          }
      
          /**
           * @dev Returns the downcasted uint120 from uint256, reverting on
           * overflow (when the input is greater than largest uint120).
           *
           * Counterpart to Solidity's `uint120` operator.
           *
           * Requirements:
           *
           * - input must fit into 120 bits
           *
           * _Available since v4.7._
           */
          function toUint120(uint256 value) internal pure returns (uint120) {
              require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
              return uint120(value);
          }
      
          /**
           * @dev Returns the downcasted uint112 from uint256, reverting on
           * overflow (when the input is greater than largest uint112).
           *
           * Counterpart to Solidity's `uint112` operator.
           *
           * Requirements:
           *
           * - input must fit into 112 bits
           *
           * _Available since v4.7._
           */
          function toUint112(uint256 value) internal pure returns (uint112) {
              require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
              return uint112(value);
          }
      
          /**
           * @dev Returns the downcasted uint104 from uint256, reverting on
           * overflow (when the input is greater than largest uint104).
           *
           * Counterpart to Solidity's `uint104` operator.
           *
           * Requirements:
           *
           * - input must fit into 104 bits
           *
           * _Available since v4.7._
           */
          function toUint104(uint256 value) internal pure returns (uint104) {
              require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
              return uint104(value);
          }
      
          /**
           * @dev Returns the downcasted uint96 from uint256, reverting on
           * overflow (when the input is greater than largest uint96).
           *
           * Counterpart to Solidity's `uint96` operator.
           *
           * Requirements:
           *
           * - input must fit into 96 bits
           *
           * _Available since v4.2._
           */
          function toUint96(uint256 value) internal pure returns (uint96) {
              require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
              return uint96(value);
          }
      
          /**
           * @dev Returns the downcasted uint88 from uint256, reverting on
           * overflow (when the input is greater than largest uint88).
           *
           * Counterpart to Solidity's `uint88` operator.
           *
           * Requirements:
           *
           * - input must fit into 88 bits
           *
           * _Available since v4.7._
           */
          function toUint88(uint256 value) internal pure returns (uint88) {
              require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
              return uint88(value);
          }
      
          /**
           * @dev Returns the downcasted uint80 from uint256, reverting on
           * overflow (when the input is greater than largest uint80).
           *
           * Counterpart to Solidity's `uint80` operator.
           *
           * Requirements:
           *
           * - input must fit into 80 bits
           *
           * _Available since v4.7._
           */
          function toUint80(uint256 value) internal pure returns (uint80) {
              require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
              return uint80(value);
          }
      
          /**
           * @dev Returns the downcasted uint72 from uint256, reverting on
           * overflow (when the input is greater than largest uint72).
           *
           * Counterpart to Solidity's `uint72` operator.
           *
           * Requirements:
           *
           * - input must fit into 72 bits
           *
           * _Available since v4.7._
           */
          function toUint72(uint256 value) internal pure returns (uint72) {
              require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
              return uint72(value);
          }
      
          /**
           * @dev Returns the downcasted uint64 from uint256, reverting on
           * overflow (when the input is greater than largest uint64).
           *
           * Counterpart to Solidity's `uint64` operator.
           *
           * Requirements:
           *
           * - input must fit into 64 bits
           *
           * _Available since v2.5._
           */
          function toUint64(uint256 value) internal pure returns (uint64) {
              require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
              return uint64(value);
          }
      
          /**
           * @dev Returns the downcasted uint56 from uint256, reverting on
           * overflow (when the input is greater than largest uint56).
           *
           * Counterpart to Solidity's `uint56` operator.
           *
           * Requirements:
           *
           * - input must fit into 56 bits
           *
           * _Available since v4.7._
           */
          function toUint56(uint256 value) internal pure returns (uint56) {
              require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
              return uint56(value);
          }
      
          /**
           * @dev Returns the downcasted uint48 from uint256, reverting on
           * overflow (when the input is greater than largest uint48).
           *
           * Counterpart to Solidity's `uint48` operator.
           *
           * Requirements:
           *
           * - input must fit into 48 bits
           *
           * _Available since v4.7._
           */
          function toUint48(uint256 value) internal pure returns (uint48) {
              require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
              return uint48(value);
          }
      
          /**
           * @dev Returns the downcasted uint40 from uint256, reverting on
           * overflow (when the input is greater than largest uint40).
           *
           * Counterpart to Solidity's `uint40` operator.
           *
           * Requirements:
           *
           * - input must fit into 40 bits
           *
           * _Available since v4.7._
           */
          function toUint40(uint256 value) internal pure returns (uint40) {
              require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
              return uint40(value);
          }
      
          /**
           * @dev Returns the downcasted uint32 from uint256, reverting on
           * overflow (when the input is greater than largest uint32).
           *
           * Counterpart to Solidity's `uint32` operator.
           *
           * Requirements:
           *
           * - input must fit into 32 bits
           *
           * _Available since v2.5._
           */
          function toUint32(uint256 value) internal pure returns (uint32) {
              require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
              return uint32(value);
          }
      
          /**
           * @dev Returns the downcasted uint24 from uint256, reverting on
           * overflow (when the input is greater than largest uint24).
           *
           * Counterpart to Solidity's `uint24` operator.
           *
           * Requirements:
           *
           * - input must fit into 24 bits
           *
           * _Available since v4.7._
           */
          function toUint24(uint256 value) internal pure returns (uint24) {
              require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
              return uint24(value);
          }
      
          /**
           * @dev Returns the downcasted uint16 from uint256, reverting on
           * overflow (when the input is greater than largest uint16).
           *
           * Counterpart to Solidity's `uint16` operator.
           *
           * Requirements:
           *
           * - input must fit into 16 bits
           *
           * _Available since v2.5._
           */
          function toUint16(uint256 value) internal pure returns (uint16) {
              require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
              return uint16(value);
          }
      
          /**
           * @dev Returns the downcasted uint8 from uint256, reverting on
           * overflow (when the input is greater than largest uint8).
           *
           * Counterpart to Solidity's `uint8` operator.
           *
           * Requirements:
           *
           * - input must fit into 8 bits
           *
           * _Available since v2.5._
           */
          function toUint8(uint256 value) internal pure returns (uint8) {
              require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
              return uint8(value);
          }
      
          /**
           * @dev Converts a signed int256 into an unsigned uint256.
           *
           * Requirements:
           *
           * - input must be greater than or equal to 0.
           *
           * _Available since v3.0._
           */
          function toUint256(int256 value) internal pure returns (uint256) {
              require(value >= 0, "SafeCast: value must be positive");
              return uint256(value);
          }
      
          /**
           * @dev Returns the downcasted int248 from int256, reverting on
           * overflow (when the input is less than smallest int248 or
           * greater than largest int248).
           *
           * Counterpart to Solidity's `int248` operator.
           *
           * Requirements:
           *
           * - input must fit into 248 bits
           *
           * _Available since v4.7._
           */
          function toInt248(int256 value) internal pure returns (int248) {
              require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
              return int248(value);
          }
      
          /**
           * @dev Returns the downcasted int240 from int256, reverting on
           * overflow (when the input is less than smallest int240 or
           * greater than largest int240).
           *
           * Counterpart to Solidity's `int240` operator.
           *
           * Requirements:
           *
           * - input must fit into 240 bits
           *
           * _Available since v4.7._
           */
          function toInt240(int256 value) internal pure returns (int240) {
              require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
              return int240(value);
          }
      
          /**
           * @dev Returns the downcasted int232 from int256, reverting on
           * overflow (when the input is less than smallest int232 or
           * greater than largest int232).
           *
           * Counterpart to Solidity's `int232` operator.
           *
           * Requirements:
           *
           * - input must fit into 232 bits
           *
           * _Available since v4.7._
           */
          function toInt232(int256 value) internal pure returns (int232) {
              require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
              return int232(value);
          }
      
          /**
           * @dev Returns the downcasted int224 from int256, reverting on
           * overflow (when the input is less than smallest int224 or
           * greater than largest int224).
           *
           * Counterpart to Solidity's `int224` operator.
           *
           * Requirements:
           *
           * - input must fit into 224 bits
           *
           * _Available since v4.7._
           */
          function toInt224(int256 value) internal pure returns (int224) {
              require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
              return int224(value);
          }
      
          /**
           * @dev Returns the downcasted int216 from int256, reverting on
           * overflow (when the input is less than smallest int216 or
           * greater than largest int216).
           *
           * Counterpart to Solidity's `int216` operator.
           *
           * Requirements:
           *
           * - input must fit into 216 bits
           *
           * _Available since v4.7._
           */
          function toInt216(int256 value) internal pure returns (int216) {
              require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
              return int216(value);
          }
      
          /**
           * @dev Returns the downcasted int208 from int256, reverting on
           * overflow (when the input is less than smallest int208 or
           * greater than largest int208).
           *
           * Counterpart to Solidity's `int208` operator.
           *
           * Requirements:
           *
           * - input must fit into 208 bits
           *
           * _Available since v4.7._
           */
          function toInt208(int256 value) internal pure returns (int208) {
              require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
              return int208(value);
          }
      
          /**
           * @dev Returns the downcasted int200 from int256, reverting on
           * overflow (when the input is less than smallest int200 or
           * greater than largest int200).
           *
           * Counterpart to Solidity's `int200` operator.
           *
           * Requirements:
           *
           * - input must fit into 200 bits
           *
           * _Available since v4.7._
           */
          function toInt200(int256 value) internal pure returns (int200) {
              require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
              return int200(value);
          }
      
          /**
           * @dev Returns the downcasted int192 from int256, reverting on
           * overflow (when the input is less than smallest int192 or
           * greater than largest int192).
           *
           * Counterpart to Solidity's `int192` operator.
           *
           * Requirements:
           *
           * - input must fit into 192 bits
           *
           * _Available since v4.7._
           */
          function toInt192(int256 value) internal pure returns (int192) {
              require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
              return int192(value);
          }
      
          /**
           * @dev Returns the downcasted int184 from int256, reverting on
           * overflow (when the input is less than smallest int184 or
           * greater than largest int184).
           *
           * Counterpart to Solidity's `int184` operator.
           *
           * Requirements:
           *
           * - input must fit into 184 bits
           *
           * _Available since v4.7._
           */
          function toInt184(int256 value) internal pure returns (int184) {
              require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
              return int184(value);
          }
      
          /**
           * @dev Returns the downcasted int176 from int256, reverting on
           * overflow (when the input is less than smallest int176 or
           * greater than largest int176).
           *
           * Counterpart to Solidity's `int176` operator.
           *
           * Requirements:
           *
           * - input must fit into 176 bits
           *
           * _Available since v4.7._
           */
          function toInt176(int256 value) internal pure returns (int176) {
              require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
              return int176(value);
          }
      
          /**
           * @dev Returns the downcasted int168 from int256, reverting on
           * overflow (when the input is less than smallest int168 or
           * greater than largest int168).
           *
           * Counterpart to Solidity's `int168` operator.
           *
           * Requirements:
           *
           * - input must fit into 168 bits
           *
           * _Available since v4.7._
           */
          function toInt168(int256 value) internal pure returns (int168) {
              require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
              return int168(value);
          }
      
          /**
           * @dev Returns the downcasted int160 from int256, reverting on
           * overflow (when the input is less than smallest int160 or
           * greater than largest int160).
           *
           * Counterpart to Solidity's `int160` operator.
           *
           * Requirements:
           *
           * - input must fit into 160 bits
           *
           * _Available since v4.7._
           */
          function toInt160(int256 value) internal pure returns (int160) {
              require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
              return int160(value);
          }
      
          /**
           * @dev Returns the downcasted int152 from int256, reverting on
           * overflow (when the input is less than smallest int152 or
           * greater than largest int152).
           *
           * Counterpart to Solidity's `int152` operator.
           *
           * Requirements:
           *
           * - input must fit into 152 bits
           *
           * _Available since v4.7._
           */
          function toInt152(int256 value) internal pure returns (int152) {
              require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
              return int152(value);
          }
      
          /**
           * @dev Returns the downcasted int144 from int256, reverting on
           * overflow (when the input is less than smallest int144 or
           * greater than largest int144).
           *
           * Counterpart to Solidity's `int144` operator.
           *
           * Requirements:
           *
           * - input must fit into 144 bits
           *
           * _Available since v4.7._
           */
          function toInt144(int256 value) internal pure returns (int144) {
              require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
              return int144(value);
          }
      
          /**
           * @dev Returns the downcasted int136 from int256, reverting on
           * overflow (when the input is less than smallest int136 or
           * greater than largest int136).
           *
           * Counterpart to Solidity's `int136` operator.
           *
           * Requirements:
           *
           * - input must fit into 136 bits
           *
           * _Available since v4.7._
           */
          function toInt136(int256 value) internal pure returns (int136) {
              require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
              return int136(value);
          }
      
          /**
           * @dev Returns the downcasted int128 from int256, reverting on
           * overflow (when the input is less than smallest int128 or
           * greater than largest int128).
           *
           * Counterpart to Solidity's `int128` operator.
           *
           * Requirements:
           *
           * - input must fit into 128 bits
           *
           * _Available since v3.1._
           */
          function toInt128(int256 value) internal pure returns (int128) {
              require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
              return int128(value);
          }
      
          /**
           * @dev Returns the downcasted int120 from int256, reverting on
           * overflow (when the input is less than smallest int120 or
           * greater than largest int120).
           *
           * Counterpart to Solidity's `int120` operator.
           *
           * Requirements:
           *
           * - input must fit into 120 bits
           *
           * _Available since v4.7._
           */
          function toInt120(int256 value) internal pure returns (int120) {
              require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
              return int120(value);
          }
      
          /**
           * @dev Returns the downcasted int112 from int256, reverting on
           * overflow (when the input is less than smallest int112 or
           * greater than largest int112).
           *
           * Counterpart to Solidity's `int112` operator.
           *
           * Requirements:
           *
           * - input must fit into 112 bits
           *
           * _Available since v4.7._
           */
          function toInt112(int256 value) internal pure returns (int112) {
              require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
              return int112(value);
          }
      
          /**
           * @dev Returns the downcasted int104 from int256, reverting on
           * overflow (when the input is less than smallest int104 or
           * greater than largest int104).
           *
           * Counterpart to Solidity's `int104` operator.
           *
           * Requirements:
           *
           * - input must fit into 104 bits
           *
           * _Available since v4.7._
           */
          function toInt104(int256 value) internal pure returns (int104) {
              require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
              return int104(value);
          }
      
          /**
           * @dev Returns the downcasted int96 from int256, reverting on
           * overflow (when the input is less than smallest int96 or
           * greater than largest int96).
           *
           * Counterpart to Solidity's `int96` operator.
           *
           * Requirements:
           *
           * - input must fit into 96 bits
           *
           * _Available since v4.7._
           */
          function toInt96(int256 value) internal pure returns (int96) {
              require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
              return int96(value);
          }
      
          /**
           * @dev Returns the downcasted int88 from int256, reverting on
           * overflow (when the input is less than smallest int88 or
           * greater than largest int88).
           *
           * Counterpart to Solidity's `int88` operator.
           *
           * Requirements:
           *
           * - input must fit into 88 bits
           *
           * _Available since v4.7._
           */
          function toInt88(int256 value) internal pure returns (int88) {
              require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
              return int88(value);
          }
      
          /**
           * @dev Returns the downcasted int80 from int256, reverting on
           * overflow (when the input is less than smallest int80 or
           * greater than largest int80).
           *
           * Counterpart to Solidity's `int80` operator.
           *
           * Requirements:
           *
           * - input must fit into 80 bits
           *
           * _Available since v4.7._
           */
          function toInt80(int256 value) internal pure returns (int80) {
              require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
              return int80(value);
          }
      
          /**
           * @dev Returns the downcasted int72 from int256, reverting on
           * overflow (when the input is less than smallest int72 or
           * greater than largest int72).
           *
           * Counterpart to Solidity's `int72` operator.
           *
           * Requirements:
           *
           * - input must fit into 72 bits
           *
           * _Available since v4.7._
           */
          function toInt72(int256 value) internal pure returns (int72) {
              require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
              return int72(value);
          }
      
          /**
           * @dev Returns the downcasted int64 from int256, reverting on
           * overflow (when the input is less than smallest int64 or
           * greater than largest int64).
           *
           * Counterpart to Solidity's `int64` operator.
           *
           * Requirements:
           *
           * - input must fit into 64 bits
           *
           * _Available since v3.1._
           */
          function toInt64(int256 value) internal pure returns (int64) {
              require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
              return int64(value);
          }
      
          /**
           * @dev Returns the downcasted int56 from int256, reverting on
           * overflow (when the input is less than smallest int56 or
           * greater than largest int56).
           *
           * Counterpart to Solidity's `int56` operator.
           *
           * Requirements:
           *
           * - input must fit into 56 bits
           *
           * _Available since v4.7._
           */
          function toInt56(int256 value) internal pure returns (int56) {
              require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
              return int56(value);
          }
      
          /**
           * @dev Returns the downcasted int48 from int256, reverting on
           * overflow (when the input is less than smallest int48 or
           * greater than largest int48).
           *
           * Counterpart to Solidity's `int48` operator.
           *
           * Requirements:
           *
           * - input must fit into 48 bits
           *
           * _Available since v4.7._
           */
          function toInt48(int256 value) internal pure returns (int48) {
              require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
              return int48(value);
          }
      
          /**
           * @dev Returns the downcasted int40 from int256, reverting on
           * overflow (when the input is less than smallest int40 or
           * greater than largest int40).
           *
           * Counterpart to Solidity's `int40` operator.
           *
           * Requirements:
           *
           * - input must fit into 40 bits
           *
           * _Available since v4.7._
           */
          function toInt40(int256 value) internal pure returns (int40) {
              require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
              return int40(value);
          }
      
          /**
           * @dev Returns the downcasted int32 from int256, reverting on
           * overflow (when the input is less than smallest int32 or
           * greater than largest int32).
           *
           * Counterpart to Solidity's `int32` operator.
           *
           * Requirements:
           *
           * - input must fit into 32 bits
           *
           * _Available since v3.1._
           */
          function toInt32(int256 value) internal pure returns (int32) {
              require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
              return int32(value);
          }
      
          /**
           * @dev Returns the downcasted int24 from int256, reverting on
           * overflow (when the input is less than smallest int24 or
           * greater than largest int24).
           *
           * Counterpart to Solidity's `int24` operator.
           *
           * Requirements:
           *
           * - input must fit into 24 bits
           *
           * _Available since v4.7._
           */
          function toInt24(int256 value) internal pure returns (int24) {
              require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
              return int24(value);
          }
      
          /**
           * @dev Returns the downcasted int16 from int256, reverting on
           * overflow (when the input is less than smallest int16 or
           * greater than largest int16).
           *
           * Counterpart to Solidity's `int16` operator.
           *
           * Requirements:
           *
           * - input must fit into 16 bits
           *
           * _Available since v3.1._
           */
          function toInt16(int256 value) internal pure returns (int16) {
              require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
              return int16(value);
          }
      
          /**
           * @dev Returns the downcasted int8 from int256, reverting on
           * overflow (when the input is less than smallest int8 or
           * greater than largest int8).
           *
           * Counterpart to Solidity's `int8` operator.
           *
           * Requirements:
           *
           * - input must fit into 8 bits
           *
           * _Available since v3.1._
           */
          function toInt8(int256 value) internal pure returns (int8) {
              require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
              return int8(value);
          }
      
          /**
           * @dev Converts an unsigned uint256 into a signed int256.
           *
           * Requirements:
           *
           * - input must be less than or equal to maxInt256.
           *
           * _Available since v3.0._
           */
          function toInt256(uint256 value) internal pure returns (int256) {
              // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
              require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
              return int256(value);
          }
      }
      
      // File: @chainlink/contracts/src/v0.8/interfaces/AggregatorInterface.sol
      
      
      pragma solidity ^0.8.0;
      
      interface AggregatorInterface {
        function latestAnswer() external view returns (int256);
      
        function latestTimestamp() external view returns (uint256);
      
        function latestRound() external view returns (uint256);
      
        function getAnswer(uint256 roundId) external view returns (int256);
      
        function getTimestamp(uint256 roundId) external view returns (uint256);
      
        event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
      
        event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
      }
      
      // File: Ethereum.sol
      
      
      
      
      
      
      
      
      
      
      pragma solidity >=0.5.0;
      
      interface ILayerZeroUserApplicationConfig {
          // @notice set the configuration of the LayerZero messaging library of the specified version
          // @param _version - messaging library version
          // @param _chainId - the chainId for the pending config change
          // @param _configType - type of configuration. every messaging library has its own convention.
          // @param _config - configuration in the bytes. can encode arbitrary content.
          function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;
      
          // @notice set the send() LayerZero messaging library version to _version
          // @param _version - new messaging library version
          function setSendVersion(uint16 _version) external;
      
          // @notice set the lzReceive() LayerZero messaging library version to _version
          // @param _version - new messaging library version
          function setReceiveVersion(uint16 _version) external;
      
          // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
          // @param _srcChainId - the chainId of the source chain
          // @param _srcAddress - the contract address of the source contract at the source chain
          function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
      }
      
      // File: contracts/interfaces/ILayerZeroEndpoint.sol
      
      
      
      pragma solidity >=0.5.0;
      
      
      interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
          // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
          // @param _dstChainId - the destination chain identifier
          // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
          // @param _payload - a custom bytes payload to send to the destination contract
          // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
          // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
          // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
          function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;
      
          // @notice used by the messaging library to publish verified payload
          // @param _srcChainId - the source chain identifier
          // @param _srcAddress - the source contract (as bytes) at the source chain
          // @param _dstAddress - the address on destination chain
          // @param _nonce - the unbound message ordering nonce
          // @param _gasLimit - the gas limit for external contract execution
          // @param _payload - verified payload to send to the destination contract
          function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;
      
          // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain
          // @param _srcChainId - the source chain identifier
          // @param _srcAddress - the source chain contract address
          function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
      
          // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
          // @param _srcAddress - the source chain contract address
          function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
      
          // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
          // @param _dstChainId - the destination chain identifier
          // @param _userApplication - the user app address on this EVM chain
          // @param _payload - the custom message to send over LayerZero
          // @param _payInZRO - if false, user app pays the protocol fee in native token
          // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
          function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);
      
          // @notice get this Endpoint's immutable source identifier
          function getChainId() external view returns (uint16);
      
          // @notice the interface to retry failed message on this Endpoint destination
          // @param _srcChainId - the source chain identifier
          // @param _srcAddress - the source chain contract address
          // @param _payload - the payload to be retried
          function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
      
          // @notice query if any STORED payload (message blocking) at the endpoint.
          // @param _srcChainId - the source chain identifier
          // @param _srcAddress - the source chain contract address
          function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
      
          // @notice query if the _libraryAddress is valid for sending msgs.
          // @param _userApplication - the user app address on this EVM chain
          function getSendLibraryAddress(address _userApplication) external view returns (address);
      
          // @notice query if the _libraryAddress is valid for receiving msgs.
          // @param _userApplication - the user app address on this EVM chain
          function getReceiveLibraryAddress(address _userApplication) external view returns (address);
      
          // @notice query if the non-reentrancy guard for send() is on
          // @return true if the guard is on. false otherwise
          function isSendingPayload() external view returns (bool);
      
          // @notice query if the non-reentrancy guard for receive() is on
          // @return true if the guard is on. false otherwise
          function isReceivingPayload() external view returns (bool);
      
          // @notice get the configuration of the LayerZero messaging library of the specified version
          // @param _version - messaging library version
          // @param _chainId - the chainId for the pending config change
          // @param _userApplication - the contract address of the user application
          // @param _configType - type of configuration. every messaging library has its own convention.
          function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);
      
          // @notice get the send() LayerZero messaging library version
          // @param _userApplication - the contract address of the user application
          function getSendVersion(address _userApplication) external view returns (uint16);
      
          // @notice get the lzReceive() LayerZero messaging library version
          // @param _userApplication - the contract address of the user application
          function getReceiveVersion(address _userApplication) external view returns (uint16);
      }
      
      // File: contracts/interfaces/ILayerZeroReceiver.sol
      
      
      
      pragma solidity >=0.5.0;
      
      interface ILayerZeroReceiver {
          // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
          // @param _srcChainId - the source endpoint identifier
          // @param _srcAddress - the source sending contract address from the source chain
          // @param _nonce - the ordered message nonce
          // @param _payload - the signed payload is the UA bytes has encoded to be sent
          function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
      }
      
      // File: @openzeppelin/contracts/access/Ownable.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
      
      pragma solidity ^0.8.0;
      
      
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
      
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
      
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
      
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
      
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
      
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
      
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
      
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      
      // File: contracts/NonblockingReceiver.sol
      
      
      pragma solidity ^0.8.6;
      abstract contract NonblockingReceiver is Ownable, ILayerZeroReceiver {
      
          ILayerZeroEndpoint internal endpoint;
      
          struct FailedMessages {
              uint payloadLength;
              bytes32 payloadHash;
          }
      
          mapping(uint16 => mapping(bytes => mapping(uint => FailedMessages))) public failedMessages;
          mapping(uint16 => bytes) public trustedRemoteLookup;
      
          event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload);
      
          function lzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) external override {
              require(msg.sender == address(endpoint)); // boilerplate! lzReceive must be called by the endpoint for security
              require(_srcAddress.length == trustedRemoteLookup[_srcChainId].length && keccak256(_srcAddress) == keccak256(trustedRemoteLookup[_srcChainId]), 
                  "NonblockingReceiver: invalid source sending contract");
      
              // try-catch all errors/exceptions
              // having failed messages does not block messages passing
              try this.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload) {
                  // do nothing
              } catch {
                  // error / exception
                  failedMessages[_srcChainId][_srcAddress][_nonce] = FailedMessages(_payload.length, keccak256(_payload));
                  emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload);
              }
          }
      
          function onLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) public {
              // only internal transaction
              require(msg.sender == address(this), "NonblockingReceiver: caller must be Bridge.");
      
              // handle incoming message
              _LzReceive( _srcChainId, _srcAddress, _nonce, _payload);
          }
      
          // abstract function
          function _LzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) virtual internal;
      
          function _lzSend(uint16 _dstChainId, bytes memory _payload, address payable _refundAddress, address _zroPaymentAddress, bytes memory _txParam) internal {
              endpoint.send{value: msg.value}(_dstChainId, trustedRemoteLookup[_dstChainId], _payload, _refundAddress, _zroPaymentAddress, _txParam);
          }
      
          function retryMessage(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes calldata _payload) external payable {
              // assert there is message to retry
              FailedMessages storage failedMsg = failedMessages[_srcChainId][_srcAddress][_nonce];
              require(failedMsg.payloadHash != bytes32(0), "NonblockingReceiver: no stored message");
              require(_payload.length == failedMsg.payloadLength && keccak256(_payload) == failedMsg.payloadHash, "LayerZero: invalid payload");
              // clear the stored message
              failedMsg.payloadLength = 0;
              failedMsg.payloadHash = bytes32(0);
              // execute the message. revert if it fails again
              this.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
          }
      
          function setTrustedRemote(uint16 _chainId, bytes calldata _trustedRemote) external onlyOwner {
              trustedRemoteLookup[_chainId] = _trustedRemote;
          }
      }
      
      // File: contracts/GhostlyGhosts.sol
      
      
      
      pragma solidity ^0.8.7;
      
      
      /*
       *      _      ______     _____                        _           
       *     | |    |___  /    |  __ \                      (_)          
       *     | |       / /     | |  | | ___  _ __ ___   __ _ _ _ __  ___ 
       *     | |      / /      | |  | |/ _ \| '_ ` _ \ / _` | | '_ \/ __|
       *     | |____ / /__     | |__| | (_) | | | | | | (_| | | | | \__ \
       *     |______/_____|    |_____/ \___/|_| |_| |_|\__,_|_|_| |_|___/
       *                                                                 
       *                                                                 
       */
      
      contract lzCore is Ownable, ERC721Enumerable, NonblockingReceiver {
          using SafeCast for int256;
          using SafeMath for uint256;
      
          AggregatorInterface internal ethUSDAPI;
      
          /*
              Ethereum ,
              Binance Chain ,
              Avalanche ,        
              Arbitrum ,
              Optimism ,        
              Fantom ,
              Polygon ,
              Harmony ,
           */
          string public chainName = "Ethereum";
          bool public paused = true;
          string public baseURI;
          int256 private fiveLetter= 5000000000000000000 * 10 **18;
          int256 private fourLetter= 30000000000000000000 * 10 **18;
          int256 private threeLetter= 100000000000000000000 * 10 **18;
          uint256 private tolerance = 98;
          uint gasForDestinationLzReceive = 350000;
          uint256 count = 0;
          struct domainLogs{
              uint256 time;
              uint256 nftID;
          }
          mapping(string => domainLogs) public domainsData;
      
          struct domainInfos{
              string name;
          }
          mapping(uint256 => domainInfos) public domainInfo;
          constructor(string memory baseURI_, address _layerZeroEndpoint) ERC721("Layer Zero Name Service", "LZNM") { 
              endpoint = ILayerZeroEndpoint(_layerZeroEndpoint);
              baseURI = baseURI_;
              ethUSDAPI = AggregatorInterface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
          }
          receive() external payable {
              /* 
                  thanks <3
              */
          }
          function ethUSD() public view returns (int256) {
              return ethUSDAPI.latestAnswer()*10**10;
          }
          function burnExpiredDomain(string memory domainName) public onlyOwner{
              require(domainsData[domainName].time < block.timestamp, "Domain is not expired. Error #66");
              if(_exists(domainsData[domainName].nftID)){
                  _burn(domainsData[domainName].nftID);
              }        
              delete domainInfo[domainsData[domainName].nftID].name;
              domainsData[domainName].time = 0;
              domainsData[domainName].nftID = 0;
          }
          function otherChainRenew(string memory domainName , uint256 newTime) public onlyOwner{
              domainsData[domainName].time = newTime;
          }
          function register(string memory domainName , uint256 year) public payable{
              require(!paused , "Register now not avaliable. Try again later. Error #1");
              require(year >= 1 , "Invalid year value. Error #30");
              require(bytes(domainName).length >= 3, "Name is too short. Names must be at least 3 characters long. Error #2");
              require(checkDomainAvaliable(domainName) == true , "Domain unavaliable (Has been registered). Error #41");
              uint256 price = domainPrice(domainName) * year;
              require(msg.value >= (price / 100) * tolerance , "Check register price. Error #3");
      
              domainsData[domainName].time = block.timestamp + year * 31557600;
              domainsData[domainName].nftID = count + 1;
      
              //set domain names
              domainInfo[count + 1].name = domainName;
              _safeMint(msg.sender, count + 1);
              count += 1;
      
          }
          function renew(string memory domainName , uint256 year) public payable{
              require(bytes(domainName).length >= 3, "Name is too short. Names must be at least 3 characters long. Error #45");
              require(msg.sender == ownerOf(domainsData[domainName].nftID) , "Access denied. Error #35");
              uint256 price = domainPrice(domainName) * year;
              require(msg.value >= (price / 100) * tolerance , "Check register price. Error #32");
              domainsData[domainName].time += year * 31557600;
      
          }    
          function domainPrice(string memory domainName) public view returns(uint256){
              uint256 lenCount = bytes(domainName).length;
              if (lenCount <= 3){
                  return (threeLetter / ethUSD()).toUint256();
              }
              else if(lenCount == 4){
                  return (fourLetter / ethUSD()).toUint256();
              }
              else if(lenCount >= 5){
                  return (fiveLetter / ethUSD()).toUint256();
              }
          }
          function checkDomainAvaliable(string memory domainName) public view returns(bool){
              if( domainsData[domainName].time == 0 ){
                  return true;
              }
              else{
                  return false;
              }
          }
          function estimateFeesView(uint16 _chainId, uint tokenId) public view returns (uint) {
              bytes memory payload = abi.encode(msg.sender , tokenId , domainsData[domainInfo[tokenId].name].time , domainInfo[tokenId].name);
      
              uint16 version = 1;
              bytes memory adapterParams = abi.encodePacked(version, gasForDestinationLzReceive);
      
              (uint messageFee, ) = endpoint.estimateFees(_chainId, address(this), payload, false, adapterParams);
              return messageFee;
          }
          function traverseChains(uint16 _chainId, uint tokenId) public payable {
              require(msg.sender == ownerOf(tokenId), "You must own the token to traverse");
              require(trustedRemoteLookup[_chainId].length > 0, "This chain is currently unavailable for travel");
      
              bytes memory payload = abi.encode(msg.sender , tokenId ,  domainsData[domainInfo[tokenId].name].time , domainInfo[tokenId].name);
      
              uint16 version = 1;
              bytes memory adapterParams = abi.encodePacked(version, gasForDestinationLzReceive);
      
              (uint messageFee, ) = endpoint.estimateFees(_chainId, address(this), payload, false, adapterParams);
              
              require(msg.value >= messageFee, "LZ: msg.value not enough to cover messageFee. Send gas for message fees");
      
              endpoint.send{value: msg.value}(
                  _chainId,                           
                  trustedRemoteLookup[_chainId],      
                  payload,                           
                  payable(msg.sender),               
                  address(0x0),                       
                  adapterParams                      
              );
              _burn(tokenId);
          }
          function _LzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) override internal {
              // decode
              (address toAddr, uint tokenId, uint256 time, string memory domainName) = abi.decode(_payload, (address, uint, uint256, string));
              domainsData[domainName].time = time;
              domainsData[domainName].nftID = tokenId;
              domainInfo[tokenId].name = domainName;
              _safeMint(toAddr, tokenId);
      
          }  
          function changePaused() external onlyOwner{
              if (paused == true) {
                  paused = false;
              }
              else{
                  paused = true;
              }
          }
          function changePrice(int256 a , int256 b , int256 c) public onlyOwner{
              if (a != 0){
                  threeLetter = a;
              }
              if ( b != 0){
                  fourLetter = b;
              }
              if (c != 0){
                  fiveLetter = c;
              }
          }
          function setBaseURI(string memory URI) external onlyOwner {
              baseURI = URI;
          }
      
          function withdraw() public payable onlyOwner {
              (bool sent, ) = payable(owner()).call{value: address(this).balance}("");
              require(sent);
          }
      
          function setGasForDestinationLzReceive(uint newVal) external onlyOwner {
              gasForDestinationLzReceive = newVal;
          }
      
          function changeTolerance(uint256 newTolerance) public onlyOwner{
              tolerance = newTolerance;
          }
      
          function getCount() public view returns(uint256){
              return count;
          }
      
          function _baseURI() override internal view returns (string memory) {
              return baseURI;
          }
          
          function walletOfOwner(address _owner) public view returns(uint256[] memory) {
              uint256 ownerTokenCount = balanceOf(_owner);
              uint256[] memory tokenIds = new uint256[](ownerTokenCount);
              for (uint256 i; i < ownerTokenCount; i++) {
                  tokenIds [i]
                  = tokenOfOwnerByIndex(_owner, i);
              }
              return tokenIds;
          }
      }

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

      File 3 of 3: AccessControlledOffchainAggregator
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.7.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;
        }
      }