ETH Price: $2,417.80 (-0.60%)

Transaction Decoder

Block:
21241654 at Nov-22-2024 07:03:23 AM +UTC
Transaction Fee:
0.000650476512386408 ETH $1.57
Gas Used:
81,658 Gas / 7.965863876 Gwei

Emitted Events:

319 SafeProxy.0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d( 0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d, 0x00000000000000000000000018e011feff8dc3f97026dca36f0d673b9586853e, 0000000000000000000000000000000000000000000000000186cc6acd4b0000 )
320 TransparentUpgradeableProxy.0x0ca214f8a19535023cdee0ea74c48997966a87ed490c81c28c235d8c93c8d19a( 0x0ca214f8a19535023cdee0ea74c48997966a87ed490c81c28c235d8c93c8d19a, 0x0000000000000000000000003d8cd9471d50b0cc318d224a55c138e6ed9241ea, 0x0000000000000000000000003d8cd9471d50b0cc318d224a55c138e6ed9241ea, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000186cc6acd4b0000, 000000000000000000000000000000000000000000007580b9dbd83e97613f54, 00000000000000000000000000000000000000000000000000000000160f7858 )

Account State Difference:

  Address   Before After State Difference Code
0x18e011Fe...b9586853E
0x3d8Cd947...6eD9241Ea
0.118787981012779195 Eth
Nonce: 19
0.008137504500392787 Eth
Nonce: 20
0.110650476512386408
0x5CAc5C3C...3e12F2Fd3 171.938260196512820667 Eth172.048260196512820667 Eth0.11
(beaverbuild)
14.254951203001692417 Eth14.254959368801692417 Eth0.0000081658

Execution Trace

