ETH Price: $2,416.35 (-3.76%)

Transaction Decoder

Block:
20370052 at Jul-23-2024 03:12:59 PM +UTC
Transaction Fee:
0.001801370274127743 ETH $4.35
Gas Used:
299,687 Gas / 6.010838889 Gwei

Emitted Events:

265 TransparentUpgradeableProxy.0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c( 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c, 0x000000000000000000000000a3965c175f83d0c1515f97cd55b08dac6ea3a9df, 0000000000000000000000000000000000000000000015908a6631bf77b00000 )
266 Token.Transfer( from=[Receiver] TransparentUpgradeableProxy, to=TransparentUpgradeableProxy, value=101836000000000000000000 )
267 Token.Approval( owner=[Receiver] TransparentUpgradeableProxy, spender=TransparentUpgradeableProxy, value=115792089237316195423570985008687907853269984665633378801984584007913129639935 )
268 TransparentUpgradeableProxy.0x6f225532a9c33b023b8e48247ad8df9d98f132ae17c769b97ff22d2b278fa73a( 0x6f225532a9c33b023b8e48247ad8df9d98f132ae17c769b97ff22d2b278fa73a, 0x000000000000000000000000a3965c175f83d0c1515f97cd55b08dac6ea3a9df, 0x0000000000000000000000000000000000000000000000000000000000018dcc, 0x0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000004c0b04d4e1f418, 00000000000000000000000000000000000000000000000407adbac9cf138000, 00000000000000000000000000000000000000000000000000000000669fc87b )
269 GnosisSafeProxy.0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d( 0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d, 0x00000000000000000000000059ac6a6944e078b780d14fe6d92dcc1ca9257bf0, 000000000000000000000000000000000000000000000000004900568eed6535 )

Account State Difference:

  Address   Before After State Difference Code
3.836711457856141997 Eth3.836736581322215821 Eth0.000025123466073824
0x59ac6a69...CA9257bf0
0x5f9772c0...F98bBE058
0x8E6692AC...64228eB9c 204.663616642849710091 Eth204.684164687914698048 Eth0.020548045064987957
0xA3965C17...C6ea3A9Df
0.0368985112062205 Eth
Nonce: 21
0.013692927322730301 Eth
Nonce: 22
0.023205583883490199
0xe876b198...D4C239153 57.886904617073084149 Eth57.887760785617458648 Eth0.000856168544374499
0xFE8526A7...BEA21FBFF

Execution Trace

