ETH Price: $1,913.42 (+4.74%)

Transaction Decoder

Block:
18803387 at Dec-17-2023 04:30:47 AM +UTC
Transaction Fee:
0.007426031307193751 ETH $14.21
Gas Used:
257,197 Gas / 28.872931283 Gwei

Emitted Events:

270 ERC1967Proxy.0xf1d95ed4d1680e6f665104f19c296ae52c1f64cd8114e84d55dc6349dbdafea3( 0xf1d95ed4d1680e6f665104f19c296ae52c1f64cd8114e84d55dc6349dbdafea3, 0x000000000000000000000000eecbe166aa1a32766a624bcff311a7fa712731d9, 0x000000000000000000000000c85daba5bc9afbaf37dc73543ebce9a3ff668612, 0x2cfa4e5b19c36400e917aa24c16d9f26c5a4dc7a6ae656616315a879bf3f31fa )
271 ERC1967Proxy.0x93a6900c7e12c8592eb245abc171ff4709f08fcba2e290729cd16cfe71380260( 0x93a6900c7e12c8592eb245abc171ff4709f08fcba2e290729cd16cfe71380260, 0x3a080877a5691bfcd36cd837149d071517b4c6dc1ada5a946110e6d7865217a2, 0000000000000000000000000000000000000000000000000000000000000001, 2cfa4e5b19c36400e917aa24c16d9f26c5a4dc7a6ae656616315a879bf3f31fa, 00000000000000000000000000000000000000000000000000000000000003e8, 000000000000000000000000eecbe166aa1a32766a624bcff311a7fa712731d9, 000000000000000000000000c85daba5bc9afbaf37dc73543ebce9a3ff668612, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000041b9a6e8584000, 00000000000000000000000000000000000000000000000000000000657e7977 )

Account State Difference:

  Address   Before After State Difference Code
0x57b8792c...12fCbC296
(EtchMarket)
19.3216900759996 Eth19.3220600759996 Eth0.00037
(beaverbuild)
17.312548850125313215 Eth17.312574569825313215 Eth0.0000257197
0xC85daBa5...3fF668612
5.377982951260349921 Eth
Nonce: 2
5.35205691995315617 Eth
Nonce: 3
0.025926031307193751
0xEecBe166...A712731d9 0.076650222952008142 Eth0.094780222952008142 Eth0.01813

Execution Trace