ETH 0.11 TransparentUpgradeableProxy.39f91003( )
  • ETH 0.11 XYZPresale.purchaseWithNativeCoin( recipient=0x3d8Cd9471D50b0Cc318d224a55C138E6eD9241Ea )
    • ETH 0.11 SafeProxy.CALL( )
      • ETH 0.11 Safe.DELEGATECALL( )
      • EACAggregatorProxy.STATICCALL( )
        • AccessControlledOCR2Aggregator.STATICCALL( )
          purchaseWithNativeCoin[XYZPresale (ln:676)]
          File 1 of 6: TransparentUpgradeableProxy
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
          pragma solidity ^0.8.20;
          import {Context} from "../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.
           *
           * The initial owner is set to the address provided by the deployer. 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;
              /**
               * @dev The caller account is not authorized to perform an operation.
               */
              error OwnableUnauthorizedAccount(address account);
              /**
               * @dev The owner is not a valid owner account. (eg. `address(0)`)
               */
              error OwnableInvalidOwner(address owner);
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
              /**
               * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
               */
              constructor(address initialOwner) {
                  if (initialOwner == address(0)) {
                      revert OwnableInvalidOwner(address(0));
                  }
                  _transferOwnership(initialOwner);
              }
              /**
               * @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 {
                  if (owner() != _msgSender()) {
                      revert OwnableUnauthorizedAccount(_msgSender());
                  }
              }
              /**
               * @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 {
                  if (newOwner == address(0)) {
                      revert OwnableInvalidOwner(address(0));
                  }
                  _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 v5.0.0) (interfaces/IERC1967.sol)
          pragma solidity ^0.8.20;
          /**
           * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
           */
          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 v5.0.0) (proxy/beacon/BeaconProxy.sol)
          pragma solidity ^0.8.20;
          import {IBeacon} from "./IBeacon.sol";
          import {Proxy} from "../Proxy.sol";
          import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
          /**
           * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
           *
           * The beacon address can only be set once during construction, and cannot be changed afterwards. It is stored in an
           * immutable variable to avoid unnecessary storage reads, and also in the beacon storage slot specified by
           * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] so that it can be accessed externally.
           *
           * CAUTION: Since the beacon address can never be changed, you must ensure that you either control the beacon, or trust
           * the beacon to not upgrade the implementation maliciously.
           *
           * IMPORTANT: Do not use the implementation logic to modify the beacon storage slot. Doing so would leave the proxy in
           * an inconsistent state where the beacon storage slot does not match the beacon address.
           */
          contract BeaconProxy is Proxy {
              // An immutable address for the beacon to avoid unnecessary SLOADs before each delegate call.
              address private immutable _beacon;
              /**
               * @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}.
               * - If `data` is empty, `msg.value` must be zero.
               */
              constructor(address beacon, bytes memory data) payable {
                  ERC1967Utils.upgradeBeaconToAndCall(beacon, data);
                  _beacon = beacon;
              }
              /**
               * @dev Returns the current implementation address of the associated beacon.
               */
              function _implementation() internal view virtual override returns (address) {
                  return IBeacon(_getBeacon()).implementation();
              }
              /**
               * @dev Returns the beacon.
               */
              function _getBeacon() internal view virtual returns (address) {
                  return _beacon;
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
          pragma solidity ^0.8.20;
          /**
           * @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.
               *
               * {UpgradeableBeacon} will check that this address is a contract.
               */
              function implementation() external view returns (address);
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/UpgradeableBeacon.sol)
          pragma solidity ^0.8.20;
          import {IBeacon} from "./IBeacon.sol";
          import {Ownable} from "../../access/Ownable.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 The `implementation` of the beacon is invalid.
               */
              error BeaconInvalidImplementation(address 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 initial owner who can upgrade the beacon.
               */
              constructor(address implementation_, address initialOwner) Ownable(initialOwner) {
                  _setImplementation(implementation_);
              }
              /**
               * @dev Returns the current implementation address.
               */
              function implementation() public view virtual 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);
              }
              /**
               * @dev Sets the implementation contract address for this beacon
               *
               * Requirements:
               *
               * - `newImplementation` must be a contract.
               */
              function _setImplementation(address newImplementation) private {
                  if (newImplementation.code.length == 0) {
                      revert BeaconInvalidImplementation(newImplementation);
                  }
                  _implementation = newImplementation;
                  emit Upgraded(newImplementation);
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)
          pragma solidity ^0.8.20;
          import {Proxy} from "../Proxy.sol";
          import {ERC1967Utils} from "./ERC1967Utils.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 {
              /**
               * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
               *
               * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
               * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
               *
               * Requirements:
               *
               * - If `data` is empty, `msg.value` must be zero.
               */
              constructor(address implementation, bytes memory _data) payable {
                  ERC1967Utils.upgradeToAndCall(implementation, _data);
              }
              /**
               * @dev Returns the current implementation address.
               *
               * 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() internal view virtual override returns (address) {
                  return ERC1967Utils.getImplementation();
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)
          pragma solidity ^0.8.20;
          import {IBeacon} from "../beacon/IBeacon.sol";
          import {Address} from "../../utils/Address.sol";
          import {StorageSlot} from "../../utils/StorageSlot.sol";
          /**
           * @dev This abstract contract provides getters and event emitting update functions for
           * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
           */
          library ERC1967Utils {
              // We re-declare ERC-1967 events here because they can't be used directly from IERC1967.
              // This will be fixed in Solidity 0.8.21. At that point we should remove these events.
              /**
               * @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);
              /**
               * @dev Storage slot with the address of the current implementation.
               * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
               */
              // solhint-disable-next-line private-vars-leading-underscore
              bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
              /**
               * @dev The `implementation` of the proxy is invalid.
               */
              error ERC1967InvalidImplementation(address implementation);
              /**
               * @dev The `admin` of the proxy is invalid.
               */
              error ERC1967InvalidAdmin(address admin);
              /**
               * @dev The `beacon` of the proxy is invalid.
               */
              error ERC1967InvalidBeacon(address beacon);
              /**
               * @dev An upgrade function sees `msg.value > 0` that may be lost.
               */
              error ERC1967NonPayable();
              /**
               * @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 {
                  if (newImplementation.code.length == 0) {
                      revert ERC1967InvalidImplementation(newImplementation);
                  }
                  StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
              }
              /**
               * @dev Performs implementation upgrade with additional setup call if data is nonempty.
               * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
               * to avoid stuck value in the contract.
               *
               * Emits an {IERC1967-Upgraded} event.
               */
              function upgradeToAndCall(address newImplementation, bytes memory data) internal {
                  _setImplementation(newImplementation);
                  emit Upgraded(newImplementation);
                  if (data.length > 0) {
                      Address.functionDelegateCall(newImplementation, data);
                  } else {
                      _checkNonPayable();
                  }
              }
              /**
               * @dev Storage slot with the admin of the contract.
               * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
               */
              // solhint-disable-next-line private-vars-leading-underscore
              bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
              /**
               * @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 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 {
                  if (newAdmin == address(0)) {
                      revert ERC1967InvalidAdmin(address(0));
                  }
                  StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
              }
              /**
               * @dev Changes the admin of the proxy.
               *
               * Emits an {IERC1967-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 the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
               */
              // solhint-disable-next-line private-vars-leading-underscore
              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 {
                  if (newBeacon.code.length == 0) {
                      revert ERC1967InvalidBeacon(newBeacon);
                  }
                  StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
                  address beaconImplementation = IBeacon(newBeacon).implementation();
                  if (beaconImplementation.code.length == 0) {
                      revert ERC1967InvalidImplementation(beaconImplementation);
                  }
              }
              /**
               * @dev Change the beacon and trigger a setup call if data is nonempty.
               * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
               * to avoid stuck value in the contract.
               *
               * Emits an {IERC1967-BeaconUpgraded} event.
               *
               * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
               * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
               * efficiency.
               */
              function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
                  _setBeacon(newBeacon);
                  emit BeaconUpgraded(newBeacon);
                  if (data.length > 0) {
                      Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                  } else {
                      _checkNonPayable();
                  }
              }
              /**
               * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
               * if an upgrade doesn't perform an initialization call.
               */
              function _checkNonPayable() private {
                  if (msg.value > 0) {
                      revert ERC1967NonPayable();
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)
          pragma solidity ^0.8.20;
          /**
           * @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 {
                  _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();
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol)
          pragma solidity ^0.8.20;
          import {ITransparentUpgradeableProxy} from "./TransparentUpgradeableProxy.sol";
          import {Ownable} from "../../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 The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)`
               * and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
               * while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string.
               * If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must
               * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
               * during an upgrade.
               */
              string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
              /**
               * @dev Sets the initial owner who can perform upgrades.
               */
              constructor(address initialOwner) Ownable(initialOwner) {}
              /**
               * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.
               * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.
               *
               * Requirements:
               *
               * - This contract must be the admin of `proxy`.
               * - If `data` is empty, `msg.value` must be zero.
               */
              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 v5.0.0) (proxy/transparent/TransparentUpgradeableProxy.sol)
          pragma solidity ^0.8.20;
          import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
          import {ERC1967Proxy} from "../ERC1967/ERC1967Proxy.sol";
          import {IERC1967} from "../../interfaces/IERC1967.sol";
          import {ProxyAdmin} from "./ProxyAdmin.sol";
          /**
           * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
           * does not implement this interface directly, and its upgradeability mechanism is 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 upgradeToAndCall(address, bytes calldata) external payable;
          }
          /**
           * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance.
           *
           * 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 the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.
           * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to
           * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating
           * the proxy admin cannot fallback to the target implementation.
           *
           * These properties mean that the admin account can only be used for upgrading the proxy, 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. For this reason, the proxy deploys an instance of {ProxyAdmin} and
           * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative
           * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership.
           *
           * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
           * inherit from that interface, and instead `upgradeToAndCall` is 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.
           *
           * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a
           * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract.
           *
           * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an
           * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be
           * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an
           * undesirable state where the admin slot is different from the actual admin.
           *
           * 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 `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency.
           */
          contract TransparentUpgradeableProxy is ERC1967Proxy {
              // An immutable address for the admin to avoid unnecessary SLOADs before each call
              // at the expense of removing the ability to change the admin once it's set.
              // This is acceptable if the admin is always a ProxyAdmin instance or similar contract
              // with its own ability to transfer the permissions to another account.
              address private immutable _admin;
              /**
               * @dev The proxy caller is the current admin, and can't fallback to the proxy target.
               */
              error ProxyDeniedAdminAccess();
              /**
               * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`,
               * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in
               * {ERC1967Proxy-constructor}.
               */
              constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
                  _admin = address(new ProxyAdmin(initialOwner));
                  // Set the storage value and emit an event for ERC-1967 compatibility
                  ERC1967Utils.changeAdmin(_proxyAdmin());
              }
              /**
               * @dev Returns the admin of this proxy.
               */
              function _proxyAdmin() internal virtual returns (address) {
                  return _admin;
              }
              /**
               * @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 == _proxyAdmin()) {
                      if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                          revert ProxyDeniedAdminAccess();
                      } else {
                          _dispatchUpgradeToAndCall();
                      }
                  } else {
                      super._fallback();
                  }
              }
              /**
               * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}.
               *
               * Requirements:
               *
               * - If `data` is empty, `msg.value` must be zero.
               */
              function _dispatchUpgradeToAndCall() private {
                  (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
                  ERC1967Utils.upgradeToAndCall(newImplementation, data);
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
          pragma solidity ^0.8.20;
          /**
           * @dev Collection of functions related to the address type
           */
          library Address {
              /**
               * @dev The ETH balance of the account is not enough to perform the operation.
               */
              error AddressInsufficientBalance(address account);
              /**
               * @dev There's no code at `target` (it is not a contract).
               */
              error AddressEmptyCode(address target);
              /**
               * @dev A call to an address target failed. The target may have reverted.
               */
              error FailedInnerCall();
              /**
               * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
               */
              function sendValue(address payable recipient, uint256 amount) internal {
                  if (address(this).balance < amount) {
                      revert AddressInsufficientBalance(address(this));
                  }
                  (bool success, ) = recipient.call{value: amount}("");
                  if (!success) {
                      revert FailedInnerCall();
                  }
              }
              /**
               * @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 or custom error, it is bubbled
               * up by this function (like regular Solidity function calls). However, if
               * the call reverted with no returned reason, this function reverts with a
               * {FailedInnerCall} error.
               *
               * 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.
               */
              function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                  return functionCallWithValue(target, data, 0);
              }
              /**
               * @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`.
               */
              function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                  if (address(this).balance < value) {
                      revert AddressInsufficientBalance(address(this));
                  }
                  (bool success, bytes memory returndata) = target.call{value: value}(data);
                  return verifyCallResultFromTarget(target, success, returndata);
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
               * but performing a static call.
               */
              function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                  (bool success, bytes memory returndata) = target.staticcall(data);
                  return verifyCallResultFromTarget(target, success, returndata);
              }
              /**
               * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
               * but performing a delegate call.
               */
              function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                  (bool success, bytes memory returndata) = target.delegatecall(data);
                  return verifyCallResultFromTarget(target, success, returndata);
              }
              /**
               * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
               * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
               * unsuccessful call.
               */
              function verifyCallResultFromTarget(
                  address target,
                  bool success,
                  bytes memory returndata
              ) internal view returns (bytes memory) {
                  if (!success) {
                      _revert(returndata);
                  } else {
                      // only check if target is a contract if the call was successful and the return data is empty
                      // otherwise we already know that it was a contract
                      if (returndata.length == 0 && target.code.length == 0) {
                          revert AddressEmptyCode(target);
                      }
                      return returndata;
                  }
              }
              /**
               * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
               * revert reason or with a default {FailedInnerCall} error.
               */
              function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
                  if (!success) {
                      _revert(returndata);
                  } else {
                      return returndata;
                  }
              }
              /**
               * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
               */
              function _revert(bytes memory returndata) 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 FailedInnerCall();
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
          pragma solidity ^0.8.20;
          /**
           * @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;
              }
              function _contextSuffixLength() internal view virtual returns (uint256) {
                  return 0;
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
          // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
          pragma solidity ^0.8.20;
          /**
           * @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:
           * ```solidity
           * 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(newImplementation.code.length > 0);
           *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
           *     }
           * }
           * ```
           */
          library StorageSlot {
              struct AddressSlot {
                  address value;
              }
              struct BooleanSlot {
                  bool value;
              }
              struct Bytes32Slot {
                  bytes32 value;
              }
              struct Uint256Slot {
                  uint256 value;
              }
              struct StringSlot {
                  string value;
              }
              struct BytesSlot {
                  bytes 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
                  }
              }
              /**
               * @dev Returns an `StringSlot` with member `value` located at `slot`.
               */
              function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      r.slot := slot
                  }
              }
              /**
               * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
               */
              function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      r.slot := store.slot
                  }
              }
              /**
               * @dev Returns an `BytesSlot` with member `value` located at `slot`.
               */
              function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      r.slot := slot
                  }
              }
              /**
               * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
               */
              function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
                  /// @solidity memory-safe-assembly
                  assembly {
                      r.slot := store.slot
                  }
              }
          }
          

          File 2 of 6: SafeProxy
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /**
           * @title IProxy - Helper interface to access the singleton address of the Proxy on-chain.
           * @author Richard Meissner - @rmeissner
           */
          interface IProxy {
              function masterCopy() external view returns (address);
          }
          /**
           * @title SafeProxy - 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 SafeProxy {
              // 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;
              /**
               * @notice 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())
                  }
              }
          }
          

          File 3 of 6: XYZPresale
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          // solhint-disable-next-line interface-starts-with-i
          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
          // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
          pragma solidity ^0.8.20;
          import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
          import {Initializable} from "../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.
           *
           * The initial owner is set to the address provided by the deployer. 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 {
              /// @custom:storage-location erc7201:openzeppelin.storage.Ownable
              struct OwnableStorage {
                  address _owner;
              }
              // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
              bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
              function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
                  assembly {
                      $.slot := OwnableStorageLocation
                  }
              }
              /**
               * @dev The caller account is not authorized to perform an operation.
               */
              error OwnableUnauthorizedAccount(address account);
              /**
               * @dev The owner is not a valid owner account. (eg. `address(0)`)
               */
              error OwnableInvalidOwner(address owner);
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
              /**
               * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
               */
              function __Ownable_init(address initialOwner) internal onlyInitializing {
                  __Ownable_init_unchained(initialOwner);
              }
              function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
                  if (initialOwner == address(0)) {
                      revert OwnableInvalidOwner(address(0));
                  }
                  _transferOwnership(initialOwner);
              }
              /**
               * @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) {
                  OwnableStorage storage $ = _getOwnableStorage();
                  return $._owner;
              }
              /**
               * @dev Throws if the sender is not the owner.
               */
              function _checkOwner() internal view virtual {
                  if (owner() != _msgSender()) {
                      revert OwnableUnauthorizedAccount(_msgSender());
                  }
              }
              /**
               * @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 {
                  if (newOwner == address(0)) {
                      revert OwnableInvalidOwner(address(0));
                  }
                  _transferOwnership(newOwner);
              }
              /**
               * @dev Transfers ownership of the contract to a new account (`newOwner`).
               * Internal function without access restriction.
               */
              function _transferOwnership(address newOwner) internal virtual {
                  OwnableStorage storage $ = _getOwnableStorage();
                  address oldOwner = $._owner;
                  $._owner = newOwner;
                  emit OwnershipTransferred(oldOwner, newOwner);
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
          pragma solidity ^0.8.20;
          /**
           * @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 Storage of the initializable contract.
               *
               * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
               * when using with upgradeable contracts.
               *
               * @custom:storage-location erc7201:openzeppelin.storage.Initializable
               */
              struct InitializableStorage {
                  /**
                   * @dev Indicates that the contract has been initialized.
                   */
                  uint64 _initialized;
                  /**
                   * @dev Indicates that the contract is in the process of being initialized.
                   */
                  bool _initializing;
              }
              // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
              bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
              /**
               * @dev The contract is already initialized.
               */
              error InvalidInitialization();
              /**
               * @dev The contract is not initializing.
               */
              error NotInitializing();
              /**
               * @dev Triggered when the contract has been initialized or reinitialized.
               */
              event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any
               * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
               * production.
               *
               * Emits an {Initialized} event.
               */
              modifier initializer() {
                  // solhint-disable-next-line var-name-mixedcase
                  InitializableStorage storage $ = _getInitializableStorage();
                  // Cache values to avoid duplicated sloads
                  bool isTopLevelCall = !$._initializing;
                  uint64 initialized = $._initialized;
                  // Allowed calls:
                  // - initialSetup: the contract is not in the initializing state and no previous version was
                  //                 initialized
                  // - construction: the contract is initialized at version 1 (no reininitialization) and the
                  //                 current contract is just being deployed
                  bool initialSetup = initialized == 0 && isTopLevelCall;
                  bool construction = initialized == 1 && address(this).code.length == 0;
                  if (!initialSetup && !construction) {
                      revert InvalidInitialization();
                  }
                  $._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 2**64 - 1 will prevent any future reinitialization.
               *
               * Emits an {Initialized} event.
               */
              modifier reinitializer(uint64 version) {
                  // solhint-disable-next-line var-name-mixedcase
                  InitializableStorage storage $ = _getInitializableStorage();
                  if ($._initializing || $._initialized >= version) {
                      revert InvalidInitialization();
                  }
                  $._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() {
                  _checkInitializing();
                  _;
              }
              /**
               * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
               */
              function _checkInitializing() internal view virtual {
                  if (!_isInitializing()) {
                      revert NotInitializing();
                  }
              }
              /**
               * @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 {
                  // solhint-disable-next-line var-name-mixedcase
                  InitializableStorage storage $ = _getInitializableStorage();
                  if ($._initializing) {
                      revert InvalidInitialization();
                  }
                  if ($._initialized != type(uint64).max) {
                      $._initialized = type(uint64).max;
                      emit Initialized(type(uint64).max);
                  }
              }
              /**
               * @dev Returns the highest version that has been initialized. See {reinitializer}.
               */
              function _getInitializedVersion() internal view returns (uint64) {
                  return _getInitializableStorage()._initialized;
              }
              /**
               * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
               */
              function _isInitializing() internal view returns (bool) {
                  return _getInitializableStorage()._initializing;
              }
              /**
               * @dev Returns a pointer to the storage namespace.
               */
              // solhint-disable-next-line var-name-mixedcase
              function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
                  assembly {
                      $.slot := INITIALIZABLE_STORAGE
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
          pragma solidity ^0.8.20;
          import {Initializable} from "../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;
              }
              function _contextSuffixLength() internal view virtual returns (uint256) {
                  return 0;
              }
          }
          // SPDX-License-Identifier: MIT
          // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
          pragma solidity ^0.8.20;
          import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
          import {Initializable} from "../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 {
              /// @custom:storage-location erc7201:openzeppelin.storage.Pausable
              struct PausableStorage {
                  bool _paused;
              }
              // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
              bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;
              function _getPausableStorage() private pure returns (PausableStorage storage $) {
                  assembly {
                      $.slot := PausableStorageLocation
                  }
              }
              /**
               * @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);
              /**
               * @dev The operation failed because the contract is paused.
               */
              error EnforcedPause();
              /**
               * @dev The operation failed because the contract is not paused.
               */
              error ExpectedPause();
              /**
               * @dev Initializes the contract in unpaused state.
               */
              function __Pausable_init() internal onlyInitializing {
                  __Pausable_init_unchained();
              }
              function __Pausable_init_unchained() internal onlyInitializing {
                  PausableStorage storage $ = _getPausableStorage();
                  $._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) {
                  PausableStorage storage $ = _getPausableStorage();
                  return $._paused;
              }
              /**
               * @dev Throws if the contract is paused.
               */
              function _requireNotPaused() internal view virtual {
                  if (paused()) {
                      revert EnforcedPause();
                  }
              }
              /**
               * @dev Throws if the contract is not paused.
               */
              function _requirePaused() internal view virtual {
                  if (!paused()) {
                      revert ExpectedPause();
                  }
              }
              /**
               * @dev Triggers stopped state.
               *
               * Requirements:
               *
               * - The contract must not be paused.
               */
              function _pause() internal virtual whenNotPaused {
                  PausableStorage storage $ = _getPausableStorage();
                  $._paused = true;
                  emit Paused(_msgSender());
              }
              /**
               * @dev Returns to normal state.
               *
               * Requirements:
               *
               * - The contract must be paused.
               */
              function _unpause() internal virtual whenPaused {
                  PausableStorage storage $ = _getPausableStorage();
                  $._paused = false;
                  emit Unpaused(_msgSender());
              }
          }
          // SPDX-License-Identifier: GPL-3.0-or-later
          pragma solidity >=0.6.0;
          // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
          library TransferHelper {
              function safeApprove(
                  address token,
                  address to,
                  uint256 value
              ) internal {
                  // bytes4(keccak256(bytes('approve(address,uint256)')));
                  (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
                  require(
                      success && (data.length == 0 || abi.decode(data, (bool))),
                      'TransferHelper::safeApprove: approve failed'
                  );
              }
              function safeTransfer(
                  address token,
                  address to,
                  uint256 value
              ) internal {
                  // bytes4(keccak256(bytes('transfer(address,uint256)')));
                  (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
                  require(
                      success && (data.length == 0 || abi.decode(data, (bool))),
                      'TransferHelper::safeTransfer: transfer failed'
                  );
              }
              function safeTransferFrom(
                  address token,
                  address from,
                  address to,
                  uint256 value
              ) internal {
                  // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
                  (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
                  require(
                      success && (data.length == 0 || abi.decode(data, (bool))),
                      'TransferHelper::transferFrom: transferFrom failed'
                  );
              }
              function safeTransferETH(address to, uint256 value) internal {
                  (bool success, ) = to.call{value: value}(new bytes(0));
                  require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
              }
          }
          // SPDX-License-Identifier: GPL-3.0
          pragma solidity ^0.8.24;
          interface IXYZPresale {
              event ExternallyPurchased(address indexed recipient, uint256 purchasedXYZ, uint128 paidUSD, bytes[] paymentDetails);
              event Purchased(
                  address indexed purchaseer,
                  address indexed recipient,
                  address indexed paymentToken,
                  uint256 paymentAmount,
                  uint256 purchasedXYZ,
                  uint256 paidUSD
              );
              event TokenStatusUpdated(address token, bool isPaymentToken);
              event TreasuryAddressUpdated(address newTreasury);
              event XYZPriceUpdated(uint256 newPrice);
              error InsufficientPurchase();
              error InvalidPaymentToken();
              error InvalidPrice();
              error NoChange();
              error ZeroDecimalsPaymentToken();
              function pause() external;
              function unpause() external;
              function creditExternalPurchase(
                  address recipient,
                  uint256 purchasedXYZ,
                  uint128 paidUSD,
                  bytes[] calldata paymentDetails
              ) external;
              function updateTokenStatus(address token, bool isPaymentToken) external;
              function updateTreasuryAddress(address newTreasury) external;
              function updateXYZPrice(uint128 newPrice) external;
              function purchaseWithNativeCoin(address recipient) external payable;
              function purchaseWithToken(address recipient, address paymentToken, uint256 paymentAmount) external;
              function balanceOf(address account) external view returns (uint256);
              function xyzPriceInNativeCoin() external view returns (uint256);
          }
          // SPDX-License-Identifier: GPL-3.0
          pragma solidity ^0.8.24;
          import './IXYZPresale.sol';
          import '@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol';
          import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
          import '@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol';
          import '@uniswap/lib/contracts/libraries/TransferHelper.sol';
          interface IERC20 {
              function decimals() external view returns (uint8);
          }
          // @notice A contract for handling the XYZ token presale, supporting payments in native coins and USD ERC20 tokens.
          contract XYZPresale is PausableUpgradeable, OwnableUpgradeable, IXYZPresale {
              uint256 constant XYZ_BASE = 1e18;
              uint256 constant USD_BASE = 1e6;
              uint256 constant NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR = 1e20; // 1e18 * 1e8 / 1e6
              AggregatorV3Interface public nativeCoinPriceFeed;
              mapping(address => uint256) public paymentTokensBases;
              uint128 public xyzPrice;
              uint128 public totalCollectedUSD;
              address public treasury;
              mapping(address => uint256) internal _balances;
              /// @custom:oz-upgrades-unsafe-allow constructor
              constructor() {
                  _disableInitializers();
              }
              /**
               * @param nativeCoinPriceFeed_ Price feed for the native currency.
               * @param paymentTokens_ Array of accepted USD ERC20 tokens for payment.
               * @param xyzPrice_ Initial price of 1 XYZ token in USD, scaled by 1e6.
               * @param treasury_ Address of the treasury to receive payments.
               * @param owner_ The contract owner address.
               */
              function initialize(
                  AggregatorV3Interface nativeCoinPriceFeed_,
                  address[] calldata paymentTokens_,
                  uint128 xyzPrice_,
                  address treasury_,
                  address owner_
              ) external initializer {
                  if (xyzPrice_ == 0) revert InvalidPrice();
                  __Ownable_init(owner_);
                  _pause();
                  nativeCoinPriceFeed = nativeCoinPriceFeed_;
                  xyzPrice = xyzPrice_;
                  treasury = treasury_;
                  for (uint256 i = 0; i < paymentTokens_.length; i++) {
                      _addPaymentToken(paymentTokens_[i]);
                  }
              }
              /**
               * @notice Owner: Pauses the presale, preventing purchases.
               */
              function pause() external onlyOwner {
                  _pause();
              }
              /**
               * @notice Owner: Unpauses the presale, allowing purchases.
               */
              function unpause() external onlyOwner {
                  _unpause();
              }
              /**
               * @notice Owner: Credits a recipient with tokens from an external purchase.
               * @param recipient Address receiving the purchased XYZ tokens.
               * @param purchasedXYZ Amount of XYZ tokens purchased.
               * @param paidUSD The amount of the USD used for the purchase, scaled by 1e6;
               * @param paymentDetails Additional details of the payment.
               */
              function creditExternalPurchase(
                  address recipient,
                  uint256 purchasedXYZ,
                  uint128 paidUSD,
                  bytes[] calldata paymentDetails
              ) external onlyOwner {
                  _balances[recipient] += purchasedXYZ;
                  totalCollectedUSD += paidUSD;
                  emit ExternallyPurchased(recipient, purchasedXYZ, paidUSD, paymentDetails);
              }
              /**
               * @notice Owner: Updates the status of an ERC20 token as a valid payment method.
               * @param token The token address to update.
               * @param isPaymentToken Whether the token is accepted for payment.
               */
              function updateTokenStatus(address token, bool isPaymentToken) external onlyOwner {
                  if (bool(paymentTokensBases[token] != 0) == isPaymentToken) revert NoChange();
                  if (isPaymentToken) {
                      _addPaymentToken(token);
                  } else {
                      paymentTokensBases[token] = 0;
                  }
                  emit TokenStatusUpdated(token, isPaymentToken);
              }
              /**
               * @notice Owner: Updates the treasury address where payments are sent.
               * @param newTreasury The new treasury address.
               */
              function updateTreasuryAddress(address newTreasury) external onlyOwner {
                  if (treasury == newTreasury) revert NoChange();
                  treasury = newTreasury;
                  emit TreasuryAddressUpdated(newTreasury);
              }
              /**
               * @notice Owner: Updates the price of the XYZ token.
               * @param newPrice The new price for XYZ in USD, scaled by 1e6.
               */
              function updateXYZPrice(uint128 newPrice) external onlyOwner {
                  if (newPrice == xyzPrice) revert NoChange();
                  if (newPrice == 0) revert InvalidPrice();
                  xyzPrice = newPrice;
                  emit XYZPriceUpdated(newPrice);
              }
              /**
               * @notice Purchase XYZ tokens using native currency.
               * @param recipient The address receiving the purchased XYZ tokens.
               */
              function purchaseWithNativeCoin(address recipient) external payable whenNotPaused {
                  TransferHelper.safeTransferETH(treasury, msg.value);
                  (, int256 nativeCoinPrice, , , ) = nativeCoinPriceFeed.latestRoundData();
                  uint256 paidUSD = (msg.value * uint256(nativeCoinPrice)) / NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR;
                  uint256 purchasedXYZ = _processPurchase(recipient, paidUSD);
                  emit Purchased(msg.sender, recipient, address(0), msg.value, purchasedXYZ, paidUSD);
              }
              /**
               * @notice Purchase XYZ tokens using an ERC20 token.
               * @param recipient The address receiving the purchased XYZ tokens.
               * @param paymentToken The ERC20 token used for payment.
               * @param paymentAmount The amount of the token used for the purchase.
               */
              function purchaseWithToken(address recipient, address paymentToken, uint256 paymentAmount) external whenNotPaused {
                  uint256 paymentTokenBase = paymentTokensBases[paymentToken];
                  if (paymentTokenBase == 0) revert InvalidPaymentToken();
                  TransferHelper.safeTransferFrom(paymentToken, msg.sender, treasury, paymentAmount);
                  uint256 paidUSD = (paymentAmount * USD_BASE) / paymentTokenBase;
                  uint256 purchasedXYZ = _processPurchase(recipient, paidUSD);
                  emit Purchased(msg.sender, recipient, paymentToken, paymentAmount, purchasedXYZ, paidUSD);
              }
              /**
               * @notice Returns the balance of XYZ tokens for `account`.
               */
              function balanceOf(address account) external view returns (uint256) {
                  return _balances[account];
              }
              /**
               * @notice Returns the current price of 1 XYZ token in native currency.
               * @return The price of 1 XYZ token in native coin.
               */
              function xyzPriceInNativeCoin() external view returns (uint256) {
                  (, int256 nativeCoinPrice, , , ) = nativeCoinPriceFeed.latestRoundData();
                  return (xyzPrice * NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR) / uint256(nativeCoinPrice);
              }
              /**
               * @notice Adds an ERC20 token to the list of accepted payment tokens.
               * @param paymentToken The ERC20 token to add.
               */
              function _addPaymentToken(address paymentToken) internal {
                  uint256 paymentTokenDecimals = IERC20(paymentToken).decimals();
                  if (paymentTokenDecimals == 0) revert ZeroDecimalsPaymentToken();
                  paymentTokensBases[paymentToken] = 10 ** paymentTokenDecimals;
              }
              /**
               * @notice Processes the purchase and calculates the amount of XYZ tokens to credit.
               * @param recipient The address receiving the purchased tokens.
               * @param paidUSD The amount of USD used for the purchase, scaled by 1e6.
               * @return The amount of XYZ tokens credited to the recipient.
               */
              function _processPurchase(address recipient, uint256 paidUSD) internal returns (uint256) {
                  uint256 purchasedXYZ = (paidUSD * XYZ_BASE) / xyzPrice;
                  if (purchasedXYZ == 0) revert InsufficientPurchase();
                  totalCollectedUSD += uint128(paidUSD);
                  _balances[recipient] += purchasedXYZ;
                  return purchasedXYZ;
              }
          }
          

          File 4 of 6: Safe
          // 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/NativeCurrencyPaymentFallback.sol";
          import "./common/Singleton.sol";
          import "./common/SignatureDecoder.sol";
          import "./common/SecuredTokenTransfer.sol";
          import "./common/StorageAccessible.sol";
          import "./interfaces/ISignatureValidator.sol";
          import "./external/SafeMath.sol";
          /**
           * @title Safe - A multisignature wallet with support for confirmations using signed messages based on EIP-712.
           * @dev Most important concepts:
           *      - Threshold: Number of required confirmations for a Safe transaction.
           *      - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and
           *        approve transactions. Managed in `OwnerManager`.
           *      - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme.
           *      - Nonce: Each transaction should have a different nonce to prevent replay attacks.
           *      - Signature: A valid signature of an owner of the Safe for a transaction hash.
           *      - Guard: Guard is a contract that can execute pre- and post- transaction checks. Managed in `GuardManager`.
           *      - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`.
           *      - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`.
           *      Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/
           *      For the events-based implementation see `SafeL2.sol`.
           * @author Stefan George - @Georgi87
           * @author Richard Meissner - @rmeissner
           */
          contract Safe is
              Singleton,
              NativeCurrencyPaymentFallback,
              ModuleManager,
              OwnerManager,
              SignatureDecoder,
              SecuredTokenTransfer,
              ISignatureValidatorConstants,
              FallbackManager,
              StorageAccessible,
              GuardManager
          {
              using SafeMath for uint256;
              string public constant VERSION = "1.4.1";
              // 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 indexed txHash, uint256 payment);
              event ExecutionSuccess(bytes32 indexed txHash, uint256 payment);
              uint256 public nonce;
              bytes32 private _deprecatedDomainSeparator;
              // Mapping to keep track of all message hashes that have been approved by ALL REQUIRED owners
              mapping(bytes32 => uint256) public signedMessages;
              // Mapping to keep track of all hashes (message or transaction) that have been approved by ANY owners
              mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
              // This constructor ensures that this contract can only be used as a singleton 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;
              }
              /**
               * @notice Sets an initial storage of the Safe contract.
               * @dev This method can only be called once.
               *      If a proxy was created without setting up, anyone can call setup and claim the proxy.
               * @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 Address 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);
              }
              /** @notice Executes a `operation` {0: Call, 1: DelegateCall}} transaction to `to` with `value` (Native Currency)
               *          and pays `gasPrice` * `gasLimit` in `gasToken` token to `refundReceiver`.
               * @dev The fees are always transferred, even if the user transaction fails.
               *      This method doesn't perform any sanity check of the transaction, such as:
               *      - if the contract at `to` address has code or not
               *      - if the `gasToken` is a contract or not
               *      It is the responsibility of the caller to perform such checks.
               * @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 Signature data that should be verified.
               *                   Can be packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), contract signature (EIP-1271) or approved hash.
               * @return success Boolean indicating transaction's success.
               */
              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);
                      }
                  }
              }
              /**
               * @notice Handles the payment for a Safe transaction.
               * @param gasUsed Gas used by 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.
               * @return payment The amount of payment made in the specified token.
               */
              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");
                  }
              }
              /**
               * @notice Checks whether the signature provided is valid for the provided data and hash. Reverts 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 packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), 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);
              }
              /**
               * @notice Checks whether the signature provided is valid for the provided data and hash. Reverts otherwise.
               * @dev Since the EIP-1271 does an external call, be mindful of reentrancy attacks.
               * @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 packed ECDSA signature ({bytes32 r}{bytes32 s}{uint8 v}), 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) {
                          require(keccak256(data) == dataHash, "GS027");
                          // 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;
                  }
              }
              /**
               * @notice Marks hash `hashToApprove` as approved.
               * @dev This can be used with a pre-approved hash transaction signature.
               *      IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures
               * @param hashToApprove The hash to mark 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);
              }
              /**
               * @notice Returns the ID of the chain the contract is currently deployed on.
               * @return The ID of the current chain as a uint256.
               */
              function getChainId() public view returns (uint256) {
                  uint256 id;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      id := chainid()
                  }
                  return id;
              }
              /**
               * @dev Returns the domain separator for this contract, as defined in the EIP-712 standard.
               * @return bytes32 The domain separator hash.
               */
              function domainSeparator() public view returns (bytes32) {
                  return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));
              }
              /**
               * @notice Returns the pre-image of the transaction hash (see getTransactionHash).
               * @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);
              }
              /**
               * @notice Returns transaction 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 - @rmeissner
           */
          abstract contract Executor {
              /**
               * @notice Executes either a delegatecall or a call with provided parameters.
               * @dev This method doesn't perform any sanity check of the transaction, such as:
               *      - if the contract at `to` address has code or not
               *      It is the responsibility of the caller to perform such checks.
               * @param to Destination address.
               * @param value Ether value.
               * @param data Data payload.
               * @param operation Operation type.
               * @return success boolean flag indicating if the call succeeded.
               */
              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 managing fallback calls made to this contract
           * @author Richard Meissner - @rmeissner
           */
          abstract contract FallbackManager is SelfAuthorized {
              event ChangedFallbackHandler(address indexed handler);
              // keccak256("fallback_manager.handler.address")
              bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;
              /**
               *  @notice Internal function to set the fallback handler.
               *  @param handler contract to handle fallback calls.
               */
              function internalSetFallbackHandler(address handler) internal {
                  /*
                      If a fallback handler is set to self, then the following attack vector is opened:
                      Imagine we have a function like this:
                      function withdraw() internal authorized {
                          withdrawalAddress.call.value(address(this).balance)("");
                      }
                      If the fallback method is triggered, the fallback handler appends the msg.sender address to the calldata and calls the fallback handler.
                      A potential attacker could call a Safe with the 3 bytes signature of a withdraw function. Since 3 bytes do not create a valid signature,
                      the call would end in a fallback handler. Since it appends the msg.sender address to the calldata, the attacker could craft an address 
                      where the first 3 bytes of the previous calldata + the first byte of the address make up a valid function signature. The subsequent call would result in unsanctioned access to Safe's internal protected methods.
                      For some reason, solidity matches the first 4 bytes of the calldata to a function signature, regardless if more data follow these 4 bytes.
                  */
                  require(handler != address(this), "GS400");
                  bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      sstore(slot, handler)
                  }
              }
              /**
               * @notice Set Fallback Handler to `handler` for the Safe.
               * @dev Only fallback calls without value and with data will be forwarded.
               *      This can only be done via a Safe transaction.
               *      Cannot be set to the Safe itself.
               * @param handler contract to handle fallback calls.
               */
              function setFallbackHandler(address handler) public authorized {
                  internalSetFallbackHandler(handler);
                  emit ChangedFallbackHandler(handler);
              }
              // @notice Forwards all calls to the fallback handler if set. Returns 0 if no handler is set.
              // @dev Appends the non-padded caller address to the calldata to be optionally used in the handler
              //      The handler can make us of `HandlerContext.sol` to extract the address.
              //      This is done because in the next call frame the `msg.sender` will be FallbackManager's address
              //      and having the original caller address may enable additional verification scenarios.
              // 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";
          import "../interfaces/IERC165.sol";
          interface Guard is IERC165 {
              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;
          }
          abstract contract BaseGuard is Guard {
              function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
                  return
                      interfaceId == type(Guard).interfaceId || // 0xe6d7a83a
                      interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7
              }
          }
          /**
           * @title Guard Manager - A contract managing transaction guards which perform pre and post-checks on Safe transactions.
           * @author Richard Meissner - @rmeissner
           */
          abstract contract GuardManager is SelfAuthorized {
              event ChangedGuard(address indexed guard);
              // keccak256("guard_manager.guard.address")
              bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
              /**
               * @dev Set a guard that checks transactions before execution
               *      This can only be done via a Safe transaction.
               *      ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution,
               *        a broken guard can cause a denial of service for the Safe. Make sure to carefully
               *        audit the guard code and design recovery mechanisms.
               * @notice Set Transaction Guard `guard` for the Safe. Make sure you trust the guard.
               * @param guard The address of the guard to be used or the 0 address to disable the guard
               */
              function setGuard(address guard) external authorized {
                  if (guard != address(0)) {
                      require(Guard(guard).supportsInterface(type(Guard).interfaceId), "GS300");
                  }
                  bytes32 slot = GUARD_STORAGE_SLOT;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      sstore(slot, guard)
                  }
                  emit ChangedGuard(guard);
              }
              /**
               * @dev Internal method to retrieve the current guard
               *      We do not have a public method because we're short on bytecode size limit,
               *      to retrieve the guard address, one can use `getStorageAt` from `StorageAccessible` contract
               *      with the slot `GUARD_STORAGE_SLOT`
               * @return guard The address of the 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 managing Safe modules
           * @notice Modules are extensions with unlimited access to a Safe that can be added to a Safe by its owners.
                     ⚠️ WARNING: Modules are a security risk since they can execute arbitrary transactions, 
                     so only trusted and audited modules should be added to a Safe. A malicious module can
                     completely takeover a Safe.
           * @author Stefan George - @Georgi87
           * @author Richard Meissner - @rmeissner
           */
          abstract contract ModuleManager is SelfAuthorized, Executor {
              event EnabledModule(address indexed module);
              event DisabledModule(address indexed module);
              event ExecutionFromModuleSuccess(address indexed module);
              event ExecutionFromModuleFailure(address indexed module);
              address internal constant SENTINEL_MODULES = address(0x1);
              mapping(address => address) internal modules;
              /**
               * @notice Setup function sets the initial storage of the contract.
               *         Optionally executes a delegate call to another contract to setup the modules.
               * @param to Optional destination address of call to execute.
               * @param data Optional data of call to execute.
               */
              function setupModules(address to, bytes memory data) internal {
                  require(modules[SENTINEL_MODULES] == address(0), "GS100");
                  modules[SENTINEL_MODULES] = SENTINEL_MODULES;
                  if (to != address(0)) {
                      require(isContract(to), "GS002");
                      // Setup has to complete successfully or transaction fails.
                      require(execute(to, 0, data, Enum.Operation.DelegateCall, type(uint256).max), "GS000");
                  }
              }
              /**
               * @notice Enables the module `module` for the Safe.
               * @dev This can only be done via a Safe transaction.
               * @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);
              }
              /**
               * @notice Disables the module `module` for the Safe.
               * @dev This can only be done via a Safe transaction.
               * @param prevModule Previous module in the modules 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);
              }
              /**
               * @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token)
               * @dev Function is virtual to allow overriding for L2 singleton to emit an event for indexing.
               * @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.
               * @return success Boolean flag indicating if the call succeeded.
               */
              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, type(uint256).max);
                  if (success) emit ExecutionFromModuleSuccess(msg.sender);
                  else emit ExecutionFromModuleFailure(msg.sender);
              }
              /**
               * @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) 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.
               * @return success Boolean flag indicating if the call succeeded.
               * @return returnData Data returned by the call.
               */
              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
                  }
              }
              /**
               * @notice 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);
              }
              /**
               * @notice Returns an array of modules.
               *         If all entries fit into a single page, the next pointer will be 0x1.
               *         If another page is present, next will be the last element of the returned array.
               * @param start Start of the page. Has to be a module or start pointer (0x1 address)
               * @param pageSize Maximum number of modules that should be returned. Has to be > 0
               * @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) {
                  require(start == SENTINEL_MODULES || isModuleEnabled(start), "GS105");
                  require(pageSize > 0, "GS106");
                  // Init array with max page size
                  array = new address[](pageSize);
                  // Populate return array
                  uint256 moduleCount = 0;
                  next = modules[start];
                  while (next != address(0) && next != SENTINEL_MODULES && moduleCount < pageSize) {
                      array[moduleCount] = next;
                      next = modules[next];
                      moduleCount++;
                  }
                  /**
                    Because of the argument validation, we can assume that the loop will always iterate over the valid module list values
                    and the `next` variable will either be an enabled module or a sentinel address (signalling the end). 
                    
                    If we haven't reached the end inside the loop, we need to set the next pointer to the last element of the modules array
                    because the `next` variable (which is a module by itself) acting as a pointer to the start of the next page is neither 
                    included to the current page, nor will it be included in the next one if you pass it as a start.
                  */
                  if (next != SENTINEL_MODULES) {
                      next = array[moduleCount - 1];
                  }
                  // Set correct size of returned array
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      mstore(array, moduleCount)
                  }
              }
              /**
               * @notice Returns true if `account` is a contract.
               * @dev This function will return false if invoked during the constructor of a contract,
               *      as the code is not actually created until after the constructor finishes.
               * @param account The address being queried
               */
              function isContract(address account) internal view returns (bool) {
                  uint256 size;
                  // solhint-disable-next-line no-inline-assembly
                  assembly {
                      size := extcodesize(account)
                  }
                  return size > 0;
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          import "../common/SelfAuthorized.sol";
          /**
           * @title OwnerManager - Manages Safe owners and a threshold to authorize transactions.
           * @dev Uses a linked list to store the owners because the code generate by the solidity compiler
           *      is more efficient than using a dynamic array.
           * @author Stefan George - @Georgi87
           * @author Richard Meissner - @rmeissner
           */
          abstract contract OwnerManager is SelfAuthorized {
              event AddedOwner(address indexed owner);
              event RemovedOwner(address indexed owner);
              event ChangedThreshold(uint256 threshold);
              address internal constant SENTINEL_OWNERS = address(0x1);
              mapping(address => address) internal owners;
              uint256 internal ownerCount;
              uint256 internal threshold;
              /**
               * @notice Sets the initial storage of the 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;
              }
              /**
               * @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
               * @dev This can only be done via a Safe transaction.
               * @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);
              }
              /**
               * @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
               * @dev This can only be done via a Safe transaction.
               * @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);
              }
              /**
               * @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
               * @dev This can only be done via a Safe transaction.
               * @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);
              }
              /**
               * @notice Changes the threshold of the Safe to `_threshold`.
               * @dev This can only be done via a Safe transaction.
               * @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);
              }
              /**
               * @notice Returns the number of required confirmations for a Safe transaction aka the threshold.
               * @return Threshold number.
               */
              function getThreshold() public view returns (uint256) {
                  return threshold;
              }
              /**
               * @notice Returns if `owner` is an owner of the Safe.
               * @return Boolean if owner is an owner of the Safe.
               */
              function isOwner(address owner) public view returns (bool) {
                  return owner != SENTINEL_OWNERS && owners[owner] != address(0);
              }
              /**
               * @notice Returns a list of Safe 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 used in Safe contracts.
           * @author Richard Meissner - @rmeissner
           */
          abstract contract Enum {
              enum Operation {
                  Call,
                  DelegateCall
              }
          }
          // SPDX-License-Identifier: LGPL-3.0-only
          pragma solidity >=0.7.0 <0.9.0;
          /**
           * @title NativeCurrencyPaymentFallback - A contract that has a fallback to accept native currency payments.
           * @author Richard Meissner - @rmeissner
           */
          abstract contract NativeCurrencyPaymentFallback {
              event SafeReceived(address indexed sender, uint256 value);
              /**
               * @notice Receive function accepts native currency transactions.
               * @dev Emits an event with sender and received value.
               */
              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 - @rmeissner
           */
          abstract contract SecuredTokenTransfer {
              /**
               * @notice Transfers a token and returns a boolean if it was a success
               * @dev It checks the return data of the transfer call and returns true if the transfer was successful.
               *      It doesn't check if the `token` address is a contract or not.
               * @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
               * @return transferred Returns true if the transfer was successful
               */
              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 to itself.
           * @author Richard Meissner - @rmeissner
           */
          abstract contract SelfAuthorized {
              function requireSelfCall() private view {
                  require(msg.sender == address(this), "GS031");
              }
              modifier authorized() {
                  // Modifiers are copied around during compilation. 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 encoded as bytes
           * @author Richard Meissner - @rmeissner
           */
          abstract contract SignatureDecoder {
              /**
               * @notice Splits signature bytes into `uint8 v, bytes32 r, bytes32 s`.
               * @dev Make sure to perform a bounds check for @param pos, to avoid out of bounds access on @param signatures
               *      The signature format is a compact form of {bytes32 r}{bytes32 s}{uint8 v}
               *      Compact means uint8 is not padded to 32 bytes.
               * @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 {r, s, v} signatures.
               * @return v Recovery ID or Safe signature type.
               * @return r Output value r of the signature.
               * @return s Output value s of the signature.
               */
              function signatureSplit(bytes memory signatures, uint256 pos) internal pure returns (uint8 v, bytes32 r, bytes32 s) {
                  // 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 the first super contract)
           *        This contract is tightly coupled to our proxy contract (see `proxies/SafeProxy.sol`)
           * @author Richard Meissner - @rmeissner
           */
          abstract contract Singleton {
              // singleton always has to be the first declared variable to ensure the same location as in the Proxy contract.
              // It should also always be ensured 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 - A generic base contract that allows callers to access all internal storage.
           * @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
           *         It removes a method from the original contract not needed for the Safe contracts.
           * @author Gnosis Developers
           */
          abstract contract StorageAccessible {
              /**
               * @notice 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 delegatecall 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 SafeMath
           * @notice Math operations with safety checks that revert on error (overflow/underflow)
           */
          library SafeMath {
              /**
               * @notice Multiplies two numbers, reverts on overflow.
               * @param a First number
               * @param b Second number
               * @return Product of a and b
               */
              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;
              }
              /**
               * @notice Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
               * @param a First number
               * @param b Second number
               * @return Difference of a and b
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
                  return c;
              }
              /**
               * @notice Adds two numbers, reverts on overflow.
               * @param a First number
               * @param b Second number
               * @return Sum of a and b
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
                  return c;
              }
              /**
               * @notice Returns the largest of two numbers.
               * @param a First number
               * @param b Second number
               * @return Largest of a and b
               */
              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;
          /// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol
          interface IERC165 {
              /**
               * @dev Returns true if this contract implements the interface defined by `interfaceId`.
               * See the corresponding EIP section
               * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified
               * to learn more about how these ids are created.
               *
               * This function call must use less than 30 000 gas.
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool);
          }
          // 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 {
              /**
               * @notice Legacy EIP1271 method to validate a signature.
               * @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);
          }
          

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

          File 6 of 6: AccessControlledOCR2Aggregator
          // SPDX-License-Identifier: MIT
          pragma solidity =0.8.19;
          import "./OCR2Aggregator.sol";
          import "./SimpleReadAccessController.sol";
          /**
           * @notice Wrapper of OCR2Aggregator which checks read access on Aggregator-interface methods
           */
          contract AccessControlledOCR2Aggregator is OCR2Aggregator, SimpleReadAccessController {
            constructor(
              LinkTokenInterface _link,
              int192 _minAnswer,
              int192 _maxAnswer,
              AccessControllerInterface _billingAccessController,
              AccessControllerInterface _requesterAccessController,
              uint8 _decimals,
              string memory description
            )
              OCR2Aggregator(
                _link,
                _minAnswer,
                _maxAnswer,
                _billingAccessController,
                _requesterAccessController,
                _decimals,
                description
              ) {
              }
            /*
             * Versioning
             */
            function typeAndVersion()
              external
              override
              pure
              virtual
              returns (string memory)
            {
              return "AccessControlledOCR2Aggregator 1.0.0";
            }
            /*
             * v2 Aggregator interface
             */
            /// @inheritdoc OCR2Aggregator
            function latestAnswer()
              public
              override
              view
              checkAccess()
              returns (int256)
            {
              return super.latestAnswer();
            }
            /// @inheritdoc OCR2Aggregator
            function latestTimestamp()
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.latestTimestamp();
            }
            /// @inheritdoc OCR2Aggregator
            function latestRound()
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.latestRound();
            }
            /// @inheritdoc OCR2Aggregator
            function getAnswer(uint256 _roundId)
              public
              override
              view
              checkAccess()
              returns (int256)
            {
              return super.getAnswer(_roundId);
            }
            /// @inheritdoc OCR2Aggregator
            function getTimestamp(uint256 _roundId)
              public
              override
              view
              checkAccess()
              returns (uint256)
            {
              return super.getTimestamp(_roundId);
            }
            /*
             * v3 Aggregator interface
             */
            /// @inheritdoc OCR2Aggregator
            function description()
              public
              override
              view
              checkAccess()
              returns (string memory)
            {
              return super.description();
            }
            /// @inheritdoc OCR2Aggregator
            function getRoundData(uint80 _roundId)
              public
              override
              view
              checkAccess()
              returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
              )
            {
              return super.getRoundData(_roundId);
            }
            /// @inheritdoc OCR2Aggregator
            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.8.0;
          import "./ConfirmedOwnerWithProposal.sol";
          /**
           * @title The ConfirmedOwner contract
           * @notice A contract with helpers for basic contract ownership.
           */
          contract ConfirmedOwner is ConfirmedOwnerWithProposal {
            constructor(
              address newOwner
            )
              ConfirmedOwnerWithProposal(
                newOwner,
                address(0)
              )
            {
            }
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "./interfaces/OwnableInterface.sol";
          /**
           * @title The ConfirmedOwner contract
           * @notice A contract with helpers for basic contract ownership.
           */
          contract ConfirmedOwnerWithProposal is OwnableInterface {
            address private s_owner;
            address private s_pendingOwner;
            event OwnershipTransferRequested(
              address indexed from,
              address indexed to
            );
            event OwnershipTransferred(
              address indexed from,
              address indexed to
            );
            constructor(
              address newOwner,
              address pendingOwner
            ) {
              require(newOwner != address(0), "Cannot set owner to zero");
              s_owner = newOwner;
              if (pendingOwner != address(0)) {
                _transferOwnership(pendingOwner);
              }
            }
            /**
             * @notice Allows an owner to begin transferring ownership to a new address,
             * pending.
             */
            function transferOwnership(
              address to
            )
              public
              override
              onlyOwner()
            {
              _transferOwnership(to);
            }
            /**
             * @notice Allows an ownership transfer to be completed by the recipient.
             */
            function acceptOwnership()
              external
              override
            {
              require(msg.sender == s_pendingOwner, "Must be proposed owner");
              address oldOwner = s_owner;
              s_owner = msg.sender;
              s_pendingOwner = address(0);
              emit OwnershipTransferred(oldOwner, msg.sender);
            }
            /**
             * @notice Get the current owner
             */
            function owner()
              public
              view
              override
              returns (
                address
              )
            {
              return s_owner;
            }
            /**
             * @notice validate, transfer ownership, and emit relevant events
             */
            function _transferOwnership(
              address to
            )
              private
            {
              require(to != msg.sender, "Cannot transfer to self");
              s_pendingOwner = to;
              emit OwnershipTransferRequested(s_owner, to);
            }
            /**
             * @notice validate access
             */
            function _validateOwnership()
              internal
              view
            {
              require(msg.sender == s_owner, "Only callable by owner");
            }
            /**
             * @notice Reverts if called by anyone other than the contract owner.
             */
            modifier onlyOwner() {
              _validateOwnership();
              _;
            }
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "./interfaces/TypeAndVersionInterface.sol";
          abstract contract OCR2Abstract is TypeAndVersionInterface {
            // Maximum number of oracles the offchain reporting protocol is designed for
            uint256 constant internal maxNumOracles = 31;
            /**
             * @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 configDigest configDigest of this configuration
             * @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 f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
             * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
             * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter
             * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
             */
            event ConfigSet(
              uint32 previousConfigBlockNumber,
              bytes32 configDigest,
              uint64 configCount,
              address[] signers,
              address[] transmitters,
              uint8 f,
              bytes onchainConfig,
              uint64 offchainConfigVersion,
              bytes offchainConfig
            );
            /**
             * @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 f number of faulty oracles the system can tolerate
             * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
             * @param offchainConfigVersion version number for offchainEncoding schema
             * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
             */
            function setConfig(
              address[] memory signers,
              address[] memory transmitters,
              uint8 f,
              bytes memory onchainConfig,
              uint64 offchainConfigVersion,
              bytes memory offchainConfig
            )
              external
              virtual;
            /**
             * @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
              virtual
              returns (
                uint32 configCount,
                uint32 blockNumber,
                bytes32 configDigest
              );
            function _configDigestFromConfigData(
              uint256 chainId,
              address contractAddress,
              uint64 configCount,
              address[] memory signers,
              address[] memory transmitters,
              uint8 f,
              bytes memory onchainConfig,
              uint64 offchainConfigVersion,
              bytes memory offchainConfig
            )
              internal
              pure
              returns (bytes32)
            {
              uint256 h = uint256(keccak256(abi.encode(chainId, contractAddress, configCount,
                signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig
              )));
              uint256 prefixMask = type(uint256).max << (256-16); // 0xFFFF00..00
              uint256 prefix = 0x0001 << (256-16); // 0x000100..00
              return bytes32((prefix & prefixMask) | (h & ~prefixMask));
            }
            /**
            * @notice optionally emitted to indicate the latest configDigest and epoch for
               which a report was successfully transmitted. Alternatively, the contract may
               use latestConfigDigestAndEpoch with scanLogs set to false.
            */
            event Transmitted(
              bytes32 configDigest,
              uint32 epoch
            );
            /**
             * @notice optionally returns the latest configDigest and epoch for which a
               report was successfully transmitted. Alternatively, the contract may return
               scanLogs set to true and use Transmitted events to provide this information
               to offchain watchers.
             * @return scanLogs indicates whether to rely on the configDigest and epoch
               returned or whether to scan logs for the Transmitted event instead.
             * @return configDigest
             * @return epoch
             */
            function latestConfigDigestAndEpoch()
              external
              view
              virtual
              returns(
                bool scanLogs,
                bytes32 configDigest,
                uint32 epoch
              );
            /**
             * @notice transmit is called to post a new report to the contract
             * @param reportContext serialized report context containing configDigest, epoch, round, extraHash
             * @param report serialized report, which the signatures are signing
             * @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
              bytes32[3] calldata reportContext,
              bytes calldata report,
              bytes32[] calldata rs, bytes32[] calldata ss, bytes32 rawVs // signatures
            )
              external
              virtual;
          }
          // SPDX-License-Identifier: MIT
          pragma solidity =0.8.19;
          import "./interfaces/AccessControllerInterface.sol";
          import "./interfaces/AggregatorV2V3Interface.sol";
          import "./interfaces/AggregatorValidatorInterface.sol";
          import "./interfaces/LinkTokenInterface.sol";
          import "./interfaces/TypeAndVersionInterface.sol";
          import "./OCR2Abstract.sol";
          import "./OwnerIsCreator.sol";
          /**
           * @notice OCR2Aggregator for numerical data with billing support.
           * @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
           * Billing 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 OCR2Aggregator is OCR2Abstract, OwnerIsCreator, AggregatorV2V3Interface {
            // This contract is divided into sections. Each section defines a set of
            // variables, events, and functions that belong together.
            /***************************************************************************
             * Section: Variables used in multiple other sections
             **************************************************************************/
            struct Transmitter {
              bool active;
              // Index of oracle in s_signersList/s_transmittersList
              uint8 index;
              // juels-denominated payment for transmitters, covering gas costs incurred
              // by the transmitter plus additional rewards. The entire LINK supply (1e9
              // LINK = 1e27 Juels) will always fit into a uint96.
              uint96 paymentJuels;
            }
            mapping (address /* transmitter address */ => Transmitter) internal s_transmitters;
            struct Signer {
              bool active;
              // Index of oracle in s_signersList/s_transmittersList
              uint8 index;
            }
            mapping (address /* signer address */ => Signer) internal s_signers;
            // s_signersList contains the signing address of each oracle
            address[] internal s_signersList;
            // s_transmittersList contains the transmission address of each oracle,
            // i.e. the address the oracle actually sends transactions to the contract from
            address[] internal s_transmittersList;
            // We assume that all oracles contribute observations to all rounds. this
            // variable tracks (per-oracle) from what round an oracle should be rewarded,
            // i.e. the oracle gets (latestAggregatorRoundId -
            // rewardFromAggregatorRoundId) * reward
            uint32[maxNumOracles] internal s_rewardFromAggregatorRoundId;
            bytes32 s_latestConfigDigest;
            // Storing these fields used on the hot path in a HotVars variable reduces the
            // retrieval of all of them to a single SLOAD.
            struct HotVars {
              // maximum number of faulty oracles
              uint8 f;
              // epoch and round from OCR protocol.
              // 32 most sig bits for epoch, 8 least sig bits for round
              uint40 latestEpochAndRound;
              // 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;
              // Highest compensated gas price, in gwei uints
              uint32 maximumGasPriceGwei;
              // If gas price is less (in gwei units), transmitter gets half the savings
              uint32 reasonableGasPriceGwei;
              // Fixed LINK reward for each observer
              uint32 observationPaymentGjuels;
              // Fixed reward for transmitter
              uint32 transmissionPaymentGjuels;
              // Overhead incurred by accounting logic
              uint24 accountingGas;
            }
            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
              uint32 observationsTimestamp; // when were observations made offchain
              uint32 transmissionTimestamp; // when was report received onchain
            }
            mapping(uint32 /* aggregator round ID */ => Transmission) internal s_transmissions;
            // 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;
            /***************************************************************************
             * Section: Constructor
             **************************************************************************/
            /**
             * @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 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(
              LinkTokenInterface link,
              int192 minAnswer_,
              int192 maxAnswer_,
              AccessControllerInterface billingAccessController,
              AccessControllerInterface requesterAccessController,
              uint8 decimals_,
              string memory description_
            ) {
              s_linkToken = link;
              emit LinkTokenSet(LinkTokenInterface(address(0)), link);
              _setBillingAccessController(billingAccessController);
              decimals = decimals_;
              s_description = description_;
              setRequesterAccessController(requesterAccessController);
              setValidatorConfig(AggregatorValidatorInterface(address(0x0)), 0);
              minAnswer = minAnswer_;
              maxAnswer = maxAnswer_;
            }
            /***************************************************************************
             * Section: OCR2Abstract Configuration
             **************************************************************************/
            // incremented each time a new config is posted. This count is incorporated
            // into the config digest to prevent replay attacks.
            uint32 internal s_configCount;
            // makes it easier for offchain systems to extract config from logs
            uint32 internal s_latestConfigBlockNumber;
            // left as a function so this check can be disabled in derived contracts
            function _requirePositiveF (
              uint256 f
            )
              internal
              pure
              virtual
            {
              require(0 < f, "f must be positive");
            }
            struct SetConfigArgs {
              address[] signers;
              address[] transmitters;
              uint8 f;
              bytes onchainConfig;
              uint64 offchainConfigVersion;
              bytes offchainConfig;
            }
            /// @inheritdoc OCR2Abstract
            function setConfig(
              address[] memory signers,
              address[] memory transmitters,
              uint8 f,
              bytes memory onchainConfig,
              uint64 offchainConfigVersion,
              bytes memory offchainConfig
            )
              external
              override
              onlyOwner()
            {
              require(signers.length <= maxNumOracles, "too many oracles");
              require(signers.length == transmitters.length, "oracle length mismatch");
              require(3*f < signers.length, "faulty-oracle f too high");
              _requirePositiveF(f);
              require(keccak256(onchainConfig) == keccak256(abi.encodePacked(uint8(1) /*version*/, minAnswer, maxAnswer)), "invalid onchainConfig");
              SetConfigArgs memory args = SetConfigArgs({
                signers: signers,
                transmitters: transmitters,
                f: f,
                onchainConfig: onchainConfig,
                offchainConfigVersion: offchainConfigVersion,
                offchainConfig: offchainConfig
              });
              s_hotVars.latestEpochAndRound = 0;
              _payOracles();
              // remove any old signer/transmitter addresses
              uint256 oldLength = s_signersList.length;
              for (uint256 i = 0; i < oldLength; i++) {
                address signer = s_signersList[i];
                address transmitter = s_transmittersList[i];
                delete s_signers[signer];
                delete s_transmitters[transmitter];
              }
              delete s_signersList;
              delete s_transmittersList;
              // add new signer/transmitter addresses
              for (uint i = 0; i < args.signers.length; i++) {
                require(
                  !s_signers[args.signers[i]].active,
                  "repeated signer address"
                );
                s_signers[args.signers[i]] = Signer({
                  active: true,
                  index: uint8(i)
                });
                require(
                  !s_transmitters[args.transmitters[i]].active,
                  "repeated transmitter address"
                );
                s_transmitters[args.transmitters[i]] = Transmitter({
                  active: true,
                  index: uint8(i),
                  paymentJuels: 0
                });
              }
              s_signersList = args.signers;
              s_transmittersList = args.transmitters;
              s_hotVars.f = args.f;
              uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
              s_latestConfigBlockNumber = uint32(block.number);
              s_configCount += 1;
              s_latestConfigDigest = _configDigestFromConfigData(
                block.chainid,
                address(this),
                s_configCount,
                args.signers,
                args.transmitters,
                args.f,
                args.onchainConfig,
                args.offchainConfigVersion,
                args.offchainConfig
              );
              emit ConfigSet(
                previousConfigBlockNumber,
                s_latestConfigDigest,
                s_configCount,
                args.signers,
                args.transmitters,
                args.f,
                args.onchainConfig,
                args.offchainConfigVersion,
                args.offchainConfig
              );
              uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
              for (uint256 i = 0; i < args.signers.length; i++) {
                s_rewardFromAggregatorRoundId[i] = latestAggregatorRoundId;
              }
            }
            /// @inheritdoc OCR2Abstract
            function latestConfigDetails()
              external
              override
              view
              returns (
                uint32 configCount,
                uint32 blockNumber,
                bytes32 configDigest
              )
            {
              return (s_configCount, s_latestConfigBlockNumber, s_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 getTransmitters()
              external
              view
              returns(address[] memory)
            {
              return s_transmittersList;
            }
            /***************************************************************************
             * Section: Onchain Validation
             **************************************************************************/
            // 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 getValidatorConfig()
              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
                  }
                }
              }
            }
            /***************************************************************************
             * Section: RequestNewRound
             **************************************************************************/
            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, bytes32 configDigest, uint32 epoch, uint8 round);
            /**
             * @notice address of the requester access controller contract
             * @return requester access controller address
             */
            function getRequesterAccessController()
              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");
              uint40 latestEpochAndRound = s_hotVars.latestEpochAndRound;
              uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
              emit RoundRequested(
                msg.sender,
                s_latestConfigDigest,
                uint32(latestEpochAndRound >> 8),
                uint8(latestEpochAndRound)
              );
              return latestAggregatorRoundId + 1;
            }
            /***************************************************************************
             * Section: Transmission
             **************************************************************************/
            /**
             * @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 to this report
             * @param transmitter address from which the report was transmitted
             * @param observationsTimestamp when were observations made offchain
             * @param observations observations transmitted with this report
             * @param observers i-th element is the oracle id of the oracle that made the i-th observation
             * @param juelsPerFeeCoin exchange rate between feeCoin (e.g. ETH on Ethereum) and LINK, denominated in juels
             * @param configDigest configDigest of transmission
             * @param epochAndRound least-significant byte is the OCR protocol round number, the other bytes give the big-endian OCR protocol epoch number
             */
            event NewTransmission(
              uint32 indexed aggregatorRoundId,
              int192 answer,
              address transmitter,
              uint32 observationsTimestamp,
              int192[] observations,
              bytes observers,
              int192 juelsPerFeeCoin,
              bytes32 configDigest,
              uint40 epochAndRound
            );
            // Used to relieve stack pressure in transmit
            struct Report {
              uint32 observationsTimestamp;
              bytes observers; // ith element is the index of the ith observer
              int192[] observations; // ith element is the ith observation
              int192 juelsPerFeeCoin;
            }
            // _decodeReport decodes a serialized report into a Report struct
            function _decodeReport(bytes memory rawReport)
              internal
              pure
              returns (
                Report memory
              )
            {
              uint32 observationsTimestamp;
              bytes32 rawObservers;
              int192[] memory observations;
              int192 juelsPerFeeCoin;
              (observationsTimestamp, rawObservers, observations, juelsPerFeeCoin) = abi.decode(rawReport, (uint32, bytes32, int192[], int192));
              _requireExpectedReportLength(rawReport, observations);
              uint256 numObservations = observations.length;
              bytes memory observers = abi.encodePacked(rawObservers);
              assembly {
                // we truncate observers from length 32 to the number of observations
                mstore(observers, numObservations)
              }
              return Report({
                observationsTimestamp: observationsTimestamp,
                observers: observers,
                observations: observations,
                juelsPerFeeCoin: juelsPerFeeCoin
              });
            }
            // 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
            uint256 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT =
              4 + // function selector
              32 * 3 + // 3 words containing reportContext
              32 + // word containing start location of abiencoded report value
              32 + // word containing start location 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
            // Make sure the calldata 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.
            function _requireExpectedMsgDataLength(
              bytes calldata report,
              bytes32[] calldata rs,
              bytes32[] calldata ss
            )
              private
              pure
            {
              // calldata will never be big enough to make this overflow
              uint256 expected = TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT +
                report.length + // one byte per entry in report
                rs.length * 32 + // 32 bytes per entry in rs
                ss.length * 32 + // 32 bytes per entry in ss
                0; // placeholder
              require(msg.data.length == expected, "calldata length mismatch");
            }
            /// @inheritdoc OCR2Abstract
            function transmit(
              // reportContext consists of:
              // reportContext[0]: ConfigDigest
              // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round
              // reportContext[2]: ExtraHash
              bytes32[3] calldata reportContext,
              bytes calldata report,
              // ECDSA signatures
              bytes32[] calldata rs,
              bytes32[] calldata ss,
              bytes32 rawVs
            )
              external
              override
            {
              // NOTE: If the arguments to this function are changed, _requireExpectedMsgDataLength and/or
              // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
              uint256 initialGas = gasleft(); // This line must come first
              HotVars memory hotVars = s_hotVars;
              uint40 epochAndRound = uint40(uint256(reportContext[1]));
              require(hotVars.latestEpochAndRound < epochAndRound, "stale report");
              require(s_transmitters[msg.sender].active, "unauthorized transmitter");
              require(s_latestConfigDigest == reportContext[0], "configDigest mismatch");
              _requireExpectedMsgDataLength(report, rs, ss);
              require(rs.length == hotVars.f + 1, "wrong number of signatures");
              require(rs.length == ss.length, "signatures out of registration");
              // Verify signatures attached to report
              {
                bytes32 h = keccak256(abi.encode(keccak256(report), reportContext));
                // i-th byte counts number of sigs made by i-th signer
                uint256 signedCount = 0;
                Signer memory signer;
                for (uint i = 0; i < rs.length; i++) {
                  address signerAddress = ecrecover(h, uint8(rawVs[i])+27, rs[i], ss[i]);
                  signer = s_signers[signerAddress];
                  require(signer.active, "signature error");
                  unchecked{
                    signedCount += 1 << (8 * signer.index);
                  }
                }
                // The first byte of the mask can be 0, because we only ever have 31 oracles
                require(signedCount & 0x0001010101010101010101010101010101010101010101010101010101010101 == signedCount, "duplicate signer");
              }
              int192 juelsPerFeeCoin = _report(hotVars, reportContext[0], epochAndRound, report);
              _payTransmitter(hotVars, juelsPerFeeCoin, uint32(initialGas), msg.sender);
            }
            /**
             * @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 (
                bytes32 configDigest,
                uint32 epoch,
                uint8 round,
                int192 latestAnswer_,
                uint64 latestTimestamp_
              )
            {
              require(msg.sender == tx.origin, "Only callable by EOA");
              return (
                s_latestConfigDigest,
                uint32(s_hotVars.latestEpochAndRound >> 8),
                uint8(s_hotVars.latestEpochAndRound),
                s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
                s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp
              );
            }
            /// @inheritdoc OCR2Abstract
            function latestConfigDigestAndEpoch()
              external
              override
              view
              virtual
              returns(
                bool scanLogs,
                bytes32 configDigest,
                uint32 epoch
              )
            {
              return (false, s_latestConfigDigest, uint32(s_hotVars.latestEpochAndRound >> 8));
            }
            function _requireExpectedReportLength(
              bytes memory report,
              int192[] memory observations
            )
              private
              pure
            {
              uint256 expected =
                32 + // observationsTimestamp
                32 + // rawObservers
                32 + // observations offset
                32 + // juelsPerFeeCoin
                32 + // observations length
                32 * observations.length + // observations payload
                0;
              require(report.length == expected, "report length mismatch");
            }
            function _report(
              HotVars memory hotVars,
              bytes32 configDigest,
              uint40 epochAndRound,
              bytes memory rawReport
            )
              internal
              returns (int192 juelsPerFeeCoin)
            {
              Report memory report = _decodeReport(rawReport);
              require(report.observations.length <= maxNumOracles, "num observations out of bounds");
              // Offchain logic ensures that a quorum of oracles is operating on a matching set of at least
              // 2f+1 observations. By assumption, up to f of those can be faulty, which includes being
              // malformed. Conversely, more than f observations have to be well-formed and sent on chain.
              require(hotVars.f < report.observations.length, "too few values to trust median");
              hotVars.latestEpochAndRound = epochAndRound;
              // get median, validate its range, store it in new aggregator round
              int192 median = report.observations[report.observations.length/2];
              require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
              hotVars.latestAggregatorRoundId++;
              s_transmissions[hotVars.latestAggregatorRoundId] =
                Transmission({
                  answer: median,
                  observationsTimestamp: report.observationsTimestamp,
                  transmissionTimestamp: uint32(block.timestamp)
                });
              // persist updates to hotVars
              s_hotVars = hotVars;
              emit NewTransmission(
                hotVars.latestAggregatorRoundId,
                median,
                msg.sender,
                report.observationsTimestamp,
                report.observations,
                report.observers,
                report.juelsPerFeeCoin,
                configDigest,
                epochAndRound
              );
              // Emit these for backwards compatibility with offchain consumers
              // that only support legacy events
              emit NewRound(
                hotVars.latestAggregatorRoundId,
                address(0x0), // use zero address since we don't have anybody "starting" the round here
                report.observationsTimestamp
              );
              emit AnswerUpdated(
                median,
                hotVars.latestAggregatorRoundId,
                block.timestamp
              );
              _validateAnswer(hotVars.latestAggregatorRoundId, median);
              return report.juelsPerFeeCoin;
            }
            /***************************************************************************
             * Section: v2 AggregatorInterface
             **************************************************************************/
            /**
             * @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].transmissionTimestamp;
            }
            /**
             * @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)].transmissionTimestamp;
            }
            /***************************************************************************
             * Section: v3 AggregatorInterface
             **************************************************************************/
            /**
             * @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 = 6;
            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 when observations were made offchain
             * @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
              )
            {
              if(roundId > type(uint32).max) { return (0, 0, 0, 0, 0); }
              Transmission memory transmission = s_transmissions[uint32(roundId)];
              return (
                roundId,
                transmission.answer,
                transmission.observationsTimestamp,
                transmission.transmissionTimestamp,
                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 when observations were made offchain
             * @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
              )
            {
              uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
              Transmission memory transmission = s_transmissions[latestAggregatorRoundId];
              return (
                latestAggregatorRoundId,
                transmission.answer,
                transmission.observationsTimestamp,
                transmission.transmissionTimestamp,
                latestAggregatorRoundId
              );
            }
            /***************************************************************************
             * Section: Configurable LINK Token
             **************************************************************************/
            // We assume that the token contract is correct. This contract is not written
            // to handle misbehaving ERC20 tokens!
            LinkTokenInterface internal s_linkToken;
            /*
             * @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 transferred
             * 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;
            }
            /***************************************************************************
             * Section: BillingAccessController Management
             **************************************************************************/
            // Controls who can change billing parameters. A billingAdmin is not able to
            // affect any OCR protocol settings and therefore cannot tamper with the
            // liveness or integrity of a data feed. However, a billingAdmin can set
            // faulty billing parameters causing oracles to be underpaid, or causing them
            // to be paid so much that further calls to setConfig, setBilling,
            // setLinkToken will always fail due to the contract being underfunded.
            AccessControllerInterface internal s_billingAccessController;
            /**
             * @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 _setBillingAccessController(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
            {
              _setBillingAccessController(_billingAccessController);
            }
            /**
             * @notice gets billingAccessController
             * @return address of billingAccessController contract
             */
            function getBillingAccessController()
              external
              view
              returns (AccessControllerInterface)
            {
              return s_billingAccessController;
            }
            /***************************************************************************
             * Section: Billing Configuration
             **************************************************************************/
            /**
             * @notice emitted when billing parameters are set
             * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
             * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
             * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
             * @param transmissionPaymentGjuels reward to transmitter of a successful report
             * @param accountingGas gas overhead incurred by accounting logic
             */
            event BillingSet(
              uint32 maximumGasPriceGwei,
              uint32 reasonableGasPriceGwei,
              uint32 observationPaymentGjuels,
              uint32 transmissionPaymentGjuels,
              uint24 accountingGas
            );
            /**
             * @notice sets billing parameters
             * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
             * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
             * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
             * @param transmissionPaymentGjuels reward to transmitter of a successful report
             * @param accountingGas gas overhead incurred by accounting logic
             * @dev access control provided by billingAccessController
             */
            function setBilling(
              uint32 maximumGasPriceGwei,
              uint32 reasonableGasPriceGwei,
              uint32 observationPaymentGjuels,
              uint32 transmissionPaymentGjuels,
              uint24 accountingGas
            )
              external
            {
              AccessControllerInterface access = s_billingAccessController;
              require(msg.sender == owner() || access.hasAccess(msg.sender, msg.data),
                "Only owner&billingAdmin can call");
              _payOracles();
              s_hotVars.maximumGasPriceGwei = maximumGasPriceGwei;
              s_hotVars.reasonableGasPriceGwei = reasonableGasPriceGwei;
              s_hotVars.observationPaymentGjuels = observationPaymentGjuels;
              s_hotVars.transmissionPaymentGjuels = transmissionPaymentGjuels;
              s_hotVars.accountingGas = accountingGas;
              emit BillingSet(maximumGasPriceGwei, reasonableGasPriceGwei,
                observationPaymentGjuels, transmissionPaymentGjuels, accountingGas);
            }
            /**
             * @notice gets billing parameters
             * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
             * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
             * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
             * @param transmissionPaymentGjuels reward to transmitter of a successful report
             * @param accountingGas gas overhead of the accounting logic
             */
            function getBilling()
              external
              view
              returns (
                uint32 maximumGasPriceGwei,
                uint32 reasonableGasPriceGwei,
                uint32 observationPaymentGjuels,
                uint32 transmissionPaymentGjuels,
                uint24 accountingGas
              )
            {
              return (
                s_hotVars.maximumGasPriceGwei,
                s_hotVars.reasonableGasPriceGwei,
                s_hotVars.observationPaymentGjuels,
                s_hotVars.transmissionPaymentGjuels,
                s_hotVars.accountingGas
              );
            }
            /***************************************************************************
             * Section: Payments and Withdrawals
             **************************************************************************/
            /**
             * @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, denominated in juels
             * @param transmitterAddress the transmitter address of the oracle
             */
            function owedPayment(address transmitterAddress)
              public
              view
              returns (uint256)
            {
              Transmitter memory transmitter = s_transmitters[transmitterAddress];
              if (!transmitter.active) { return 0; }
              // safe from overflow:
              // s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index] <= 2**32
              // s_hotVars.observationPaymentGjuels <= 2**32
              // 1 gwei <= 2**32
              // hence juelsAmount <= 2**96
              uint256 juelsAmount =
                uint256(s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index]) *
                uint256(s_hotVars.observationPaymentGjuels) *
                (1 gwei);
              juelsAmount += transmitter.paymentJuels;
              return juelsAmount;
            }
            /**
             * @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 transmitterAddress)
              internal
            {
              Transmitter memory transmitter = s_transmitters[transmitterAddress];
              if (!transmitter.active) { return; }
              uint256 juelsAmount = owedPayment(transmitterAddress);
              if (juelsAmount > 0) {
                address payee = s_payees[transmitterAddress];
                // Poses no re-entrancy issues, because LINK.transfer does not yield
                // control flow.
                require(s_linkToken.transfer(payee, juelsAmount), "insufficient funds");
                s_rewardFromAggregatorRoundId[transmitter.index] = s_hotVars.latestAggregatorRoundId;
                s_transmitters[transmitterAddress].paymentJuels = 0;
                emit OraclePaid(transmitterAddress, payee, juelsAmount, 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
            {
              unchecked {
                LinkTokenInterface linkToken = s_linkToken;
                uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
                uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
                address[] memory transmitters = s_transmittersList;
                for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
                  uint256 reimbursementAmountJuels = s_transmitters[transmitters[transmitteridx]].paymentJuels;
                  s_transmitters[transmitters[transmitteridx]].paymentJuels = 0;
                  uint256 obsCount = latestAggregatorRoundId - rewardFromAggregatorRoundId[transmitteridx];
                  uint256 juelsAmount =
                    obsCount * uint256(s_hotVars.observationPaymentGjuels) * (1 gwei) + reimbursementAmountJuels;
                  if (juelsAmount > 0) {
                      address payee = s_payees[transmitters[transmitteridx]];
                      // Poses no re-entrancy issues, because LINK.transfer does not yield
                      // control flow.
                      require(linkToken.transfer(payee, juelsAmount), "insufficient funds");
                      rewardFromAggregatorRoundId[transmitteridx] = latestAggregatorRoundId;
                      emit OraclePaid(transmitters[transmitteridx], payee, juelsAmount, linkToken);
                    }
                }
                // "Zero" the accounting storage variables
                s_rewardFromAggregatorRoundId = rewardFromAggregatorRoundId;
              }
            }
            /**
             * @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 (denominated in Juels).
            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 observationPaymentGjuels, 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 96
              //   bits. Hence 101 bits are sufficient for this part.
              // So we never need more than 102 bits.
              address[] memory transmitters = s_transmittersList;
              uint256 n = transmitters.length;
              uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
              uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
              for (uint i = 0; i < n; i++) {
                linkDue += latestAggregatorRoundId - rewardFromAggregatorRoundId[i];
              }
              // Convert observationPaymentGjuels to uint256, or this overflows!
              linkDue *= uint256(s_hotVars.observationPaymentGjuels) * (1 gwei);
              for (uint i = 0; i < n; i++) {
                linkDue += uint256(s_transmitters[transmitters[i]].paymentJuels);
              }
            }
            /**
             * @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**102, 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 transmitterAddress address used by oracle for signing or transmitting reports
             */
            function oracleObservationCount(address transmitterAddress)
              external
              view
              returns (uint32)
            {
              Transmitter memory transmitter = s_transmitters[transmitterAddress];
              if (!transmitter.active) { return 0; }
              return s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index];
            }
            /***************************************************************************
             * Section: Transmitter Payment
             **************************************************************************/
            // Gas price at which the transmitter should be reimbursed, in gwei/gas
            function _reimbursementGasPriceGwei(
              uint256 txGasPriceGwei,
              uint256 reasonableGasPriceGwei,
              uint256 maximumGasPriceGwei
            )
              internal
              pure
              returns (uint256)
            {
              // this happens on the path for transmissions. we'd rather pay out
              // a wrong reward than risk a liveness failure due to a revert.
              unchecked {
                // Reward the transmitter for choosing an efficient gas price: if they manage
                // to come in lower than considered reasonable, give them half the savings.
                uint256 gasPriceGwei = txGasPriceGwei;
                if (txGasPriceGwei < reasonableGasPriceGwei) {
                  // Give transmitter half the savings for coming in under the reasonable gas price
                  gasPriceGwei += (reasonableGasPriceGwei - txGasPriceGwei) / 2;
                }
                // Don't reimburse a gas price higher than maximumGasPriceGwei
                return _min(gasPriceGwei, maximumGasPriceGwei);
              }
            }
            // gas reimbursement due the transmitter, in wei
            function _transmitterGasCostWei(
              uint256 initialGas,
              uint256 gasPriceGwei,
              uint256 callDataGas,
              uint256 accountingGas,
              uint256 leftGas
            )
              internal
              pure
              returns (uint256)
            {
              // this happens on the path for transmissions. we'd rather pay out
              // a wrong reward than risk a liveness failure due to a revert.
              unchecked {
                require(initialGas >= leftGas, "leftGas cannot exceed initialGas");
                uint256 usedGas =
                  initialGas - leftGas + // observed gas usage
                  callDataGas + accountingGas; // estimated gas usage
                uint256 fullGasCostWei = usedGas * gasPriceGwei * (1 gwei);
                return fullGasCostWei;
              }
            }
            function _payTransmitter(
              HotVars memory hotVars,
              int192 juelsPerFeeCoin,
              uint32 initialGas,
              address transmitter
            )
              internal
              virtual
            {
              // this happens on the path for transmissions. we'd rather pay out
              // a wrong reward than risk a liveness failure due to a revert.
              unchecked {
                // we can't deal with negative juelsPerFeeCoin, better to just not pay
                if (juelsPerFeeCoin < 0) {
                  return;
                }
                // Reimburse transmitter of the report for gas usage
                uint256 gasPriceGwei = _reimbursementGasPriceGwei(
                  tx.gasprice / (1 gwei), // convert to ETH-gwei units
                  hotVars.reasonableGasPriceGwei,
                  hotVars.maximumGasPriceGwei
                );
                // 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;
                uint256 gasLeft = gasleft();
                uint256 gasCostEthWei = _transmitterGasCostWei(
                  uint256(initialGas),
                  gasPriceGwei,
                  callDataGasCost,
                  hotVars.accountingGas,
                  gasLeft
                );
                // Even if we assume absurdly large values, this still does not overflow. With
                // - usedGas <= 1'000'000 gas <= 2**20 gas
                // - weiPerGas <= 1'000'000 gwei <= 2**50 wei
                // - hence gasCostEthWei <= 2**70
                // - juelsPerFeeCoin <= 2**96 (more than the entire supply)
                // we still fit into 166 bits
                uint256 gasCostJuels = (gasCostEthWei * uint192(juelsPerFeeCoin))/1e18;
                uint96 oldTransmitterPaymentJuels = s_transmitters[transmitter].paymentJuels;
                uint96 newTransmitterPaymentJuels = uint96(uint256(oldTransmitterPaymentJuels) +
                  gasCostJuels + uint256(hotVars.transmissionPaymentGjuels) * (1 gwei));
                // overflow *should* never happen, but if it does, let's not persist it.
                if (newTransmitterPaymentJuels < oldTransmitterPaymentJuels) {
                  return;
                }
                s_transmitters[transmitter].paymentJuels = newTransmitterPaymentJuels;
              }
            }
            /***************************************************************************
             * Section: Payee Management
             **************************************************************************/
            // 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;
            /**
             * @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 payee 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 payee 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);
            }
            /***************************************************************************
             * Section: TypeAndVersionInterface
             **************************************************************************/
            function typeAndVersion()
              external
              override
              pure
              virtual
              returns (string memory)
            {
              return "OCR2Aggregator 1.0.0";
            }
            /***************************************************************************
             * Section: Helper Functions
             **************************************************************************/
            function _min(
              uint256 a,
              uint256 b
            )
              internal
              pure
              returns (uint256)
            {
              unchecked {
                if (a < b) { return a; }
                return b;
              }
            }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity =0.8.19;
          import "./interfaces/TypeAndVersionInterface.sol";
          import "./lib/ConfigDigestUtilEVMSimple.sol";
          import "./OwnerIsCreator.sol";
          import "./OCR2Abstract.sol";
          /// @title OCRConfigurationStoreEVMSimple
          /// @notice This contract stores configurations for protocol versions OCR2 and
          /// above in contract storage. It uses the "EVMSimple" config digester.
          contract OCRConfigurationStoreEVMSimple is TypeAndVersionInterface {
              struct ConfigurationEVMSimple {
                  address[] signers;
                  address[] transmitters;
                  bytes onchainConfig;
                  bytes offchainConfig;
                  address contractAddress;
                  uint64 offchainConfigVersion;
                  uint32 configCount;
                  uint8 f;
              }
              /// @notice a list of configurations keyed by their digest
              mapping(bytes32 => ConfigurationEVMSimple) internal s_configurations;
              /// @notice emitted when a new configuration is added
              event NewConfiguration(bytes32 indexed configDigest);
              /// @notice adds a new configuration to the store
              function addConfig(ConfigurationEVMSimple calldata configuration) external returns (bytes32) {
                  bytes32 configDigest = ConfigDigestUtilEVMSimple.configDigestFromConfigData(
                      block.chainid,
                      configuration.contractAddress,
                      configuration.configCount,
                      configuration.signers,
                      configuration.transmitters,
                      configuration.f,
                      configuration.onchainConfig,
                      configuration.offchainConfigVersion,
                      configuration.offchainConfig
                  );
                  s_configurations[configDigest] = configuration;
                  emit NewConfiguration(configDigest);
                  return configDigest;
              }
              /// @notice reads a configuration from the store
              function readConfig(bytes32 configDigest) external view returns (ConfigurationEVMSimple memory) {
                  return s_configurations[configDigest];
              }
              /// @inheritdoc TypeAndVersionInterface
              function typeAndVersion() external override pure virtual returns (string memory)
              {
                  return "OCRConfigurationStoreEVMSimple 1.0.0";
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "./ConfirmedOwner.sol";
          /**
           * @title The OwnerIsCreator contract
           * @notice A contract with helpers for basic contract ownership.
           */
          contract OwnerIsCreator is ConfirmedOwner {
            constructor(
            )
              ConfirmedOwner(
                msg.sender
              )
            {
            }
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          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.8.0;
          import "./OwnerIsCreator.sol";
          import "./interfaces/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, OwnerIsCreator {
            bool public checkEnabled;
            mapping(address => bool) internal accessList;
            event AddedAccess(address user);
            event RemovedAccess(address user);
            event CheckAccessEnabled();
            event CheckAccessDisabled();
            constructor()
            // TODO
            // this is modified from the version in the Chainlink monorepo
            //  OwnerIsCreator()
            {
              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()
            {
              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.8.0;
          interface AccessControllerInterface {
            function hasAccess(address user, bytes calldata data) external view returns (bool);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          interface AggregatorInterface {
            function latestAnswer() external view returns (int256);
            function latestTimestamp() external view returns (uint256);
            function latestRound() external view returns (uint256);
            function getAnswer(uint256 roundId) external view returns (int256);
            function getTimestamp(uint256 roundId) external view returns (uint256);
            event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
            event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import "./AggregatorInterface.sol";
          import "./AggregatorV3Interface.sol";
          interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
          {
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.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.8.0;
          interface AggregatorValidatorInterface {
            function validate(
              uint256 previousRoundId,
              int256 previousAnswer,
              uint256 currentRoundId,
              int256 currentAnswer
            ) external returns (bool);
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.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.8.0;
          interface OwnableInterface {
            function owner()
              external
              returns (
                address
              );
            function transferOwnership(
              address recipient
            )
              external;
            function acceptOwnership()
              external;
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          interface TypeAndVersionInterface{
            function typeAndVersion()
              external
              pure
              returns (string memory);
          }// SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          /// @title ConfigDigestUtilEVMSimple
          /// @notice ConfigDigest related utility functions for "EVMSimple" config
          /// digester
          library ConfigDigestUtilEVMSimple {
              function configDigestFromConfigData(
                  uint256 chainId,
                  address contractAddress,
                  uint64 configCount,
                  address[] memory signers,
                  address[] memory transmitters,
                  uint8 f,
                  bytes memory onchainConfig,
                  uint64 offchainConfigVersion,
                  bytes memory offchainConfig
              ) internal pure returns (bytes32)
              {
                  uint256 hash = uint256(
                      keccak256(
                          abi.encode(
                              chainId,
                              contractAddress,
                              configCount,
                              signers,
                              transmitters,
                              f,
                              onchainConfig,
                              offchainConfigVersion,
                              offchainConfig
                  )));
                  uint256 prefixMask = type(uint256).max << (256-16); // 0xFFFF00..00
                  uint256 prefix = 0x0001 << (256-16); // 0x000100..00
                  return bytes32((prefix & prefixMask) | (hash & ~prefixMask));
              }
          }