ETH Price: $2,442.53 (-4.23%)

Transaction Decoder

Block:
15723630 at Oct-11-2022 08:19:35 AM +UTC
Transaction Fee:
0.00521759264540253 ETH $12.74
Gas Used:
178,078 Gas / 29.299479135 Gwei

Emitted Events:

140 GnosisSafeProxy.0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d( 0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d, 0x000000000000000000000000f2e391f11cd1609679d03a1ac965b1d0432a7007, 00000000000000000000000000000000000000000000000004f63849fee3763d )
141 TransparentUpgradeableProxy.0x4d8aead3491b7eba4b5c7a65fc17e493b9e63f9e433522fc5f6a85a168fc9d36( 0x4d8aead3491b7eba4b5c7a65fc17e493b9e63f9e433522fc5f6a85a168fc9d36, 0x00000000000000000000000000d53e9e7763acbf3e2f08cde135e3415eadc055, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000639c, 00000000000000000000000000000000000000000000000004f63849fee3763d, 0000000000000000000000000000000000000000000000000000000063452717 )

Account State Difference:

  Address   Before After State Difference Code
0x00D53E9E...15eAdC055
0.372638141123801748 Eth
Nonce: 3
0.009885437595778229 Eth
Nonce: 4
0.362752703528023519
0x8250AC55...a862804A3 258.55660467905624889 Eth258.914139789938869879 Eth0.357535110882620989
0xf2e391F1...0432a7007
3.950194992342424714 Eth3.950640187342424714 Eth0.000445195

Execution Trace