ETH 0.112 ERC1967Proxy.39f976d1( )
  • ETH 0.112 0xea437684e4e67d2885f42725bec8a93898b3de92.39f976d1( )
    • ETH 0.0185 ERC1967Proxy.ee2f675e( )
      • ETH 0.0185 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
        • Null: 0x000...001.3a080877( )
        • ETH 0.01813 0xeecbe166aa1a32766a624bcff311a7fa712731d9.CALL( )
        • ETH 0.019 ERC1967Proxy.ee2f675e( )
          • ETH 0.019 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
          • ETH 0.0185 ERC1967Proxy.ee2f675e( )
            • ETH 0.0185 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
            • ETH 0.019 ERC1967Proxy.ee2f675e( )
              • ETH 0.019 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
              • ETH 0.0185 ERC1967Proxy.ee2f675e( )
                • ETH 0.0185 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
                • ETH 0.0185 ERC1967Proxy.ee2f675e( )
                  • ETH 0.0185 0x08592c1ac3c01379a8ea1fcc12ea297af2c4d026.ee2f675e( )
                  • ETH 0.0935 0xc85daba5bc9afbaf37dc73543ebce9a3ff668612.CALL( )
                    File 1 of 2: ERC1967Proxy
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
                    pragma solidity ^0.8.0;
                    import "../utils/Context.sol";
                    /**
                     * @dev Contract module which provides a basic access control mechanism, where
                     * there is an account (an owner) that can be granted exclusive access to
                     * specific functions.
                     *
                     * By default, the owner account will be the one that deploys the contract. This
                     * can later be changed with {transferOwnership}.
                     *
                     * This module is used through inheritance. It will make available the modifier
                     * `onlyOwner`, which can be applied to your functions to restrict their use to
                     * the owner.
                     */
                    abstract contract Ownable is Context {
                        address private _owner;
                        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                        /**
                         * @dev Initializes the contract setting the deployer as the initial owner.
                         */
                        constructor() {
                            _transferOwnership(_msgSender());
                        }
                        /**
                         * @dev Throws if called by any account other than the owner.
                         */
                        modifier onlyOwner() {
                            _checkOwner();
                            _;
                        }
                        /**
                         * @dev Returns the address of the current owner.
                         */
                        function owner() public view virtual returns (address) {
                            return _owner;
                        }
                        /**
                         * @dev Throws if the sender is not the owner.
                         */
                        function _checkOwner() internal view virtual {
                            require(owner() == _msgSender(), "Ownable: caller is not the owner");
                        }
                        /**
                         * @dev Leaves the contract without owner. It will not be possible to call
                         * `onlyOwner` functions anymore. Can only be called by the current owner.
                         *
                         * NOTE: Renouncing ownership will leave the contract without an owner,
                         * thereby removing any functionality that is only available to the owner.
                         */
                        function renounceOwnership() public virtual onlyOwner {
                            _transferOwnership(address(0));
                        }
                        /**
                         * @dev Transfers ownership of the contract to a new account (`newOwner`).
                         * Can only be called by the current owner.
                         */
                        function transferOwnership(address newOwner) public virtual onlyOwner {
                            require(newOwner != address(0), "Ownable: new owner is the zero address");
                            _transferOwnership(newOwner);
                        }
                        /**
                         * @dev Transfers ownership of the contract to a new account (`newOwner`).
                         * Internal function without access restriction.
                         */
                        function _transferOwnership(address newOwner) internal virtual {
                            address oldOwner = _owner;
                            _owner = newOwner;
                            emit OwnershipTransferred(oldOwner, newOwner);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
                     * proxy whose upgrades are fully controlled by the current implementation.
                     */
                    interface IERC1822Proxiable {
                        /**
                         * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                         * address.
                         *
                         * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                         * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                         * function revert if invoked through a proxy.
                         */
                        function proxiableUUID() external view returns (bytes32);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
                     *
                     * _Available since v4.9._
                     */
                    interface IERC1967 {
                        /**
                         * @dev Emitted when the implementation is upgraded.
                         */
                        event Upgraded(address indexed implementation);
                        /**
                         * @dev Emitted when the admin account has changed.
                         */
                        event AdminChanged(address previousAdmin, address newAdmin);
                        /**
                         * @dev Emitted when the beacon is changed.
                         */
                        event BeaconUpgraded(address indexed beacon);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)
                    pragma solidity ^0.8.0;
                    import "./IBeacon.sol";
                    import "../Proxy.sol";
                    import "../ERC1967/ERC1967Upgrade.sol";
                    /**
                     * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
                     *
                     * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
                     * conflict with the storage layout of the implementation behind the proxy.
                     *
                     * _Available since v3.4._
                     */
                    contract BeaconProxy is Proxy, ERC1967Upgrade {
                        /**
                         * @dev Initializes the proxy with `beacon`.
                         *
                         * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
                         * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
                         * constructor.
                         *
                         * Requirements:
                         *
                         * - `beacon` must be a contract with the interface {IBeacon}.
                         */
                        constructor(address beacon, bytes memory data) payable {
                            _upgradeBeaconToAndCall(beacon, data, false);
                        }
                        /**
                         * @dev Returns the current beacon address.
                         */
                        function _beacon() internal view virtual returns (address) {
                            return _getBeacon();
                        }
                        /**
                         * @dev Returns the current implementation address of the associated beacon.
                         */
                        function _implementation() internal view virtual override returns (address) {
                            return IBeacon(_getBeacon()).implementation();
                        }
                        /**
                         * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
                         *
                         * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
                         *
                         * Requirements:
                         *
                         * - `beacon` must be a contract.
                         * - The implementation returned by `beacon` must be a contract.
                         */
                        function _setBeacon(address beacon, bytes memory data) internal virtual {
                            _upgradeBeaconToAndCall(beacon, data, false);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev This is the interface that {BeaconProxy} expects of its beacon.
                     */
                    interface IBeacon {
                        /**
                         * @dev Must return an address that can be used as a delegate call target.
                         *
                         * {BeaconProxy} will check that this address is a contract.
                         */
                        function implementation() external view returns (address);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)
                    pragma solidity ^0.8.0;
                    import "./IBeacon.sol";
                    import "../../access/Ownable.sol";
                    import "../../utils/Address.sol";
                    /**
                     * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
                     * implementation contract, which is where they will delegate all function calls.
                     *
                     * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
                     */
                    contract UpgradeableBeacon is IBeacon, Ownable {
                        address private _implementation;
                        /**
                         * @dev Emitted when the implementation returned by the beacon is changed.
                         */
                        event Upgraded(address indexed implementation);
                        /**
                         * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
                         * beacon.
                         */
                        constructor(address implementation_) {
                            _setImplementation(implementation_);
                        }
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function implementation() public view virtual override returns (address) {
                            return _implementation;
                        }
                        /**
                         * @dev Upgrades the beacon to a new implementation.
                         *
                         * Emits an {Upgraded} event.
                         *
                         * Requirements:
                         *
                         * - msg.sender must be the owner of the contract.
                         * - `newImplementation` must be a contract.
                         */
                        function upgradeTo(address newImplementation) public virtual onlyOwner {
                            _setImplementation(newImplementation);
                            emit Upgraded(newImplementation);
                        }
                        /**
                         * @dev Sets the implementation contract address for this beacon
                         *
                         * Requirements:
                         *
                         * - `newImplementation` must be a contract.
                         */
                        function _setImplementation(address newImplementation) private {
                            require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
                            _implementation = newImplementation;
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
                    pragma solidity ^0.8.0;
                    import "../Proxy.sol";
                    import "./ERC1967Upgrade.sol";
                    /**
                     * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
                     * implementation address that can be changed. This address is stored in storage in the location specified by
                     * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
                     * implementation behind the proxy.
                     */
                    contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                        /**
                         * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                         *
                         * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                         * function call, and allows initializing the storage of the proxy like a Solidity constructor.
                         */
                        constructor(address _logic, bytes memory _data) payable {
                            _upgradeToAndCall(_logic, _data, false);
                        }
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function _implementation() internal view virtual override returns (address impl) {
                            return ERC1967Upgrade._getImplementation();
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol)
                    pragma solidity ^0.8.2;
                    import "../beacon/IBeacon.sol";
                    import "../../interfaces/IERC1967.sol";
                    import "../../interfaces/draft-IERC1822.sol";
                    import "../../utils/Address.sol";
                    import "../../utils/StorageSlot.sol";
                    /**
                     * @dev This abstract contract provides getters and event emitting update functions for
                     * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
                     *
                     * _Available since v4.1._
                     *
                     * @custom:oz-upgrades-unsafe-allow delegatecall
                     */
                    abstract contract ERC1967Upgrade is IERC1967 {
                        // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                        bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                        /**
                         * @dev Storage slot with the address of the current implementation.
                         * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                         * validated in the constructor.
                         */
                        bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function _getImplementation() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                        }
                        /**
                         * @dev Stores a new address in the EIP1967 implementation slot.
                         */
                        function _setImplementation(address newImplementation) private {
                            require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                            StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                        }
                        /**
                         * @dev Perform implementation upgrade
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeTo(address newImplementation) internal {
                            _setImplementation(newImplementation);
                            emit Upgraded(newImplementation);
                        }
                        /**
                         * @dev Perform implementation upgrade with additional setup call.
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeToAndCall(
                            address newImplementation,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            _upgradeTo(newImplementation);
                            if (data.length > 0 || forceCall) {
                                Address.functionDelegateCall(newImplementation, data);
                            }
                        }
                        /**
                         * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeToAndCallUUPS(
                            address newImplementation,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            // Upgrades from old implementations will perform a rollback test. This test requires the new
                            // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                            // this special case will break upgrade paths from old UUPS implementation to new ones.
                            if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                                _setImplementation(newImplementation);
                            } else {
                                try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                                    require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                                } catch {
                                    revert("ERC1967Upgrade: new implementation is not UUPS");
                                }
                                _upgradeToAndCall(newImplementation, data, forceCall);
                            }
                        }
                        /**
                         * @dev Storage slot with the admin of the contract.
                         * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                         * validated in the constructor.
                         */
                        bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                        /**
                         * @dev Returns the current admin.
                         */
                        function _getAdmin() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                        }
                        /**
                         * @dev Stores a new address in the EIP1967 admin slot.
                         */
                        function _setAdmin(address newAdmin) private {
                            require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                            StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                        }
                        /**
                         * @dev Changes the admin of the proxy.
                         *
                         * Emits an {AdminChanged} event.
                         */
                        function _changeAdmin(address newAdmin) internal {
                            emit AdminChanged(_getAdmin(), newAdmin);
                            _setAdmin(newAdmin);
                        }
                        /**
                         * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                         * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                         */
                        bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                        /**
                         * @dev Returns the current beacon.
                         */
                        function _getBeacon() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                        }
                        /**
                         * @dev Stores a new beacon in the EIP1967 beacon slot.
                         */
                        function _setBeacon(address newBeacon) private {
                            require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                            require(
                                Address.isContract(IBeacon(newBeacon).implementation()),
                                "ERC1967: beacon implementation is not a contract"
                            );
                            StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                        }
                        /**
                         * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                         * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                         *
                         * Emits a {BeaconUpgraded} event.
                         */
                        function _upgradeBeaconToAndCall(
                            address newBeacon,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            _setBeacon(newBeacon);
                            emit BeaconUpgraded(newBeacon);
                            if (data.length > 0 || forceCall) {
                                Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                            }
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
                     * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
                     * be specified by overriding the virtual {_implementation} function.
                     *
                     * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
                     * different contract through the {_delegate} function.
                     *
                     * The success and return data of the delegated call will be returned back to the caller of the proxy.
                     */
                    abstract contract Proxy {
                        /**
                         * @dev Delegates the current call to `implementation`.
                         *
                         * This function does not return to its internal call site, it will return directly to the external caller.
                         */
                        function _delegate(address implementation) internal virtual {
                            assembly {
                                // Copy msg.data. We take full control of memory in this inline assembly
                                // block because it will not return to Solidity code. We overwrite the
                                // Solidity scratch pad at memory position 0.
                                calldatacopy(0, 0, calldatasize())
                                // Call the implementation.
                                // out and outsize are 0 because we don't know the size yet.
                                let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                                // Copy the returned data.
                                returndatacopy(0, 0, returndatasize())
                                switch result
                                // delegatecall returns 0 on error.
                                case 0 {
                                    revert(0, returndatasize())
                                }
                                default {
                                    return(0, returndatasize())
                                }
                            }
                        }
                        /**
                         * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
                         * and {_fallback} should delegate.
                         */
                        function _implementation() internal view virtual returns (address);
                        /**
                         * @dev Delegates the current call to the address returned by `_implementation()`.
                         *
                         * This function does not return to its internal call site, it will return directly to the external caller.
                         */
                        function _fallback() internal virtual {
                            _beforeFallback();
                            _delegate(_implementation());
                        }
                        /**
                         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                         * function in the contract matches the call data.
                         */
                        fallback() external payable virtual {
                            _fallback();
                        }
                        /**
                         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                         * is empty.
                         */
                        receive() external payable virtual {
                            _fallback();
                        }
                        /**
                         * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                         * call, or as part of the Solidity `fallback` or `receive` functions.
                         *
                         * If overridden should call `super._beforeFallback()`.
                         */
                        function _beforeFallback() internal virtual {}
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)
                    pragma solidity ^0.8.0;
                    import "./TransparentUpgradeableProxy.sol";
                    import "../../access/Ownable.sol";
                    /**
                     * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
                     * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
                     */
                    contract ProxyAdmin is Ownable {
                        /**
                         * @dev Returns the current implementation of `proxy`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
                            // We need to manually run the static call since the getter cannot be flagged as view
                            // bytes4(keccak256("implementation()")) == 0x5c60da1b
                            (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
                            require(success);
                            return abi.decode(returndata, (address));
                        }
                        /**
                         * @dev Returns the current admin of `proxy`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
                            // We need to manually run the static call since the getter cannot be flagged as view
                            // bytes4(keccak256("admin()")) == 0xf851a440
                            (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
                            require(success);
                            return abi.decode(returndata, (address));
                        }
                        /**
                         * @dev Changes the admin of `proxy` to `newAdmin`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the current admin of `proxy`.
                         */
                        function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
                            proxy.changeAdmin(newAdmin);
                        }
                        /**
                         * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
                            proxy.upgradeTo(implementation);
                        }
                        /**
                         * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
                         * {TransparentUpgradeableProxy-upgradeToAndCall}.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function upgradeAndCall(
                            ITransparentUpgradeableProxy proxy,
                            address implementation,
                            bytes memory data
                        ) public payable virtual onlyOwner {
                            proxy.upgradeToAndCall{value: msg.value}(implementation, data);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/TransparentUpgradeableProxy.sol)
                    pragma solidity ^0.8.0;
                    import "../ERC1967/ERC1967Proxy.sol";
                    /**
                     * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
                     * does not implement this interface directly, and some of its functions are implemented by an internal dispatch
                     * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
                     * include them in the ABI so this interface must be used to interact with it.
                     */
                    interface ITransparentUpgradeableProxy is IERC1967 {
                        function admin() external view returns (address);
                        function implementation() external view returns (address);
                        function changeAdmin(address) external;
                        function upgradeTo(address) external;
                        function upgradeToAndCall(address, bytes memory) external payable;
                    }
                    /**
                     * @dev This contract implements a proxy that is upgradeable by an admin.
                     *
                     * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
                     * clashing], which can potentially be used in an attack, this contract uses the
                     * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
                     * things that go hand in hand:
                     *
                     * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
                     * that call matches one of the admin functions exposed by the proxy itself.
                     * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
                     * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
                     * "admin cannot fallback to proxy target".
                     *
                     * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
                     * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
                     * to sudden errors when trying to call a function from the proxy implementation.
                     *
                     * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
                     * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
                     *
                     * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
                     * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch
                     * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
                     * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
                     * implementation.
                     *
                     * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler
                     * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function
                     * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could
                     * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.
                     */
                    contract TransparentUpgradeableProxy is ERC1967Proxy {
                        /**
                         * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                         * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
                         */
                        constructor(
                            address _logic,
                            address admin_,
                            bytes memory _data
                        ) payable ERC1967Proxy(_logic, _data) {
                            _changeAdmin(admin_);
                        }
                        /**
                         * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                         *
                         * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the
                         * implementation provides a function with the same selector.
                         */
                        modifier ifAdmin() {
                            if (msg.sender == _getAdmin()) {
                                _;
                            } else {
                                _fallback();
                            }
                        }
                        /**
                         * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior
                         */
                        function _fallback() internal virtual override {
                            if (msg.sender == _getAdmin()) {
                                bytes memory ret;
                                bytes4 selector = msg.sig;
                                if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {
                                    ret = _dispatchUpgradeTo();
                                } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                                    ret = _dispatchUpgradeToAndCall();
                                } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {
                                    ret = _dispatchChangeAdmin();
                                } else if (selector == ITransparentUpgradeableProxy.admin.selector) {
                                    ret = _dispatchAdmin();
                                } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {
                                    ret = _dispatchImplementation();
                                } else {
                                    revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                                }
                                assembly {
                                    return(add(ret, 0x20), mload(ret))
                                }
                            } else {
                                super._fallback();
                            }
                        }
                        /**
                         * @dev Returns the current admin.
                         *
                         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                         * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                         */
                        function _dispatchAdmin() private returns (bytes memory) {
                            _requireZeroValue();
                            address admin = _getAdmin();
                            return abi.encode(admin);
                        }
                        /**
                         * @dev Returns the current implementation.
                         *
                         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                         * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                         */
                        function _dispatchImplementation() private returns (bytes memory) {
                            _requireZeroValue();
                            address implementation = _implementation();
                            return abi.encode(implementation);
                        }
                        /**
                         * @dev Changes the admin of the proxy.
                         *
                         * Emits an {AdminChanged} event.
                         */
                        function _dispatchChangeAdmin() private returns (bytes memory) {
                            _requireZeroValue();
                            address newAdmin = abi.decode(msg.data[4:], (address));
                            _changeAdmin(newAdmin);
                            return "";
                        }
                        /**
                         * @dev Upgrade the implementation of the proxy.
                         */
                        function _dispatchUpgradeTo() private returns (bytes memory) {
                            _requireZeroValue();
                            address newImplementation = abi.decode(msg.data[4:], (address));
                            _upgradeToAndCall(newImplementation, bytes(""), false);
                            return "";
                        }
                        /**
                         * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                         * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                         * proxied contract.
                         */
                        function _dispatchUpgradeToAndCall() private returns (bytes memory) {
                            (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
                            _upgradeToAndCall(newImplementation, data, true);
                            return "";
                        }
                        /**
                         * @dev Returns the current admin.
                         */
                        function _admin() internal view virtual returns (address) {
                            return _getAdmin();
                        }
                        /**
                         * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to
                         * emulate some proxy functions being non-payable while still allowing value to pass through.
                         */
                        function _requireZeroValue() private {
                            require(msg.value == 0);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
                    pragma solidity ^0.8.1;
                    /**
                     * @dev Collection of functions related to the address type
                     */
                    library Address {
                        /**
                         * @dev Returns true if `account` is a contract.
                         *
                         * [IMPORTANT]
                         * ====
                         * It is unsafe to assume that an address for which this function returns
                         * false is an externally-owned account (EOA) and not a contract.
                         *
                         * Among others, `isContract` will return false for the following
                         * types of addresses:
                         *
                         *  - an externally-owned account
                         *  - a contract in construction
                         *  - an address where a contract will be created
                         *  - an address where a contract lived, but was destroyed
                         * ====
                         *
                         * [IMPORTANT]
                         * ====
                         * You shouldn't rely on `isContract` to protect against flash loan attacks!
                         *
                         * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                         * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                         * constructor.
                         * ====
                         */
                        function isContract(address account) internal view returns (bool) {
                            // This method relies on extcodesize/address.code.length, which returns 0
                            // for contracts in construction, since the code is only stored at the end
                            // of the constructor execution.
                            return account.code.length > 0;
                        }
                        /**
                         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                         * `recipient`, forwarding all available gas and reverting on errors.
                         *
                         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                         * of certain opcodes, possibly making contracts go over the 2300 gas limit
                         * imposed by `transfer`, making them unable to receive funds via
                         * `transfer`. {sendValue} removes this limitation.
                         *
                         * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                         *
                         * IMPORTANT: because control is transferred to `recipient`, care must be
                         * taken to not create reentrancy vulnerabilities. Consider using
                         * {ReentrancyGuard} or the
                         * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                         */
                        function sendValue(address payable recipient, uint256 amount) internal {
                            require(address(this).balance >= amount, "Address: insufficient balance");
                            (bool success, ) = recipient.call{value: amount}("");
                            require(success, "Address: unable to send value, recipient may have reverted");
                        }
                        /**
                         * @dev Performs a Solidity function call using a low level `call`. A
                         * plain `call` is an unsafe replacement for a function call: use this
                         * function instead.
                         *
                         * If `target` reverts with a revert reason, it is bubbled up by this
                         * function (like regular Solidity function calls).
                         *
                         * Returns the raw returned data. To convert to the expected return value,
                         * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                         *
                         * Requirements:
                         *
                         * - `target` must be a contract.
                         * - calling `target` with `data` must not revert.
                         *
                         * _Available since v3.1._
                         */
                        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                         * `errorMessage` as a fallback revert reason when `target` reverts.
                         *
                         * _Available since v3.1._
                         */
                        function functionCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, 0, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but also transferring `value` wei to `target`.
                         *
                         * Requirements:
                         *
                         * - the calling contract must have an ETH balance of at least `value`.
                         * - the called Solidity function must be `payable`.
                         *
                         * _Available since v3.1._
                         */
                        function functionCallWithValue(
                            address target,
                            bytes memory data,
                            uint256 value
                        ) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                         * with `errorMessage` as a fallback revert reason when `target` reverts.
                         *
                         * _Available since v3.1._
                         */
                        function functionCallWithValue(
                            address target,
                            bytes memory data,
                            uint256 value,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            require(address(this).balance >= value, "Address: insufficient balance for call");
                            (bool success, bytes memory returndata) = target.call{value: value}(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but performing a static call.
                         *
                         * _Available since v3.3._
                         */
                        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                            return functionStaticCall(target, data, "Address: low-level static call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                         * but performing a static call.
                         *
                         * _Available since v3.3._
                         */
                        function functionStaticCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal view returns (bytes memory) {
                            (bool success, bytes memory returndata) = target.staticcall(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but performing a delegate call.
                         *
                         * _Available since v3.4._
                         */
                        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                            return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                         * but performing a delegate call.
                         *
                         * _Available since v3.4._
                         */
                        function functionDelegateCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            (bool success, bytes memory returndata) = target.delegatecall(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                         * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                         *
                         * _Available since v4.8._
                         */
                        function verifyCallResultFromTarget(
                            address target,
                            bool success,
                            bytes memory returndata,
                            string memory errorMessage
                        ) internal view returns (bytes memory) {
                            if (success) {
                                if (returndata.length == 0) {
                                    // only check isContract if the call was successful and the return data is empty
                                    // otherwise we already know that it was a contract
                                    require(isContract(target), "Address: call to non-contract");
                                }
                                return returndata;
                            } else {
                                _revert(returndata, errorMessage);
                            }
                        }
                        /**
                         * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                         * revert reason or using the provided one.
                         *
                         * _Available since v4.3._
                         */
                        function verifyCallResult(
                            bool success,
                            bytes memory returndata,
                            string memory errorMessage
                        ) internal pure returns (bytes memory) {
                            if (success) {
                                return returndata;
                            } else {
                                _revert(returndata, errorMessage);
                            }
                        }
                        function _revert(bytes memory returndata, string memory errorMessage) private pure {
                            // Look for revert reason and bubble it up if present
                            if (returndata.length > 0) {
                                // The easiest way to bubble the revert reason is using memory via assembly
                                /// @solidity memory-safe-assembly
                                assembly {
                                    let returndata_size := mload(returndata)
                                    revert(add(32, returndata), returndata_size)
                                }
                            } else {
                                revert(errorMessage);
                            }
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev Provides information about the current execution context, including the
                     * sender of the transaction and its data. While these are generally available
                     * via msg.sender and msg.data, they should not be accessed in such a direct
                     * manner, since when dealing with meta-transactions the account sending and
                     * paying for execution may not be the actual sender (as far as an application
                     * is concerned).
                     *
                     * This contract is only required for intermediate, library-like contracts.
                     */
                    abstract contract Context {
                        function _msgSender() internal view virtual returns (address) {
                            return msg.sender;
                        }
                        function _msgData() internal view virtual returns (bytes calldata) {
                            return msg.data;
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev Library for reading and writing primitive types to specific storage slots.
                     *
                     * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
                     * This library helps with reading and writing to such slots without the need for inline assembly.
                     *
                     * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
                     *
                     * Example usage to set ERC1967 implementation slot:
                     * ```
                     * contract ERC1967 {
                     *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                     *
                     *     function _getImplementation() internal view returns (address) {
                     *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                     *     }
                     *
                     *     function _setImplementation(address newImplementation) internal {
                     *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                     *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                     *     }
                     * }
                     * ```
                     *
                     * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
                     */
                    library StorageSlot {
                        struct AddressSlot {
                            address value;
                        }
                        struct BooleanSlot {
                            bool value;
                        }
                        struct Bytes32Slot {
                            bytes32 value;
                        }
                        struct Uint256Slot {
                            uint256 value;
                        }
                        /**
                         * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                         */
                        function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                         */
                        function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                         */
                        function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                         */
                        function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                    }
                    

                    File 2 of 2: ERC1967Proxy
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
                    pragma solidity ^0.8.0;
                    import "../utils/Context.sol";
                    /**
                     * @dev Contract module which provides a basic access control mechanism, where
                     * there is an account (an owner) that can be granted exclusive access to
                     * specific functions.
                     *
                     * By default, the owner account will be the one that deploys the contract. This
                     * can later be changed with {transferOwnership}.
                     *
                     * This module is used through inheritance. It will make available the modifier
                     * `onlyOwner`, which can be applied to your functions to restrict their use to
                     * the owner.
                     */
                    abstract contract Ownable is Context {
                        address private _owner;
                        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                        /**
                         * @dev Initializes the contract setting the deployer as the initial owner.
                         */
                        constructor() {
                            _transferOwnership(_msgSender());
                        }
                        /**
                         * @dev Throws if called by any account other than the owner.
                         */
                        modifier onlyOwner() {
                            _checkOwner();
                            _;
                        }
                        /**
                         * @dev Returns the address of the current owner.
                         */
                        function owner() public view virtual returns (address) {
                            return _owner;
                        }
                        /**
                         * @dev Throws if the sender is not the owner.
                         */
                        function _checkOwner() internal view virtual {
                            require(owner() == _msgSender(), "Ownable: caller is not the owner");
                        }
                        /**
                         * @dev Leaves the contract without owner. It will not be possible to call
                         * `onlyOwner` functions anymore. Can only be called by the current owner.
                         *
                         * NOTE: Renouncing ownership will leave the contract without an owner,
                         * thereby removing any functionality that is only available to the owner.
                         */
                        function renounceOwnership() public virtual onlyOwner {
                            _transferOwnership(address(0));
                        }
                        /**
                         * @dev Transfers ownership of the contract to a new account (`newOwner`).
                         * Can only be called by the current owner.
                         */
                        function transferOwnership(address newOwner) public virtual onlyOwner {
                            require(newOwner != address(0), "Ownable: new owner is the zero address");
                            _transferOwnership(newOwner);
                        }
                        /**
                         * @dev Transfers ownership of the contract to a new account (`newOwner`).
                         * Internal function without access restriction.
                         */
                        function _transferOwnership(address newOwner) internal virtual {
                            address oldOwner = _owner;
                            _owner = newOwner;
                            emit OwnershipTransferred(oldOwner, newOwner);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
                     * proxy whose upgrades are fully controlled by the current implementation.
                     */
                    interface IERC1822Proxiable {
                        /**
                         * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                         * address.
                         *
                         * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                         * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                         * function revert if invoked through a proxy.
                         */
                        function proxiableUUID() external view returns (bytes32);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
                     *
                     * _Available since v4.9._
                     */
                    interface IERC1967 {
                        /**
                         * @dev Emitted when the implementation is upgraded.
                         */
                        event Upgraded(address indexed implementation);
                        /**
                         * @dev Emitted when the admin account has changed.
                         */
                        event AdminChanged(address previousAdmin, address newAdmin);
                        /**
                         * @dev Emitted when the beacon is changed.
                         */
                        event BeaconUpgraded(address indexed beacon);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)
                    pragma solidity ^0.8.0;
                    import "./IBeacon.sol";
                    import "../Proxy.sol";
                    import "../ERC1967/ERC1967Upgrade.sol";
                    /**
                     * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
                     *
                     * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
                     * conflict with the storage layout of the implementation behind the proxy.
                     *
                     * _Available since v3.4._
                     */
                    contract BeaconProxy is Proxy, ERC1967Upgrade {
                        /**
                         * @dev Initializes the proxy with `beacon`.
                         *
                         * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
                         * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
                         * constructor.
                         *
                         * Requirements:
                         *
                         * - `beacon` must be a contract with the interface {IBeacon}.
                         */
                        constructor(address beacon, bytes memory data) payable {
                            _upgradeBeaconToAndCall(beacon, data, false);
                        }
                        /**
                         * @dev Returns the current beacon address.
                         */
                        function _beacon() internal view virtual returns (address) {
                            return _getBeacon();
                        }
                        /**
                         * @dev Returns the current implementation address of the associated beacon.
                         */
                        function _implementation() internal view virtual override returns (address) {
                            return IBeacon(_getBeacon()).implementation();
                        }
                        /**
                         * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
                         *
                         * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
                         *
                         * Requirements:
                         *
                         * - `beacon` must be a contract.
                         * - The implementation returned by `beacon` must be a contract.
                         */
                        function _setBeacon(address beacon, bytes memory data) internal virtual {
                            _upgradeBeaconToAndCall(beacon, data, false);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev This is the interface that {BeaconProxy} expects of its beacon.
                     */
                    interface IBeacon {
                        /**
                         * @dev Must return an address that can be used as a delegate call target.
                         *
                         * {BeaconProxy} will check that this address is a contract.
                         */
                        function implementation() external view returns (address);
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)
                    pragma solidity ^0.8.0;
                    import "./IBeacon.sol";
                    import "../../access/Ownable.sol";
                    import "../../utils/Address.sol";
                    /**
                     * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
                     * implementation contract, which is where they will delegate all function calls.
                     *
                     * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
                     */
                    contract UpgradeableBeacon is IBeacon, Ownable {
                        address private _implementation;
                        /**
                         * @dev Emitted when the implementation returned by the beacon is changed.
                         */
                        event Upgraded(address indexed implementation);
                        /**
                         * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
                         * beacon.
                         */
                        constructor(address implementation_) {
                            _setImplementation(implementation_);
                        }
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function implementation() public view virtual override returns (address) {
                            return _implementation;
                        }
                        /**
                         * @dev Upgrades the beacon to a new implementation.
                         *
                         * Emits an {Upgraded} event.
                         *
                         * Requirements:
                         *
                         * - msg.sender must be the owner of the contract.
                         * - `newImplementation` must be a contract.
                         */
                        function upgradeTo(address newImplementation) public virtual onlyOwner {
                            _setImplementation(newImplementation);
                            emit Upgraded(newImplementation);
                        }
                        /**
                         * @dev Sets the implementation contract address for this beacon
                         *
                         * Requirements:
                         *
                         * - `newImplementation` must be a contract.
                         */
                        function _setImplementation(address newImplementation) private {
                            require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
                            _implementation = newImplementation;
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
                    pragma solidity ^0.8.0;
                    import "../Proxy.sol";
                    import "./ERC1967Upgrade.sol";
                    /**
                     * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
                     * implementation address that can be changed. This address is stored in storage in the location specified by
                     * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
                     * implementation behind the proxy.
                     */
                    contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                        /**
                         * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                         *
                         * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                         * function call, and allows initializing the storage of the proxy like a Solidity constructor.
                         */
                        constructor(address _logic, bytes memory _data) payable {
                            _upgradeToAndCall(_logic, _data, false);
                        }
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function _implementation() internal view virtual override returns (address impl) {
                            return ERC1967Upgrade._getImplementation();
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol)
                    pragma solidity ^0.8.2;
                    import "../beacon/IBeacon.sol";
                    import "../../interfaces/IERC1967.sol";
                    import "../../interfaces/draft-IERC1822.sol";
                    import "../../utils/Address.sol";
                    import "../../utils/StorageSlot.sol";
                    /**
                     * @dev This abstract contract provides getters and event emitting update functions for
                     * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
                     *
                     * _Available since v4.1._
                     *
                     * @custom:oz-upgrades-unsafe-allow delegatecall
                     */
                    abstract contract ERC1967Upgrade is IERC1967 {
                        // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                        bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                        /**
                         * @dev Storage slot with the address of the current implementation.
                         * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                         * validated in the constructor.
                         */
                        bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                        /**
                         * @dev Returns the current implementation address.
                         */
                        function _getImplementation() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                        }
                        /**
                         * @dev Stores a new address in the EIP1967 implementation slot.
                         */
                        function _setImplementation(address newImplementation) private {
                            require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                            StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                        }
                        /**
                         * @dev Perform implementation upgrade
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeTo(address newImplementation) internal {
                            _setImplementation(newImplementation);
                            emit Upgraded(newImplementation);
                        }
                        /**
                         * @dev Perform implementation upgrade with additional setup call.
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeToAndCall(
                            address newImplementation,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            _upgradeTo(newImplementation);
                            if (data.length > 0 || forceCall) {
                                Address.functionDelegateCall(newImplementation, data);
                            }
                        }
                        /**
                         * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                         *
                         * Emits an {Upgraded} event.
                         */
                        function _upgradeToAndCallUUPS(
                            address newImplementation,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            // Upgrades from old implementations will perform a rollback test. This test requires the new
                            // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                            // this special case will break upgrade paths from old UUPS implementation to new ones.
                            if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                                _setImplementation(newImplementation);
                            } else {
                                try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                                    require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                                } catch {
                                    revert("ERC1967Upgrade: new implementation is not UUPS");
                                }
                                _upgradeToAndCall(newImplementation, data, forceCall);
                            }
                        }
                        /**
                         * @dev Storage slot with the admin of the contract.
                         * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                         * validated in the constructor.
                         */
                        bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                        /**
                         * @dev Returns the current admin.
                         */
                        function _getAdmin() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                        }
                        /**
                         * @dev Stores a new address in the EIP1967 admin slot.
                         */
                        function _setAdmin(address newAdmin) private {
                            require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                            StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                        }
                        /**
                         * @dev Changes the admin of the proxy.
                         *
                         * Emits an {AdminChanged} event.
                         */
                        function _changeAdmin(address newAdmin) internal {
                            emit AdminChanged(_getAdmin(), newAdmin);
                            _setAdmin(newAdmin);
                        }
                        /**
                         * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                         * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                         */
                        bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                        /**
                         * @dev Returns the current beacon.
                         */
                        function _getBeacon() internal view returns (address) {
                            return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                        }
                        /**
                         * @dev Stores a new beacon in the EIP1967 beacon slot.
                         */
                        function _setBeacon(address newBeacon) private {
                            require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                            require(
                                Address.isContract(IBeacon(newBeacon).implementation()),
                                "ERC1967: beacon implementation is not a contract"
                            );
                            StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                        }
                        /**
                         * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                         * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                         *
                         * Emits a {BeaconUpgraded} event.
                         */
                        function _upgradeBeaconToAndCall(
                            address newBeacon,
                            bytes memory data,
                            bool forceCall
                        ) internal {
                            _setBeacon(newBeacon);
                            emit BeaconUpgraded(newBeacon);
                            if (data.length > 0 || forceCall) {
                                Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                            }
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
                     * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
                     * be specified by overriding the virtual {_implementation} function.
                     *
                     * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
                     * different contract through the {_delegate} function.
                     *
                     * The success and return data of the delegated call will be returned back to the caller of the proxy.
                     */
                    abstract contract Proxy {
                        /**
                         * @dev Delegates the current call to `implementation`.
                         *
                         * This function does not return to its internal call site, it will return directly to the external caller.
                         */
                        function _delegate(address implementation) internal virtual {
                            assembly {
                                // Copy msg.data. We take full control of memory in this inline assembly
                                // block because it will not return to Solidity code. We overwrite the
                                // Solidity scratch pad at memory position 0.
                                calldatacopy(0, 0, calldatasize())
                                // Call the implementation.
                                // out and outsize are 0 because we don't know the size yet.
                                let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                                // Copy the returned data.
                                returndatacopy(0, 0, returndatasize())
                                switch result
                                // delegatecall returns 0 on error.
                                case 0 {
                                    revert(0, returndatasize())
                                }
                                default {
                                    return(0, returndatasize())
                                }
                            }
                        }
                        /**
                         * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
                         * and {_fallback} should delegate.
                         */
                        function _implementation() internal view virtual returns (address);
                        /**
                         * @dev Delegates the current call to the address returned by `_implementation()`.
                         *
                         * This function does not return to its internal call site, it will return directly to the external caller.
                         */
                        function _fallback() internal virtual {
                            _beforeFallback();
                            _delegate(_implementation());
                        }
                        /**
                         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                         * function in the contract matches the call data.
                         */
                        fallback() external payable virtual {
                            _fallback();
                        }
                        /**
                         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                         * is empty.
                         */
                        receive() external payable virtual {
                            _fallback();
                        }
                        /**
                         * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                         * call, or as part of the Solidity `fallback` or `receive` functions.
                         *
                         * If overridden should call `super._beforeFallback()`.
                         */
                        function _beforeFallback() internal virtual {}
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)
                    pragma solidity ^0.8.0;
                    import "./TransparentUpgradeableProxy.sol";
                    import "../../access/Ownable.sol";
                    /**
                     * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
                     * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
                     */
                    contract ProxyAdmin is Ownable {
                        /**
                         * @dev Returns the current implementation of `proxy`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
                            // We need to manually run the static call since the getter cannot be flagged as view
                            // bytes4(keccak256("implementation()")) == 0x5c60da1b
                            (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
                            require(success);
                            return abi.decode(returndata, (address));
                        }
                        /**
                         * @dev Returns the current admin of `proxy`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
                            // We need to manually run the static call since the getter cannot be flagged as view
                            // bytes4(keccak256("admin()")) == 0xf851a440
                            (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
                            require(success);
                            return abi.decode(returndata, (address));
                        }
                        /**
                         * @dev Changes the admin of `proxy` to `newAdmin`.
                         *
                         * Requirements:
                         *
                         * - This contract must be the current admin of `proxy`.
                         */
                        function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
                            proxy.changeAdmin(newAdmin);
                        }
                        /**
                         * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
                            proxy.upgradeTo(implementation);
                        }
                        /**
                         * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
                         * {TransparentUpgradeableProxy-upgradeToAndCall}.
                         *
                         * Requirements:
                         *
                         * - This contract must be the admin of `proxy`.
                         */
                        function upgradeAndCall(
                            ITransparentUpgradeableProxy proxy,
                            address implementation,
                            bytes memory data
                        ) public payable virtual onlyOwner {
                            proxy.upgradeToAndCall{value: msg.value}(implementation, data);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/TransparentUpgradeableProxy.sol)
                    pragma solidity ^0.8.0;
                    import "../ERC1967/ERC1967Proxy.sol";
                    /**
                     * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
                     * does not implement this interface directly, and some of its functions are implemented by an internal dispatch
                     * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
                     * include them in the ABI so this interface must be used to interact with it.
                     */
                    interface ITransparentUpgradeableProxy is IERC1967 {
                        function admin() external view returns (address);
                        function implementation() external view returns (address);
                        function changeAdmin(address) external;
                        function upgradeTo(address) external;
                        function upgradeToAndCall(address, bytes memory) external payable;
                    }
                    /**
                     * @dev This contract implements a proxy that is upgradeable by an admin.
                     *
                     * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
                     * clashing], which can potentially be used in an attack, this contract uses the
                     * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
                     * things that go hand in hand:
                     *
                     * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
                     * that call matches one of the admin functions exposed by the proxy itself.
                     * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
                     * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
                     * "admin cannot fallback to proxy target".
                     *
                     * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
                     * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
                     * to sudden errors when trying to call a function from the proxy implementation.
                     *
                     * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
                     * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
                     *
                     * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
                     * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch
                     * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
                     * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
                     * implementation.
                     *
                     * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler
                     * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function
                     * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could
                     * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.
                     */
                    contract TransparentUpgradeableProxy is ERC1967Proxy {
                        /**
                         * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                         * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
                         */
                        constructor(
                            address _logic,
                            address admin_,
                            bytes memory _data
                        ) payable ERC1967Proxy(_logic, _data) {
                            _changeAdmin(admin_);
                        }
                        /**
                         * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                         *
                         * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the
                         * implementation provides a function with the same selector.
                         */
                        modifier ifAdmin() {
                            if (msg.sender == _getAdmin()) {
                                _;
                            } else {
                                _fallback();
                            }
                        }
                        /**
                         * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior
                         */
                        function _fallback() internal virtual override {
                            if (msg.sender == _getAdmin()) {
                                bytes memory ret;
                                bytes4 selector = msg.sig;
                                if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {
                                    ret = _dispatchUpgradeTo();
                                } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                                    ret = _dispatchUpgradeToAndCall();
                                } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {
                                    ret = _dispatchChangeAdmin();
                                } else if (selector == ITransparentUpgradeableProxy.admin.selector) {
                                    ret = _dispatchAdmin();
                                } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {
                                    ret = _dispatchImplementation();
                                } else {
                                    revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                                }
                                assembly {
                                    return(add(ret, 0x20), mload(ret))
                                }
                            } else {
                                super._fallback();
                            }
                        }
                        /**
                         * @dev Returns the current admin.
                         *
                         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                         * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                         */
                        function _dispatchAdmin() private returns (bytes memory) {
                            _requireZeroValue();
                            address admin = _getAdmin();
                            return abi.encode(admin);
                        }
                        /**
                         * @dev Returns the current implementation.
                         *
                         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                         * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                         */
                        function _dispatchImplementation() private returns (bytes memory) {
                            _requireZeroValue();
                            address implementation = _implementation();
                            return abi.encode(implementation);
                        }
                        /**
                         * @dev Changes the admin of the proxy.
                         *
                         * Emits an {AdminChanged} event.
                         */
                        function _dispatchChangeAdmin() private returns (bytes memory) {
                            _requireZeroValue();
                            address newAdmin = abi.decode(msg.data[4:], (address));
                            _changeAdmin(newAdmin);
                            return "";
                        }
                        /**
                         * @dev Upgrade the implementation of the proxy.
                         */
                        function _dispatchUpgradeTo() private returns (bytes memory) {
                            _requireZeroValue();
                            address newImplementation = abi.decode(msg.data[4:], (address));
                            _upgradeToAndCall(newImplementation, bytes(""), false);
                            return "";
                        }
                        /**
                         * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                         * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                         * proxied contract.
                         */
                        function _dispatchUpgradeToAndCall() private returns (bytes memory) {
                            (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
                            _upgradeToAndCall(newImplementation, data, true);
                            return "";
                        }
                        /**
                         * @dev Returns the current admin.
                         */
                        function _admin() internal view virtual returns (address) {
                            return _getAdmin();
                        }
                        /**
                         * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to
                         * emulate some proxy functions being non-payable while still allowing value to pass through.
                         */
                        function _requireZeroValue() private {
                            require(msg.value == 0);
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
                    pragma solidity ^0.8.1;
                    /**
                     * @dev Collection of functions related to the address type
                     */
                    library Address {
                        /**
                         * @dev Returns true if `account` is a contract.
                         *
                         * [IMPORTANT]
                         * ====
                         * It is unsafe to assume that an address for which this function returns
                         * false is an externally-owned account (EOA) and not a contract.
                         *
                         * Among others, `isContract` will return false for the following
                         * types of addresses:
                         *
                         *  - an externally-owned account
                         *  - a contract in construction
                         *  - an address where a contract will be created
                         *  - an address where a contract lived, but was destroyed
                         * ====
                         *
                         * [IMPORTANT]
                         * ====
                         * You shouldn't rely on `isContract` to protect against flash loan attacks!
                         *
                         * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                         * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                         * constructor.
                         * ====
                         */
                        function isContract(address account) internal view returns (bool) {
                            // This method relies on extcodesize/address.code.length, which returns 0
                            // for contracts in construction, since the code is only stored at the end
                            // of the constructor execution.
                            return account.code.length > 0;
                        }
                        /**
                         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                         * `recipient`, forwarding all available gas and reverting on errors.
                         *
                         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                         * of certain opcodes, possibly making contracts go over the 2300 gas limit
                         * imposed by `transfer`, making them unable to receive funds via
                         * `transfer`. {sendValue} removes this limitation.
                         *
                         * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                         *
                         * IMPORTANT: because control is transferred to `recipient`, care must be
                         * taken to not create reentrancy vulnerabilities. Consider using
                         * {ReentrancyGuard} or the
                         * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                         */
                        function sendValue(address payable recipient, uint256 amount) internal {
                            require(address(this).balance >= amount, "Address: insufficient balance");
                            (bool success, ) = recipient.call{value: amount}("");
                            require(success, "Address: unable to send value, recipient may have reverted");
                        }
                        /**
                         * @dev Performs a Solidity function call using a low level `call`. A
                         * plain `call` is an unsafe replacement for a function call: use this
                         * function instead.
                         *
                         * If `target` reverts with a revert reason, it is bubbled up by this
                         * function (like regular Solidity function calls).
                         *
                         * Returns the raw returned data. To convert to the expected return value,
                         * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                         *
                         * Requirements:
                         *
                         * - `target` must be a contract.
                         * - calling `target` with `data` must not revert.
                         *
                         * _Available since v3.1._
                         */
                        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, 0, "Address: low-level call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                         * `errorMessage` as a fallback revert reason when `target` reverts.
                         *
                         * _Available since v3.1._
                         */
                        function functionCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, 0, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but also transferring `value` wei to `target`.
                         *
                         * Requirements:
                         *
                         * - the calling contract must have an ETH balance of at least `value`.
                         * - the called Solidity function must be `payable`.
                         *
                         * _Available since v3.1._
                         */
                        function functionCallWithValue(
                            address target,
                            bytes memory data,
                            uint256 value
                        ) internal returns (bytes memory) {
                            return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                         * with `errorMessage` as a fallback revert reason when `target` reverts.
                         *
                         * _Available since v3.1._
                         */
                        function functionCallWithValue(
                            address target,
                            bytes memory data,
                            uint256 value,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            require(address(this).balance >= value, "Address: insufficient balance for call");
                            (bool success, bytes memory returndata) = target.call{value: value}(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but performing a static call.
                         *
                         * _Available since v3.3._
                         */
                        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                            return functionStaticCall(target, data, "Address: low-level static call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                         * but performing a static call.
                         *
                         * _Available since v3.3._
                         */
                        function functionStaticCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal view returns (bytes memory) {
                            (bool success, bytes memory returndata) = target.staticcall(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                         * but performing a delegate call.
                         *
                         * _Available since v3.4._
                         */
                        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                            return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                        }
                        /**
                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                         * but performing a delegate call.
                         *
                         * _Available since v3.4._
                         */
                        function functionDelegateCall(
                            address target,
                            bytes memory data,
                            string memory errorMessage
                        ) internal returns (bytes memory) {
                            (bool success, bytes memory returndata) = target.delegatecall(data);
                            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                        }
                        /**
                         * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                         * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                         *
                         * _Available since v4.8._
                         */
                        function verifyCallResultFromTarget(
                            address target,
                            bool success,
                            bytes memory returndata,
                            string memory errorMessage
                        ) internal view returns (bytes memory) {
                            if (success) {
                                if (returndata.length == 0) {
                                    // only check isContract if the call was successful and the return data is empty
                                    // otherwise we already know that it was a contract
                                    require(isContract(target), "Address: call to non-contract");
                                }
                                return returndata;
                            } else {
                                _revert(returndata, errorMessage);
                            }
                        }
                        /**
                         * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                         * revert reason or using the provided one.
                         *
                         * _Available since v4.3._
                         */
                        function verifyCallResult(
                            bool success,
                            bytes memory returndata,
                            string memory errorMessage
                        ) internal pure returns (bytes memory) {
                            if (success) {
                                return returndata;
                            } else {
                                _revert(returndata, errorMessage);
                            }
                        }
                        function _revert(bytes memory returndata, string memory errorMessage) private pure {
                            // Look for revert reason and bubble it up if present
                            if (returndata.length > 0) {
                                // The easiest way to bubble the revert reason is using memory via assembly
                                /// @solidity memory-safe-assembly
                                assembly {
                                    let returndata_size := mload(returndata)
                                    revert(add(32, returndata), returndata_size)
                                }
                            } else {
                                revert(errorMessage);
                            }
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev Provides information about the current execution context, including the
                     * sender of the transaction and its data. While these are generally available
                     * via msg.sender and msg.data, they should not be accessed in such a direct
                     * manner, since when dealing with meta-transactions the account sending and
                     * paying for execution may not be the actual sender (as far as an application
                     * is concerned).
                     *
                     * This contract is only required for intermediate, library-like contracts.
                     */
                    abstract contract Context {
                        function _msgSender() internal view virtual returns (address) {
                            return msg.sender;
                        }
                        function _msgData() internal view virtual returns (bytes calldata) {
                            return msg.data;
                        }
                    }
                    // SPDX-License-Identifier: MIT
                    // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
                    pragma solidity ^0.8.0;
                    /**
                     * @dev Library for reading and writing primitive types to specific storage slots.
                     *
                     * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
                     * This library helps with reading and writing to such slots without the need for inline assembly.
                     *
                     * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
                     *
                     * Example usage to set ERC1967 implementation slot:
                     * ```
                     * contract ERC1967 {
                     *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                     *
                     *     function _getImplementation() internal view returns (address) {
                     *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                     *     }
                     *
                     *     function _setImplementation(address newImplementation) internal {
                     *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                     *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                     *     }
                     * }
                     * ```
                     *
                     * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
                     */
                    library StorageSlot {
                        struct AddressSlot {
                            address value;
                        }
                        struct BooleanSlot {
                            bool value;
                        }
                        struct Bytes32Slot {
                            bytes32 value;
                        }
                        struct Uint256Slot {
                            uint256 value;
                        }
                        /**
                         * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                         */
                        function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                         */
                        function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                         */
                        function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                        /**
                         * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                         */
                        function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                            /// @solidity memory-safe-assembly
                            assembly {
                                r.slot := slot
                            }
                        }
                    }