ETH 0.02189 TransparentUpgradeableProxy.2c65169e( )
  • ETH 0.02189 PresaleV1.buyWithEth( amount=101836, stake=True ) => ( True )
    • EACAggregatorProxy.STATICCALL( )
      • AccessControlledOffchainAggregator.STATICCALL( )
      • TransparentUpgradeableProxy.91c61966( )
        • stakingManager.depositByPresale( _user=0xA3965C175F83d0c1515F97CD55B08daC6ea3A9Df, _amount=101836000000000000000000 )
          • Token.transferFrom( sender=0x59ac6a6944e078B780d14fE6D92Dcc1CA9257bf0, recipient=0x5f9772c051BBeb27f1CB2a1A59D21BfF98bBE058, amount=101836000000000000000000 ) => ( True )
          • ETH 0.020548045064987957 GnosisSafeProxy.CALL( )
            • ETH 0.020548045064987957 GnosisSafe.DELEGATECALL( )
            • ETH 0.000856168544374498 0xe876b198e91c77069ffcd49a174a155d4c239153.CALL( )
            • ETH 0.000000000000000001 0xe876b198e91c77069ffcd49a174a155d4c239153.CALL( )
            • ETH 0.000485786390637544 0xa3965c175f83d0c1515f97cd55b08dac6ea3a9df.CALL( )
              File 1 of 9: TransparentUpgradeableProxy
              // SPDX-License-Identifier: MIT
              pragma solidity ^0.8.0;
              import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
              import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
              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 "./IBeacon.sol";
              import "../Proxy.sol";
              import "../ERC1967/ERC1967Upgrade.sol";
              /**
               * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
               *
               * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
               * conflict with the storage layout of the implementation behind the proxy.
               *
               * _Available since v3.4._
               */
              contract BeaconProxy is Proxy, ERC1967Upgrade {
                  /**
                   * @dev Initializes the proxy with `beacon`.
                   *
                   * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
                   * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
                   * constructor.
                   *
                   * Requirements:
                   *
                   * - `beacon` must be a contract with the interface {IBeacon}.
                   */
                  constructor(address beacon, bytes memory data) payable {
                      assert(_BEACON_SLOT == bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1));
                      _upgradeBeaconToAndCall(beacon, data, false);
                  }
                  /**
                   * @dev Returns the current beacon address.
                   */
                  function _beacon() internal view virtual returns (address) {
                      return _getBeacon();
                  }
                  /**
                   * @dev Returns the current implementation address of the associated beacon.
                   */
                  function _implementation() internal view virtual override returns (address) {
                      return IBeacon(_getBeacon()).implementation();
                  }
                  /**
                   * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
                   *
                   * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
                   *
                   * Requirements:
                   *
                   * - `beacon` must be a contract.
                   * - The implementation returned by `beacon` must be a contract.
                   */
                  function _setBeacon(address beacon, bytes memory data) internal virtual {
                      _upgradeBeaconToAndCall(beacon, data, false);
                  }
              }
              // SPDX-License-Identifier: MIT
              pragma solidity ^0.8.0;
              import "./IBeacon.sol";
              import "../../access/Ownable.sol";
              import "../../utils/Address.sol";
              /**
               * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
               * implementation contract, which is where they will delegate all function calls.
               *
               * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
               */
              contract UpgradeableBeacon is IBeacon, Ownable {
                  address private _implementation;
                  /**
                   * @dev Emitted when the implementation returned by the beacon is changed.
                   */
                  event Upgraded(address indexed implementation);
                  /**
                   * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
                   * beacon.
                   */
                  constructor(address implementation_) {
                      _setImplementation(implementation_);
                  }
                  /**
                   * @dev Returns the current implementation address.
                   */
                  function implementation() public view virtual override returns (address) {
                      return _implementation;
                  }
                  /**
                   * @dev Upgrades the beacon to a new implementation.
                   *
                   * Emits an {Upgraded} event.
                   *
                   * Requirements:
                   *
                   * - msg.sender must be the owner of the contract.
                   * - `newImplementation` must be a contract.
                   */
                  function upgradeTo(address newImplementation) public virtual onlyOwner {
                      _setImplementation(newImplementation);
                      emit Upgraded(newImplementation);
                  }
                  /**
                   * @dev Sets the implementation contract address for this beacon
                   *
                   * Requirements:
                   *
                   * - `newImplementation` must be a contract.
                   */
                  function _setImplementation(address newImplementation) private {
                      require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
                      _implementation = newImplementation;
                  }
              }
              // 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 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 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 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;
                  }
              }
              

              File 2 of 9: TransparentUpgradeableProxy
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
              pragma solidity ^0.8.0;
              import "../utils/Context.sol";
              /**
               * @dev Contract module which provides a basic access control mechanism, where
               * there is an account (an owner) that can be granted exclusive access to
               * specific functions.
               *
               * By default, the owner account will be the one that deploys the contract. This
               * can later be changed with {transferOwnership}.
               *
               * This module is used through inheritance. It will make available the modifier
               * `onlyOwner`, which can be applied to your functions to restrict their use to
               * the owner.
               */
              abstract contract Ownable is Context {
                  address private _owner;
                  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                  /**
                   * @dev Initializes the contract setting the deployer as the initial owner.
                   */
                  constructor() {
                      _transferOwnership(_msgSender());
                  }
                  /**
                   * @dev 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);
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
              pragma solidity ^0.8.0;
              /**
               * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
               * proxy whose upgrades are fully controlled by the current implementation.
               */
              interface IERC1822Proxiable {
                  /**
                   * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                   * address.
                   *
                   * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                   * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                   * function revert if invoked through a proxy.
                   */
                  function proxiableUUID() external view returns (bytes32);
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol)
              pragma solidity ^0.8.0;
              /**
               * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
               *
               * _Available since v4.9._
               */
              interface IERC1967 {
                  /**
                   * @dev Emitted when the implementation is upgraded.
                   */
                  event Upgraded(address indexed implementation);
                  /**
                   * @dev Emitted when the admin account has changed.
                   */
                  event AdminChanged(address previousAdmin, address newAdmin);
                  /**
                   * @dev Emitted when the beacon is changed.
                   */
                  event BeaconUpgraded(address indexed beacon);
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)
              pragma solidity ^0.8.0;
              import "./IBeacon.sol";
              import "../Proxy.sol";
              import "../ERC1967/ERC1967Upgrade.sol";
              /**
               * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
               *
               * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
               * conflict with the storage layout of the implementation behind the proxy.
               *
               * _Available since v3.4._
               */
              contract BeaconProxy is Proxy, ERC1967Upgrade {
                  /**
                   * @dev Initializes the proxy with `beacon`.
                   *
                   * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
                   * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
                   * constructor.
                   *
                   * Requirements:
                   *
                   * - `beacon` must be a contract with the interface {IBeacon}.
                   */
                  constructor(address beacon, bytes memory data) payable {
                      _upgradeBeaconToAndCall(beacon, data, false);
                  }
                  /**
                   * @dev Returns the current beacon address.
                   */
                  function _beacon() internal view virtual returns (address) {
                      return _getBeacon();
                  }
                  /**
                   * @dev Returns the current implementation address of the associated beacon.
                   */
                  function _implementation() internal view virtual override returns (address) {
                      return IBeacon(_getBeacon()).implementation();
                  }
                  /**
                   * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
                   *
                   * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
                   *
                   * Requirements:
                   *
                   * - `beacon` must be a contract.
                   * - The implementation returned by `beacon` must be a contract.
                   */
                  function _setBeacon(address beacon, bytes memory data) internal virtual {
                      _upgradeBeaconToAndCall(beacon, data, false);
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
              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
              // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)
              pragma solidity ^0.8.0;
              import "./IBeacon.sol";
              import "../../access/Ownable.sol";
              import "../../utils/Address.sol";
              /**
               * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
               * implementation contract, which is where they will delegate all function calls.
               *
               * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
               */
              contract UpgradeableBeacon is IBeacon, Ownable {
                  address private _implementation;
                  /**
                   * @dev Emitted when the implementation returned by the beacon is changed.
                   */
                  event Upgraded(address indexed implementation);
                  /**
                   * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
                   * beacon.
                   */
                  constructor(address implementation_) {
                      _setImplementation(implementation_);
                  }
                  /**
                   * @dev Returns the current implementation address.
                   */
                  function implementation() public view virtual override returns (address) {
                      return _implementation;
                  }
                  /**
                   * @dev Upgrades the beacon to a new implementation.
                   *
                   * Emits an {Upgraded} event.
                   *
                   * Requirements:
                   *
                   * - msg.sender must be the owner of the contract.
                   * - `newImplementation` must be a contract.
                   */
                  function upgradeTo(address newImplementation) public virtual onlyOwner {
                      _setImplementation(newImplementation);
                      emit Upgraded(newImplementation);
                  }
                  /**
                   * @dev Sets the implementation contract address for this beacon
                   *
                   * Requirements:
                   *
                   * - `newImplementation` must be a contract.
                   */
                  function _setImplementation(address newImplementation) private {
                      require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
                      _implementation = newImplementation;
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
              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 initializing the storage of the proxy like a Solidity constructor.
                   */
                  constructor(address _logic, bytes memory _data) payable {
                      _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
              // OpenZeppelin Contracts (last updated v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol)
              pragma solidity ^0.8.2;
              import "../beacon/IBeacon.sol";
              import "../../interfaces/IERC1967.sol";
              import "../../interfaces/draft-IERC1822.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 is IERC1967 {
                  // 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 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 {
                      _upgradeTo(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 _upgradeToAndCallUUPS(
                      address newImplementation,
                      bytes memory data,
                      bool forceCall
                  ) internal {
                      // Upgrades from old implementations will perform a rollback test. This test requires the new
                      // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                      // this special case will break upgrade paths from old UUPS implementation to new ones.
                      if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                          _setImplementation(newImplementation);
                      } else {
                          try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                              require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                          } catch {
                              revert("ERC1967Upgrade: new implementation is not UUPS");
                          }
                          _upgradeToAndCall(newImplementation, data, forceCall);
                      }
                  }
                  /**
                   * @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 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 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;
                  }
                  /**
                   * @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);
                      }
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
              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 internal call site, it will return directly to the external caller.
                   */
                  function _delegate(address implementation) internal virtual {
                      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 overridden 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 internal 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 overridden should call `super._beforeFallback()`.
                   */
                  function _beforeFallback() internal virtual {}
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)
              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(ITransparentUpgradeableProxy 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(ITransparentUpgradeableProxy 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(ITransparentUpgradeableProxy 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(ITransparentUpgradeableProxy 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(
                      ITransparentUpgradeableProxy proxy,
                      address implementation,
                      bytes memory data
                  ) public payable virtual onlyOwner {
                      proxy.upgradeToAndCall{value: msg.value}(implementation, data);
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/TransparentUpgradeableProxy.sol)
              pragma solidity ^0.8.0;
              import "../ERC1967/ERC1967Proxy.sol";
              /**
               * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
               * does not implement this interface directly, and some of its functions are implemented by an internal dispatch
               * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
               * include them in the ABI so this interface must be used to interact with it.
               */
              interface ITransparentUpgradeableProxy is IERC1967 {
                  function admin() external view returns (address);
                  function implementation() external view returns (address);
                  function changeAdmin(address) external;
                  function upgradeTo(address) external;
                  function upgradeToAndCall(address, bytes memory) external payable;
              }
              /**
               * @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.
               *
               * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
               * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch
               * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
               * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
               * implementation.
               *
               * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler
               * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function
               * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could
               * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.
               */
              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) {
                      _changeAdmin(admin_);
                  }
                  /**
                   * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                   *
                   * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the
                   * implementation provides a function with the same selector.
                   */
                  modifier ifAdmin() {
                      if (msg.sender == _getAdmin()) {
                          _;
                      } else {
                          _fallback();
                      }
                  }
                  /**
                   * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior
                   */
                  function _fallback() internal virtual override {
                      if (msg.sender == _getAdmin()) {
                          bytes memory ret;
                          bytes4 selector = msg.sig;
                          if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {
                              ret = _dispatchUpgradeTo();
                          } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                              ret = _dispatchUpgradeToAndCall();
                          } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {
                              ret = _dispatchChangeAdmin();
                          } else if (selector == ITransparentUpgradeableProxy.admin.selector) {
                              ret = _dispatchAdmin();
                          } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {
                              ret = _dispatchImplementation();
                          } else {
                              revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                          }
                          assembly {
                              return(add(ret, 0x20), mload(ret))
                          }
                      } else {
                          super._fallback();
                      }
                  }
                  /**
                   * @dev Returns the current admin.
                   *
                   * 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 _dispatchAdmin() private returns (bytes memory) {
                      _requireZeroValue();
                      address admin = _getAdmin();
                      return abi.encode(admin);
                  }
                  /**
                   * @dev Returns the current implementation.
                   *
                   * 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 _dispatchImplementation() private returns (bytes memory) {
                      _requireZeroValue();
                      address implementation = _implementation();
                      return abi.encode(implementation);
                  }
                  /**
                   * @dev Changes the admin of the proxy.
                   *
                   * Emits an {AdminChanged} event.
                   */
                  function _dispatchChangeAdmin() private returns (bytes memory) {
                      _requireZeroValue();
                      address newAdmin = abi.decode(msg.data[4:], (address));
                      _changeAdmin(newAdmin);
                      return "";
                  }
                  /**
                   * @dev Upgrade the implementation of the proxy.
                   */
                  function _dispatchUpgradeTo() private returns (bytes memory) {
                      _requireZeroValue();
                      address newImplementation = abi.decode(msg.data[4:], (address));
                      _upgradeToAndCall(newImplementation, bytes(""), false);
                      return "";
                  }
                  /**
                   * @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.
                   */
                  function _dispatchUpgradeToAndCall() private returns (bytes memory) {
                      (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
                      _upgradeToAndCall(newImplementation, data, true);
                      return "";
                  }
                  /**
                   * @dev Returns the current admin.
                   */
                  function _admin() internal view virtual returns (address) {
                      return _getAdmin();
                  }
                  /**
                   * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to
                   * emulate some proxy functions being non-payable while still allowing value to pass through.
                   */
                  function _requireZeroValue() private {
                      require(msg.value == 0);
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
              pragma solidity ^0.8.1;
              /**
               * @dev Collection of functions related to the address type
               */
              library Address {
                  /**
                   * @dev Returns true if `account` is a contract.
                   *
                   * [IMPORTANT]
                   * ====
                   * It is unsafe to assume that an address for which this function returns
                   * false is an externally-owned account (EOA) and not a contract.
                   *
                   * Among others, `isContract` will return false for the following
                   * types of addresses:
                   *
                   *  - an externally-owned account
                   *  - a contract in construction
                   *  - an address where a contract will be created
                   *  - an address where a contract lived, but was destroyed
                   * ====
                   *
                   * [IMPORTANT]
                   * ====
                   * You shouldn't rely on `isContract` to protect against flash loan attacks!
                   *
                   * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                   * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                   * constructor.
                   * ====
                   */
                  function isContract(address account) internal view returns (bool) {
                      // This method relies on extcodesize/address.code.length, which returns 0
                      // for contracts in construction, since the code is only stored at the end
                      // of the constructor execution.
                      return account.code.length > 0;
                  }
                  /**
                   * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                   * `recipient`, forwarding all available gas and reverting on errors.
                   *
                   * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                   * of certain opcodes, possibly making contracts go over the 2300 gas limit
                   * imposed by `transfer`, making them unable to receive funds via
                   * `transfer`. {sendValue} removes this limitation.
                   *
                   * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                   *
                   * IMPORTANT: because control is transferred to `recipient`, care must be
                   * taken to not create reentrancy vulnerabilities. Consider using
                   * {ReentrancyGuard} or the
                   * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                   */
                  function sendValue(address payable recipient, uint256 amount) internal {
                      require(address(this).balance >= amount, "Address: insufficient balance");
                      (bool success, ) = recipient.call{value: amount}("");
                      require(success, "Address: unable to send value, recipient may have reverted");
                  }
                  /**
                   * @dev Performs a Solidity function call using a low level `call`. A
                   * plain `call` is an unsafe replacement for a function call: use this
                   * function instead.
                   *
                   * If `target` reverts with a revert reason, it is bubbled up by this
                   * function (like regular Solidity function calls).
                   *
                   * Returns the raw returned data. To convert to the expected return value,
                   * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                   *
                   * Requirements:
                   *
                   * - `target` must be a contract.
                   * - calling `target` with `data` must not revert.
                   *
                   * _Available since v3.1._
                   */
                  function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                      return functionCallWithValue(target, data, 0, "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");
                      (bool success, bytes memory returndata) = target.call{value: value}(data);
                      return verifyCallResultFromTarget(target, 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) {
                      (bool success, bytes memory returndata) = target.staticcall(data);
                      return verifyCallResultFromTarget(target, 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) {
                      (bool success, bytes memory returndata) = target.delegatecall(data);
                      return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                  }
                  /**
                   * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                   * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                   *
                   * _Available since v4.8._
                   */
                  function verifyCallResultFromTarget(
                      address target,
                      bool success,
                      bytes memory returndata,
                      string memory errorMessage
                  ) internal view returns (bytes memory) {
                      if (success) {
                          if (returndata.length == 0) {
                              // only check isContract if the call was successful and the return data is empty
                              // otherwise we already know that it was a contract
                              require(isContract(target), "Address: call to non-contract");
                          }
                          return returndata;
                      } else {
                          _revert(returndata, errorMessage);
                      }
                  }
                  /**
                   * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                   * revert reason or 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 {
                          _revert(returndata, errorMessage);
                      }
                  }
                  function _revert(bytes memory returndata, string memory errorMessage) private pure {
                      // 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 v4.4.1 (utils/Context.sol)
              pragma solidity ^0.8.0;
              /**
               * @dev Provides information about the current execution context, including the
               * sender of the transaction and its data. While these are generally available
               * via msg.sender and msg.data, they should not be accessed in such a direct
               * manner, since when dealing with meta-transactions the account sending and
               * paying for execution may not be the actual sender (as far as an application
               * is concerned).
               *
               * This contract is only required for intermediate, library-like contracts.
               */
              abstract contract Context {
                  function _msgSender() internal view virtual returns (address) {
                      return msg.sender;
                  }
                  function _msgData() internal view virtual returns (bytes calldata) {
                      return msg.data;
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
              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) {
                      /// @solidity memory-safe-assembly
                      assembly {
                          r.slot := slot
                      }
                  }
                  /**
                   * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                   */
                  function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                      /// @solidity memory-safe-assembly
                      assembly {
                          r.slot := slot
                      }
                  }
                  /**
                   * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                   */
                  function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                      /// @solidity memory-safe-assembly
                      assembly {
                          r.slot := slot
                      }
                  }
                  /**
                   * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                   */
                  function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                      /// @solidity memory-safe-assembly
                      assembly {
                          r.slot := slot
                      }
                  }
              }
              

              File 3 of 9: Token
              // SPDX-License-Identifier: MIT
              pragma solidity 0.8.9;
              /**
               * @dev Interface of the ERC20 standard as defined in the EIP.
               */
              interface IERC20 {
                /**
                 * @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);
              }
              /**
               * @dev Interface for the optional metadata functions from the ERC20 standard.
               *
               * _Available since v4.1._
               */
              interface IERC20Metadata is IERC20 {
                /**
                 * @dev Returns the name of the token.
                 */
                function name() external view returns (string memory);
                /**
                 * @dev Returns the symbol of the token.
                 */
                function symbol() external view returns (string memory);
                /**
                 * @dev Returns the decimals places of the token.
                 */
                function decimals() external view returns (uint8);
              }
              /**
               * @dev Provides information about the current execution context, including the
               * sender of the transaction and its data. While these are generally available
               * via msg.sender and msg.data, they should not be accessed in such a direct
               * manner, since when dealing with meta-transactions the account sending and
               * paying for execution may not be the actual sender (as far as an application
               * is concerned).
               *
               * This contract is only required for intermediate, library-like contracts.
               */
              abstract contract Context {
                function _msgSender() internal view virtual returns (address) {
                  return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes calldata) {
                  return msg.data;
                }
              }
              /**
               * @dev Contract module which provides a basic access control mechanism, where
               * there is an account (an owner) that can be granted exclusive access to
               * specific functions.
               *
               * By default, the owner account will be the one that deploys the contract. This
               * can later be changed with {transferOwnership}.
               *
               * This module is used through inheritance. It will make available the modifier
               * `onlyOwner`, which can be applied to your functions to restrict their use to
               * the owner.
               */
              abstract contract Ownable is Context {
                address private _owner;
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Initializes the contract setting the deployer as the initial owner.
                 */
                constructor() {
                  _transferOwnership(_msgSender());
                }
                /**
                 * @dev 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. Can only be called by the current owner.
                 *
                 * NOTE: Renouncing ownership will leave the contract without an owner,
                 * thereby disabling 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);
                }
              }
              contract Token is Context, IERC20Metadata, Ownable {
                mapping(address => uint256) private _balances;
                mapping(address => mapping(address => uint256)) private _allowances;
                uint256 private _totalSupply;
                string private _name;
                string private _symbol;
                uint8 private constant _decimals = 18;
                uint256 public constant presaleReserve = 20_700_000_000 * (10 ** _decimals);
                uint256 public constant stakingReserve = 13_800_000_000 * (10 ** _decimals);
                uint256 public constant marketingReserve = 13_800_000_000 * (10 ** _decimals);
                uint256 public constant communityRewardsReserve = 13_800_000_000 * (10 ** _decimals);
                uint256 public constant liquidityReserve = 6_900_000_000 * (10 ** _decimals);
                /**
                 * @dev Contract constructor.
                 */
                constructor() {
                  _name = 'Wiener AI';
                  _symbol = 'WAI';
                  _mint(0x8757b3EA8C2e67c493382f11F944f70Da3bB4575, presaleReserve);
                  _mint(0xDC63c3f515bde020cf42e9a6508f53Cc731A9038, stakingReserve);
                  _mint(0xEcf65CEF5eD53914711ce24B7493ECB1Bab25686, marketingReserve);
                  _mint(0x69040979199B1750F2CFf39a4A8Eb22fb0C111d3, communityRewardsReserve);
                  _mint(0xCdC2837AFD4dDE6f0bE5faD757F8335d06E4b36C, liquidityReserve);
                }
                /**
                 * @dev Returns the name of the token.
                 * @return The name of the token.
                 */
                function name() public view virtual override returns (string memory) {
                  return _name;
                }
                /**
                 * @dev Returns the symbol of the token.
                 * @return The symbol of the token.
                 */
                function symbol() public view virtual override returns (string memory) {
                  return _symbol;
                }
                /**
                 * @dev Returns the number of decimals used for token display.
                 * @return The number of decimals.
                 */
                function decimals() public view virtual override returns (uint8) {
                  return _decimals;
                }
                /**
                 * @dev Returns the total supply of the token.
                 * @return The total supply.
                 */
                function totalSupply() public view virtual override returns (uint256) {
                  return _totalSupply;
                }
                /**
                 * @dev Returns the balance of the specified account.
                 * @param account The address to check the balance for.
                 * @return The balance of the account.
                 */
                function balanceOf(address account) public view virtual override returns (uint256) {
                  return _balances[account];
                }
                /**
                 * @dev Transfers tokens from the caller to a specified recipient.
                 * @param recipient The address to transfer tokens to.
                 * @param amount The amount of tokens to transfer.
                 * @return A boolean value indicating whether the transfer was successful.
                 */
                function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(_msgSender(), recipient, amount);
                  return true;
                }
                /**
                 * @dev Returns the amount of tokens that the spender is allowed to spend on behalf of the owner.
                 * @param from The address that approves the spending.
                 * @param to The address that is allowed to spend.
                 * @return The remaining allowance for the spender.
                 */
                function allowance(address from, address to) public view virtual override returns (uint256) {
                  return _allowances[from][to];
                }
                /**
                 * @dev Approves the specified address to spend the specified amount of tokens on behalf of the caller.
                 * @param to The address to approve the spending for.
                 * @param amount The amount of tokens to approve.
                 * @return A boolean value indicating whether the approval was successful.
                 */
                function approve(address to, uint256 amount) public virtual override returns (bool) {
                  _approve(_msgSender(), to, amount);
                  return true;
                }
                /**
                 * @dev Transfers tokens from one address to another.
                 * @param sender The address to transfer tokens from.
                 * @param recipient The address to transfer tokens to.
                 * @param amount The amount of tokens to transfer.
                 * @return A boolean value indicating whether the transfer was successful.
                 */
                function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
                  _transfer(sender, recipient, amount);
                  uint256 currentAllowance = _allowances[sender][_msgSender()];
                  require(currentAllowance >= amount, 'ERC20: transfer amount exceeds allowance');
                  unchecked {
                    _approve(sender, _msgSender(), currentAllowance - amount);
                  }
                  return true;
                }
                /**
                 * @dev Increases the allowance of the specified address to spend tokens on behalf of the caller.
                 * @param to The address to increase the allowance for.
                 * @param addedValue The amount of tokens to increase the allowance by.
                 * @return A boolean value indicating whether the increase was successful.
                 */
                function increaseAllowance(address to, uint256 addedValue) public virtual returns (bool) {
                  _approve(_msgSender(), to, _allowances[_msgSender()][to] + addedValue);
                  return true;
                }
                /**
                 * @dev Decreases the allowance granted by the owner of the tokens to `to` account.
                 * @param to The account allowed to spend the tokens.
                 * @param subtractedValue The amount of tokens to decrease the allowance by.
                 * @return A boolean value indicating whether the operation succeeded.
                 */
                function decreaseAllowance(address to, uint256 subtractedValue) public virtual returns (bool) {
                  uint256 currentAllowance = _allowances[_msgSender()][to];
                  require(currentAllowance >= subtractedValue, 'ERC20: decreased allowance below zero');
                  unchecked {
                    _approve(_msgSender(), to, currentAllowance - subtractedValue);
                  }
                  return true;
                }
                /**
                 * @dev Transfers `amount` tokens from `sender` to `recipient`.
                 * @param sender The account to transfer tokens from.
                 * @param recipient The account to transfer tokens to.
                 * @param amount The amount of tokens to transfer.
                 */
                function _transfer(address sender, address recipient, uint256 amount) internal virtual {
                  require(amount > 0, 'ERC20: transfer amount zero');
                  require(sender != address(0), 'ERC20: transfer from the zero address');
                  require(recipient != address(0), 'ERC20: transfer to the zero address');
                  uint256 senderBalance = _balances[sender];
                  require(senderBalance >= amount, 'ERC20: transfer amount exceeds balance');
                  unchecked {
                    _balances[sender] = senderBalance - amount;
                  }
                  _balances[recipient] += amount;
                  emit Transfer(sender, recipient, amount);
                }
                /**
                 * @dev Creates `amount` tokens and assigns them to `account`.
                 * @param account The account to assign the newly created tokens to.
                 * @param amount The amount of tokens to create.
                 */
                function _mint(address account, uint256 amount) internal virtual {
                  require(account != address(0), 'ERC20: mint to the zero address');
                  _totalSupply += amount;
                  _balances[account] += amount;
                  emit Transfer(address(0), account, amount);
                }
                /**
                 * @dev Destroys `amount` tokens from `account`, reducing the total supply.
                 * @param account The account to burn tokens from.
                 * @param amount The amount of tokens to burn.
                 */
                function _burn(address account, uint256 amount) internal virtual {
                  require(account != address(0), 'ERC20: burn from the zero address');
                  uint256 accountBalance = _balances[account];
                  require(accountBalance >= amount, 'ERC20: burn amount exceeds balance');
                  unchecked {
                    _balances[account] = accountBalance - amount;
                  }
                  _totalSupply -= amount;
                  emit Transfer(account, address(0), amount);
                }
                /**
                 * @dev Destroys `amount` tokens from the caller's account, reducing the total supply.
                 * @param amount The amount of tokens to burn.
                 */
                function burn(uint256 amount) external {
                  _burn(_msgSender(), amount);
                }
                /**
                 * @dev Sets `amount` as the allowance of `to` over the caller's tokens.
                 * @param from The account granting the allowance.
                 * @param to The account allowed to spend the tokens.
                 * @param amount The amount of tokens to allow.
                 */
                function _approve(address from, address to, uint256 amount) internal virtual {
                  require(from != address(0), 'ERC20: approve from the zero address');
                  require(to != address(0), 'ERC20: approve to the zero address');
                  _allowances[from][to] = amount;
                  emit Approval(from, to, amount);
                }
              }
              

              File 4 of 9: 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 5 of 9: PresaleV1
              // 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;
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.8.1) (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.
                   *
                   * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
                   * constructor.
                   *
                   * Emits an {Initialized} event.
                   */
                  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.
                   *
                   * 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.
                   *
                   * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
                   * cannot be nested. If one is invoked in the context of another, execution will revert.
                   *
                   * 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.
                   *
                   * WARNING: setting the version to 255 will prevent any future reinitialization.
                   *
                   * Emits an {Initialized} event.
                   */
                  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.
                   *
                   * Emits an {Initialized} event the first time it is successfully executed.
                   */
                  function _disableInitializers() internal virtual {
                      require(!_initializing, "Initializable: contract is initializing");
                      if (_initialized < type(uint8).max) {
                          _initialized = type(uint8).max;
                          emit Initialized(type(uint8).max);
                      }
                  }
                  /**
                   * @dev Returns the highest version that has been initialized. See {reinitializer}.
                   */
                  function _getInitializedVersion() internal view returns (uint8) {
                      return _initialized;
                  }
                  /**
                   * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
                   */
                  function _isInitializing() internal view returns (bool) {
                      return _initializing;
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
              pragma solidity ^0.8.0;
              import "../utils/ContextUpgradeable.sol";
              import "../proxy/utils/Initializable.sol";
              /**
               * @dev Contract module which allows children to implement an emergency stop
               * mechanism that can be triggered by an authorized account.
               *
               * This module is used through inheritance. It will make available the
               * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
               * the functions of your contract. Note that they will not be pausable by
               * simply including this module, only once the modifiers are put in place.
               */
              abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
                  /**
                   * @dev Emitted when the pause is triggered by `account`.
                   */
                  event Paused(address account);
                  /**
                   * @dev Emitted when the pause is lifted by `account`.
                   */
                  event Unpaused(address account);
                  bool private _paused;
                  /**
                   * @dev Initializes the contract in unpaused state.
                   */
                  function __Pausable_init() internal onlyInitializing {
                      __Pausable_init_unchained();
                  }
                  function __Pausable_init_unchained() internal onlyInitializing {
                      _paused = false;
                  }
                  /**
                   * @dev Modifier to make a function callable only when the contract is not paused.
                   *
                   * Requirements:
                   *
                   * - The contract must not be paused.
                   */
                  modifier whenNotPaused() {
                      _requireNotPaused();
                      _;
                  }
                  /**
                   * @dev Modifier to make a function callable only when the contract is paused.
                   *
                   * Requirements:
                   *
                   * - The contract must be paused.
                   */
                  modifier whenPaused() {
                      _requirePaused();
                      _;
                  }
                  /**
                   * @dev Returns true if the contract is paused, and false otherwise.
                   */
                  function paused() public view virtual returns (bool) {
                      return _paused;
                  }
                  /**
                   * @dev Throws if the contract is paused.
                   */
                  function _requireNotPaused() internal view virtual {
                      require(!paused(), "Pausable: paused");
                  }
                  /**
                   * @dev Throws if the contract is not paused.
                   */
                  function _requirePaused() internal view virtual {
                      require(paused(), "Pausable: not paused");
                  }
                  /**
                   * @dev Triggers stopped state.
                   *
                   * Requirements:
                   *
                   * - The contract must not be paused.
                   */
                  function _pause() internal virtual whenNotPaused {
                      _paused = true;
                      emit Paused(_msgSender());
                  }
                  /**
                   * @dev Returns to normal state.
                   *
                   * Requirements:
                   *
                   * - The contract must be paused.
                   */
                  function _unpause() internal virtual whenPaused {
                      _paused = false;
                      emit Unpaused(_msgSender());
                  }
                  /**
                   * @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.8.0) (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() {
                      _nonReentrantBefore();
                      _;
                      _nonReentrantAfter();
                  }
                  function _nonReentrantBefore() private {
                      // On the first call to nonReentrant, _status will be _NOT_ENTERED
                      require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
                      // Any calls to nonReentrant after this point will fail
                      _status = _ENTERED;
                  }
                  function _nonReentrantAfter() private {
                      // 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.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 (last updated v4.8.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 functionCallWithValue(target, data, 0, "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");
                      (bool success, bytes memory returndata) = target.call{value: value}(data);
                      return verifyCallResultFromTarget(target, 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) {
                      (bool success, bytes memory returndata) = target.staticcall(data);
                      return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                  }
                  /**
                   * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                   * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                   *
                   * _Available since v4.8._
                   */
                  function verifyCallResultFromTarget(
                      address target,
                      bool success,
                      bytes memory returndata,
                      string memory errorMessage
                  ) internal view returns (bytes memory) {
                      if (success) {
                          if (returndata.length == 0) {
                              // only check isContract if the call was successful and the return data is empty
                              // otherwise we already know that it was a contract
                              require(isContract(target), "Address: call to non-contract");
                          }
                          return returndata;
                      } else {
                          _revert(returndata, errorMessage);
                      }
                  }
                  /**
                   * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                   * revert reason or 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 {
                          _revert(returndata, errorMessage);
                      }
                  }
                  function _revert(bytes memory returndata, string memory errorMessage) private pure {
                      // 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 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
              //               _    _____                                        _
              // __      _____| |__|___ / _ __   __ _ _   _ _ __ ___   ___ _ __ | |_ ___
              // \\ \\ /\\ / / _ \\ '_ \\ |_ \\| '_ \\ / _` | | | | '_ ` _ \\ / _ \\ '_ \\| __/ __|
              //  \\ V  V /  __/ |_) |__) | |_) | (_| | |_| | | | | | |  __/ | | | |_\\__ \\
              //   \\_/\\_/ \\___|_.__/____/| .__/ \\__,_|\\__, |_| |_| |_|\\___|_| |_|\\__|___/
              //                         |_|          |___/
              //
              pragma solidity 0.8.9;
              import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
              import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.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);
              }
              interface StakingManager {
                function depositByPresale(address _user, uint256 _amount) external;
              }
              contract PresaleV1 is Initializable, ReentrancyGuardUpgradeable, OwnableUpgradeable, PausableUpgradeable {
                uint256 public totalTokensSold;
                uint256 public startTime;
                uint256 public endTime;
                uint256 public claimStart;
                address public saleToken;
                uint256 public baseDecimals;
                uint256 public maxTokensToBuy;
                uint256 public currentStep;
                uint256 public checkPoint;
                uint256 public usdRaised;
                uint256 public timeConstant;
                uint256 public totalBoughtAndStaked;
                uint256[][3] public rounds;
                uint256[] public prevCheckpoints;
                uint256[] public remainingTokensTracker;
                uint256[] public percentages;
                address[] public wallets;
                address public paymentWallet;
                address public admin;
                bool public dynamicTimeFlag;
                bool public whitelistClaimOnly;
                bool public stakeingWhitelistStatus;
                IERC20Upgradeable public USDTInterface;
                Aggregator public aggregatorInterface;
                mapping(address => uint256) public userDeposits;
                mapping(address => bool) public hasClaimed;
                mapping(address => bool) public isBlacklisted;
                mapping(address => bool) public isWhitelisted;
                mapping(address => bool) public wertWhitelisted;
                StakingManager public stakingManagerInterface;
                event SaleTimeSet(uint256 _start, uint256 _end, uint256 timestamp);
                event SaleTimeUpdated(bytes32 indexed key, uint256 prevValue, uint256 newValue, uint256 timestamp);
                event TokensBought(address indexed user, uint256 indexed tokensBought, address indexed purchaseToken, uint256 amountPaid, uint256 usdEq, uint256 timestamp);
                event TokensAdded(address indexed token, uint256 noOfTokens, uint256 timestamp);
                event TokensClaimed(address indexed user, uint256 amount, uint256 timestamp);
                event ClaimStartUpdated(uint256 prevValue, uint256 newValue, uint256 timestamp);
                event MaxTokensUpdated(uint256 prevValue, uint256 newValue, uint256 timestamp);
                event TokensBoughtAndStaked(address indexed user, uint256 indexed tokensBought, address indexed purchaseToken, uint256 amountPaid, uint256 usdEq, uint256 timestamp);
                event TokensClaimedAndStaked(address indexed user, uint256 amount, 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
                 * @param _startTime start time of the presale
                 * @param _endTime end time of the presale
                 * @param _rounds array of round details
                 * @param _maxTokensToBuy amount of max tokens to buy
                 * @param _paymentWallet address to recive payments
                 */
                function initialize(address _oracle, address _usdt, uint256 _startTime, uint256 _endTime, uint256[][3] memory _rounds, uint256 _maxTokensToBuy, address _paymentWallet) external initializer {
                  require(_oracle != address(0), "Zero aggregator address");
                  require(_usdt != address(0), "Zero USDT address");
                  require(_startTime > block.timestamp && _endTime > _startTime, "Invalid time");
                  __Pausable_init_unchained();
                  __Ownable_init_unchained();
                  __ReentrancyGuard_init_unchained();
                  baseDecimals = (10 ** 18);
                  aggregatorInterface = Aggregator(_oracle);
                  USDTInterface = IERC20Upgradeable(_usdt);
                  startTime = _startTime;
                  endTime = _endTime;
                  rounds = _rounds;
                  maxTokensToBuy = _maxTokensToBuy;
                  paymentWallet = _paymentWallet;
                  emit SaleTimeSet(startTime, endTime, block.timestamp);
                }
                /**
                 * @dev To pause the presale
                 */
                function pause() external onlyOwner {
                  _pause();
                }
                /**
                 * @dev To unpause the presale
                 */
                function unpause() external onlyOwner {
                  _unpause();
                }
                /**
                 * @dev To calculate the price in USD for given amount of tokens.
                 * @param _amount No of tokens
                 */
                function calculatePrice(uint256 _amount) public view returns (uint256) {
                  uint256 USDTAmount;
                  uint256 total = checkPoint == 0 ? totalTokensSold : checkPoint;
                  require(_amount <= maxTokensToBuy, "Amount exceeds max tokens to buy");
                  if (_amount + total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
                    require(currentStep < (rounds[0].length - 1), "Wrong params");
                    if (block.timestamp >= rounds[2][currentStep]) {
                      require(rounds[0][currentStep] + _amount <= rounds[0][currentStep + 1], "Cant Purchase More in individual tx");
                      USDTAmount = _amount * rounds[1][currentStep + 1];
                    } else {
                      uint256 tokenAmountForCurrentPrice = rounds[0][currentStep] - total;
                      USDTAmount = tokenAmountForCurrentPrice * rounds[1][currentStep] + (_amount - tokenAmountForCurrentPrice) * rounds[1][currentStep + 1];
                    }
                  } else USDTAmount = _amount * rounds[1][currentStep];
                  return USDTAmount;
                }
                /**
                 * @dev To update the sale times
                 * @param _startTime New start time
                 * @param _endTime New end time
                 */
                function changeSaleTimes(uint256 _startTime, uint256 _endTime) external onlyOwner {
                  require(_startTime > 0 || _endTime > 0, "Invalid parameters");
                  if (_startTime > 0) {
                    require(block.timestamp < startTime, "Sale already started");
                    require(block.timestamp < _startTime, "Sale time in past");
                    uint256 prevValue = startTime;
                    startTime = _startTime;
                    emit SaleTimeUpdated(bytes32("START"), prevValue, _startTime, block.timestamp);
                  }
                  if (_endTime > 0) {
                    require(_endTime > startTime, "Invalid endTime");
                    uint256 prevValue = endTime;
                    endTime = _endTime;
                    emit SaleTimeUpdated(bytes32("END"), prevValue, _endTime, block.timestamp);
                  }
                }
                /**
                 * @dev To get latest ETH price in 10**18 format
                 */
                function getLatestPrice() public view returns (uint256) {
                  (, int256 price, , , ) = aggregatorInterface.latestRoundData();
                  price = (price * (10 ** 10));
                  return uint256(price);
                }
                function setSplits(address[] memory _wallets, uint256[] memory _percentages) public onlyOwner {
                  require(_wallets.length == _percentages.length, "Mismatched arrays");
                  delete wallets;
                  delete percentages;
                  uint256 totalPercentage = 0;
                  for (uint256 i = 0; i < _wallets.length; i++) {
                    require(_percentages[i] > 0, "Percentage must be greater than 0");
                    totalPercentage += _percentages[i];
                    wallets.push(_wallets[i]);
                    percentages.push(_percentages[i]);
                  }
                  require(totalPercentage == 100, "Total percentage must equal 100");
                }
                modifier checkSaleState(uint256 amount) {
                  require(block.timestamp >= startTime && block.timestamp <= endTime, "Invalid time for buying");
                  require(amount > 0, "Invalid sale amount");
                  _;
                }
                /**
                 * @dev To buy into a presale using USDT
                 * @param amount No of tokens to buy
                 * @param stake boolean flag for token staking
                 */
                function buyWithUSDT(uint256 amount, bool stake) external checkSaleState(amount) whenNotPaused returns (bool) {
                  uint256 usdPrice = calculatePrice(amount);
                  totalTokensSold += amount;
                  uint256 price = usdPrice / (10 ** 12);
                  if (checkPoint != 0) checkPoint += amount;
                  uint256 total = totalTokensSold > checkPoint ? totalTokensSold : checkPoint;
                  if (total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
                    if (block.timestamp >= rounds[2][currentStep]) {
                      checkPoint = rounds[0][currentStep] + amount;
                    }
                    if (dynamicTimeFlag) {
                      manageTimeDiff();
                    }
                    uint256 unsoldTokens = total > rounds[0][currentStep] ? 0 : rounds[0][currentStep] - total - amount;
                    remainingTokensTracker.push(unsoldTokens);
                    currentStep += 1;
                  }
                  if (stake) {
                    if (stakeingWhitelistStatus) {
                      require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
                    }
                    stakingManagerInterface.depositByPresale(_msgSender(), amount * baseDecimals);
                    totalBoughtAndStaked += amount;
                    emit TokensBoughtAndStaked(_msgSender(), amount, address(USDTInterface), price, usdPrice, block.timestamp);
                  } else {
                    userDeposits[_msgSender()] += (amount * baseDecimals);
                    emit TokensBought(_msgSender(), amount, address(USDTInterface), price, usdPrice, block.timestamp);
                  }
                  usdRaised += usdPrice;
                  uint256 ourAllowance = USDTInterface.allowance(_msgSender(), address(this));
                  require(price <= ourAllowance, "Make sure to add enough allowance");
                  splitUSDTValue(price);
                  return true;
                }
                /**
                 * @dev To buy into a presale using ETH
                 * @param amount No of tokens to buy
                 * @param stake boolean flag for token staking
                 */
                function buyWithEth(uint256 amount, bool stake) external payable checkSaleState(amount) whenNotPaused nonReentrant returns (bool) {
                  uint256 usdPrice = calculatePrice(amount);
                  uint256 ethAmount = (usdPrice * baseDecimals) / getLatestPrice();
                  require(msg.value >= ethAmount, "Less payment");
                  uint256 excess = msg.value - ethAmount;
                  totalTokensSold += amount;
                  if (checkPoint != 0) checkPoint += amount;
                  uint256 total = totalTokensSold > checkPoint ? totalTokensSold : checkPoint;
                  if (total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
                    if (block.timestamp >= rounds[2][currentStep]) {
                      checkPoint = rounds[0][currentStep] + amount;
                    }
                    if (dynamicTimeFlag) {
                      manageTimeDiff();
                    }
                    uint256 unsoldTokens = total > rounds[0][currentStep] ? 0 : rounds[0][currentStep] - total - amount;
                    remainingTokensTracker.push(unsoldTokens);
                    currentStep += 1;
                  }
                  if (stake) {
                    if (stakeingWhitelistStatus) {
                      require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
                    }
                    stakingManagerInterface.depositByPresale(_msgSender(), amount * baseDecimals);
                    totalBoughtAndStaked += amount;
                    emit TokensBoughtAndStaked(_msgSender(), amount, address(0), ethAmount, usdPrice, block.timestamp);
                  } else {
                    userDeposits[_msgSender()] += (amount * baseDecimals);
                    emit TokensBought(_msgSender(), amount, address(0), ethAmount, usdPrice, block.timestamp);
                  }
                  usdRaised += usdPrice;
                  splitETHValue(ethAmount);
                  if (excess > 0) sendValue(payable(_msgSender()), excess);
                  return true;
                }
                /**
                 * @dev To buy ETH directly from wert .*wert contract address should be whitelisted if wertBuyRestrictionStatus is set true
                 * @param _user address of the user
                 * @param _amount No of ETH to buy
                 * @param stake boolean flag for token staking
                 */
                function buyWithETHWert(address _user, uint256 _amount, bool stake) external payable checkSaleState(_amount) whenNotPaused nonReentrant returns (bool) {
                  require(wertWhitelisted[_msgSender()], "User not whitelisted for this tx");
                  uint256 usdPrice = calculatePrice(_amount);
                  uint256 ethAmount = (usdPrice * baseDecimals) / getLatestPrice();
                  require(msg.value >= ethAmount, "Less payment");
                  uint256 excess = msg.value - ethAmount;
                  totalTokensSold += _amount;
                  if (checkPoint != 0) checkPoint += _amount;
                  uint256 total = totalTokensSold > checkPoint ? totalTokensSold : checkPoint;
                  if (total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
                    if (block.timestamp >= rounds[2][currentStep]) {
                      checkPoint = rounds[0][currentStep] + _amount;
                    }
                    if (dynamicTimeFlag) {
                      manageTimeDiff();
                    }
                    uint256 unsoldTokens = total > rounds[0][currentStep] ? 0 : rounds[0][currentStep] - total - _amount;
                    remainingTokensTracker.push(unsoldTokens);
                    currentStep += 1;
                  }
                  if (stake) {
                    if (stakeingWhitelistStatus) {
                      require(isWhitelisted[_user], "User not whitelisted for stake");
                    }
                    stakingManagerInterface.depositByPresale(_user, _amount * baseDecimals);
                    totalBoughtAndStaked += _amount;
                    emit TokensBoughtAndStaked(_user, _amount, address(0), ethAmount, usdPrice, block.timestamp);
                  } else {
                    userDeposits[_user] += (_amount * baseDecimals);
                    emit TokensBought(_user, _amount, address(0), ethAmount, usdPrice, block.timestamp);
                  }
                  usdRaised += usdPrice;
                  splitETHValue(ethAmount);
                  if (excess > 0) sendValue(payable(_user), excess);
                  return true;
                }
                /**
                 * @dev Helper funtion to get ETH price for given amount
                 * @param amount No of tokens to buy
                 */
                function ethBuyHelper(uint256 amount) external view returns (uint256 ethAmount) {
                  uint256 usdPrice = calculatePrice(amount);
                  ethAmount = (usdPrice * baseDecimals) / getLatestPrice();
                }
                /**
                 * @dev Helper funtion to get USDT price for given amount
                 * @param amount No of tokens to buy
                 */
                function usdtBuyHelper(uint256 amount) external view returns (uint256 usdPrice) {
                  usdPrice = calculatePrice(amount);
                  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");
                }
                function splitETHValue(uint256 _amount) internal {
                  if (wallets.length == 0) {
                    require(paymentWallet != address(0), "Payment wallet not set");
                    sendValue(payable(paymentWallet), _amount);
                  } else {
                    uint256 tempCalc;
                    for (uint256 i = 0; i < wallets.length; i++) {
                      uint256 amountToTransfer = (_amount * percentages[i]) / 100;
                      sendValue(payable(wallets[i]), amountToTransfer);
                      tempCalc += amountToTransfer;
                    }
                    if ((_amount - tempCalc) > 0) {
                      sendValue(payable(wallets[wallets.length - 1]), _amount - tempCalc);
                    }
                  }
                }
                function splitUSDTValue(uint256 _amount) internal {
                  if (wallets.length == 0) {
                    require(paymentWallet != address(0), "Payment wallet not set");
                    (bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), paymentWallet, _amount));
                    require(success, "Token payment failed");
                  } else {
                    uint256 tempCalc;
                    for (uint256 i = 0; i < wallets.length; i++) {
                      uint256 amountToTransfer = (_amount * percentages[i]) / 100;
                      (bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), wallets[i], amountToTransfer));
                      require(success, "Token payment failed");
                      tempCalc += amountToTransfer;
                    }
                    if ((_amount - tempCalc) > 0) {
                      (bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), wallets[wallets.length - 1], _amount - tempCalc));
                      require(success, "Token payment failed");
                    }
                  }
                }
                /**
                 * @dev to initialize staking manager with new addredd
                 * @param _stakingManagerAddress address of the staking smartcontract
                 */
                function setStakingManager(address _stakingManagerAddress) external onlyOwner {
                  require(_stakingManagerAddress != address(0), "staking manager cannot be inatialized with zero address");
                  stakingManagerInterface = StakingManager(_stakingManagerAddress);
                  IERC20Upgradeable(saleToken).approve(_stakingManagerAddress, type(uint256).max);
                }
                /**
                 * @dev To set the claim start time and sale token address by the owner
                 * @param _claimStart claim start time
                 * @param noOfTokens no of tokens to add to the contract
                 * @param _saleToken sale toke address
                 */
                function startClaim(uint256 _claimStart, uint256 noOfTokens, address _saleToken, address _stakingManagerAddress) external onlyOwner returns (bool) {
                  require(_saleToken != address(0), "Zero token address");
                  require(claimStart == 0, "Claim already set");
                  claimStart = _claimStart;
                  saleToken = _saleToken;
                  whitelistClaimOnly = true;
                  stakingManagerInterface = StakingManager(_stakingManagerAddress);
                  IERC20Upgradeable(_saleToken).approve(_stakingManagerAddress, type(uint256).max);
                  bool success = IERC20Upgradeable(_saleToken).transferFrom(_msgSender(), address(this), noOfTokens);
                  require(success, "Token transfer failed");
                  emit TokensAdded(_saleToken, noOfTokens, block.timestamp);
                  return true;
                }
                /**
                 * @dev To set status for claim whitelisting
                 * @param _status bool value
                 */
                function setStakeingWhitelistStatus(bool _status) external onlyOwner {
                  stakeingWhitelistStatus = _status;
                }
                /**
                 * @dev To change the claim start time by the owner
                 * @param _claimStart new claim start time
                 */
                function changeClaimStart(uint256 _claimStart) external onlyOwner returns (bool) {
                  require(claimStart > 0, "Initial claim data not set");
                  require(_claimStart > endTime, "Sale in progress");
                  require(_claimStart > block.timestamp, "Claim start in past");
                  uint256 prevValue = claimStart;
                  claimStart = _claimStart;
                  emit ClaimStartUpdated(prevValue, _claimStart, block.timestamp);
                  return true;
                }
                /**
                 * @dev To claim tokens after claiming starts
                 */
                function claim() external whenNotPaused returns (bool) {
                  require(saleToken != address(0), "Sale token not added");
                  require(!isBlacklisted[_msgSender()], "This Address is Blacklisted");
                  if (whitelistClaimOnly) {
                    require(isWhitelisted[_msgSender()], "User not whitelisted for claim");
                  }
                  require(block.timestamp >= claimStart, "Claim has not started yet");
                  require(!hasClaimed[_msgSender()], "Already claimed");
                  hasClaimed[_msgSender()] = true;
                  uint256 amount = userDeposits[_msgSender()];
                  require(amount > 0, "Nothing to claim");
                  delete userDeposits[_msgSender()];
                  bool success = IERC20Upgradeable(saleToken).transfer(_msgSender(), amount);
                  require(success, "Token transfer failed");
                  emit TokensClaimed(_msgSender(), amount, block.timestamp);
                  return true;
                }
                function claimAndStake() external whenNotPaused returns (bool) {
                  require(saleToken != address(0), "Sale token not added");
                  require(!isBlacklisted[_msgSender()], "This Address is Blacklisted");
                  if (stakeingWhitelistStatus) {
                    require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
                  }
                  uint256 amount = userDeposits[_msgSender()];
                  require(amount > 0, "Nothing to stake");
                  stakingManagerInterface.depositByPresale(_msgSender(), amount);
                  delete userDeposits[_msgSender()];
                  emit TokensClaimedAndStaked(_msgSender(), amount, block.timestamp);
                  return true;
                }
                /**
                 * @dev To add wert contract addresses to whitelist
                 * @param _addressesToWhitelist addresses of the contract
                 */
                function whitelistUsersForWERT(address[] calldata _addressesToWhitelist) external onlyOwner {
                  for (uint256 i = 0; i < _addressesToWhitelist.length; i++) {
                    wertWhitelisted[_addressesToWhitelist[i]] = true;
                  }
                }
                /**
                 * @dev To remove wert contract addresses to whitelist
                 * @param _addressesToRemoveFromWhitelist addresses of the contracts
                 */
                function removeFromWhitelistForWERT(address[] calldata _addressesToRemoveFromWhitelist) external onlyOwner {
                  for (uint256 i = 0; i < _addressesToRemoveFromWhitelist.length; i++) {
                    wertWhitelisted[_addressesToRemoveFromWhitelist[i]] = false;
                  }
                }
                function changeMaxTokensToBuy(uint256 _maxTokensToBuy) external onlyOwner {
                  require(_maxTokensToBuy > 0, "Zero max tokens to buy value");
                  uint256 prevValue = maxTokensToBuy;
                  maxTokensToBuy = _maxTokensToBuy;
                  emit MaxTokensUpdated(prevValue, _maxTokensToBuy, block.timestamp);
                }
                function changeRoundsData(uint256[][3] memory _rounds) external onlyOwner {
                  rounds = _rounds;
                }
                /**
                 * @dev To add users to blacklist which restricts blacklisted users from claiming
                 * @param _usersToBlacklist addresses of the users
                 */
                function blacklistUsers(address[] calldata _usersToBlacklist) external onlyOwner {
                  for (uint256 i = 0; i < _usersToBlacklist.length; i++) {
                    isBlacklisted[_usersToBlacklist[i]] = true;
                  }
                }
                /**
                 * @dev To remove users from blacklist which restricts blacklisted users from claiming
                 * @param _userToRemoveFromBlacklist addresses of the users
                 */
                function removeFromBlacklist(address[] calldata _userToRemoveFromBlacklist) external onlyOwner {
                  for (uint256 i = 0; i < _userToRemoveFromBlacklist.length; i++) {
                    isBlacklisted[_userToRemoveFromBlacklist[i]] = false;
                  }
                }
                /**
                 * @dev To add users to whitelist which restricts users from claiming if claimWhitelistStatus is true
                 * @param _usersToWhitelist addresses of the users
                 */
                function whitelistUsers(address[] calldata _usersToWhitelist) external onlyOwner {
                  for (uint256 i = 0; i < _usersToWhitelist.length; i++) {
                    isWhitelisted[_usersToWhitelist[i]] = true;
                  }
                }
                /**
                 * @dev To remove users from whitelist which restricts users from claiming if claimWhitelistStatus is true
                 * @param _userToRemoveFromWhitelist addresses of the users
                 */
                function removeFromWhitelist(address[] calldata _userToRemoveFromWhitelist) external onlyOwner {
                  for (uint256 i = 0; i < _userToRemoveFromWhitelist.length; i++) {
                    isWhitelisted[_userToRemoveFromWhitelist[i]] = false;
                  }
                }
                /**
                 * @dev To set status for claim whitelisting
                 * @param _status bool value
                 */
                function setClaimWhitelistStatus(bool _status) external onlyOwner {
                  whitelistClaimOnly = _status;
                }
                /**
                 * @dev To set payment wallet address
                 * @param _newPaymentWallet new payment wallet address
                 */
                function changePaymentWallet(address _newPaymentWallet) external onlyOwner {
                  require(_newPaymentWallet != address(0), "address cannot be zero");
                  paymentWallet = _newPaymentWallet;
                }
                /**
                 * @dev To manage time gap between two rounds
                 */
                function manageTimeDiff() internal {
                  for (uint256 i; i < rounds[2].length - currentStep; i++) {
                    rounds[2][currentStep + i] = block.timestamp + i * timeConstant;
                  }
                }
                /**
                 * @dev To set time constant for manageTimeDiff()
                 * @param _timeConstant time in <days>*24*60*60 format
                 */
                function setTimeConstant(uint256 _timeConstant) external onlyOwner {
                  timeConstant = _timeConstant;
                }
                /**
                 * @dev To get array of round details at once
                 * @param _no array index
                 */
                function roundDetails(uint256 _no) external view returns (uint256[] memory) {
                  return rounds[_no];
                }
                /**
                 * @dev to update userDeposits for purchases made on BSC
                 * @param _users array of users
                 * @param _userDeposits array of userDeposits associated with users
                 */
                function updateFromBSC(address[] calldata _users, uint256[] calldata _userDeposits) external onlyOwner {
                  require(_users.length == _userDeposits.length, "Length mismatch");
                  for (uint256 i = 0; i < _users.length; i++) {
                    userDeposits[_users[i]] += _userDeposits[i];
                  }
                }
                /**
                 * @dev To increment the rounds from backend
                 */
                function incrementCurrentStep() external {
                  require(msg.sender == admin || msg.sender == owner(), "caller not admin or owner");
                  prevCheckpoints.push(checkPoint);
                  if (dynamicTimeFlag) {
                    manageTimeDiff();
                  }
                  if (checkPoint < rounds[0][currentStep]) {
                    if (currentStep == 0) {
                      remainingTokensTracker.push(rounds[0][currentStep] - totalTokensSold);
                    } else {
                      remainingTokensTracker.push(rounds[0][currentStep] - checkPoint);
                    }
                    checkPoint = rounds[0][currentStep];
                  }
                  currentStep++;
                }
                /**
                 * @dev To set admin
                 * @param _admin new admin wallet address
                 */
                function setAdmin(address _admin) external onlyOwner {
                  admin = _admin;
                }
                /**
                 * @dev To change details of the round
                 * @param _step round for which you want to change the details
                 * @param _checkpoint token tracker amount
                 */
                function setCurrentStep(uint256 _step, uint256 _checkpoint) external onlyOwner {
                  currentStep = _step;
                  checkPoint = _checkpoint;
                }
                /**
                 * @dev To set time shift functionality on/off
                 * @param _dynamicTimeFlag bool value
                 */
                function setDynamicTimeFlag(bool _dynamicTimeFlag) external onlyOwner {
                  dynamicTimeFlag = _dynamicTimeFlag;
                }
                /**
                 * @dev     Function to return remainingTokenTracker Array
                 */
                function trackRemainingTokens() external view returns (uint256[] memory) {
                  return remainingTokensTracker;
                }
                /**
                 * @dev     To update remainingTokensTracker Array
                 * @param   _unsoldTokens  input parameters in uint256 array format
                 */
                function setRemainingTokensArray(uint256[] memory _unsoldTokens) public {
                  require(msg.sender == admin || msg.sender == owner(), "caller not admin or owner");
                  require(_unsoldTokens.length != 0, "cannot update invalid values");
                  delete remainingTokensTracker;
                  for (uint256 i; i < _unsoldTokens.length; i++) {
                    remainingTokensTracker.push(_unsoldTokens[i]);
                  }
                }
              }
              

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

              File 8 of 9: stakingManager
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.
                   *
                   * NOTE: Renouncing ownership will leave the contract without an owner,
                   * thereby disabling 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;
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.9.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]
               * ```solidity
               * 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.
                   *
                   * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
                   * constructor.
                   *
                   * Emits an {Initialized} event.
                   */
                  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.
                   *
                   * 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.
                   *
                   * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
                   * cannot be nested. If one is invoked in the context of another, execution will revert.
                   *
                   * 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.
                   *
                   * WARNING: setting the version to 255 will prevent any future reinitialization.
                   *
                   * Emits an {Initialized} event.
                   */
                  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.
                   *
                   * Emits an {Initialized} event the first time it is successfully executed.
                   */
                  function _disableInitializers() internal virtual {
                      require(!_initializing, "Initializable: contract is initializing");
                      if (_initialized != type(uint8).max) {
                          _initialized = type(uint8).max;
                          emit Initialized(type(uint8).max);
                      }
                  }
                  /**
                   * @dev Returns the highest version that has been initialized. See {reinitializer}.
                   */
                  function _getInitializedVersion() internal view returns (uint8) {
                      return _initialized;
                  }
                  /**
                   * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
                   */
                  function _isInitializing() internal view returns (bool) {
                      return _initializing;
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
              pragma solidity ^0.8.0;
              /**
               * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
               * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
               *
               * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
               * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
               * need to send a transaction, and thus is not required to hold Ether at all.
               */
              interface IERC20PermitUpgradeable {
                  /**
                   * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
                   * given ``owner``'s signed approval.
                   *
                   * IMPORTANT: The same issues {IERC20-approve} has related to transaction
                   * ordering also apply here.
                   *
                   * Emits an {Approval} event.
                   *
                   * Requirements:
                   *
                   * - `spender` cannot be the zero address.
                   * - `deadline` must be a timestamp in the future.
                   * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
                   * over the EIP712-formatted function arguments.
                   * - the signature must use ``owner``'s current nonce (see {nonces}).
                   *
                   * For more information on the signature format, see the
                   * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
                   * section].
                   */
                  function permit(
                      address owner,
                      address spender,
                      uint256 value,
                      uint256 deadline,
                      uint8 v,
                      bytes32 r,
                      bytes32 s
                  ) external;
                  /**
                   * @dev Returns the current nonce for `owner`. This value must be
                   * included whenever a signature is generated for {permit}.
                   *
                   * Every successful call to {permit} increases ``owner``'s nonce by one. This
                   * prevents a signature from being used multiple times.
                   */
                  function nonces(address owner) external view returns (uint256);
                  /**
                   * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
                   */
                  // solhint-disable-next-line func-name-mixedcase
                  function DOMAIN_SEPARATOR() external view returns (bytes32);
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.9.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 (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
              pragma solidity ^0.8.0;
              import "../IERC20Upgradeable.sol";
              import "../extensions/IERC20PermitUpgradeable.sol";
              import "../../../utils/AddressUpgradeable.sol";
              /**
               * @title SafeERC20
               * @dev Wrappers around ERC20 operations that throw on failure (when the token
               * contract returns false). Tokens that return no value (and instead revert or
               * throw on failure) are also supported, non-reverting calls are assumed to be
               * successful.
               * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
               * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
               */
              library SafeERC20Upgradeable {
                  using AddressUpgradeable for address;
                  /**
                   * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
                   * non-reverting calls are assumed to be successful.
                   */
                  function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
                      _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                  }
                  /**
                   * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
                   * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
                   */
                  function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
                      _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
                  }
                  /**
                   * @dev Deprecated. This function has issues similar to the ones found in
                   * {IERC20-approve}, and its usage is discouraged.
                   *
                   * Whenever possible, use {safeIncreaseAllowance} and
                   * {safeDecreaseAllowance} instead.
                   */
                  function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
                      // safeApprove should only be called when setting an initial allowance,
                      // or when resetting it to zero. To increase and decrease it, use
                      // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                      require(
                          (value == 0) || (token.allowance(address(this), spender) == 0),
                          "SafeERC20: approve from non-zero to non-zero allowance"
                      );
                      _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
                  }
                  /**
                   * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
                   * non-reverting calls are assumed to be successful.
                   */
                  function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
                      uint256 oldAllowance = token.allowance(address(this), spender);
                      _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
                  }
                  /**
                   * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
                   * non-reverting calls are assumed to be successful.
                   */
                  function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
                      unchecked {
                          uint256 oldAllowance = token.allowance(address(this), spender);
                          require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                          _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
                      }
                  }
                  /**
                   * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
                   * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
                   * to be set to zero before setting it to a non-zero value, such as USDT.
                   */
                  function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
                      bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
                      if (!_callOptionalReturnBool(token, approvalCall)) {
                          _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
                          _callOptionalReturn(token, approvalCall);
                      }
                  }
                  /**
                   * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
                   * Revert on invalid signature.
                   */
                  function safePermit(
                      IERC20PermitUpgradeable token,
                      address owner,
                      address spender,
                      uint256 value,
                      uint256 deadline,
                      uint8 v,
                      bytes32 r,
                      bytes32 s
                  ) internal {
                      uint256 nonceBefore = token.nonces(owner);
                      token.permit(owner, spender, value, deadline, v, r, s);
                      uint256 nonceAfter = token.nonces(owner);
                      require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
                  }
                  /**
                   * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                   * on the return value: the return value is optional (but if data is returned, it must not be false).
                   * @param token The token targeted by the call.
                   * @param data The call data (encoded using abi.encode or one of its variants).
                   */
                  function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
                      // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                      // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
                      // the target address contains contract code and also asserts for success in the low-level call.
                      bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                      require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                  }
                  /**
                   * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                   * on the return value: the return value is optional (but if data is returned, it must not be false).
                   * @param token The token targeted by the call.
                   * @param data The call data (encoded using abi.encode or one of its variants).
                   *
                   * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
                   */
                  function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {
                      // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                      // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
                      // and not revert is the subcall reverts.
                      (bool success, bytes memory returndata) = address(token).call(data);
                      return
                          success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));
                  }
              }
              // SPDX-License-Identifier: MIT
              // OpenZeppelin Contracts (last updated v4.9.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
                   *
                   * Furthermore, `isContract` will also return true if the target contract within
                   * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
                   * which only has an effect at the end of a transaction.
                   * ====
                   *
                   * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
                      (bool success, bytes memory returndata) = target.call{value: value}(data);
                      return verifyCallResultFromTarget(target, 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) {
                      (bool success, bytes memory returndata) = target.staticcall(data);
                      return verifyCallResultFromTarget(target, 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) {
                      (bool success, bytes memory returndata) = target.delegatecall(data);
                      return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                  }
                  /**
                   * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                   * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                   *
                   * _Available since v4.8._
                   */
                  function verifyCallResultFromTarget(
                      address target,
                      bool success,
                      bytes memory returndata,
                      string memory errorMessage
                  ) internal view returns (bytes memory) {
                      if (success) {
                          if (returndata.length == 0) {
                              // only check isContract if the call was successful and the return data is empty
                              // otherwise we already know that it was a contract
                              require(isContract(target), "Address: call to non-contract");
                          }
                          return returndata;
                      } else {
                          _revert(returndata, errorMessage);
                      }
                  }
                  /**
                   * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                   * revert reason or 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 {
                          _revert(returndata, errorMessage);
                      }
                  }
                  function _revert(bytes memory returndata, string memory errorMessage) private pure {
                      // 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 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: Unlicense
              pragma solidity 0.8.9;
              import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol';
              import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol';
              import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
              contract stakingManager is OwnableUpgradeable {
                using SafeERC20Upgradeable for IERC20Upgradeable; // Wrappers around ERC20 operations that throw on failure
                IERC20Upgradeable public stakeToken; // Token to be staked and rewarded
                address public presaleContract; //presale contract address
                uint256 public tokensStakedByPresale; //total tokens staked by preSale
                uint256 public tokensStaked; // Total tokens staked
                uint256 private lastRewardedBlock; // Last block number the user had their rewards calculated
                uint256 private accumulatedRewardsPerShare; // Accumulated rewards per share times REWARDS_PRECISION
                uint256 public rewardTokensPerBlock; // Number of reward tokens minted per block
                uint256 private constant REWARDS_PRECISION = 1e12; // A big number to perform mul and div operations
                uint256 public lockedTime; //To lock the tokens in contract for definite time.
                bool public harvestLock; //To lock the harvest/claim.
                uint public endBlock; //At this block,the rewards generation will be stopped.
                uint256 public claimStart; //Users can claim after this time in epoch.
                // Staking user for a pool
                struct PoolStaker {
                  uint256 amount; // The tokens quantity the user has staked.
                  uint256 stakedTime; //the time at tokens staked
                  uint256 lastUpdatedBlock;
                  uint256 Harvestedrewards; // The reward tokens quantity the user  harvested
                  uint256 rewardDebt; // The amount relative to accumulatedRewardsPerShare the user can't get as reward
                }
                //  staker address => PoolStaker
                mapping(address => PoolStaker) public poolStakers;
                mapping(address => bool) public isBlacklisted;
                mapping(address => uint) public userLockedRewards;
                // Events
                event Deposit(address indexed user, uint256 amount);
                event Withdraw(address indexed user, uint256 amount);
                event HarvestRewards(address indexed user, uint256 amount);
                /// @custom:oz-upgrades-unsafe-allow constructor
                constructor() {
                  _disableInitializers();
                }
                function __stakingManager_init(address _rewardTokenAddress, address _presale, uint256 _rewardTokensPerBlock, uint _lockTime, uint _endBlock) public initializer {
                  __Ownable_init_unchained();
                  rewardTokensPerBlock = _rewardTokensPerBlock;
                  stakeToken = IERC20Upgradeable(_rewardTokenAddress);
                  presaleContract = _presale;
                  lockedTime = _lockTime;
                  endBlock = _endBlock;
                  harvestLock = true;
                }
                modifier onlyPresale() {
                  require(msg.sender == presaleContract, 'This method is only for presale Contract');
                  _;
                }
                /**
                 * @dev Deposit tokens to the pool
                 */
                function deposit(uint256 _amount) external {
                  require(block.number < endBlock, 'staking has been ended');
                  require(_amount > 0, "Deposit amount can't be zero");
                  PoolStaker storage staker = poolStakers[msg.sender];
                  // Update pool stakers
                  harvestRewards();
                  // Update current staker
                  staker.amount += _amount;
                  staker.rewardDebt = (staker.amount * accumulatedRewardsPerShare) / REWARDS_PRECISION;
                  staker.stakedTime = block.timestamp;
                  staker.lastUpdatedBlock = block.number;
                  // Update pool
                  tokensStaked += _amount;
                  // Deposit tokens
                  emit Deposit(msg.sender, _amount);
                  stakeToken.safeTransferFrom(msg.sender, address(this), _amount);
                }
                /**
                 * @dev Deposit tokens to  pool by presale contract
                 */
                function depositByPresale(address _user, uint256 _amount) external onlyPresale {
                  require(block.number < endBlock, 'staking has been ended');
                  require(_amount > 0, "Deposit amount can't be zero");
                  PoolStaker storage staker = poolStakers[_user];
                  // Update pool stakers
                  _harvestRewards(_user);
                  // Update current staker
                  staker.amount += _amount;
                  staker.rewardDebt = (staker.amount * accumulatedRewardsPerShare) / REWARDS_PRECISION;
                  staker.stakedTime = block.timestamp;
                  // Update pool
                  tokensStaked += _amount;
                  tokensStakedByPresale += _amount;
                  // Deposit tokens
                  emit Deposit(_user, _amount);
                  stakeToken.safeTransferFrom(presaleContract, address(this), _amount);
                }
                /**
                 * @dev Withdraw all tokens from existing pool
                 */
                function withdraw() external {
                  PoolStaker memory staker = poolStakers[msg.sender];
                  uint256 amount = staker.amount;
                  require(staker.stakedTime + lockedTime <= block.timestamp && claimStart + lockedTime <= block.timestamp, 'you are not allowed to withdraw before locked Time');
                  require(amount > 0, "Withdraw amount can't be zero");
                  // Pay rewards
                  harvestRewards();
                  //delete staker
                  delete poolStakers[msg.sender];
                  // Update pool
                  tokensStaked -= amount;
                  // Withdraw tokens
                  emit Withdraw(msg.sender, amount);
                  stakeToken.safeTransfer(msg.sender, amount);
                }
                /**
                 * @dev Harvest user rewards
                 */
                function harvestRewards() public {
                  _harvestRewards(msg.sender);
                }
                /**
                 * @dev Harvest user rewards
                 */
                function _harvestRewards(address _user) private {
                  require(!isBlacklisted[_msgSender()], 'This Address is Blacklisted');
                  updatePoolRewards();
                  PoolStaker storage staker = poolStakers[_user];
                  uint256 rewardsToHarvest = ((staker.amount * accumulatedRewardsPerShare) / REWARDS_PRECISION) - staker.rewardDebt;
                  if (rewardsToHarvest == 0) {
                    return;
                  }
                  staker.Harvestedrewards += rewardsToHarvest;
                  staker.rewardDebt = (staker.amount * accumulatedRewardsPerShare) / REWARDS_PRECISION;
                  if (!harvestLock) {
                    if (userLockedRewards[_user] > 0) {
                      rewardsToHarvest += userLockedRewards[_user];
                      userLockedRewards[_user] = 0;
                    }
                    emit HarvestRewards(_user, rewardsToHarvest);
                    stakeToken.safeTransfer(_user, rewardsToHarvest);
                  } else {
                    userLockedRewards[_user] += rewardsToHarvest;
                  }
                }
                /**
                 * @dev Update pool's accumulatedRewardsPerShare and lastRewardedBlock
                 */
                function updatePoolRewards() private {
                  if (tokensStaked == 0) {
                    lastRewardedBlock = block.number;
                    return;
                  }
                  uint256 blocksSinceLastReward = block.number > endBlock ? endBlock - lastRewardedBlock : block.number - lastRewardedBlock;
                  uint256 rewards = blocksSinceLastReward * rewardTokensPerBlock;
                  accumulatedRewardsPerShare = accumulatedRewardsPerShare + ((rewards * REWARDS_PRECISION) / tokensStaked);
                  lastRewardedBlock = block.number > endBlock ? endBlock : block.number;
                }
                /**
                 *@dev To get the number of rewards that user can get
                 */
                function getRewards(address _user) public view returns (uint) {
                  if (tokensStaked == 0) {
                    return 0;
                  }
                  uint256 blocksSinceLastReward = block.number > endBlock ? endBlock - lastRewardedBlock : block.number - lastRewardedBlock;
                  uint256 rewards = blocksSinceLastReward * rewardTokensPerBlock;
                  uint256 accCalc = accumulatedRewardsPerShare + ((rewards * REWARDS_PRECISION) / tokensStaked);
                  PoolStaker memory staker = poolStakers[_user];
                  return ((staker.amount * accCalc) / REWARDS_PRECISION) - staker.rewardDebt + userLockedRewards[_user];
                }
                function setHarvestLock(bool _harvestlock) external onlyOwner {
                  harvestLock = _harvestlock;
                }
                function setPresale(address _presale) external onlyOwner {
                  presaleContract = _presale;
                }
                function setStakeToken(address _stakeToken) external onlyOwner {
                  stakeToken = IERC20Upgradeable(_stakeToken);
                }
                function setLockedTime(uint _time) external onlyOwner {
                  lockedTime = _time;
                }
                function setEndBlock(uint _endBlock) external onlyOwner {
                  endBlock = _endBlock;
                }
                function setClaimStart(uint _claimStart) external onlyOwner {
                  claimStart = _claimStart;
                }
                /**
                 * @dev To add users to blacklist which restricts blacklisted users from claiming
                 * @param _usersToBlacklist addresses of the users
                 */
                function blacklistUsers(address[] calldata _usersToBlacklist) external onlyOwner {
                  for (uint256 i = 0; i < _usersToBlacklist.length; i++) {
                    isBlacklisted[_usersToBlacklist[i]] = true;
                  }
                }
                /**
                 * @dev To remove users from blacklist which restricts blacklisted users from claiming
                 * @param _userToRemoveFromBlacklist addresses of the users
                 */
                function removeFromBlacklist(address[] calldata _userToRemoveFromBlacklist) external onlyOwner {
                  for (uint256 i = 0; i < _userToRemoveFromBlacklist.length; i++) {
                    isBlacklisted[_userToRemoveFromBlacklist[i]] = false;
                  }
                }
              }
              

              File 9 of 9: 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);
              }