ETH 0.357535110882620989 TransparentUpgradeableProxy.eeb38ab4( )
  • ETH 0.357535110882620989 Sale.buyWithEth( _id=1, amount=25500 ) => ( True )
    • EACAggregatorProxy.STATICCALL( )
      • AccessControlledOffchainAggregator.STATICCALL( )
      • ETH 0.357535110882620989 GnosisSafeProxy.CALL( )
        • ETH 0.357535110882620989 GnosisSafe.DELEGATECALL( )
          File 1 of 6: TransparentUpgradeableProxy
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
          import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
          import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
          // Kept for backwards compatibility with older versions of Hardhat and Truffle plugins.
          contract AdminUpgradeabilityProxy is TransparentUpgradeableProxy {
              constructor(address logic, address admin, bytes memory data) payable TransparentUpgradeableProxy(logic, admin, data) {}
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "../Proxy.sol";
          import "./ERC1967Upgrade.sol";
          /**
           * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
           * implementation address that can be changed. This address is stored in storage in the location specified by
           * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
           * implementation behind the proxy.
           */
          contract ERC1967Proxy is Proxy, ERC1967Upgrade {
              /**
               * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
               *
               * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
               * function call, and allows initializating the storage of the proxy like a Solidity constructor.
               */
              constructor(address _logic, bytes memory _data) payable {
                  assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                  _upgradeToAndCall(_logic, _data, false);
              }
              /**
               * @dev Returns the current implementation address.
               */
              function _implementation() internal view virtual override returns (address impl) {
                  return ERC1967Upgrade._getImplementation();
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "../ERC1967/ERC1967Proxy.sol";
          /**
           * @dev This contract implements a proxy that is upgradeable by an admin.
           *
           * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
           * clashing], which can potentially be used in an attack, this contract uses the
           * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
           * things that go hand in hand:
           *
           * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
           * that call matches one of the admin functions exposed by the proxy itself.
           * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
           * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
           * "admin cannot fallback to proxy target".
           *
           * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
           * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
           * to sudden errors when trying to call a function from the proxy implementation.
           *
           * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
           * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
           */
          contract TransparentUpgradeableProxy is ERC1967Proxy {
              /**
               * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
               * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
               */
              constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
                  assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
                  _changeAdmin(admin_);
              }
              /**
               * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
               */
              modifier ifAdmin() {
                  if (msg.sender == _getAdmin()) {
                      _;
                  } else {
                      _fallback();
                  }
              }
              /**
               * @dev Returns the current admin.
               *
               * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
               *
               * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
               * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
               * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
               */
              function admin() external ifAdmin returns (address admin_) {
                  admin_ = _getAdmin();
              }
              /**
               * @dev Returns the current implementation.
               *
               * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
               *
               * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
               * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
               * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
               */
              function implementation() external ifAdmin returns (address implementation_) {
                  implementation_ = _implementation();
              }
              /**
               * @dev Changes the admin of the proxy.
               *
               * Emits an {AdminChanged} event.
               *
               * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
               */
              function changeAdmin(address newAdmin) external virtual ifAdmin {
                  _changeAdmin(newAdmin);
              }
              /**
               * @dev Upgrade the implementation of the proxy.
               *
               * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
               */
              function upgradeTo(address newImplementation) external ifAdmin {
                  _upgradeToAndCall(newImplementation, bytes(""), false);
              }
              /**
               * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
               * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
               * proxied contract.
               *
               * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
               */
              function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
                  _upgradeToAndCall(newImplementation, data, true);
              }
              /**
               * @dev Returns the current admin.
               */
              function _admin() internal view virtual returns (address) {
                  return _getAdmin();
              }
              /**
               * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
               */
              function _beforeFallback() internal virtual override {
                  require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                  super._beforeFallback();
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "./TransparentUpgradeableProxy.sol";
          import "../../access/Ownable.sol";
          /**
           * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
           * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
           */
          contract ProxyAdmin is Ownable {
              /**
               * @dev Returns the current implementation of `proxy`.
               *
               * Requirements:
               *
               * - This contract must be the admin of `proxy`.
               */
              function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
                  // We need to manually run the static call since the getter cannot be flagged as view
                  // bytes4(keccak256("implementation()")) == 0x5c60da1b
                  (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
                  require(success);
                  return abi.decode(returndata, (address));
              }
              /**
               * @dev Returns the current admin of `proxy`.
               *
               * Requirements:
               *
               * - This contract must be the admin of `proxy`.
               */
              function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
                  // We need to manually run the static call since the getter cannot be flagged as view
                  // bytes4(keccak256("admin()")) == 0xf851a440
                  (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
                  require(success);
                  return abi.decode(returndata, (address));
              }
              /**
               * @dev Changes the admin of `proxy` to `newAdmin`.
               *
               * Requirements:
               *
               * - This contract must be the current admin of `proxy`.
               */
              function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
                  proxy.changeAdmin(newAdmin);
              }
              /**
               * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
               *
               * Requirements:
               *
               * - This contract must be the admin of `proxy`.
               */
              function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
                  proxy.upgradeTo(implementation);
              }
              /**
               * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
               * {TransparentUpgradeableProxy-upgradeToAndCall}.
               *
               * Requirements:
               *
               * - This contract must be the admin of `proxy`.
               */
              function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual onlyOwner {
                  proxy.upgradeToAndCall{value: msg.value}(implementation, data);
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          /**
           * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
           * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
           * be specified by overriding the virtual {_implementation} function.
           *
           * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
           * different contract through the {_delegate} function.
           *
           * The success and return data of the delegated call will be returned back to the caller of the proxy.
           */
          abstract contract Proxy {
              /**
               * @dev Delegates the current call to `implementation`.
               *
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _delegate(address implementation) internal virtual {
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      // Copy msg.data. We take full control of memory in this inline assembly
                      // block because it will not return to Solidity code. We overwrite the
                      // Solidity scratch pad at memory position 0.
                      calldatacopy(0, 0, calldatasize())
                      // Call the implementation.
                      // out and outsize are 0 because we don't know the size yet.
                      let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                      // Copy the returned data.
                      returndatacopy(0, 0, returndatasize())
                      switch result
                      // delegatecall returns 0 on error.
                      case 0 { revert(0, returndatasize()) }
                      default { return(0, returndatasize()) }
                  }
              }
              /**
               * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
               * and {_fallback} should delegate.
               */
              function _implementation() internal view virtual returns (address);
              /**
               * @dev Delegates the current call to the address returned by `_implementation()`.
               *
               * This function does not return to its internall call site, it will return directly to the external caller.
               */
              function _fallback() internal virtual {
                  _beforeFallback();
                  _delegate(_implementation());
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
               * function in the contract matches the call data.
               */
              fallback () external payable virtual {
                  _fallback();
              }
              /**
               * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
               * is empty.
               */
              receive () external payable virtual {
                  _fallback();
              }
              /**
               * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
               * call, or as part of the Solidity `fallback` or `receive` functions.
               *
               * If overriden should call `super._beforeFallback()`.
               */
              function _beforeFallback() internal virtual {
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.2;
          import "../beacon/IBeacon.sol";
          import "../../utils/Address.sol";
          import "../../utils/StorageSlot.sol";
          /**
           * @dev This abstract contract provides getters and event emitting update functions for
           * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
           *
           * _Available since v4.1._
           *
           * @custom:oz-upgrades-unsafe-allow delegatecall
           */
          abstract contract ERC1967Upgrade {
              // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
              bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
              /**
               * @dev Storage slot with the address of the current implementation.
               * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
               * validated in the constructor.
               */
              bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
              /**
               * @dev Emitted when the implementation is upgraded.
               */
              event Upgraded(address indexed implementation);
              /**
               * @dev Returns the current implementation address.
               */
              function _getImplementation() internal view returns (address) {
                  return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
              }
              /**
               * @dev Stores a new address in the EIP1967 implementation slot.
               */
              function _setImplementation(address newImplementation) private {
                  require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                  StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
              }
              /**
               * @dev Perform implementation upgrade
               *
               * Emits an {Upgraded} event.
               */
              function _upgradeTo(address newImplementation) internal {
                  _setImplementation(newImplementation);
                  emit Upgraded(newImplementation);
              }
              /**
               * @dev Perform implementation upgrade with additional setup call.
               *
               * Emits an {Upgraded} event.
               */
              function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
                  _setImplementation(newImplementation);
                  emit Upgraded(newImplementation);
                  if (data.length > 0 || forceCall) {
                      Address.functionDelegateCall(newImplementation, data);
                  }
              }
              /**
               * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
               *
               * Emits an {Upgraded} event.
               */
              function _upgradeToAndCallSecure(address newImplementation, bytes memory data, bool forceCall) internal {
                  address oldImplementation = _getImplementation();
                  // Initial upgrade and setup call
                  _setImplementation(newImplementation);
                  if (data.length > 0 || forceCall) {
                      Address.functionDelegateCall(newImplementation, data);
                  }
                  // Perform rollback test if not already in progress
                  StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
                  if (!rollbackTesting.value) {
                      // Trigger rollback using upgradeTo from the new implementation
                      rollbackTesting.value = true;
                      Address.functionDelegateCall(
                          newImplementation,
                          abi.encodeWithSignature(
                              "upgradeTo(address)",
                              oldImplementation
                          )
                      );
                      rollbackTesting.value = false;
                      // Check rollback was effective
                      require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
                      // Finally reset to the new implementation and log the upgrade
                      _setImplementation(newImplementation);
                      emit Upgraded(newImplementation);
                  }
              }
              /**
               * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
               * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
               *
               * Emits a {BeaconUpgraded} event.
               */
              function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
                  _setBeacon(newBeacon);
                  emit BeaconUpgraded(newBeacon);
                  if (data.length > 0 || forceCall) {
                      Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                  }
              }
              /**
               * @dev Storage slot with the admin of the contract.
               * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
               * validated in the constructor.
               */
              bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
              /**
               * @dev Emitted when the admin account has changed.
               */
              event AdminChanged(address previousAdmin, address newAdmin);
              /**
               * @dev Returns the current admin.
               */
              function _getAdmin() internal view returns (address) {
                  return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
              }
              /**
               * @dev Stores a new address in the EIP1967 admin slot.
               */
              function _setAdmin(address newAdmin) private {
                  require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                  StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
              }
              /**
               * @dev Changes the admin of the proxy.
               *
               * Emits an {AdminChanged} event.
               */
              function _changeAdmin(address newAdmin) internal {
                  emit AdminChanged(_getAdmin(), newAdmin);
                  _setAdmin(newAdmin);
              }
              /**
               * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
               * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
               */
              bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
              /**
               * @dev Emitted when the beacon is upgraded.
               */
              event BeaconUpgraded(address indexed beacon);
              /**
               * @dev Returns the current beacon.
               */
              function _getBeacon() internal view returns (address) {
                  return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
              }
              /**
               * @dev Stores a new beacon in the EIP1967 beacon slot.
               */
              function _setBeacon(address newBeacon) private {
                  require(
                      Address.isContract(newBeacon),
                      "ERC1967: new beacon is not a contract"
                  );
                  require(
                      Address.isContract(IBeacon(newBeacon).implementation()),
                      "ERC1967: beacon implementation is not a contract"
                  );
                  StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          /**
           * @dev This is the interface that {BeaconProxy} expects of its beacon.
           */
          interface IBeacon {
              /**
               * @dev Must return an address that can be used as a delegate call target.
               *
               * {BeaconProxy} will check that this address is a contract.
               */
              function implementation() external view returns (address);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          /**
           * @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
               * ====
               */
              function isContract(address account) internal view returns (bool) {
                  // This method relies on extcodesize, which returns 0 for contracts in
                  // construction, since the code is only stored at the end of the
                  // constructor execution.
                  uint256 size;
                  // solhint-disable-next-line no-inline-assembly
                  assembly { size := extcodesize(account) }
                  return size > 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");
                  // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                  (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");
                  // solhint-disable-next-line avoid-low-level-calls
                  (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");
                  // solhint-disable-next-line avoid-low-level-calls
                  (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");
                  // solhint-disable-next-line avoid-low-level-calls
                  (bool success, bytes memory returndata) = target.delegatecall(data);
                  return _verifyCallResult(success, returndata, errorMessage);
              }
              function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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
                          // solhint-disable-next-line no-inline-assembly
                          assembly {
                              let returndata_size := mload(returndata)
                              revert(add(32, returndata), returndata_size)
                          }
                      } else {
                          revert(errorMessage);
                      }
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          /**
           * @dev Library for reading and writing primitive types to specific storage slots.
           *
           * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
           * This library helps with reading and writing to such slots without the need for inline assembly.
           *
           * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
           *
           * Example usage to set ERC1967 implementation slot:
           * ```
           * contract ERC1967 {
           *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
           *
           *     function _getImplementation() internal view returns (address) {
           *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
           *     }
           *
           *     function _setImplementation(address newImplementation) internal {
           *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
           *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
           *     }
           * }
           * ```
           *
           * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
           */
          library StorageSlot {
              struct AddressSlot {
                  address value;
              }
              struct BooleanSlot {
                  bool value;
              }
              struct Bytes32Slot {
                  bytes32 value;
              }
              struct Uint256Slot {
                  uint256 value;
              }
              /**
               * @dev Returns an `AddressSlot` with member `value` located at `slot`.
               */
              function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                  assembly {
                      r.slot := slot
                  }
              }
              /**
               * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
               */
              function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                  assembly {
                      r.slot := slot
                  }
              }
              /**
               * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
               */
              function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                  assembly {
                      r.slot := slot
                  }
              }
              /**
               * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
               */
              function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                  assembly {
                      r.slot := slot
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "../utils/Context.sol";
          /**
           * @dev Contract module which provides a basic access control mechanism, where
           * there is an account (an owner) that can be granted exclusive access to
           * specific functions.
           *
           * By default, the owner account will be the one that deploys the contract. This
           * can later be changed with {transferOwnership}.
           *
           * This module is used through inheritance. It will make available the modifier
           * `onlyOwner`, which can be applied to your functions to restrict their use to
           * the owner.
           */
          abstract contract Ownable is Context {
              address private _owner;
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
              /**
               * @dev Initializes the contract setting the deployer as the initial owner.
               */
              constructor () {
                  address msgSender = _msgSender();
                  _owner = msgSender;
                  emit OwnershipTransferred(address(0), 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 {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = 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");
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          // SPDX-License-Identifier: MIT
          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) {
                  this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                  return msg.data;
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "../ERC1967/ERC1967Upgrade.sol";
          /**
           * @dev Base contract for building openzeppelin-upgrades compatible implementations for the {ERC1967Proxy}. It includes
           * publicly available upgrade functions that are called by the plugin and by the secure upgrade mechanism to verify
           * continuation of the upgradability.
           *
           * The {_authorizeUpgrade} function MUST be overridden to include access restriction to the upgrade mechanism.
           *
           * _Available since v4.1._
           */
          abstract contract UUPSUpgradeable is ERC1967Upgrade {
              function upgradeTo(address newImplementation) external virtual {
                  _authorizeUpgrade(newImplementation);
                  _upgradeToAndCallSecure(newImplementation, bytes(""), false);
              }
              function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual {
                  _authorizeUpgrade(newImplementation);
                  _upgradeToAndCallSecure(newImplementation, data, true);
              }
              function _authorizeUpgrade(address newImplementation) internal virtual;
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.2;
          import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
          abstract contract Proxiable is UUPSUpgradeable {
              function _authorizeUpgrade(address newImplementation) internal override {
                  _beforeUpgrade(newImplementation);
              }
              function _beforeUpgrade(address newImplementation) internal virtual;
          }
          contract ChildOfProxiable is Proxiable {
              function _beforeUpgrade(address newImplementation) internal virtual override {}
          }
          

          File 2 of 6: GnosisSafeProxy
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          
          /// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain
          /// @author Richard Meissner - <[email protected]>
          interface IProxy {
              function masterCopy() external view returns (address);
          }
          
          /// @title GnosisSafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
          /// @author Stefan George - <[email protected]>
          /// @author Richard Meissner - <[email protected]>
          contract GnosisSafeProxy {
              // singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
              // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
              address internal singleton;
          
              /// @dev Constructor function sets address of singleton contract.
              /// @param _singleton Singleton address.
              constructor(address _singleton) {
                  require(_singleton != address(0), "Invalid singleton address provided");
                  singleton = _singleton;
              }
          
              /// @dev Fallback function forwards all transactions and returns all received return data.
              fallback() external payable {
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
                      // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
                      if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
                          mstore(0, _singleton)
                          return(0, 0x20)
                      }
                      calldatacopy(0, 0, calldatasize())
                      let success := delegatecall(gas(), _singleton, 0, calldatasize(), 0, 0)
                      returndatacopy(0, 0, returndatasize())
                      if eq(success, 0) {
                          revert(0, returndatasize())
                      }
                      return(0, returndatasize())
                  }
              }
          }
          
          /// @title Proxy Factory - Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
          /// @author Stefan George - <[email protected]>
          contract GnosisSafeProxyFactory {
              event ProxyCreation(GnosisSafeProxy proxy, address singleton);
          
              /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
              /// @param singleton Address of singleton contract.
              /// @param data Payload for message call sent to new proxy contract.
              function createProxy(address singleton, bytes memory data) public returns (GnosisSafeProxy proxy) {
                  proxy = new GnosisSafeProxy(singleton);
                  if (data.length > 0)
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          if eq(call(gas(), proxy, 0, add(data, 0x20), mload(data), 0, 0), 0) {
                              revert(0, 0)
                          }
                      }
                  emit ProxyCreation(proxy, singleton);
              }
          
              /// @dev Allows to retrieve the runtime code of a deployed Proxy. This can be used to check that the expected Proxy was deployed.
              function proxyRuntimeCode() public pure returns (bytes memory) {
                  return type(GnosisSafeProxy).runtimeCode;
              }
          
              /// @dev Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address.
              function proxyCreationCode() public pure returns (bytes memory) {
                  return type(GnosisSafeProxy).creationCode;
              }
          
              /// @dev Allows to create new proxy contact using CREATE2 but it doesn't run the initializer.
              ///      This method is only meant as an utility to be called from other methods
              /// @param _singleton Address of singleton contract.
              /// @param initializer Payload for message call sent to new proxy contract.
              /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
              function deployProxyWithNonce(
                  address _singleton,
                  bytes memory initializer,
                  uint256 saltNonce
              ) internal returns (GnosisSafeProxy proxy) {
                  // If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it
                  bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
                  bytes memory deploymentData = abi.encodePacked(type(GnosisSafeProxy).creationCode, uint256(uint160(_singleton)));
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)
                  }
                  require(address(proxy) != address(0), "Create2 call failed");
              }
          
              /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
              /// @param _singleton Address of singleton contract.
              /// @param initializer Payload for message call sent to new proxy contract.
              /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
              function createProxyWithNonce(
                  address _singleton,
                  bytes memory initializer,
                  uint256 saltNonce
              ) public returns (GnosisSafeProxy proxy) {
                  proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);
                  if (initializer.length > 0)
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          if eq(call(gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0), 0) {
                              revert(0, 0)
                          }
                      }
                  emit ProxyCreation(proxy, _singleton);
              }
          
              /// @dev Allows to create new proxy contact, execute a message call to the new proxy and call a specified callback within one transaction
              /// @param _singleton Address of singleton contract.
              /// @param initializer Payload for message call sent to new proxy contract.
              /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
              /// @param callback Callback that will be invoced after the new proxy contract has been successfully deployed and initialized.
              function createProxyWithCallback(
                  address _singleton,
                  bytes memory initializer,
                  uint256 saltNonce,
                  IProxyCreationCallback callback
              ) public returns (GnosisSafeProxy proxy) {
                  uint256 saltNonceWithCallback = uint256(keccak256(abi.encodePacked(saltNonce, callback)));
                  proxy = createProxyWithNonce(_singleton, initializer, saltNonceWithCallback);
                  if (address(callback) != address(0)) callback.proxyCreated(proxy, _singleton, initializer, saltNonce);
              }
          
              /// @dev Allows to get the address for a new proxy contact created via `createProxyWithNonce`
              ///      This method is only meant for address calculation purpose when you use an initializer that would revert,
              ///      therefore the response is returned with a revert. When calling this method set `from` to the address of the proxy factory.
              /// @param _singleton Address of singleton contract.
              /// @param initializer Payload for message call sent to new proxy contract.
              /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
              function calculateCreateProxyWithNonceAddress(
                  address _singleton,
                  bytes calldata initializer,
                  uint256 saltNonce
              ) external returns (GnosisSafeProxy proxy) {
                  proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);
                  revert(string(abi.encodePacked(proxy)));
              }
          }
          
          interface IProxyCreationCallback {
              function proxyCreated(
                  GnosisSafeProxy proxy,
                  address _singleton,
                  bytes calldata initializer,
                  uint256 saltNonce
              ) external;
          }

          File 3 of 6: Sale
          //SPDX-License-Identifier: MIT
          pragma solidity 0.8.9;
          import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
          import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
          import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
          import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
          import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
          import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
          interface Aggregator {
              function latestRoundData()
                  external
                  view
                  returns (
                      uint80 roundId,
                      int256 answer,
                      uint256 startedAt,
                      uint256 updatedAt,
                      uint80 answeredInRound
                  );
          }
          contract Sale is Initializable, ReentrancyGuardUpgradeable, OwnableUpgradeable {
              uint256 public presaleId;
              uint256 public BASE_MULTIPLIER;
              uint256 public MONTH;
              struct Presale {
                  address saleToken;
                  uint256 startTime;
                  uint256 endTime;
                  uint256 price;
                  uint256 tokensToSell;
                  uint256 baseDecimals;
                  uint256 inSale;
                  uint256 vestingStartTime;
                  uint256 vestingCliff;
                  uint256 vestingPeriod;
              }
              struct Vesting {
                  uint256 totalAmount;
                  uint256 claimedAmount;
                  uint256 claimStart;
                  uint256 claimEnd;
              }
              IERC20Upgradeable public USDTInterface;
              Aggregator internal aggregatorInterface;
              // https://docs.chain.link/docs/ethereum-addresses/ => (ETH / USD)
              mapping(uint256 => bool) public paused;
              mapping(uint256 => Presale) public presale;
              mapping(address => mapping(uint256 => Vesting)) public userVesting;
              event PresaleCreated(
                  uint256 indexed _id,
                  uint256 _totalTokens,
                  uint256 _startTime,
                  uint256 _endTime
              );
              event PresaleUpdated(
                  bytes32 indexed key,
                  uint256 prevValue,
                  uint256 newValue,
                  uint256 timestamp
              );
              event TokensBought(
                  address indexed user,
                  uint256 indexed id,
                  address indexed purchaseToken,
                  uint256 tokensBought,
                  uint256 amountPaid,
                  uint256 timestamp
              );
              event TokensClaimed(
                  address indexed user,
                  uint256 indexed id,
                  uint256 amount,
                  uint256 timestamp
              );
              event PresaleTokenAddressUpdated(
                  address indexed prevValue,
                  address indexed newValue,
                  uint256 timestamp
              );
              event PresalePaused(uint256 indexed id, uint256 timestamp);
              event PresaleUnpaused(uint256 indexed id, uint256 timestamp);
              /// @custom:oz-upgrades-unsafe-allow constructor
              constructor() initializer {}
              /**
               * @dev Initializes the contract and sets key parameters
               * @param _oracle Oracle contract to fetch ETH/USDT price
               * @param _usdt USDT token contract address
               */
              function initialize(address _oracle, address _usdt) external initializer {
                  require(_oracle != address(0), "Zero aggregator address");
                  require(_usdt != address(0), "Zero USDT address");
                  __Ownable_init_unchained();
                  __ReentrancyGuard_init_unchained();
                  aggregatorInterface = Aggregator(_oracle);
                  USDTInterface = IERC20Upgradeable(_usdt);
                  BASE_MULTIPLIER = (10**18);
                  MONTH = (30 * 24 * 3600);
              }
              /**
               * @dev Creates a new presale
               * @param _startTime start time of the sale
               * @param _endTime end time of the sale
               * @param _price Per token price multiplied by (10**18)
               * @param _tokensToSell No of tokens to sell without denomination. If 1 million tokens to be sold then - 1_000_000 has to be passed
               * @param _baseDecimals No of decimals for the token. (10**18), for 18 decimal token
               * @param _vestingStartTime Start time for the vesting - UNIX timestamp
               * @param _vestingCliff Cliff period for vesting in seconds
               * @param _vestingPeriod Total vesting period(after vesting cliff) in seconds
               */
              function createPresale(
                  uint256 _startTime,
                  uint256 _endTime,
                  uint256 _price,
                  uint256 _tokensToSell,
                  uint256 _baseDecimals,
                  uint256 _vestingStartTime,
                  uint256 _vestingCliff,
                  uint256 _vestingPeriod
              ) external onlyOwner {
                  require(
                      _startTime > block.timestamp && _endTime > _startTime,
                      "Invalid time"
                  );
                  require(_price > 0, "Zero price");
                  require(_tokensToSell > 0, "Zero tokens to sell");
                  require(_baseDecimals > 0, "Zero decimals for the token");
                  require(
                      _vestingStartTime >= _endTime,
                      "Vesting starts before Presale ends"
                  );
                  presaleId++;
                  presale[presaleId] = Presale(
                      address(0),
                      _startTime,
                      _endTime,
                      _price,
                      _tokensToSell,
                      _baseDecimals,
                      _tokensToSell,
                      _vestingStartTime,
                      _vestingCliff,
                      _vestingPeriod
                  );
                  emit PresaleCreated(presaleId, _tokensToSell, _startTime, _endTime);
              }
              /**
               * @dev To update the sale times
               * @param _id Presale id to update
               * @param _startTime New start time
               * @param _endTime New end time
               */
              function changeSaleTimes(
                  uint256 _id,
                  uint256 _startTime,
                  uint256 _endTime
              ) external checkPresaleId(_id) onlyOwner {
                  require(_startTime > 0 || _endTime > 0, "Invalid parameters");
                  if (_startTime > 0) {
                      require(
                          block.timestamp < presale[_id].startTime,
                          "Sale already started"
                      );
                      require(block.timestamp < _startTime, "Sale time in past");
                      uint256 prevValue = presale[_id].startTime;
                      presale[_id].startTime = _startTime;
                      emit PresaleUpdated(
                          bytes32("START"),
                          prevValue,
                          _startTime,
                          block.timestamp
                      );
                  }
                  if (_endTime > 0) {
                      require(
                          block.timestamp < presale[_id].endTime,
                          "Sale already ended"
                      );
                      require(_endTime > presale[_id].startTime, "Invalid endTime");
                      uint256 prevValue = presale[_id].endTime;
                      presale[_id].endTime = _endTime;
                      emit PresaleUpdated(
                          bytes32("END"),
                          prevValue,
                          _endTime,
                          block.timestamp
                      );
                  }
              }
              /**
               * @dev To update the vesting start time
               * @param _id Presale id to update
               * @param _vestingStartTime New vesting start time
               */
              function changeVestingStartTime(uint256 _id, uint256 _vestingStartTime)
                  external
                  checkPresaleId(_id)
                  onlyOwner
              {
                  require(
                      _vestingStartTime >= presale[_id].endTime,
                      "Vesting starts before Presale ends"
                  );
                  uint256 prevValue = presale[_id].vestingStartTime;
                  presale[_id].vestingStartTime = _vestingStartTime;
                  emit PresaleUpdated(
                      "VESTING_START_TIME",
                      prevValue,
                      _vestingStartTime,
                      block.timestamp
                  );
              }
              /**
               * @dev To update the sale token address
               * @param _id Presale id to update
               * @param _newAddress Sale token address
               */
              function changeSaleTokenAddress(uint256 _id, address _newAddress)
                  external
                  checkPresaleId(_id)
                  onlyOwner
              {
                  require(_newAddress != address(0), "Zero token address");
                  address prevValue = presale[_id].saleToken;
                  presale[_id].saleToken = _newAddress;
                  emit PresaleTokenAddressUpdated(
                      prevValue,
                      _newAddress,
                      block.timestamp
                  );
              }
              /**
               * @dev To update the price
               * @param _id Presale id to update
               * @param _newPrice New sale price of the token
               */
              function changePrice(uint256 _id, uint256 _newPrice)
                  external
                  checkPresaleId(_id)
                  onlyOwner
              {
                  require(_newPrice > 0, "Zero price");
                  require(
                      presale[_id].startTime > block.timestamp,
                      "Sale already started"
                  );
                  uint256 prevValue = presale[_id].price;
                  presale[_id].price = _newPrice;
                  emit PresaleUpdated(
                      bytes32("PRICE"),
                      prevValue,
                      _newPrice,
                      block.timestamp
                  );
              }
              /**
               * @dev To pause the presale
               * @param _id Presale id to update
               */
              function pausePresale(uint256 _id) external checkPresaleId(_id) onlyOwner {
                  require(!paused[_id], "Already paused");
                  paused[_id] = true;
                  emit PresalePaused(_id, block.timestamp);
              }
              /**
               * @dev To unpause the presale
               * @param _id Presale id to update
               */
              function unPausePresale(uint256 _id)
                  external
                  checkPresaleId(_id)
                  onlyOwner
              {
                  require(paused[_id], "Not paused");
                  paused[_id] = false;
                  emit PresaleUnpaused(_id, block.timestamp);
              }
              /**
               * @dev To get latest ethereum price in 10**18 format
               */
              function getLatestPrice() public view returns (uint256) {
                  (, int256 price, , , ) = aggregatorInterface.latestRoundData();
                  price = (price * (10**10));
                  return uint256(price);
              }
              modifier checkPresaleId(uint256 _id) {
                  require(_id > 0 && _id <= presaleId, "Invalid presale id");
                  _;
              }
              modifier checkSaleState(uint256 _id, uint256 amount) {
                  require(
                      block.timestamp >= presale[_id].startTime &&
                          block.timestamp <= presale[_id].endTime,
                      "Invalid time for buying"
                  );
                  require(
                      amount > 0 && amount <= presale[_id].inSale,
                      "Invalid sale amount"
                  );
                  _;
              }
              /**
               * @dev To buy into a presale using USDT
               * @param _id Presale id
               * @param amount No of tokens to buy
               */
              function buyWithUSDT(uint256 _id, uint256 amount)
                  external
                  checkPresaleId(_id)
                  checkSaleState(_id, amount)
                  returns (bool)
              {
                  require(!paused[_id], "Presale paused");
                  uint256 usdPrice = amount * presale[_id].price;
                  usdPrice = usdPrice / (10**12);
                  presale[_id].inSale -= amount;
                  Presale memory _presale = presale[_id];
                  if (userVesting[_msgSender()][_id].totalAmount > 0) {
                      userVesting[_msgSender()][_id].totalAmount += (amount *
                          _presale.baseDecimals);
                  } else {
                      userVesting[_msgSender()][_id] = Vesting(
                          (amount * _presale.baseDecimals),
                          0,
                          _presale.vestingStartTime + _presale.vestingCliff,
                          _presale.vestingStartTime +
                              _presale.vestingCliff +
                              _presale.vestingPeriod
                      );
                  }
                  uint256 ourAllowance = USDTInterface.allowance(
                      _msgSender(),
                      address(this)
                  );
                  require(usdPrice <= ourAllowance, "Make sure to add enough allowance");
                  (bool success, ) = address(USDTInterface).call(
                      abi.encodeWithSignature(
                          "transferFrom(address,address,uint256)",
                          _msgSender(),
                          owner(),
                          usdPrice
                      )
                  );
                  require(success, "Token payment failed");
                  emit TokensBought(
                      _msgSender(),
                      _id,
                      address(USDTInterface),
                      amount,
                      usdPrice,
                      block.timestamp
                  );
                  return true;
              }
              /**
               * @dev To buy into a presale using ETH
               * @param _id Presale id
               * @param amount No of tokens to buy
               */
              function buyWithEth(uint256 _id, uint256 amount)
                  external
                  payable
                  checkPresaleId(_id)
                  checkSaleState(_id, amount)
                  nonReentrant
                  returns (bool)
              {
                  require(!paused[_id], "Presale paused");
                  uint256 usdPrice = amount * presale[_id].price;
                  uint256 ethAmount = (usdPrice * BASE_MULTIPLIER) / getLatestPrice();
                  require(msg.value >= ethAmount, "Less payment");
                  uint256 excess = msg.value - ethAmount;
                  presale[_id].inSale -= amount;
                  Presale memory _presale = presale[_id];
                  if (userVesting[_msgSender()][_id].totalAmount > 0) {
                      userVesting[_msgSender()][_id].totalAmount += (amount *
                          _presale.baseDecimals);
                  } else {
                      userVesting[_msgSender()][_id] = Vesting(
                          (amount * _presale.baseDecimals),
                          0,
                          _presale.vestingStartTime + _presale.vestingCliff,
                          _presale.vestingStartTime +
                              _presale.vestingCliff +
                              _presale.vestingPeriod
                      );
                  }
                  sendValue(payable(owner()), ethAmount);
                  if (excess > 0) sendValue(payable(_msgSender()), excess);
                  emit TokensBought(
                      _msgSender(),
                      _id,
                      address(0),
                      amount,
                      ethAmount,
                      block.timestamp
                  );
                  return true;
              }
              /**
               * @dev Helper funtion to get ETH price for given amount
               * @param _id Presale id
               * @param amount No of tokens to buy
               */
              function ethBuyHelper(uint256 _id, uint256 amount)
                  external
                  view
                  checkPresaleId(_id)
                  returns (uint256 ethAmount)
              {
                  uint256 usdPrice = amount * presale[_id].price;
                  ethAmount = (usdPrice * BASE_MULTIPLIER) / getLatestPrice();
              }
              /**
               * @dev Helper funtion to get USDT price for given amount
               * @param _id Presale id
               * @param amount No of tokens to buy
               */
              function usdtBuyHelper(uint256 _id, uint256 amount)
                  external
                  view
                  checkPresaleId(_id)
                  returns (uint256 usdPrice)
              {
                  usdPrice = amount * presale[_id].price;
                  usdPrice = usdPrice / (10**12);
              }
              function sendValue(address payable recipient, uint256 amount) internal {
                  require(address(this).balance >= amount, "Low balance");
                  (bool success, ) = recipient.call{value: amount}("");
                  require(success, "ETH Payment failed");
              }
              /**
               * @dev Helper funtion to get claimable tokens for a given presale.
               * @param user User address
               * @param _id Presale id
               */
              function claimableAmount(address user, uint256 _id)
                  public
                  view
                  checkPresaleId(_id)
                  returns (uint256)
              {
                  Vesting memory _user = userVesting[user][_id];
                  require(_user.totalAmount > 0, "Nothing to claim");
                  uint256 amount = _user.totalAmount - _user.claimedAmount;
                  require(amount > 0, "Already claimed");
                  if (block.timestamp < _user.claimStart) return 0;
                  if (block.timestamp >= _user.claimEnd) return amount;
                  uint256 noOfMonthsPassed = (block.timestamp - _user.claimStart) / MONTH;
                  uint256 perMonthClaim = (_user.totalAmount * BASE_MULTIPLIER * MONTH) /
                      (_user.claimEnd - _user.claimStart);
                  uint256 amountToClaim = ((noOfMonthsPassed * perMonthClaim) /
                      BASE_MULTIPLIER) - _user.claimedAmount;
                  return amountToClaim;
              }
              /**
               * @dev To claim tokens after vesting cliff from a presale
               * @param user User address
               * @param _id Presale id
               */
              function claim(address user, uint256 _id) public returns (bool) {
                  uint256 amount = claimableAmount(user, _id);
                  require(amount > 0, "Zero claim amount");
                  require(
                      presale[_id].saleToken != address(0),
                      "Presale token address not set"
                  );
                  require(
                      amount <=
                          IERC20Upgradeable(presale[_id].saleToken).balanceOf(
                              address(this)
                          ),
                      "Not enough tokens in the contract"
                  );
                  userVesting[user][_id].claimedAmount += amount;
                  bool status = IERC20Upgradeable(presale[_id].saleToken).transfer(
                      user,
                      amount
                  );
                  require(status, "Token transfer failed");
                  emit TokensClaimed(user, _id, amount, block.timestamp);
                  return true;
              }
              /**
               * @dev To claim tokens after vesting cliff from a presale
               * @param users Array of user addresses
               * @param _id Presale id
               */
              function claimMultiple(address[] calldata users, uint256 _id)
                  external
                  returns (bool)
              {
                  require(users.length > 0, "Zero users length");
                  for (uint256 i; i < users.length; i++) {
                      require(claim(users[i], _id), "Claim failed");
                  }
                  return true;
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
          pragma solidity ^0.8.0;
          import "../proxy/utils/Initializable.sol";
          /**
           * @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 ContextUpgradeable is Initializable {
              function __Context_init() internal onlyInitializing {
              }
              function __Context_init_unchained() internal onlyInitializing {
              }
              function _msgSender() internal view virtual returns (address) {
                  return msg.sender;
              }
              function _msgData() internal view virtual returns (bytes calldata) {
                  return msg.data;
              }
              /**
               * @dev This empty reserved space is put in place to allow future versions to add new
               * variables without shifting down storage in the inheritance chain.
               * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
               */
              uint256[50] private __gap;
          }
          // SPDX-License-Identifier: MIT
          // 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 AddressUpgradeable {
              /**
               * @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 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);
                      }
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
          pragma solidity ^0.8.0;
          /**
           * @dev Interface of the ERC20 standard as defined in the EIP.
           */
          interface IERC20Upgradeable {
              /**
               * @dev Emitted when `value` tokens are moved from one account (`from`) to
               * another (`to`).
               *
               * Note that `value` may be zero.
               */
              event Transfer(address indexed from, address indexed to, uint256 value);
              /**
               * @dev Emitted when the allowance of a `spender` for an `owner` is set by
               * a call to {approve}. `value` is the new allowance.
               */
              event Approval(address indexed owner, address indexed spender, uint256 value);
              /**
               * @dev Returns the amount of tokens in existence.
               */
              function totalSupply() external view returns (uint256);
              /**
               * @dev Returns the amount of tokens owned by `account`.
               */
              function balanceOf(address account) external view returns (uint256);
              /**
               * @dev Moves `amount` tokens from the caller's account to `to`.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transfer(address to, uint256 amount) external returns (bool);
              /**
               * @dev Returns the remaining number of tokens that `spender` will be
               * allowed to spend on behalf of `owner` through {transferFrom}. This is
               * zero by default.
               *
               * This value changes when {approve} or {transferFrom} are called.
               */
              function allowance(address owner, address spender) external view returns (uint256);
              /**
               * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * IMPORTANT: Beware that changing an allowance with this method brings the risk
               * that someone may use both the old and the new allowance by unfortunate
               * transaction ordering. One possible solution to mitigate this race
               * condition is to first reduce the spender's allowance to 0 and set the
               * desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               *
               * Emits an {Approval} event.
               */
              function approve(address spender, uint256 amount) external returns (bool);
              /**
               * @dev Moves `amount` tokens from `from` to `to` using the
               * allowance mechanism. `amount` is then deducted from the caller's
               * allowance.
               *
               * Returns a boolean value indicating whether the operation succeeded.
               *
               * Emits a {Transfer} event.
               */
              function transferFrom(
                  address from,
                  address to,
                  uint256 amount
              ) external returns (bool);
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
          pragma solidity ^0.8.0;
          import "../proxy/utils/Initializable.sol";
          /**
           * @dev Contract module that helps prevent reentrant calls to a function.
           *
           * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
           * available, which can be applied to functions to make sure there are no nested
           * (reentrant) calls to them.
           *
           * Note that because there is a single `nonReentrant` guard, functions marked as
           * `nonReentrant` may not call one another. This can be worked around by making
           * those functions `private`, and then adding `external` `nonReentrant` entry
           * points to them.
           *
           * TIP: If you would like to learn more about reentrancy and alternative ways
           * to protect against it, check out our blog post
           * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
           */
          abstract contract ReentrancyGuardUpgradeable is Initializable {
              // Booleans are more expensive than uint256 or any type that takes up a full
              // word because each write operation emits an extra SLOAD to first read the
              // slot's contents, replace the bits taken up by the boolean, and then write
              // back. This is the compiler's defense against contract upgrades and
              // pointer aliasing, and it cannot be disabled.
              // The values being non-zero value makes deployment a bit more expensive,
              // but in exchange the refund on every call to nonReentrant will be lower in
              // amount. Since refunds are capped to a percentage of the total
              // transaction's gas, it is best to keep them low in cases like this one, to
              // increase the likelihood of the full refund coming into effect.
              uint256 private constant _NOT_ENTERED = 1;
              uint256 private constant _ENTERED = 2;
              uint256 private _status;
              function __ReentrancyGuard_init() internal onlyInitializing {
                  __ReentrancyGuard_init_unchained();
              }
              function __ReentrancyGuard_init_unchained() internal onlyInitializing {
                  _status = _NOT_ENTERED;
              }
              /**
               * @dev Prevents a contract from calling itself, directly or indirectly.
               * Calling a `nonReentrant` function from another `nonReentrant`
               * function is not supported. It is possible to prevent this from happening
               * by making the `nonReentrant` function external, and making it call a
               * `private` function that does the actual work.
               */
              modifier nonReentrant() {
                  // On the first call to nonReentrant, _notEntered will be true
                  require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
                  // Any calls to nonReentrant after this point will fail
                  _status = _ENTERED;
                  _;
                  // By storing the original value once again, a refund is triggered (see
                  // https://eips.ethereum.org/EIPS/eip-2200)
                  _status = _NOT_ENTERED;
              }
              /**
               * @dev This empty reserved space is put in place to allow future versions to add new
               * variables without shifting down storage in the inheritance chain.
               * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
               */
              uint256[49] private __gap;
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
          pragma solidity ^0.8.2;
          import "../../utils/AddressUpgradeable.sol";
          /**
           * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
           * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
           * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
           * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
           *
           * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
           * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
           * case an upgrade adds a module that needs to be initialized.
           *
           * For example:
           *
           * [.hljs-theme-light.nopadding]
           * ```
           * contract MyToken is ERC20Upgradeable {
           *     function initialize() initializer public {
           *         __ERC20_init("MyToken", "MTK");
           *     }
           * }
           * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
           *     function initializeV2() reinitializer(2) public {
           *         __ERC20Permit_init("MyToken");
           *     }
           * }
           * ```
           *
           * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
           * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
           *
           * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
           * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
           *
           * [CAUTION]
           * ====
           * Avoid leaving a contract uninitialized.
           *
           * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
           * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
           * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
           *
           * [.hljs-theme-light.nopadding]
           * ```
           * /// @custom:oz-upgrades-unsafe-allow constructor
           * constructor() {
           *     _disableInitializers();
           * }
           * ```
           * ====
           */
          abstract contract Initializable {
              /**
               * @dev Indicates that the contract has been initialized.
               * @custom:oz-retyped-from bool
               */
              uint8 private _initialized;
              /**
               * @dev Indicates that the contract is in the process of being initialized.
               */
              bool private _initializing;
              /**
               * @dev Triggered when the contract has been initialized or reinitialized.
               */
              event Initialized(uint8 version);
              /**
               * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
               * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
               */
              modifier initializer() {
                  bool isTopLevelCall = !_initializing;
                  require(
                      (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
                      "Initializable: contract is already initialized"
                  );
                  _initialized = 1;
                  if (isTopLevelCall) {
                      _initializing = true;
                  }
                  _;
                  if (isTopLevelCall) {
                      _initializing = false;
                      emit Initialized(1);
                  }
              }
              /**
               * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
               * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
               * used to initialize parent contracts.
               *
               * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
               * initialization step. This is essential to configure modules that are added through upgrades and that require
               * initialization.
               *
               * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
               * a contract, executing them in the right order is up to the developer or operator.
               */
              modifier reinitializer(uint8 version) {
                  require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
                  _initialized = version;
                  _initializing = true;
                  _;
                  _initializing = false;
                  emit Initialized(version);
              }
              /**
               * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
               * {initializer} and {reinitializer} modifiers, directly or indirectly.
               */
              modifier onlyInitializing() {
                  require(_initializing, "Initializable: contract is not initializing");
                  _;
              }
              /**
               * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
               * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
               * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
               * through proxies.
               */
              function _disableInitializers() internal virtual {
                  require(!_initializing, "Initializable: contract is initializing");
                  if (_initialized < type(uint8).max) {
                      _initialized = type(uint8).max;
                      emit Initialized(type(uint8).max);
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
          pragma solidity ^0.8.0;
          import "../utils/ContextUpgradeable.sol";
          import "../proxy/utils/Initializable.sol";
          /**
           * @dev Contract module which provides a basic access control mechanism, where
           * there is an account (an owner) that can be granted exclusive access to
           * specific functions.
           *
           * By default, the owner account will be the one that deploys the contract. This
           * can later be changed with {transferOwnership}.
           *
           * This module is used through inheritance. It will make available the modifier
           * `onlyOwner`, which can be applied to your functions to restrict their use to
           * the owner.
           */
          abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
              address private _owner;
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
              /**
               * @dev Initializes the contract setting the deployer as the initial owner.
               */
              function __Ownable_init() internal onlyInitializing {
                  __Ownable_init_unchained();
              }
              function __Ownable_init_unchained() internal onlyInitializing {
                  _transferOwnership(_msgSender());
              }
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  _checkOwner();
                  _;
              }
              /**
               * @dev Returns the address of the current owner.
               */
              function owner() public view virtual returns (address) {
                  return _owner;
              }
              /**
               * @dev Throws if the sender is not the owner.
               */
              function _checkOwner() internal view virtual {
                  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);
              }
              /**
               * @dev This empty reserved space is put in place to allow future versions to add new
               * variables without shifting down storage in the inheritance chain.
               * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
               */
              uint256[49] private __gap;
          }
          

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

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

          File 6 of 6: GnosisSafe
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "./base/ModuleManager.sol";
          import "./base/OwnerManager.sol";
          import "./base/FallbackManager.sol";
          import "./base/GuardManager.sol";
          import "./common/EtherPaymentFallback.sol";
          import "./common/Singleton.sol";
          import "./common/SignatureDecoder.sol";
          import "./common/SecuredTokenTransfer.sol";
          import "./common/StorageAccessible.sol";
          import "./interfaces/ISignatureValidator.sol";
          import "./external/GnosisSafeMath.sol";
          /// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
          /// @author Stefan George - <[email protected]>
          /// @author Richard Meissner - <[email protected]>
          contract GnosisSafe is
              EtherPaymentFallback,
              Singleton,
              ModuleManager,
              OwnerManager,
              SignatureDecoder,
              SecuredTokenTransfer,
              ISignatureValidatorConstants,
              FallbackManager,
              StorageAccessible,
              GuardManager
          {
              using GnosisSafeMath for uint256;
              string public constant VERSION = "1.3.0";
              // keccak256(
              //     "EIP712Domain(uint256 chainId,address verifyingContract)"
              // );
              bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;
              // keccak256(
              //     "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)"
              // );
              bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8;
              event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler);
              event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
              event SignMsg(bytes32 indexed msgHash);
              event ExecutionFailure(bytes32 txHash, uint256 payment);
              event ExecutionSuccess(bytes32 txHash, uint256 payment);
              uint256 public nonce;
              bytes32 private _deprecatedDomainSeparator;
              // Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners
              mapping(bytes32 => uint256) public signedMessages;
              // Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners
              mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
              // This constructor ensures that this contract can only be used as a master copy for Proxy contracts
              constructor() {
                  // By setting the threshold it is not possible to call setup anymore,
                  // so we create a Safe with 0 owners and threshold 1.
                  // This is an unusable Safe, perfect for the singleton
                  threshold = 1;
              }
              /// @dev Setup function sets initial storage of contract.
              /// @param _owners List of Safe owners.
              /// @param _threshold Number of required confirmations for a Safe transaction.
              /// @param to Contract address for optional delegate call.
              /// @param data Data payload for optional delegate call.
              /// @param fallbackHandler Handler for fallback calls to this contract
              /// @param paymentToken Token that should be used for the payment (0 is ETH)
              /// @param payment Value that should be paid
              /// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin)
              function setup(
                  address[] calldata _owners,
                  uint256 _threshold,
                  address to,
                  bytes calldata data,
                  address fallbackHandler,
                  address paymentToken,
                  uint256 payment,
                  address payable paymentReceiver
              ) external {
                  // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
                  setupOwners(_owners, _threshold);
                  if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler);
                  // As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules
                  setupModules(to, data);
                  if (payment > 0) {
                      // To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself)
                      // baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment
                      handlePayment(payment, 0, 1, paymentToken, paymentReceiver);
                  }
                  emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler);
              }
              /// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
              ///      Note: The fees are always transferred, even if the user transaction fails.
              /// @param to Destination address of Safe transaction.
              /// @param value Ether value of Safe transaction.
              /// @param data Data payload of Safe transaction.
              /// @param operation Operation type of Safe transaction.
              /// @param safeTxGas Gas that should be used for the Safe transaction.
              /// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
              /// @param gasPrice Gas price that should be used for the payment calculation.
              /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
              /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
              /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
              function execTransaction(
                  address to,
                  uint256 value,
                  bytes calldata data,
                  Enum.Operation operation,
                  uint256 safeTxGas,
                  uint256 baseGas,
                  uint256 gasPrice,
                  address gasToken,
                  address payable refundReceiver,
                  bytes memory signatures
              ) public payable virtual returns (bool success) {
                  bytes32 txHash;
                  // Use scope here to limit variable lifetime and prevent `stack too deep` errors
                  {
                      bytes memory txHashData =
                          encodeTransactionData(
                              // Transaction info
                              to,
                              value,
                              data,
                              operation,
                              safeTxGas,
                              // Payment info
                              baseGas,
                              gasPrice,
                              gasToken,
                              refundReceiver,
                              // Signature info
                              nonce
                          );
                      // Increase nonce and execute transaction.
                      nonce++;
                      txHash = keccak256(txHashData);
                      checkSignatures(txHash, txHashData, signatures);
                  }
                  address guard = getGuard();
                  {
                      if (guard != address(0)) {
                          Guard(guard).checkTransaction(
                              // Transaction info
                              to,
                              value,
                              data,
                              operation,
                              safeTxGas,
                              // Payment info
                              baseGas,
                              gasPrice,
                              gasToken,
                              refundReceiver,
                              // Signature info
                              signatures,
                              msg.sender
                          );
                      }
                  }
                  // We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
                  // We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150
                  require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, "GS010");
                  // Use scope here to limit variable lifetime and prevent `stack too deep` errors
                  {
                      uint256 gasUsed = gasleft();
                      // If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas)
                      // We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas
                      success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas);
                      gasUsed = gasUsed.sub(gasleft());
                      // If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful
                      // This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert
                      require(success || safeTxGas != 0 || gasPrice != 0, "GS013");
                      // We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls
                      uint256 payment = 0;
                      if (gasPrice > 0) {
                          payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver);
                      }
                      if (success) emit ExecutionSuccess(txHash, payment);
                      else emit ExecutionFailure(txHash, payment);
                  }
                  {
                      if (guard != address(0)) {
                          Guard(guard).checkAfterExecution(txHash, success);
                      }
                  }
              }
              function handlePayment(
                  uint256 gasUsed,
                  uint256 baseGas,
                  uint256 gasPrice,
                  address gasToken,
                  address payable refundReceiver
              ) private returns (uint256 payment) {
                  // solhint-disable-next-line avoid-tx-origin
                  address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
                  if (gasToken == address(0)) {
                      // For ETH we will only adjust the gas price to not be higher than the actual used gas price
                      payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);
                      require(receiver.send(payment), "GS011");
                  } else {
                      payment = gasUsed.add(baseGas).mul(gasPrice);
                      require(transferToken(gasToken, receiver, payment), "GS012");
                  }
              }
              /**
               * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
               * @param dataHash Hash of the data (could be either a message hash or transaction hash)
               * @param data That should be signed (this is passed to an external validator contract)
               * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
               */
              function checkSignatures(
                  bytes32 dataHash,
                  bytes memory data,
                  bytes memory signatures
              ) public view {
                  // Load threshold to avoid multiple storage loads
                  uint256 _threshold = threshold;
                  // Check that a threshold is set
                  require(_threshold > 0, "GS001");
                  checkNSignatures(dataHash, data, signatures, _threshold);
              }
              /**
               * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
               * @param dataHash Hash of the data (could be either a message hash or transaction hash)
               * @param data That should be signed (this is passed to an external validator contract)
               * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
               * @param requiredSignatures Amount of required valid signatures.
               */
              function checkNSignatures(
                  bytes32 dataHash,
                  bytes memory data,
                  bytes memory signatures,
                  uint256 requiredSignatures
              ) public view {
                  // Check that the provided signature data is not too short
                  require(signatures.length >= requiredSignatures.mul(65), "GS020");
                  // There cannot be an owner with address 0.
                  address lastOwner = address(0);
                  address currentOwner;
                  uint8 v;
                  bytes32 r;
                  bytes32 s;
                  uint256 i;
                  for (i = 0; i < requiredSignatures; i++) {
                      (v, r, s) = signatureSplit(signatures, i);
                      if (v == 0) {
                          // If v is 0 then it is a contract signature
                          // When handling contract signatures the address of the contract is encoded into r
                          currentOwner = address(uint160(uint256(r)));
                          // Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes
                          // This check is not completely accurate, since it is possible that more signatures than the threshold are send.
                          // Here we only check that the pointer is not pointing inside the part that is being processed
                          require(uint256(s) >= requiredSignatures.mul(65), "GS021");
                          // Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes)
                          require(uint256(s).add(32) <= signatures.length, "GS022");
                          // Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length
                          uint256 contractSignatureLen;
                          // solhint-disable-next-line no-inline-assembly
                          assembly {
                              contractSignatureLen := mload(add(add(signatures, s), 0x20))
                          }
                          require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023");
                          // Check signature
                          bytes memory contractSignature;
                          // solhint-disable-next-line no-inline-assembly
                          assembly {
                              // The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s
                              contractSignature := add(add(signatures, s), 0x20)
                          }
                          require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024");
                      } else if (v == 1) {
                          // If v is 1 then it is an approved hash
                          // When handling approved hashes the address of the approver is encoded into r
                          currentOwner = address(uint160(uint256(r)));
                          // Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction
                          require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, "GS025");
                      } else if (v > 30) {
                          // If v > 30 then default va (27,28) has been adjusted for eth_sign flow
                          // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
                          currentOwner = ecrecover(keccak256(abi.encodePacked("\\x19Ethereum Signed Message:\
          32", dataHash)), v - 4, r, s);
                      } else {
                          // Default is the ecrecover flow with the provided data hash
                          // Use ecrecover with the messageHash for EOA signatures
                          currentOwner = ecrecover(dataHash, v, r, s);
                      }
                      require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "GS026");
                      lastOwner = currentOwner;
                  }
              }
              /// @dev Allows to estimate a Safe transaction.
              ///      This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data.
              ///      Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction`
              /// @param to Destination address of Safe transaction.
              /// @param value Ether value of Safe transaction.
              /// @param data Data payload of Safe transaction.
              /// @param operation Operation type of Safe transaction.
              /// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).
              /// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.
              function requiredTxGas(
                  address to,
                  uint256 value,
                  bytes calldata data,
                  Enum.Operation operation
              ) external returns (uint256) {
                  uint256 startGas = gasleft();
                  // We don't provide an error message here, as we use it to return the estimate
                  require(execute(to, value, data, operation, gasleft()));
                  uint256 requiredGas = startGas - gasleft();
                  // Convert response to string and return via error message
                  revert(string(abi.encodePacked(requiredGas)));
              }
              /**
               * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
               * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
               */
              function approveHash(bytes32 hashToApprove) external {
                  require(owners[msg.sender] != address(0), "GS030");
                  approvedHashes[msg.sender][hashToApprove] = 1;
                  emit ApproveHash(hashToApprove, msg.sender);
              }
              /// @dev Returns the chain id used by this contract.
              function getChainId() public view returns (uint256) {
                  uint256 id;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      id := chainid()
                  }
                  return id;
              }
              function domainSeparator() public view returns (bytes32) {
                  return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));
              }
              /// @dev Returns the bytes that are hashed to be signed by owners.
              /// @param to Destination address.
              /// @param value Ether value.
              /// @param data Data payload.
              /// @param operation Operation type.
              /// @param safeTxGas Gas that should be used for the safe transaction.
              /// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
              /// @param gasPrice Maximum gas price that should be used for this transaction.
              /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
              /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
              /// @param _nonce Transaction nonce.
              /// @return Transaction hash bytes.
              function encodeTransactionData(
                  address to,
                  uint256 value,
                  bytes calldata data,
                  Enum.Operation operation,
                  uint256 safeTxGas,
                  uint256 baseGas,
                  uint256 gasPrice,
                  address gasToken,
                  address refundReceiver,
                  uint256 _nonce
              ) public view returns (bytes memory) {
                  bytes32 safeTxHash =
                      keccak256(
                          abi.encode(
                              SAFE_TX_TYPEHASH,
                              to,
                              value,
                              keccak256(data),
                              operation,
                              safeTxGas,
                              baseGas,
                              gasPrice,
                              gasToken,
                              refundReceiver,
                              _nonce
                          )
                      );
                  return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash);
              }
              /// @dev Returns hash to be signed by owners.
              /// @param to Destination address.
              /// @param value Ether value.
              /// @param data Data payload.
              /// @param operation Operation type.
              /// @param safeTxGas Fas that should be used for the safe transaction.
              /// @param baseGas Gas costs for data used to trigger the safe transaction.
              /// @param gasPrice Maximum gas price that should be used for this transaction.
              /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
              /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
              /// @param _nonce Transaction nonce.
              /// @return Transaction hash.
              function getTransactionHash(
                  address to,
                  uint256 value,
                  bytes calldata data,
                  Enum.Operation operation,
                  uint256 safeTxGas,
                  uint256 baseGas,
                  uint256 gasPrice,
                  address gasToken,
                  address refundReceiver,
                  uint256 _nonce
              ) public view returns (bytes32) {
                  return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/Enum.sol";
          /// @title Executor - A contract that can execute transactions
          /// @author Richard Meissner - <[email protected]>
          contract Executor {
              function execute(
                  address to,
                  uint256 value,
                  bytes memory data,
                  Enum.Operation operation,
                  uint256 txGas
              ) internal returns (bool success) {
                  if (operation == Enum.Operation.DelegateCall) {
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
                      }
                  } else {
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
                      }
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/SelfAuthorized.sol";
          /// @title Fallback Manager - A contract that manages fallback calls made to this contract
          /// @author Richard Meissner - <[email protected]>
          contract FallbackManager is SelfAuthorized {
              event ChangedFallbackHandler(address handler);
              // keccak256("fallback_manager.handler.address")
              bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;
              function internalSetFallbackHandler(address handler) internal {
                  bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      sstore(slot, handler)
                  }
              }
              /// @dev Allows to add a contract to handle fallback calls.
              ///      Only fallback calls without value and with data will be forwarded.
              ///      This can only be done via a Safe transaction.
              /// @param handler contract to handle fallbacks calls.
              function setFallbackHandler(address handler) public authorized {
                  internalSetFallbackHandler(handler);
                  emit ChangedFallbackHandler(handler);
              }
              // solhint-disable-next-line payable-fallback,no-complex-fallback
              fallback() external {
                  bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      let handler := sload(slot)
                      if iszero(handler) {
                          return(0, 0)
                      }
                      calldatacopy(0, 0, calldatasize())
                      // The msg.sender address is shifted to the left by 12 bytes to remove the padding
                      // Then the address without padding is stored right after the calldata
                      mstore(calldatasize(), shl(96, caller()))
                      // Add 20 bytes for the address appended add the end
                      let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)
                      returndatacopy(0, 0, returndatasize())
                      if iszero(success) {
                          revert(0, returndatasize())
                      }
                      return(0, returndatasize())
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/Enum.sol";
          import "../common/SelfAuthorized.sol";
          interface Guard {
              function checkTransaction(
                  address to,
                  uint256 value,
                  bytes memory data,
                  Enum.Operation operation,
                  uint256 safeTxGas,
                  uint256 baseGas,
                  uint256 gasPrice,
                  address gasToken,
                  address payable refundReceiver,
                  bytes memory signatures,
                  address msgSender
              ) external;
              function checkAfterExecution(bytes32 txHash, bool success) external;
          }
          /// @title Fallback Manager - A contract that manages fallback calls made to this contract
          /// @author Richard Meissner - <[email protected]>
          contract GuardManager is SelfAuthorized {
              event ChangedGuard(address guard);
              // keccak256("guard_manager.guard.address")
              bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
              /// @dev Set a guard that checks transactions before execution
              /// @param guard The address of the guard to be used or the 0 address to disable the guard
              function setGuard(address guard) external authorized {
                  bytes32 slot = GUARD_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      sstore(slot, guard)
                  }
                  emit ChangedGuard(guard);
              }
              function getGuard() internal view returns (address guard) {
                  bytes32 slot = GUARD_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      guard := sload(slot)
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/Enum.sol";
          import "../common/SelfAuthorized.sol";
          import "./Executor.sol";
          /// @title Module Manager - A contract that manages modules that can execute transactions via this contract
          /// @author Stefan George - <[email protected]>
          /// @author Richard Meissner - <[email protected]>
          contract ModuleManager is SelfAuthorized, Executor {
              event EnabledModule(address module);
              event DisabledModule(address module);
              event ExecutionFromModuleSuccess(address indexed module);
              event ExecutionFromModuleFailure(address indexed module);
              address internal constant SENTINEL_MODULES = address(0x1);
              mapping(address => address) internal modules;
              function setupModules(address to, bytes memory data) internal {
                  require(modules[SENTINEL_MODULES] == address(0), "GS100");
                  modules[SENTINEL_MODULES] = SENTINEL_MODULES;
                  if (to != address(0))
                      // Setup has to complete successfully or transaction fails.
                      require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), "GS000");
              }
              /// @dev Allows to add a module to the whitelist.
              ///      This can only be done via a Safe transaction.
              /// @notice Enables the module `module` for the Safe.
              /// @param module Module to be whitelisted.
              function enableModule(address module) public authorized {
                  // Module address cannot be null or sentinel.
                  require(module != address(0) && module != SENTINEL_MODULES, "GS101");
                  // Module cannot be added twice.
                  require(modules[module] == address(0), "GS102");
                  modules[module] = modules[SENTINEL_MODULES];
                  modules[SENTINEL_MODULES] = module;
                  emit EnabledModule(module);
              }
              /// @dev Allows to remove a module from the whitelist.
              ///      This can only be done via a Safe transaction.
              /// @notice Disables the module `module` for the Safe.
              /// @param prevModule Module that pointed to the module to be removed in the linked list
              /// @param module Module to be removed.
              function disableModule(address prevModule, address module) public authorized {
                  // Validate module address and check that it corresponds to module index.
                  require(module != address(0) && module != SENTINEL_MODULES, "GS101");
                  require(modules[prevModule] == module, "GS103");
                  modules[prevModule] = modules[module];
                  modules[module] = address(0);
                  emit DisabledModule(module);
              }
              /// @dev Allows a Module to execute a Safe transaction without any further confirmations.
              /// @param to Destination address of module transaction.
              /// @param value Ether value of module transaction.
              /// @param data Data payload of module transaction.
              /// @param operation Operation type of module transaction.
              function execTransactionFromModule(
                  address to,
                  uint256 value,
                  bytes memory data,
                  Enum.Operation operation
              ) public virtual returns (bool success) {
                  // Only whitelisted modules are allowed.
                  require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104");
                  // Execute transaction without further confirmations.
                  success = execute(to, value, data, operation, gasleft());
                  if (success) emit ExecutionFromModuleSuccess(msg.sender);
                  else emit ExecutionFromModuleFailure(msg.sender);
              }
              /// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data
              /// @param to Destination address of module transaction.
              /// @param value Ether value of module transaction.
              /// @param data Data payload of module transaction.
              /// @param operation Operation type of module transaction.
              function execTransactionFromModuleReturnData(
                  address to,
                  uint256 value,
                  bytes memory data,
                  Enum.Operation operation
              ) public returns (bool success, bytes memory returnData) {
                  success = execTransactionFromModule(to, value, data, operation);
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      // Load free memory location
                      let ptr := mload(0x40)
                      // We allocate memory for the return data by setting the free memory location to
                      // current free memory location + data size + 32 bytes for data size value
                      mstore(0x40, add(ptr, add(returndatasize(), 0x20)))
                      // Store the size
                      mstore(ptr, returndatasize())
                      // Store the data
                      returndatacopy(add(ptr, 0x20), 0, returndatasize())
                      // Point the return data to the correct memory location
                      returnData := ptr
                  }
              }
              /// @dev Returns if an module is enabled
              /// @return True if the module is enabled
              function isModuleEnabled(address module) public view returns (bool) {
                  return SENTINEL_MODULES != module && modules[module] != address(0);
              }
              /// @dev Returns array of modules.
              /// @param start Start of the page.
              /// @param pageSize Maximum number of modules that should be returned.
              /// @return array Array of modules.
              /// @return next Start of the next page.
              function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) {
                  // Init array with max page size
                  array = new address[](pageSize);
                  // Populate return array
                  uint256 moduleCount = 0;
                  address currentModule = modules[start];
                  while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) {
                      array[moduleCount] = currentModule;
                      currentModule = modules[currentModule];
                      moduleCount++;
                  }
                  next = currentModule;
                  // Set correct size of returned array
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      mstore(array, moduleCount)
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/SelfAuthorized.sol";
          /// @title OwnerManager - Manages a set of owners and a threshold to perform actions.
          /// @author Stefan George - <[email protected]>
          /// @author Richard Meissner - <[email protected]>
          contract OwnerManager is SelfAuthorized {
              event AddedOwner(address owner);
              event RemovedOwner(address owner);
              event ChangedThreshold(uint256 threshold);
              address internal constant SENTINEL_OWNERS = address(0x1);
              mapping(address => address) internal owners;
              uint256 internal ownerCount;
              uint256 internal threshold;
              /// @dev Setup function sets initial storage of contract.
              /// @param _owners List of Safe owners.
              /// @param _threshold Number of required confirmations for a Safe transaction.
              function setupOwners(address[] memory _owners, uint256 _threshold) internal {
                  // Threshold can only be 0 at initialization.
                  // Check ensures that setup function can only be called once.
                  require(threshold == 0, "GS200");
                  // Validate that threshold is smaller than number of added owners.
                  require(_threshold <= _owners.length, "GS201");
                  // There has to be at least one Safe owner.
                  require(_threshold >= 1, "GS202");
                  // Initializing Safe owners.
                  address currentOwner = SENTINEL_OWNERS;
                  for (uint256 i = 0; i < _owners.length; i++) {
                      // Owner address cannot be null.
                      address owner = _owners[i];
                      require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203");
                      // No duplicate owners allowed.
                      require(owners[owner] == address(0), "GS204");
                      owners[currentOwner] = owner;
                      currentOwner = owner;
                  }
                  owners[currentOwner] = SENTINEL_OWNERS;
                  ownerCount = _owners.length;
                  threshold = _threshold;
              }
              /// @dev Allows to add a new owner to the Safe and update the threshold at the same time.
              ///      This can only be done via a Safe transaction.
              /// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
              /// @param owner New owner address.
              /// @param _threshold New threshold.
              function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized {
                  // Owner address cannot be null, the sentinel or the Safe itself.
                  require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "GS203");
                  // No duplicate owners allowed.
                  require(owners[owner] == address(0), "GS204");
                  owners[owner] = owners[SENTINEL_OWNERS];
                  owners[SENTINEL_OWNERS] = owner;
                  ownerCount++;
                  emit AddedOwner(owner);
                  // Change threshold if threshold was changed.
                  if (threshold != _threshold) changeThreshold(_threshold);
              }
              /// @dev Allows to remove an owner from the Safe and update the threshold at the same time.
              ///      This can only be done via a Safe transaction.
              /// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
              /// @param prevOwner Owner that pointed to the owner to be removed in the linked list
              /// @param owner Owner address to be removed.
              /// @param _threshold New threshold.
              function removeOwner(
                  address prevOwner,
                  address owner,
                  uint256 _threshold
              ) public authorized {
                  // Only allow to remove an owner, if threshold can still be reached.
                  require(ownerCount - 1 >= _threshold, "GS201");
                  // Validate owner address and check that it corresponds to owner index.
                  require(owner != address(0) && owner != SENTINEL_OWNERS, "GS203");
                  require(owners[prevOwner] == owner, "GS205");
                  owners[prevOwner] = owners[owner];
                  owners[owner] = address(0);
                  ownerCount--;
                  emit RemovedOwner(owner);
                  // Change threshold if threshold was changed.
                  if (threshold != _threshold) changeThreshold(_threshold);
              }
              /// @dev Allows to swap/replace an owner from the Safe with another address.
              ///      This can only be done via a Safe transaction.
              /// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
              /// @param prevOwner Owner that pointed to the owner to be replaced in the linked list
              /// @param oldOwner Owner address to be replaced.
              /// @param newOwner New owner address.
              function swapOwner(
                  address prevOwner,
                  address oldOwner,
                  address newOwner
              ) public authorized {
                  // Owner address cannot be null, the sentinel or the Safe itself.
                  require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "GS203");
                  // No duplicate owners allowed.
                  require(owners[newOwner] == address(0), "GS204");
                  // Validate oldOwner address and check that it corresponds to owner index.
                  require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "GS203");
                  require(owners[prevOwner] == oldOwner, "GS205");
                  owners[newOwner] = owners[oldOwner];
                  owners[prevOwner] = newOwner;
                  owners[oldOwner] = address(0);
                  emit RemovedOwner(oldOwner);
                  emit AddedOwner(newOwner);
              }
              /// @dev Allows to update the number of required confirmations by Safe owners.
              ///      This can only be done via a Safe transaction.
              /// @notice Changes the threshold of the Safe to `_threshold`.
              /// @param _threshold New threshold.
              function changeThreshold(uint256 _threshold) public authorized {
                  // Validate that threshold is smaller than number of owners.
                  require(_threshold <= ownerCount, "GS201");
                  // There has to be at least one Safe owner.
                  require(_threshold >= 1, "GS202");
                  threshold = _threshold;
                  emit ChangedThreshold(threshold);
              }
              function getThreshold() public view returns (uint256) {
                  return threshold;
              }
              function isOwner(address owner) public view returns (bool) {
                  return owner != SENTINEL_OWNERS && owners[owner] != address(0);
              }
              /// @dev Returns array of owners.
              /// @return Array of Safe owners.
              function getOwners() public view returns (address[] memory) {
                  address[] memory array = new address[](ownerCount);
                  // populate return array
                  uint256 index = 0;
                  address currentOwner = owners[SENTINEL_OWNERS];
                  while (currentOwner != SENTINEL_OWNERS) {
                      array[index] = currentOwner;
                      currentOwner = owners[currentOwner];
                      index++;
                  }
                  return array;
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title Enum - Collection of enums
          /// @author Richard Meissner - <[email protected]>
          contract Enum {
              enum Operation {Call, DelegateCall}
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments
          /// @author Richard Meissner - <[email protected]>
          contract EtherPaymentFallback {
              event SafeReceived(address indexed sender, uint256 value);
              /// @dev Fallback function accepts Ether transactions.
              receive() external payable {
                  emit SafeReceived(msg.sender, msg.value);
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title SecuredTokenTransfer - Secure token transfer
          /// @author Richard Meissner - <[email protected]>
          contract SecuredTokenTransfer {
              /// @dev Transfers a token and returns if it was a success
              /// @param token Token that should be transferred
              /// @param receiver Receiver to whom the token should be transferred
              /// @param amount The amount of tokens that should be transferred
              function transferToken(
                  address token,
                  address receiver,
                  uint256 amount
              ) internal returns (bool transferred) {
                  // 0xa9059cbb - keccack("transfer(address,uint256)")
                  bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      // We write the return value to scratch space.
                      // See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory
                      let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)
                      switch returndatasize()
                          case 0 {
                              transferred := success
                          }
                          case 0x20 {
                              transferred := iszero(or(iszero(success), iszero(mload(0))))
                          }
                          default {
                              transferred := 0
                          }
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title SelfAuthorized - authorizes current contract to perform actions
          /// @author Richard Meissner - <[email protected]>
          contract SelfAuthorized {
              function requireSelfCall() private view {
                  require(msg.sender == address(this), "GS031");
              }
              modifier authorized() {
                  // This is a function call as it minimized the bytecode size
                  requireSelfCall();
                  _;
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title SignatureDecoder - Decodes signatures that a encoded as bytes
          /// @author Richard Meissner - <[email protected]>
          contract SignatureDecoder {
              /// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.
              /// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures
              /// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
              /// @param signatures concatenated rsv signatures
              function signatureSplit(bytes memory signatures, uint256 pos)
                  internal
                  pure
                  returns (
                      uint8 v,
                      bytes32 r,
                      bytes32 s
                  )
              {
                  // The signature format is a compact form of:
                  //   {bytes32 r}{bytes32 s}{uint8 v}
                  // Compact means, uint8 is not padded to 32 bytes.
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      let signaturePos := mul(0x41, pos)
                      r := mload(add(signatures, add(signaturePos, 0x20)))
                      s := mload(add(signatures, add(signaturePos, 0x40)))
                      // Here we are loading the last 32 bytes, including 31 bytes
                      // of 's'. There is no 'mload8' to do this.
                      //
                      // 'byte' is not working due to the Solidity parser, so lets
                      // use the second best option, 'and'
                      v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title Singleton - Base for singleton contracts (should always be first super contract)
          ///         This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`)
          /// @author Richard Meissner - <[email protected]>
          contract Singleton {
              // singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.
              // It should also always be ensured that the address is stored alone (uses a full word)
              address private singleton;
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
          /// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
          contract StorageAccessible {
              /**
               * @dev Reads `length` bytes of storage in the currents contract
               * @param offset - the offset in the current contract's storage in words to start reading from
               * @param length - the number of words (32 bytes) of data to read
               * @return the bytes that were read.
               */
              function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
                  bytes memory result = new bytes(length * 32);
                  for (uint256 index = 0; index < length; index++) {
                      // solhint-disable-next-line no-inline-assembly
                      assembly {
                          let word := sload(add(offset, index))
                          mstore(add(add(result, 0x20), mul(index, 0x20)), word)
                      }
                  }
                  return result;
              }
              /**
               * @dev Performs a delegetecall on a targetContract in the context of self.
               * Internally reverts execution to avoid side effects (making it static).
               *
               * This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
               * Specifically, the `returndata` after a call to this method will be:
               * `success:bool || response.length:uint256 || response:bytes`.
               *
               * @param targetContract Address of the contract containing the code to execute.
               * @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
               */
              function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)
                      mstore(0x00, success)
                      mstore(0x20, returndatasize())
                      returndatacopy(0x40, 0, returndatasize())
                      revert(0, add(returndatasize(), 0x40))
                  }
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /**
           * @title GnosisSafeMath
           * @dev Math operations with safety checks that revert on error
           * Renamed from SafeMath to GnosisSafeMath to avoid conflicts
           * TODO: remove once open zeppelin update to solc 0.5.0
           */
          library GnosisSafeMath {
              /**
               * @dev Multiplies two numbers, reverts on overflow.
               */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
                  uint256 c = a * b;
                  require(c / a == b);
                  return c;
              }
              /**
               * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
                  return c;
              }
              /**
               * @dev Adds two numbers, reverts on overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
                  return c;
              }
              /**
               * @dev Returns the largest of two numbers.
               */
              function max(uint256 a, uint256 b) internal pure returns (uint256) {
                  return a >= b ? a : b;
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          contract ISignatureValidatorConstants {
              // bytes4(keccak256("isValidSignature(bytes,bytes)")
              bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
          }
          abstract contract ISignatureValidator is ISignatureValidatorConstants {
              /**
               * @dev Should return whether the signature provided is valid for the provided data
               * @param _data Arbitrary length data signed on the behalf of address(this)
               * @param _signature Signature byte array associated with _data
               *
               * MUST return the bytes4 magic value 0x20c13b0b when function passes.
               * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
               * MUST allow external calls
               */
              function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);
          }