AVAX Price: $36.31 (+3.84%)
Gas: 1.1 nAVAX
 

Overview

AVAX Balance

Avalanche C-Chain LogoAvalanche C-Chain LogoAvalanche C-Chain Logo0 AVAX

AVAX Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer562862382025-01-24 12:23:457 mins ago1737721425IN
0x00000000...D69a9012a
0 AVAX0.000057721.06483454
Batch Mint562861452025-01-24 12:20:3311 mins ago1737721233IN
0x00000000...D69a9012a
0 AVAX0.000066451.06331828
Approve562849962025-01-24 11:43:0648 mins ago1737718986IN
0x00000000...D69a9012a
0 AVAX0.000131962.58771378
Approve562849712025-01-24 11:42:2049 mins ago1737718940IN
0x00000000...D69a9012a
0 AVAX0.00004231.25
Approve562849662025-01-24 11:42:0749 mins ago1737718927IN
0x00000000...D69a9012a
0 AVAX0.000043321.28
Approve562849352025-01-24 11:41:0350 mins ago1737718863IN
0x00000000...D69a9012a
0 AVAX0.000044671.32
Approve562849082025-01-24 11:40:0651 mins ago1737718806IN
0x00000000...D69a9012a
0 AVAX0.000128652.52339457
Approve562848462025-01-24 11:38:0453 mins ago1737718684IN
0x00000000...D69a9012a
0 AVAX0.000085052.51371329
Approve562848442025-01-24 11:37:5853 mins ago1737718678IN
0x00000000...D69a9012a
0 AVAX0.000086732.56259373
Approve562847632025-01-24 11:35:1756 mins ago1737718517IN
0x00000000...D69a9012a
0 AVAX0.000128742.52464943
Approve562847362025-01-24 11:34:2057 mins ago1737718460IN
0x00000000...D69a9012a
0 AVAX0.000130212.53671388
Approve562842912025-01-24 11:19:301 hr ago1737717570IN
0x00000000...D69a9012a
0 AVAX0.000053541.05
Approve562837452025-01-24 11:01:211 hr ago1737716481IN
0x00000000...D69a9012a
0 AVAX0.000047381.4
Approve562836362025-01-24 10:57:381 hr ago1737716258IN
0x00000000...D69a9012a
0 AVAX0.000052971.04
Transfer562835112025-01-24 10:53:291 hr ago1737716009IN
0x00000000...D69a9012a
0 AVAX0.000042261.14
Approve562831882025-01-24 10:42:451 hr ago1737715365IN
0x00000000...D69a9012a
0 AVAX0.000053021.04
Approve562830222025-01-24 10:37:211 hr ago1737715041IN
0x00000000...D69a9012a
0 AVAX0.000064161.25
Approve562830122025-01-24 10:36:591 hr ago1737715019IN
0x00000000...D69a9012a
0 AVAX0.000042291.25
Approve562829662025-01-24 10:35:321 hr ago1737714932IN
0x00000000...D69a9012a
0 AVAX0.000056181.10210712
Approve562826262025-01-24 10:24:172 hrs ago1737714257IN
0x00000000...D69a9012a
0 AVAX0.00005281.56
Approve562823702025-01-24 10:15:352 hrs ago1737713735IN
0x00000000...D69a9012a
0 AVAX0.000051331
Approve562807862025-01-24 9:24:323 hrs ago1737710672IN
0x00000000...D69a9012a
0 AVAX0.00004231.25
Approve562802322025-01-24 9:06:593 hrs ago1737709619IN
0x00000000...D69a9012a
0 AVAX0.000136612.66148877
Approve562792452025-01-24 8:35:183 hrs ago1737707718IN
0x00000000...D69a9012a
0 AVAX0.000054631.06440543
Approve562789162025-01-24 8:24:574 hrs ago1737707097IN
0x00000000...D69a9012a
0 AVAX0.000035811.0561304
View all transactions

Latest 2 internal transactions

Parent Transaction Hash Block From To
485079972024-07-27 15:45:55180 days ago1722095155
0x00000000...D69a9012a
 Contract Creation0 AVAX
485079972024-07-27 15:45:55180 days ago1722095155  Contract Creation0 AVAX
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AgoraDollarErc1967Proxy

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 100000000 runs

Other Settings:
shanghai EvmVersion, None license
File 1 of 27 : AgoraDollarErc1967Proxy.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ===================== AgoraDollarErc1967Proxy ======================
// ====================================================================

import { Proxy } from "@openzeppelin/contracts/proxy/Proxy.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SafeCastLib } from "solady/src/utils/SafeCastLib.sol";

import { Eip3009, Eip712 } from "../Eip3009.sol";
import { AgoraProxyAdmin } from "./AgoraProxyAdmin.sol";

import { StorageLib } from "./StorageLib.sol";

import { ITransparentUpgradeableProxy } from "../interfaces/ITransparentUpgradeableProxy.sol";

/// @notice The constructor params for the AgoraDollarErc1967Proxy contract
/// @dev Allows for an experience closer to named parameters in constructor calls
/// @param proxyAdminOwnerAddress The address of the proxy admin owner
/// @param eip712Name The name of the Eip712 domain
/// @param eip712Version The version of the Eip712 domain
struct ConstructorParams {
    address proxyAdminOwnerAddress;
    string eip712Name;
    string eip712Version;
}

/// @title AgoraDollarErc1967Proxy
/// @notice The AgoraDollarErc1967Proxy contract is a proxy contract that delegatecalls to an implementation contract
/// @dev The AgoraDollarErc1967Proxy contract implements some additional functionality directly for gas savings
/// @author Agora
contract AgoraDollarErc1967Proxy is Eip3009, Proxy {
    using SafeCastLib for uint256;
    using StorageLib for uint256;

    address private immutable PROXY_ADMIN_ADDRESS;

    /// @notice The AgoraDollarErc1967Proxy constructor
    /// @param _params The constructor params for the AgoraDollarErc1967Proxy contract
    constructor(
        ConstructorParams memory _params
    ) payable Eip712(_params.eip712Name, _params.eip712Version, address(this)) {
        // Effects: Set the proxy admin address in both bytecode and storage
        // Stored directly in bytecode for gas efficiency
        PROXY_ADMIN_ADDRESS = address(new AgoraProxyAdmin({ _initialOwner: _params.proxyAdminOwnerAddress }));
        // Stored again in storage to comply with Erc1967 standard
        StorageLib.getPointerToAgoraDollarErc1967ProxyAdminStorage().proxyAdminAddress = PROXY_ADMIN_ADDRESS;

        // Emit event
        emit AdminChanged({ previousAdmin: address(0), newAdmin: PROXY_ADMIN_ADDRESS });
    }

    fallback() external payable override {
        _fallback();
    }

    //==============================================================================
    // Proxy Functions
    //==============================================================================

    function _implementation() internal view override returns (address _implementationAddress) {
        _implementationAddress = StorageLib.sloadImplementationSlotDataAsUint256().implementation();
    }

    /// @notice The ```_fallback``` function is an internal function which allows the proxy to delegate to the new implementation address
    /// @dev ProxyAdmin is restricted to only calling upgradeToAndCall
    function _fallback() internal override {
        if (msg.sender == PROXY_ADMIN_ADDRESS) {
            if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                revert ProxyDeniedAdminAccess();
            } else {
                (address _newImplementation, bytes memory _callData) = abi.decode(msg.data[4:], (address, bytes));
                _upgradeToAndCall({ _newImplementation: _newImplementation, _callData: _callData });
            }
        } else {
            super._fallback();
        }
    }

    /// @notice The ```_upgradeToAndCall``` function is an internal function which sets the new implementation address and calls the new implementation with the given calldata
    /// @param _newImplementation The address of the new implementation
    /// @param _callData The call data using the new implementation as a target
    function _upgradeToAndCall(address _newImplementation, bytes memory _callData) internal {
        // Checks: Ensure the new implementation is a contract
        if (_newImplementation.code.length == 0) revert ImplementationTargetNotAContract();

        // Effects: Write the storage value for new implementation
        StorageLib.AgoraDollarErc1967ProxyContractStorage storage contractData = StorageLib
            .getPointerToAgoraDollarErc1967ProxyContractStorage();
        contractData.implementationAddress = _newImplementation;

        // Emit event
        emit Upgraded({ implementation: _newImplementation });

        // Execute calldata for new implementation
        if (_callData.length > 0) Address.functionDelegateCall({ target: _newImplementation, data: _callData });
        else if (msg.value > 0) revert AgoraDollarErc1967NonPayable();
    }

    //==============================================================================
    // Erc20 Overridden Functions
    //==============================================================================

    /// @notice The ```transfer``` function transfers tokens which belong to the caller
    /// @dev This function reverts on failure
    /// @param _to The address of the recipient
    /// @param _transferValue The amount of tokens to transfer
    /// @return A boolean indicating success or failure
    function transfer(address _to, uint256 _transferValue) external returns (bool) {
        // Get data from implementation slot as a uint256
        uint256 _contractData = StorageLib.sloadImplementationSlotDataAsUint256();

        bool _isTransferUpgraded = _contractData.isTransferUpgraded();
        if (_isTransferUpgraded) {
            // new implementation address is stored in the least significant 160 bits of the contract data
            address _newImplementation = address(uint160(_contractData));
            _delegate({ implementation: _newImplementation });
        } else {
            // Checks: contract-wide access control
            if (_contractData.isTransferPaused()) revert StorageLib.TransferPaused();

            // Effects: Transfer the tokens
            _transfer({ _from: msg.sender, _to: _to, _transferValue: _transferValue.toUint248() });
            return true;
        }
    }

    /// @notice The ```transferFrom``` function transfers tokens on behalf of an owner
    /// @dev This function reverts on failure
    /// @param _from The address of the owner of the tokens to transfer
    /// @param _to The address of the recipient of the tokens
    /// @param _transferValue The amount of tokens to transfer
    /// @return A boolean indicating success or failure
    function transferFrom(address _from, address _to, uint256 _transferValue) external returns (bool) {
        uint256 _contractData = StorageLib.sloadImplementationSlotDataAsUint256();

        bool _isTransferFromUpgraded = _contractData.isTransferFromUpgraded();
        if (_isTransferFromUpgraded) {
            // new implementation address is stored in the least significant 160 bits of the contract data
            address _newImplementation = address(uint160(_contractData));
            _delegate({ implementation: _newImplementation });
        } else {
            // Reading account data for sender adds gas so we should only do it if set true
            bool _isMsgSenderFrozenCheckEnabled = _contractData.isMsgSenderFrozenCheckEnabled();
            if (
                _isMsgSenderFrozenCheckEnabled &&
                StorageLib.getPointerToErc20CoreStorage().accountData[msg.sender].isFrozen
            ) revert AccountIsFrozen({ frozenAccount: msg.sender });

            // Checks: contract-wide access control
            if (_contractData.isTransferPaused()) revert StorageLib.TransferPaused();

            // Effects: Decrease the allowance of the spender
            _spendAllowance({ _owner: _from, _spender: msg.sender, _value: _transferValue });

            // Effects: Transfer the tokens
            _transfer({ _from: _from, _to: _to, _transferValue: _transferValue.toUint248() });
            return true;
        }
    }

    //==============================================================================
    // Eip-3009 Overridden Functions
    //==============================================================================

    /// @notice The ```transferWithAuthorization``` function executes a transfer with a signed authorization according to Eip3009
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The block.timestamp after which the authorization is valid
    /// @param _validBefore The block.timestamp before which the authorization is valid
    /// @param _nonce Unique nonce
    /// @param _v ECDSA signature parameter v
    /// @param _r ECDSA signature parameters r
    /// @param _s ECDSA signature parameters s
    function transferWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    ) external {
        // Packs signature pieces into bytes
        transferWithAuthorization({
            _from: _from,
            _to: _to,
            _value: _value,
            _validAfter: _validAfter,
            _validBefore: _validBefore,
            _nonce: _nonce,
            _signature: abi.encodePacked(_r, _s, _v)
        });
    }

    /// @notice The ```transferWithAuthorization``` function executes a transfer with a signed authorization according to Eip3009
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The block.timestamp after which the authorization is valid
    /// @param _validBefore The block.timestamp before which the authorization is valid
    /// @param _nonce Unique nonce
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function transferWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        bytes memory _signature
    ) public {
        // Get data from implementation slot as a uint256
        uint256 _contractData = StorageLib.sloadImplementationSlotDataAsUint256();

        bool _isTransferWithAuthorizationUpgraded = _contractData.isTransferWithAuthorizationUpgraded();
        if (_isTransferWithAuthorizationUpgraded) {
            // new implementation address is stored in the least significant 160 bits of the contract data
            address _newImplementation = address(uint160(_contractData));
            _delegate({ implementation: _newImplementation });
        } else {
            // Reading account data for sender adds gas so we should only do it if set true
            bool _isMsgSenderFrozenCheckEnabled = _contractData.isMsgSenderFrozenCheckEnabled();
            if (
                _isMsgSenderFrozenCheckEnabled &&
                StorageLib.getPointerToErc20CoreStorage().accountData[msg.sender].isFrozen
            ) revert AccountIsFrozen({ frozenAccount: msg.sender });

            // Checks: contract-wide access control
            if (_contractData.isTransferPaused()) revert StorageLib.TransferPaused();
            if (_contractData.isSignatureVerificationPaused()) revert StorageLib.SignatureVerificationPaused();

            // Effects: transfer the tokens
            _transferWithAuthorization({
                _from: _from,
                _to: _to,
                _value: _value,
                _validAfter: _validAfter,
                _validBefore: _validBefore,
                _nonce: _nonce,
                _signature: _signature
            });
        }
    }

    /// @notice The ```receiveWithAuthorization``` function receives a transfer with a signed authorization from the payer
    /// @dev This has an additional check to ensure that the payee's address matches the caller of this function to prevent front-running attacks
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The block.timestamp after which the authorization is valid
    /// @param _validBefore The block.timestamp before which the authorization is valid
    /// @param _nonce Unique nonce
    /// @param _v ECDSA signature parameter v
    /// @param _r ECDSA signature parameters r
    /// @param _s ECDSA signature parameters s
    function receiveWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    ) external {
        // Packs signature pieces into bytes
        receiveWithAuthorization({
            _from: _from,
            _to: _to,
            _value: _value,
            _validAfter: _validAfter,
            _validBefore: _validBefore,
            _nonce: _nonce,
            _signature: abi.encodePacked(_r, _s, _v)
        });
    }

    /// @notice The ```receiveWithAuthorization``` function receives a transfer with a signed authorization from the payer
    /// @dev This has an additional check to ensure that the payee's address matches the caller of this function to prevent front-running attacks
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The block.timestamp after which the authorization is valid
    /// @param _validBefore The block.timestamp before which the authorization is valid
    /// @param _nonce Unique nonce
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function receiveWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        bytes memory _signature
    ) public {
        // Get data from implementation slot as a uint256
        uint256 _contractData = StorageLib.sloadImplementationSlotDataAsUint256();

        bool _isReceiveWithAuthorizationUpgraded = _contractData.isReceiveWithAuthorizationUpgraded();
        if (_isReceiveWithAuthorizationUpgraded) {
            // new implementation address is stored in the least significant 160 bits of the contract data
            address _newImplementation = address(uint160(_contractData));
            _delegate({ implementation: _newImplementation });
        } else {
            // Checks: contract-wide access control
            if (_contractData.isTransferPaused()) revert StorageLib.TransferPaused();
            if (_contractData.isSignatureVerificationPaused()) revert StorageLib.SignatureVerificationPaused();

            // Effects: transfer the tokens
            _receiveWithAuthorization({
                _from: _from,
                _to: _to,
                _value: _value,
                _validAfter: _validAfter,
                _validBefore: _validBefore,
                _nonce: _nonce,
                _signature: _signature
            });
        }
    }

    //==============================================================================
    // Events
    //==============================================================================

    /// @notice The ```Upgraded``` event is emitted when the implementation is upgraded
    /// @param implementation The address of the new implementation
    event Upgraded(address indexed implementation);

    /// @notice The ```AdminChanged``` event is emitted when the admin account has changed
    /// @param previousAdmin The address of the previous admin
    /// @param newAdmin The address of the new admin
    event AdminChanged(address previousAdmin, address newAdmin);

    //==============================================================================
    // Errors
    //==============================================================================

    /// @notice The ```AgoraDollarErc1967NonPayable``` error is emitted when trying to send ether to a non-payable contract
    error AgoraDollarErc1967NonPayable();

    /// @notice The ```ProxyDeniedAdminAccess``` error is emitted when the proxy admin tries to call a function that is not upgradeToAndCall
    error ProxyDeniedAdminAccess();

    /// @notice The ```ImplementationTargetNotAContract``` error is emitted when the target of the proxy is not a contract
    error ImplementationTargetNotAContract();
}

File 2 of 27 : Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)

pragma solidity ^0.8.20;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback
     * function and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }
}

File 3 of 27 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

File 4 of 27 : SafeCastLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe integer casting library that reverts on overflow.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)
library SafeCastLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    error Overflow();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*          UNSIGNED INTEGER SAFE CASTING OPERATIONS          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function toUint8(uint256 x) internal pure returns (uint8) {
        if (x >= 1 << 8) _revertOverflow();
        return uint8(x);
    }

    function toUint16(uint256 x) internal pure returns (uint16) {
        if (x >= 1 << 16) _revertOverflow();
        return uint16(x);
    }

    function toUint24(uint256 x) internal pure returns (uint24) {
        if (x >= 1 << 24) _revertOverflow();
        return uint24(x);
    }

    function toUint32(uint256 x) internal pure returns (uint32) {
        if (x >= 1 << 32) _revertOverflow();
        return uint32(x);
    }

    function toUint40(uint256 x) internal pure returns (uint40) {
        if (x >= 1 << 40) _revertOverflow();
        return uint40(x);
    }

    function toUint48(uint256 x) internal pure returns (uint48) {
        if (x >= 1 << 48) _revertOverflow();
        return uint48(x);
    }

    function toUint56(uint256 x) internal pure returns (uint56) {
        if (x >= 1 << 56) _revertOverflow();
        return uint56(x);
    }

    function toUint64(uint256 x) internal pure returns (uint64) {
        if (x >= 1 << 64) _revertOverflow();
        return uint64(x);
    }

    function toUint72(uint256 x) internal pure returns (uint72) {
        if (x >= 1 << 72) _revertOverflow();
        return uint72(x);
    }

    function toUint80(uint256 x) internal pure returns (uint80) {
        if (x >= 1 << 80) _revertOverflow();
        return uint80(x);
    }

    function toUint88(uint256 x) internal pure returns (uint88) {
        if (x >= 1 << 88) _revertOverflow();
        return uint88(x);
    }

    function toUint96(uint256 x) internal pure returns (uint96) {
        if (x >= 1 << 96) _revertOverflow();
        return uint96(x);
    }

    function toUint104(uint256 x) internal pure returns (uint104) {
        if (x >= 1 << 104) _revertOverflow();
        return uint104(x);
    }

    function toUint112(uint256 x) internal pure returns (uint112) {
        if (x >= 1 << 112) _revertOverflow();
        return uint112(x);
    }

    function toUint120(uint256 x) internal pure returns (uint120) {
        if (x >= 1 << 120) _revertOverflow();
        return uint120(x);
    }

    function toUint128(uint256 x) internal pure returns (uint128) {
        if (x >= 1 << 128) _revertOverflow();
        return uint128(x);
    }

    function toUint136(uint256 x) internal pure returns (uint136) {
        if (x >= 1 << 136) _revertOverflow();
        return uint136(x);
    }

    function toUint144(uint256 x) internal pure returns (uint144) {
        if (x >= 1 << 144) _revertOverflow();
        return uint144(x);
    }

    function toUint152(uint256 x) internal pure returns (uint152) {
        if (x >= 1 << 152) _revertOverflow();
        return uint152(x);
    }

    function toUint160(uint256 x) internal pure returns (uint160) {
        if (x >= 1 << 160) _revertOverflow();
        return uint160(x);
    }

    function toUint168(uint256 x) internal pure returns (uint168) {
        if (x >= 1 << 168) _revertOverflow();
        return uint168(x);
    }

    function toUint176(uint256 x) internal pure returns (uint176) {
        if (x >= 1 << 176) _revertOverflow();
        return uint176(x);
    }

    function toUint184(uint256 x) internal pure returns (uint184) {
        if (x >= 1 << 184) _revertOverflow();
        return uint184(x);
    }

    function toUint192(uint256 x) internal pure returns (uint192) {
        if (x >= 1 << 192) _revertOverflow();
        return uint192(x);
    }

    function toUint200(uint256 x) internal pure returns (uint200) {
        if (x >= 1 << 200) _revertOverflow();
        return uint200(x);
    }

    function toUint208(uint256 x) internal pure returns (uint208) {
        if (x >= 1 << 208) _revertOverflow();
        return uint208(x);
    }

    function toUint216(uint256 x) internal pure returns (uint216) {
        if (x >= 1 << 216) _revertOverflow();
        return uint216(x);
    }

    function toUint224(uint256 x) internal pure returns (uint224) {
        if (x >= 1 << 224) _revertOverflow();
        return uint224(x);
    }

    function toUint232(uint256 x) internal pure returns (uint232) {
        if (x >= 1 << 232) _revertOverflow();
        return uint232(x);
    }

    function toUint240(uint256 x) internal pure returns (uint240) {
        if (x >= 1 << 240) _revertOverflow();
        return uint240(x);
    }

    function toUint248(uint256 x) internal pure returns (uint248) {
        if (x >= 1 << 248) _revertOverflow();
        return uint248(x);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*           SIGNED INTEGER SAFE CASTING OPERATIONS           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function toInt8(int256 x) internal pure returns (int8) {
        int8 y = int8(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt16(int256 x) internal pure returns (int16) {
        int16 y = int16(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt24(int256 x) internal pure returns (int24) {
        int24 y = int24(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt32(int256 x) internal pure returns (int32) {
        int32 y = int32(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt40(int256 x) internal pure returns (int40) {
        int40 y = int40(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt48(int256 x) internal pure returns (int48) {
        int48 y = int48(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt56(int256 x) internal pure returns (int56) {
        int56 y = int56(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt64(int256 x) internal pure returns (int64) {
        int64 y = int64(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt72(int256 x) internal pure returns (int72) {
        int72 y = int72(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt80(int256 x) internal pure returns (int80) {
        int80 y = int80(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt88(int256 x) internal pure returns (int88) {
        int88 y = int88(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt96(int256 x) internal pure returns (int96) {
        int96 y = int96(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt104(int256 x) internal pure returns (int104) {
        int104 y = int104(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt112(int256 x) internal pure returns (int112) {
        int112 y = int112(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt120(int256 x) internal pure returns (int120) {
        int120 y = int120(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt128(int256 x) internal pure returns (int128) {
        int128 y = int128(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt136(int256 x) internal pure returns (int136) {
        int136 y = int136(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt144(int256 x) internal pure returns (int144) {
        int144 y = int144(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt152(int256 x) internal pure returns (int152) {
        int152 y = int152(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt160(int256 x) internal pure returns (int160) {
        int160 y = int160(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt168(int256 x) internal pure returns (int168) {
        int168 y = int168(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt176(int256 x) internal pure returns (int176) {
        int176 y = int176(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt184(int256 x) internal pure returns (int184) {
        int184 y = int184(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt192(int256 x) internal pure returns (int192) {
        int192 y = int192(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt200(int256 x) internal pure returns (int200) {
        int200 y = int200(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt208(int256 x) internal pure returns (int208) {
        int208 y = int208(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt216(int256 x) internal pure returns (int216) {
        int216 y = int216(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt224(int256 x) internal pure returns (int224) {
        int224 y = int224(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt232(int256 x) internal pure returns (int232) {
        int232 y = int232(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt240(int256 x) internal pure returns (int240) {
        int240 y = int240(x);
        if (x != y) _revertOverflow();
        return y;
    }

    function toInt248(int256 x) internal pure returns (int248) {
        int248 y = int248(x);
        if (x != y) _revertOverflow();
        return y;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               OTHER SAFE CASTING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function toInt256(uint256 x) internal pure returns (int256) {
        if (x >= 1 << 255) _revertOverflow();
        return int256(x);
    }

    function toUint256(int256 x) internal pure returns (uint256) {
        if (x < 0) _revertOverflow();
        return uint256(x);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _revertOverflow() private pure {
        /// @solidity memory-safe-assembly
        assembly {
            // Store the function selector of `Overflow()`.
            mstore(0x00, 0x35278d12)
            // Revert with (offset, size).
            revert(0x1c, 0x04)
        }
    }
}

File 5 of 27 : Eip3009.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ============================= Eip3009 ==============================
// ====================================================================

import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import { SafeCastLib } from "solady/src/utils/SafeCastLib.sol";
import { SignatureCheckerLib } from "solady/src/utils/SignatureCheckerLib.sol";

import { Eip712 } from "./Eip712.sol";
import { Erc20Core } from "./Erc20Core.sol";

import { StorageLib } from "./proxy/StorageLib.sol";

/// @title Eip3009
/// @notice Eip3009 provides internal implementations for gas-abstracted transfers under Eip3009 guidelines
/// @author Agora, inspired by Circle's Eip3009 implementation
abstract contract Eip3009 is Eip712, Erc20Core {
    using SafeCastLib for uint256;
    using StorageLib for uint256;

    /// @notice keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)")
    bytes32 internal constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH_ =
        0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;

    /// @notice keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)")
    bytes32 internal constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH_ =
        0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;

    /// @notice keccak256("CancelAuthorization(address authorizer,bytes32 nonce)")
    bytes32 internal constant CANCEL_AUTHORIZATION_TYPEHASH_ =
        0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429;

    //==============================================================================
    // Internal Procedural Functions
    //==============================================================================

    /// @notice The ```_transferWithAuthorization``` function executes a transfer with a signed authorization
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The time after which this is valid (unix time)
    /// @param _validBefore The time before which this is valid (unix time)
    /// @param _nonce Unique nonce
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function _transferWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        bytes memory _signature
    ) internal {
        // Checks: authorization validity
        if (block.timestamp <= _validAfter) revert InvalidAuthorization();
        if (block.timestamp >= _validBefore) revert ExpiredAuthorization();
        _requireUnusedAuthorization({ _authorizer: _from, _nonce: _nonce });

        // Checks: valid signature
        _requireIsValidSignatureNow({
            _signer: _from,
            _dataHash: keccak256(
                abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH_, _from, _to, _value, _validAfter, _validBefore, _nonce)
            ),
            _signature: _signature
        });

        // Effects: mark authorization as used and transfer
        _markAuthorizationAsUsed({ _authorizer: _from, _nonce: _nonce });
        _transfer({ _from: _from, _to: _to, _transferValue: _value.toUint248() });
    }

    /// @notice The ```_receiveWithAuthorization``` function receives a transfer with a signed authorization from the payer
    /// @dev This has an additional check to ensure that the payee's address matches the caller of this function to prevent front-running attacks
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _from Payer's address (Authorizer)
    /// @param _to Payee's address
    /// @param _value Amount to be transferred
    /// @param _validAfter The block.timestamp after which the authorization is valid
    /// @param _validBefore The block.timestamp before which the authorization is valid
    /// @param _nonce Unique nonce
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function _receiveWithAuthorization(
        address _from,
        address _to,
        uint256 _value,
        uint256 _validAfter,
        uint256 _validBefore,
        bytes32 _nonce,
        bytes memory _signature
    ) internal {
        // Checks: authorization validity
        if (_to != msg.sender) revert InvalidPayee({ caller: msg.sender, payee: _to });
        if (block.timestamp <= _validAfter) revert InvalidAuthorization();
        if (block.timestamp >= _validBefore) revert ExpiredAuthorization();
        _requireUnusedAuthorization({ _authorizer: _from, _nonce: _nonce });

        // Checks: valid signature
        _requireIsValidSignatureNow({
            _signer: _from,
            _dataHash: keccak256(
                abi.encode(RECEIVE_WITH_AUTHORIZATION_TYPEHASH_, _from, _to, _value, _validAfter, _validBefore, _nonce)
            ),
            _signature: _signature
        });

        // Effects: mark authorization as used and transfer
        _markAuthorizationAsUsed({ _authorizer: _from, _nonce: _nonce });
        _transfer({ _from: _from, _to: _to, _transferValue: _value.toUint248() });
    }

    /// @notice The ```_cancelAuthorization``` function cancels an authorization
    /// @dev EOA wallet signatures should be packed in the order of r, s, v
    /// @param _authorizer Authorizer's address
    /// @param _nonce Nonce of the authorization
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function _cancelAuthorization(address _authorizer, bytes32 _nonce, bytes memory _signature) internal {
        _requireUnusedAuthorization({ _authorizer: _authorizer, _nonce: _nonce });
        _requireIsValidSignatureNow({
            _signer: _authorizer,
            _dataHash: keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH_, _authorizer, _nonce)),
            _signature: _signature
        });

        StorageLib.getPointerToEip3009Storage().isAuthorizationUsed[_authorizer][_nonce] = true;
        emit AuthorizationCanceled({ authorizer: _authorizer, nonce: _nonce });
    }

    //==============================================================================
    // Internal Checks Functions
    //==============================================================================

    /// @notice The ```_requireIsValidSignatureNow``` function validates that signature against input data struct
    /// @param _signer Signer's address
    /// @param _dataHash Hash of encoded data struct
    /// @param _signature Signature byte array produced by an EOA wallet or a contract wallet
    function _requireIsValidSignatureNow(address _signer, bytes32 _dataHash, bytes memory _signature) private view {
        if (
            !SignatureCheckerLib.isValidSignatureNow({
                signer: _signer,
                hash: MessageHashUtils.toTypedDataHash({
                    domainSeparator: _domainSeparatorV4(),
                    structHash: _dataHash
                }),
                signature: _signature
            })
        ) revert InvalidSignature();
    }

    /// @notice The ```_requireUnusedAuthorization``` checks that an authorization nonce is unused
    /// @param _authorizer    Authorizer's address
    /// @param _nonce         Nonce of the authorization
    function _requireUnusedAuthorization(address _authorizer, bytes32 _nonce) private view {
        if (StorageLib.getPointerToEip3009Storage().isAuthorizationUsed[_authorizer][_nonce])
            revert UsedOrCanceledAuthorization();
    }

    //==============================================================================
    // Internal Effects Functions
    //==============================================================================

    /// @notice The ```_markAuthorizationAsUsed``` function marks an authorization nonce as used
    /// @param _authorizer    Authorizer's address
    /// @param _nonce         Nonce of the authorization
    function _markAuthorizationAsUsed(address _authorizer, bytes32 _nonce) private {
        StorageLib.getPointerToEip3009Storage().isAuthorizationUsed[_authorizer][_nonce] = true;
        emit AuthorizationUsed({ authorizer: _authorizer, nonce: _nonce });
    }

    //==============================================================================
    // Events
    //==============================================================================

    /// @notice ```AuthorizationUsed``` event is emitted when an authorization is used
    /// @param authorizer Authorizer's address
    /// @param nonce Nonce of the authorization
    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);

    /// @notice ```AuthorizationCanceled``` event is emitted when an authorization is canceled
    /// @param authorizer Authorizer's address
    /// @param nonce Nonce of the authorization
    event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce);

    //==============================================================================
    // Errors
    //==============================================================================

    /// @notice The ```InvalidPayee``` error is emitted when the payee does not match sender in receiveWithAuthorization
    /// @param caller The caller of the function
    /// @param payee The expected payee in the function
    error InvalidPayee(address caller, address payee);

    /// @notice The ```InvalidAuthorization``` error is emitted when the authorization is invalid because its too early
    error InvalidAuthorization();

    /// @notice The ```ExpiredAuthorization``` error is emitted when the authorization is expired
    error ExpiredAuthorization();

    /// @notice The ```InvalidSignature``` error is emitted when the signature is invalid
    error InvalidSignature();

    /// @notice The ```UsedOrCanceledAuthorization``` error is emitted when the authorization nonce is already used or canceled
    error UsedOrCanceledAuthorization();
}

File 6 of 27 : AgoraProxyAdmin.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ======================== AgoraProxyAdmin ===========================
// ====================================================================

import { Ownable, Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

/// @title AgoraProxyAdmin
/// @notice A proxy admin contract that extends the OpenZeppelin ProxyAdmin contract and adds a two-step ownership transfer mechanism
/// @author Agora
contract AgoraProxyAdmin is ProxyAdmin, Ownable2Step {
    /// @notice Initializes the contract with the initial owner
    /// @param _initialOwner The address that will be set as the initial owner of the contract
    constructor(address _initialOwner) ProxyAdmin(_initialOwner) {}

    /// @notice Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one
    /// @dev Can only be called by the current owner
    /// @param _newOwner The address to which ownership of the contract will be transferred
    function transferOwnership(address _newOwner) public override(Ownable, Ownable2Step) onlyOwner {
        // NOTE: Order of inheritance/override is important to ensure we are calling Ownable2Step version of transferOwnership
        super.transferOwnership({ newOwner: _newOwner });
    }

    /// @notice Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner
    /// @dev Internal function without access restriction
    /// @param _newOwner The address to which ownership of the contract will be transferred
    function _transferOwnership(address _newOwner) internal override(Ownable, Ownable2Step) {
        // NOTE: Order of inheritance/override is important to ensure we are calling Ownable2Step version of _transferOwnership
        super._transferOwnership({ newOwner: _newOwner });
    }
}

File 7 of 27 : StorageLib.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ============================ StorageLib ============================
// ====================================================================

/**
 * This library contains information for accessing unstructured storage following erc1967
 * and erc7201 standards.
 *
 * The erc1967 storage slots are defined using their own formula/namespace.
 * These are listed last in the contract.
 *
 * The erc7201 namespace is defined as <ContractName>.<Namespace>
 * The deriveErc7201StorageSlot() function is used to derive the storage slot for a given namespace
 * and to check that value against the hard-coded bytes32 value for the slot location in testing frameworks
 * Each inherited contract has its own struct of the form <ContractName>Storage which matches <Namespace>
 * from above. Each struct is held in a unique namespace and has a unique storage slot.
 * See: https://eips.ethereum.org/EIPS/eip-7201 for additional information regarding this standard
 */
/// @title StorageLib
/// @dev Implements pure functions for calculating and accessing storage slots according to eip1967 and eip7201
/// @author Agora
library StorageLib {
    /// @notice Global namespace for use in deriving storage slot locations
    string internal constant GLOBAL_ERC7201_NAMESPACE = "AgoraDollarErc1967Proxy";

    // Use this function to check hardcoded bytes32 values against the expected formula
    function deriveErc7201StorageSlot(string memory _localNamespace) internal pure returns (bytes32) {
        bytes memory _namespace = abi.encodePacked(GLOBAL_ERC7201_NAMESPACE, ".", _localNamespace);
        return keccak256(abi.encode(uint256(keccak256(_namespace)) - 1)) & ~bytes32(uint256(0xff));
    }

    //==============================================================================
    // Eip3009 Storage Items
    //==============================================================================

    /// @notice The EIP3009 namespace
    string internal constant EIP3009_NAMESPACE = "Eip3009Storage";

    /// @notice The Eip3009Storage struct
    /// @param isAuthorizationUsed A mapping of authorizer to nonce to boolean to indicate if the nonce has been used
    /// @custom:storage-location erc7201:AgoraDollarErc1967Proxy.Eip3009Storage
    struct Eip3009Storage {
        mapping(address _authorizer => mapping(bytes32 _nonce => bool _isNonceUsed)) isAuthorizationUsed;
    }

    /// @notice The ```EIP3009_STORAGE_SLOT_``` is the storage slot for the Eip3009Storage struct
    /// @dev keccak256(abi.encode(uint256(keccak256("AgoraDollarErc1967Proxy.Eip3009Storage")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 internal constant EIP3009_STORAGE_SLOT_ =
        0xbb0a37da742be2e3b68bdb11d195150f4243c03fb37d3cdfa756046082a38600;

    /// @notice The ```getPointerToEip3009Storage``` function returns a pointer to the Eip3009Storage struct
    /// @return $ A pointer to the Eip3009Storage struct
    function getPointerToEip3009Storage() internal pure returns (Eip3009Storage storage $) {
        /// @solidity memory-safe-assembly
        assembly {
            $.slot := EIP3009_STORAGE_SLOT_
        }
    }

    //==============================================================================
    // Erc2612 Storage Items
    //==============================================================================

    /// @notice The Erc2612 namespace
    string internal constant ERC2612_NAMESPACE = "Erc2612Storage";

    /// @notice The Erc2612Storage struct
    /// @param nonces A mapping of signer address to uint256 to store the nonce
    /// @custom:storage-location erc7201:AgoraDollarErc1967Proxy.Erc2612Storage
    struct Erc2612Storage {
        mapping(address _signer => uint256 _nonce) nonces;
    }

    /// @notice The ```ERC2612_STORAGE_SLOT_``` is the storage slot for the Erc2612Storage struct
    /// @dev keccak256(abi.encode(uint256(keccak256("AgoraDollarErc1967Proxy.Erc2612Storage")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 internal constant ERC2612_STORAGE_SLOT_ =
        0x69e87f5b9323740fce20cdf574dacd1d10e756da64a1f2df70fd1ace4c7cc300;

    /// @notice The ```getPointerToErc2612Storage``` function returns a pointer to the Erc2612Storage struct
    /// @return $ A pointer to the Erc2612Storage struct
    function getPointerToErc2612Storage() internal pure returns (Erc2612Storage storage $) {
        /// @solidity memory-safe-assembly
        assembly {
            $.slot := ERC2612_STORAGE_SLOT_
        }
    }

    //==============================================================================
    // Erc20Core Storage Items
    //==============================================================================

    /// @notice The Erc20Core namespace
    string internal constant ERC20_CORE_NAMESPACE = "Erc20CoreStorage";

    /// @notice The Erc20AccountData struct
    /// @param isFrozen A boolean to indicate if the account is frozen
    /// @param balance A uint248 to store the balance of the account
    struct Erc20AccountData {
        bool isFrozen;
        uint248 balance;
    }

    /// @notice The Erc20CoreStorage struct
    /// @param accountData A mapping of address to Erc20AccountData to store account data
    /// @param accountAllowances A mapping of owner to spender to uint256 to store the allowance
    /// @param totalSupply A uint256 to store the total supply of tokens
    /// @custom:storage-location erc7201:AgoraDollarErc1967Proxy.Erc20CoreStorage
    struct Erc20CoreStorage {
        /// @dev _account The account whose data we are accessing
        /// @dev _accountData The account data for the account
        mapping(address _account => Erc20AccountData _accountData) accountData;
        /// @dev _owner The owner of the tokens
        /// @dev _spender The spender of the tokens
        /// @dev _accountAllowance The allowance of the spender
        mapping(address _owner => mapping(address _spender => uint256 _accountAllowance)) accountAllowances;
        /// @dev The total supply of tokens
        uint256 totalSupply;
    }

    /// @notice The ```ERC20_CORE_STORAGE_SLOT_``` is the storage slot for the Erc20CoreStorage struct
    /// @dev keccak256(abi.encode(uint256(keccak256("AgoraDollarErc1967Proxy.Erc20CoreStorage")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 internal constant ERC20_CORE_STORAGE_SLOT_ =
        0x455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b700;

    /// @notice The ```getPointerToErc20CoreStorage``` function returns a pointer to the Erc20CoreStorage struct
    /// @return $ A pointer to the Erc20CoreStorage struct
    function getPointerToErc20CoreStorage() internal pure returns (Erc20CoreStorage storage $) {
        /// @solidity memory-safe-assembly
        assembly {
            $.slot := ERC20_CORE_STORAGE_SLOT_
        }
    }

    //==============================================================================
    // AgoraDollarAccessControl Storage Items
    //==============================================================================

    /// @notice The AgoraDollarAccessControl namespace
    string internal constant AGORA_DOLLAR_ACCESS_CONTROL_NAMESPACE = "AgoraDollarAccessControlStorage";

    /// @notice The RoleData struct
    /// @param pendingRoleAddress The address of the nominated (pending) role
    /// @param currentRoleAddress The address of the current role
    struct AgoraDollarAccessControlRoleData {
        address pendingRoleAddress;
        address currentRoleAddress;
    }

    /// @notice The AgoraDollarAccessControlStorage struct
    /// @param roleData A mapping of role identifier to AgoraDollarAccessControlRoleData to store role data
    /// @custom:storage-location erc7201:AgoraDollarErc1967Proxy.AgoraDollarAccessControlStorage
    struct AgoraDollarAccessControlStorage {
        mapping(bytes32 _role => AgoraDollarAccessControlRoleData _roleData) roleData;
    }

    /// @notice The ```AGORA_DOLLAR_ACCESS_CONTROL_STORAGE_SLOT_``` is the storage slot for the AgoraDollarAccessControlStorage struct
    /// @dev keccak256(abi.encode(uint256(keccak256("AgoraDollarErc1967Proxy.AgoraDollarAccessControlStorage")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 internal constant AGORA_DOLLAR_ACCESS_CONTROL_STORAGE_SLOT_ =
        0x9d28e63f6379c0b2127b14120db65179caba9597ddafa73863de41a4ba1fe700;

    /// @notice The ```getPointerToAgoraDollarAccessControlStorage``` function returns a pointer to the AgoraDollarAccessControlStorage struct
    /// @return $ A pointer to the AgoraDollarAccessControlStorage struct
    function getPointerToAgoraDollarAccessControlStorage()
        internal
        pure
        returns (AgoraDollarAccessControlStorage storage $)
    {
        /// @solidity memory-safe-assembly
        assembly {
            $.slot := AGORA_DOLLAR_ACCESS_CONTROL_STORAGE_SLOT_
        }
    }

    //==============================================================================
    // AgoraDollarErc1967 Admin Slot Items
    //==============================================================================

    /// @notice The AgoraDollarErc1967ProxyAdminStorage struct
    /// @param proxyAdminAddress The address of the proxy admin contract
    /// @custom:storage-location erc1967:eip1967.proxy.admin
    struct AgoraDollarErc1967ProxyAdminStorage {
        address proxyAdminAddress;
    }

    /// @notice The ```AGORA_DOLLAR_ERC1967_PROXY_ADMIN_STORAGE_SLOT_``` is the storage slot for the AgoraDollarErc1967ProxyAdminStorage struct
    /// @dev NOTE: deviates from erc7201 standard because erc1967 defines its own storage slot algorithm
    /// @dev bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)
    bytes32 internal constant AGORA_DOLLAR_ERC1967_PROXY_ADMIN_STORAGE_SLOT_ =
        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /// @notice The ```getPointerToAgoraDollarErc1967ProxyAdminStorage``` function returns a pointer to the AgoraDollarErc1967ProxyAdminStorage struct
    /// @return adminSlot A pointer to the AgoraDollarErc1967ProxyAdminStorage struct
    function getPointerToAgoraDollarErc1967ProxyAdminStorage()
        internal
        pure
        returns (AgoraDollarErc1967ProxyAdminStorage storage adminSlot)
    {
        /// @solidity memory-safe-assembly
        assembly {
            adminSlot.slot := AGORA_DOLLAR_ERC1967_PROXY_ADMIN_STORAGE_SLOT_
        }
    }

    //==============================================================================
    // AgoraDollarErc1967Proxy Implementation Slot Items
    //==============================================================================

    /// @notice The AgoraDollarErc1967ProxyContractStorage struct
    /// @param implementationAddress The address of the implementation contract
    /// @param placeholder A placeholder for bits to be used as bitmask items
    /// @custom:storage-location erc1967:eip1967.proxy.implementation
    struct AgoraDollarErc1967ProxyContractStorage {
        address implementationAddress; // least significant bits first
        uint96 placeholder; // Placeholder for bitmask items defined below
    }

    /// @notice The ```AGORA_DOLLAR_ERC1967_PROXY_CONTRACT_STORAGE_SLOT_``` is the storage slot for the AgoraDollarErc1967ProxyContractStorage struct
    /// @dev bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)
    bytes32 internal constant AGORA_DOLLAR_ERC1967_PROXY_CONTRACT_STORAGE_SLOT_ =
        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /// @notice The ```getPointerToAgoraDollarErc1967ProxyContractStorage``` function returns a pointer to the storage slot for the implementation address
    /// @return contractData A pointer to the data in the storage slot for the implementation address and other contract data
    function getPointerToAgoraDollarErc1967ProxyContractStorage()
        internal
        pure
        returns (AgoraDollarErc1967ProxyContractStorage storage contractData)
    {
        /// @solidity memory-safe-assembly
        assembly {
            contractData.slot := AGORA_DOLLAR_ERC1967_PROXY_CONTRACT_STORAGE_SLOT_
        }
    }

    /// @notice The ```sloadImplementationSlotDataAsUint256``` function returns the data at the implementation slot as a uint256
    /// @dev Named this way to draw attention to the sload call
    /// @return _contractData The data at the implementation slot as a uint256
    function sloadImplementationSlotDataAsUint256() internal view returns (uint256 _contractData) {
        /// @solidity memory-safe-assembly
        assembly {
            _contractData := sload(AGORA_DOLLAR_ERC1967_PROXY_CONTRACT_STORAGE_SLOT_)
        }
    }

    /// @notice The ```sstoreImplementationSlotDataAsUint256``` function stores the data at the implementation slot
    /// @dev Named this way to draw attention to the sstore call
    /// @param _contractData The data to store at the implementation slot, given as a uint256
    function sstoreImplementationSlotDataAsUint256(uint256 _contractData) internal {
        /// @solidity memory-safe-assembly
        assembly {
            sstore(AGORA_DOLLAR_ERC1967_PROXY_CONTRACT_STORAGE_SLOT_, _contractData)
        }
    }

    // Contract Access Control masks
    uint256 internal constant IS_MSG_SENDER_FROZEN_CHECK_ENABLED_BIT_POSITION_ = 1 << (255 - 95);
    uint256 internal constant IS_MINT_PAUSED_BIT_POSITION_ = 1 << (255 - 94);
    uint256 internal constant IS_BURN_FROM_PAUSED_BIT_POSITION_ = 1 << (255 - 93);
    uint256 internal constant IS_FREEZING_PAUSED_BIT_POSITION_ = 1 << (255 - 92);
    uint256 internal constant IS_TRANSFER_PAUSED_BIT_POSITION_ = 1 << (255 - 91);
    uint256 internal constant IS_SIGNATURE_VERIFICATION_PAUSED_BIT_POSITION_ = 1 << (255 - 90);

    // internal function upgrade masks
    // Erc20
    uint256 internal constant IS_TRANSFER_UPGRADED_BIT_POSITION_ = 1 << (255 - 89);
    uint256 internal constant IS_TRANSFER_FROM_UPGRADED_BIT_POSITION_ = 1 << (255 - 88);

    // Eip 3009
    uint256 internal constant IS_TRANSFER_WITH_AUTHORIZATION_UPGRADED_BIT_POSITION_ = 1 << (255 - 87);
    uint256 internal constant IS_RECEIVE_WITH_AUTHORIZATION_UPGRADED_BIT_POSITION_ = 1 << (255 - 86);

    //==============================================================================
    // Bitmask Functions
    //==============================================================================

    // These function use a bitmask to check if a specific bit is set in the contract data
    function isMsgSenderFrozenCheckEnabled(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_MSG_SENDER_FROZEN_CHECK_ENABLED_BIT_POSITION_ != 0;
    }

    function isMintPaused(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_MINT_PAUSED_BIT_POSITION_ != 0;
    }

    function isBurnFromPaused(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_BURN_FROM_PAUSED_BIT_POSITION_ != 0;
    }

    function isFreezingPaused(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_FREEZING_PAUSED_BIT_POSITION_ != 0;
    }

    function isTransferPaused(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_TRANSFER_PAUSED_BIT_POSITION_ != 0;
    }

    function isSignatureVerificationPaused(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_SIGNATURE_VERIFICATION_PAUSED_BIT_POSITION_ != 0;
    }

    function isTransferUpgraded(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_TRANSFER_UPGRADED_BIT_POSITION_ != 0;
    }

    function isTransferFromUpgraded(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_TRANSFER_FROM_UPGRADED_BIT_POSITION_ != 0;
    }

    function isTransferWithAuthorizationUpgraded(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_TRANSFER_WITH_AUTHORIZATION_UPGRADED_BIT_POSITION_ != 0;
    }

    function isReceiveWithAuthorizationUpgraded(uint256 _contractData) internal pure returns (bool) {
        return _contractData & IS_RECEIVE_WITH_AUTHORIZATION_UPGRADED_BIT_POSITION_ != 0;
    }

    function implementation(uint256 _contractData) internal pure returns (address) {
        // return least significant 160 bits and cast to an address
        return address(uint160(_contractData));
    }

    function setBitWithMask(
        uint256 _original,
        uint256 _bitToSet,
        bool _setBitToOne
    ) internal pure returns (uint256 _new) {
        // Sets the specified bit to 1 or 0
        _new = _setBitToOne ? _original | _bitToSet : _original & ~_bitToSet;
    }

    //==============================================================================
    // Errors
    //==============================================================================

    /// @notice The ```TransferPaused``` error is emitted when transfers are paused during an attempted transfer
    error TransferPaused();

    /// @notice The ```SignatureVerificationPaused``` error is emitted when signature verification is paused during an attempted transfer
    error SignatureVerificationPaused();

    /// @notice The ```MintPaused``` error is emitted when minting is paused during an attempted mint
    error MintPaused();

    /// @notice The ```BurnFromPaused``` error is emitted when burning is paused during an attempted burn
    error BurnFromPaused();

    /// @notice The ```FreezingPaused``` error is emitted when freezing is paused during an attempted call to freeze() or unfreeze()
    error FreezingPaused();
}

File 8 of 27 : ITransparentUpgradeableProxy.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;

interface ITransparentUpgradeableProxy {
    function upgradeToAndCall(address, bytes calldata) external payable;
}

File 9 of 27 : MessageHashUtils.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;

import {Strings} from "../Strings.sol";

/**
 * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
 *
 * The library provides methods for generating a hash of a message that conforms to the
 * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
 * specifications.
 */
library MessageHashUtils {
    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing a bytes32 `messageHash` with
     * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
     * keccak256, although any bytes32 value can be safely used because the final digest will
     * be re-hashed.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
        }
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing an arbitrary `message` with
     * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
        return
            keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x00` (data with intended validator).
     *
     * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
     * `validator` address. Then hashing the result.
     *
     * See {ECDSA-recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(hex"19_00", validator, data));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
     *
     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
     * `\x19\x01` and hashing the result. It corresponds to the hash signed by the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
     *
     * See {ECDSA-recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

File 10 of 27 : SignatureCheckerLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Signature verification helper that supports both ECDSA signatures from EOAs
/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)
///
/// @dev Note:
/// - The signature checking functions use the ecrecover precompile (0x1).
/// - The `bytes memory signature` variants use the identity precompile (0x4)
///   to copy memory internally.
/// - Unlike ECDSA signatures, contract signatures are revocable.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library SignatureCheckerLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               SIGNATURE CHECKING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                // Copy the `signature` over.
                let n := add(0x20, mload(signature))
                pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(returndatasize(), 0x44), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether `signature` is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.
                    let t :=
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                        isValid := 1
                        mstore(0x60, 0) // Restore the zero slot.
                        mstore(0x40, m) // Restore the free memory pointer.
                        break
                    }
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), signature.length)
                // Copy the `signature` over.
                calldatacopy(add(m, 0x64), signature.offset, signature.length)
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        add(signature.length, 0x64), // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                break
            }
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, add(shr(255, vs), 27)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, shr(1, shl(1, vs))) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), mload(0x60)) // `s`.
                mstore8(add(m, 0xa4), mload(0x20)) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.
    /// If `signer` is a smart contract, the signature is validated with ERC1271.
    /// Otherwise, the signature is validated with `ECDSA.recover`.
    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Clean the upper 96 bits of `signer` in case they are dirty.
            for { signer := shr(96, shl(96, signer)) } signer {} {
                let m := mload(0x40)
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff)) // `v`.
                mstore(0x40, r) // `r`.
                mstore(0x60, s) // `s`.
                let t :=
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {
                    isValid := 1
                    mstore(0x60, 0) // Restore the zero slot.
                    mstore(0x40, m) // Restore the free memory pointer.
                    break
                }

                let f := shl(224, 0x1626ba7e)
                mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
                mstore(add(m, 0x04), hash)
                let d := add(m, 0x24)
                mstore(d, 0x40) // The offset of the `signature` in the calldata.
                mstore(add(m, 0x44), 65) // Length of the signature.
                mstore(add(m, 0x64), r) // `r`.
                mstore(add(m, 0x84), s) // `s`.
                mstore8(add(m, 0xa4), v) // `v`.
                // forgefmt: disable-next-item
                isValid := and(
                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                    eq(mload(d), f),
                    // Whether the staticcall does not revert.
                    // This must be placed at the end of the `and` clause,
                    // as the arguments are evaluated from right to left.
                    staticcall(
                        gas(), // Remaining gas.
                        signer, // The `signer` address.
                        m, // Offset of calldata in memory.
                        0xa5, // Length of calldata in memory.
                        d, // Offset of returndata.
                        0x20 // Length of returndata to write.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     ERC1271 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            // Copy the `signature` over.
            let n := add(0x20, mload(signature))
            pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(returndatasize(), 0x44), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNowCalldata(
        address signer,
        bytes32 hash,
        bytes calldata signature
    ) internal view returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), signature.length)
            // Copy the `signature` over.
            calldatacopy(add(m, 0x64), signature.offset, signature.length)
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    add(signature.length, 0x64), // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.
            mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`
    /// for an ERC1271 `signer` contract.
    function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            let f := shl(224, 0x1626ba7e)
            mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`.
            mstore(add(m, 0x04), hash)
            let d := add(m, 0x24)
            mstore(d, 0x40) // The offset of the `signature` in the calldata.
            mstore(add(m, 0x44), 65) // Length of the signature.
            mstore(add(m, 0x64), r) // `r`.
            mstore(add(m, 0x84), s) // `s`.
            mstore8(add(m, 0xa4), v) // `v`.
            // forgefmt: disable-next-item
            isValid := and(
                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).
                eq(mload(d), f),
                // Whether the staticcall does not revert.
                // This must be placed at the end of the `and` clause,
                // as the arguments are evaluated from right to left.
                staticcall(
                    gas(), // Remaining gas.
                    signer, // The `signer` address.
                    m, // Offset of calldata in memory.
                    0xa5, // Length of calldata in memory.
                    d, // Offset of returndata.
                    0x20 // Length of returndata to write.
                )
            )
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 11 of 27 : Eip712.sol
// SPDX-License-Identifier: Apache-2.0

// ***NOTE***: This file has been modified to remove external functions and storage for use in a transparent-ish proxy
// ***NOTE***: Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/dbb6104ce834628e473d2173bbc9d47f81a9eec3/contracts/utils/cryptography/EIP712.sol

pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ============================= Eip712 ===============================
// ====================================================================

import { ShortString, ShortStrings } from "@openzeppelin/contracts/utils/ShortStrings.sol";
import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
 * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
 * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
 * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 */

/// @title Eip712
/// @author Agora, modified from OpenZeppelin implementation
abstract contract Eip712 {
    using ShortStrings for *;

    bytes32 private constant TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     */
    constructor(string memory name, string memory version, address expectedProxyAddress) {
        _name = name.toShortString();
        _version = version.toShortString();
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = keccak256(
            abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, expectedProxyAddress)
        );
        _cachedThis = expectedProxyAddress;
    }

    /// @dev Returns the domain separator for the current chain
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) return _cachedDomainSeparator;
        else return _buildDomainSeparator();
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) {
        return MessageHashUtils.toTypedDataHash({ domainSeparator: _domainSeparatorV4(), structHash: structHash });
    }

    /**
     * @dev The name parameter for the Eip712 domain.
     *
     * NOTE: By default this function reads _name which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _Eip712Name() internal view returns (string memory) {
        return _name.toString();
    }

    /**
     * @dev The version parameter for the Eip712 domain.
     *
     * NOTE: By default this function reads _version which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _Eip712Version() internal view returns (string memory) {
        return _version.toString();
    }
}

File 12 of 27 : Erc20Core.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.21;

// ====================================================================
//             _        ______     ___   _______          _
//            / \     .' ___  |  .'   `.|_   __ \        / \
//           / _ \   / .'   \_| /  .-.  \ | |__) |      / _ \
//          / ___ \  | |   ____ | |   | | |  __ /      / ___ \
//        _/ /   \ \_\ `.___]  |\  `-'  /_| |  \ \_  _/ /   \ \_
//       |____| |____|`._____.'  `.___.'|____| |___||____| |____|
// ====================================================================
// ============================ Erc20Core =============================
// ====================================================================

import { IERC20Errors as IErc20Errors } from "@openzeppelin/contracts/interfaces/draft-IErc6093.sol";
import { SafeCastLib } from "solady/src/utils/SafeCastLib.sol";

import { StorageLib } from "./proxy/StorageLib.sol";

/// @notice The ```Erc20Core``` contract is a base contract for the Erc20 standard
/// @title Erc20Core
/// @author Agora
abstract contract Erc20Core is IErc20Errors {
    using StorageLib for uint256;
    using SafeCastLib for uint256;

    //==============================================================================
    // Internal Procedural Functions
    //==============================================================================

    /// The ```_approve``` function is used to approve a spender to spend a certain amount of tokens on behalf of the caller
    /// @dev This function reverts on failure
    /// @param _spender The address of the spender
    /// @param _value The amount of tokens to approve for spending
    function _approve(address _owner, address _spender, uint256 _value) internal {
        StorageLib.getPointerToErc20CoreStorage().accountAllowances[_owner][_spender] = _value;
        emit Approval({ owner: _owner, spender: _spender, value: _value });
    }

    /// @notice The ```_transfer``` function transfers tokens which belong to the caller
    /// @dev This function reverts on failure
    /// @param _to The address of the recipient
    /// @param _transferValue The amount of tokens to transfer
    function _transfer(address _from, address _to, uint248 _transferValue) internal {
        // Checks: Ensure _from address is not frozen
        StorageLib.Erc20AccountData memory _accountDataFrom = StorageLib.getPointerToErc20CoreStorage().accountData[
            _from
        ];
        if (_accountDataFrom.isFrozen) revert AccountIsFrozen({ frozenAccount: _from });

        // Checks: Ensure _from has enough balance
        if (_accountDataFrom.balance < _transferValue)
            revert ERC20InsufficientBalance({
                sender: _from,
                balance: _accountDataFrom.balance,
                needed: _transferValue
            });

        // Effects: update balances on the _from account
        unchecked {
            // Underflow not possible: _transferValue <= fromBalance asserted above
            StorageLib.getPointerToErc20CoreStorage().accountData[_from].balance =
                _accountDataFrom.balance -
                _transferValue;
        }

        // NOTE: typically checks are done before effects, but in this case we need to handle the case where _to == _from and so we want to read the latest values
        // Checks: Ensure _to address is not frozen
        StorageLib.Erc20AccountData memory _accountDataTo = StorageLib.getPointerToErc20CoreStorage().accountData[_to];
        if (_accountDataTo.isFrozen) revert AccountIsFrozen({ frozenAccount: _to });

        // Effects: update balances on the _to account
        unchecked {
            // Overflow not possible: _transferValue + toBalance <= (2^248 -1) x 10^-6 [more money than atoms in the galaxy]
            StorageLib.getPointerToErc20CoreStorage().accountData[_to].balance =
                _accountDataTo.balance +
                _transferValue;
        }

        emit Transfer({ from: _from, to: _to, value: _transferValue });
    }

    /// @notice The ```_spendAllowance``` function decrements a spenders allowance
    /// @dev Treats type(uint256).max as infinite allowance and does not update balance
    /// @param _owner The address of the owner
    /// @param _spender The address of the spender
    /// @param _value The amount of allowance to decrement
    function _spendAllowance(address _owner, address _spender, uint256 _value) internal {
        uint256 _currentAllowance = StorageLib.getPointerToErc20CoreStorage().accountAllowances[_owner][_spender];

        // We treat uint256.max as infinite allowance, so we don't need to read/write storage in that case
        if (_currentAllowance != type(uint256).max) {
            if (_currentAllowance < _value)
                revert ERC20InsufficientAllowance({ spender: _spender, allowance: _currentAllowance, needed: _value });
            unchecked {
                StorageLib.getPointerToErc20CoreStorage().accountAllowances[_owner][_spender] =
                    _currentAllowance -
                    _value;
            }
        }
    }

    //==============================================================================
    // Events
    //==============================================================================

    /// @notice The ```Transfer``` event is emitted when tokens are transferred from one account to another
    /// @param from The account that is transferring tokens
    /// @param to The account that is receiving tokens
    /// @param value The amount of tokens being transferred
    event Transfer(address indexed from, address indexed to, uint256 value);

    /// @notice ```Approval``` emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}
    /// @param owner The account that is allowing the spender to spend
    /// @param spender The account that is allowed to spend
    /// @param value The amount of funds that the spender is allowed to spend
    event Approval(address indexed owner, address indexed spender, uint256 value);

    //==============================================================================
    // Errors
    //==============================================================================

    /// @notice ```AccountIsFrozen``` error is emitted when an account is frozen and a transfer is attempted
    /// @param frozenAccount The account that is frozen
    error AccountIsFrozen(address frozenAccount);
}

File 13 of 27 : Ownable2Step.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

import {Ownable} from "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

File 14 of 27 : ProxyAdmin.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol)

pragma solidity ^0.8.20;

import {ITransparentUpgradeableProxy} from "./TransparentUpgradeableProxy.sol";
import {Ownable} from "../../access/Ownable.sol";

/**
 * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
 * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
 */
contract ProxyAdmin is Ownable {
    /**
     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)`
     * and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
     * while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string.
     * If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must
     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
     * during an upgrade.
     */
    string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";

    /**
     * @dev Sets the initial owner who can perform upgrades.
     */
    constructor(address initialOwner) Ownable(initialOwner) {}

    /**
     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.
     * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     * - If `data` is empty, `msg.value` must be zero.
     */
    function upgradeAndCall(
        ITransparentUpgradeableProxy proxy,
        address implementation,
        bytes memory data
    ) public payable virtual onlyOwner {
        proxy.upgradeToAndCall{value: msg.value}(implementation, data);
    }
}

File 15 of 27 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 16 of 27 : ShortStrings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;

import {StorageSlot} from "./StorageSlot.sol";

// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using
     * {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

File 17 of 27 : draft-IErc6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 18 of 27 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 19 of 27 : TransparentUpgradeableProxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/TransparentUpgradeableProxy.sol)

pragma solidity ^0.8.20;

import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
import {ERC1967Proxy} from "../ERC1967/ERC1967Proxy.sol";
import {IERC1967} from "../../interfaces/IERC1967.sol";
import {ProxyAdmin} from "./ProxyAdmin.sol";

/**
 * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
 * does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch
 * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
 * include them in the ABI so this interface must be used to interact with it.
 */
interface ITransparentUpgradeableProxy is IERC1967 {
    function upgradeToAndCall(address, bytes calldata) external payable;
}

/**
 * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance.
 *
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 *
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to
 * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating
 * the proxy admin cannot fallback to the target implementation.
 *
 * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a
 * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to
 * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and
 * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative
 * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership.
 *
 * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
 * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch
 * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
 * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
 * implementation.
 *
 * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a
 * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract.
 *
 * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an
 * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be
 * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an
 * undesirable state where the admin slot is different from the actual admin.
 *
 * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the
 * compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new
 * function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This
 * could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency.
 */
contract TransparentUpgradeableProxy is ERC1967Proxy {
    // An immutable address for the admin to avoid unnecessary SLOADs before each call
    // at the expense of removing the ability to change the admin once it's set.
    // This is acceptable if the admin is always a ProxyAdmin instance or similar contract
    // with its own ability to transfer the permissions to another account.
    address private immutable _admin;

    /**
     * @dev The proxy caller is the current admin, and can't fallback to the proxy target.
     */
    error ProxyDeniedAdminAccess();

    /**
     * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`,
     * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in
     * {ERC1967Proxy-constructor}.
     */
    constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
        _admin = address(new ProxyAdmin(initialOwner));
        // Set the storage value and emit an event for ERC-1967 compatibility
        ERC1967Utils.changeAdmin(_proxyAdmin());
    }

    /**
     * @dev Returns the admin of this proxy.
     */
    function _proxyAdmin() internal virtual returns (address) {
        return _admin;
    }

    /**
     * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior.
     */
    function _fallback() internal virtual override {
        if (msg.sender == _proxyAdmin()) {
            if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                revert ProxyDeniedAdminAccess();
            } else {
                _dispatchUpgradeToAndCall();
            }
        } else {
            super._fallback();
        }
    }

    /**
     * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}.
     *
     * Requirements:
     *
     * - If `data` is empty, `msg.value` must be zero.
     */
    function _dispatchUpgradeToAndCall() private {
        (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
        ERC1967Utils.upgradeToAndCall(newImplementation, data);
    }
}

File 20 of 27 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 21 of 27 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 22 of 27 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 23 of 27 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 24 of 27 : ERC1967Utils.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)

pragma solidity ^0.8.20;

import {IBeacon} from "../beacon/IBeacon.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 */
library ERC1967Utils {
    // We re-declare ERC-1967 events here because they can't be used directly from IERC1967.
    // This will be fixed in Solidity 0.8.21. At that point we should remove these events.
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
     */
    // solhint-disable-next-line private-vars-leading-underscore
    bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev The `implementation` of the proxy is invalid.
     */
    error ERC1967InvalidImplementation(address implementation);

    /**
     * @dev The `admin` of the proxy is invalid.
     */
    error ERC1967InvalidAdmin(address admin);

    /**
     * @dev The `beacon` of the proxy is invalid.
     */
    error ERC1967InvalidBeacon(address beacon);

    /**
     * @dev An upgrade function sees `msg.value > 0` that may be lost.
     */
    error ERC1967NonPayable();

    /**
     * @dev Returns the current implementation address.
     */
    function getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        if (newImplementation.code.length == 0) {
            revert ERC1967InvalidImplementation(newImplementation);
        }
        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Performs implementation upgrade with additional setup call if data is nonempty.
     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
     * to avoid stuck value in the contract.
     *
     * Emits an {IERC1967-Upgraded} event.
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);

        if (data.length > 0) {
            Address.functionDelegateCall(newImplementation, data);
        } else {
            _checkNonPayable();
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
     */
    // solhint-disable-next-line private-vars-leading-underscore
    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        if (newAdmin == address(0)) {
            revert ERC1967InvalidAdmin(address(0));
        }
        StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {IERC1967-AdminChanged} event.
     */
    function changeAdmin(address newAdmin) internal {
        emit AdminChanged(getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
     */
    // solhint-disable-next-line private-vars-leading-underscore
    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        if (newBeacon.code.length == 0) {
            revert ERC1967InvalidBeacon(newBeacon);
        }

        StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;

        address beaconImplementation = IBeacon(newBeacon).implementation();
        if (beaconImplementation.code.length == 0) {
            revert ERC1967InvalidImplementation(beaconImplementation);
        }
    }

    /**
     * @dev Change the beacon and trigger a setup call if data is nonempty.
     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
     * to avoid stuck value in the contract.
     *
     * Emits an {IERC1967-BeaconUpgraded} event.
     *
     * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
     * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
     * efficiency.
     */
    function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);

        if (data.length > 0) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        } else {
            _checkNonPayable();
        }
    }

    /**
     * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
     * if an upgrade doesn't perform an initialization call.
     */
    function _checkNonPayable() private {
        if (msg.value > 0) {
            revert ERC1967NonPayable();
        }
    }
}

File 25 of 27 : ERC1967Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.20;

import {Proxy} from "../Proxy.sol";
import {ERC1967Utils} from "./ERC1967Utils.sol";

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
     * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
     *
     * Requirements:
     *
     * - If `data` is empty, `msg.value` must be zero.
     */
    constructor(address implementation, bytes memory _data) payable {
        ERC1967Utils.upgradeToAndCall(implementation, _data);
    }

    /**
     * @dev Returns the current implementation address.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function _implementation() internal view virtual override returns (address) {
        return ERC1967Utils.getImplementation();
    }
}

File 26 of 27 : IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.20;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 */
interface IERC1967 {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

File 27 of 27 : IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {UpgradeableBeacon} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

Settings
{
  "remappings": [
    "contracts/=agora-dollar-evm/src/contracts/",
    "interfaces/=agora-dollar-evm/src/contracts/interfaces/",
    "forge-std/=agora-dollar-evm/node_modules/forge-std/src/",
    "ds-test/=agora-dollar-evm/node_modules/ds-test/src/",
    "@openzeppelin/=agora-dollar-evm/node_modules/@openzeppelin/",
    "solady/=agora-dollar-evm/node_modules/solady/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"components":[{"internalType":"address","name":"proxyAdminOwnerAddress","type":"address"},{"internalType":"string","name":"eip712Name","type":"string"},{"internalType":"string","name":"eip712Version","type":"string"}],"internalType":"struct ConstructorParams","name":"_params","type":"tuple"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"frozenAccount","type":"address"}],"name":"AccountIsFrozen","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"AgoraDollarErc1967NonPayable","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"ExpiredAuthorization","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ImplementationTargetNotAContract","type":"error"},{"inputs":[],"name":"InvalidAuthorization","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"payee","type":"address"}],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"ProxyDeniedAdminAccess","type":"error"},{"inputs":[],"name":"SignatureVerificationPaused","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"TransferPaused","type":"error"},{"inputs":[],"name":"UsedOrCanceledAuthorization","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authorizer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"AuthorizationUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_validAfter","type":"uint256"},{"internalType":"uint256","name":"_validBefore","type":"uint256"},{"internalType":"bytes32","name":"_nonce","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_validAfter","type":"uint256"},{"internalType":"uint256","name":"_validBefore","type":"uint256"},{"internalType":"bytes32","name":"_nonce","type":"bytes32"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"receiveWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_transferValue","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_transferValue","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_validAfter","type":"uint256"},{"internalType":"uint256","name":"_validBefore","type":"uint256"},{"internalType":"bytes32","name":"_nonce","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_validAfter","type":"uint256"},{"internalType":"uint256","name":"_validBefore","type":"uint256"},{"internalType":"bytes32","name":"_nonce","type":"bytes32"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"transferWithAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101806040908082526200223880380380916200001d828562000267565b83398101916020908183850312620002635782516001600160401b039384821162000263570190606082860312620002635780519160608301838110868211176200024f57825280516001600160a01b0391908281168103620002635784528481015186811162000263578762000096918301620002ae565b96858501978852838201518781116200026357620000b59201620002ae565b9586838501525192620000c88462000309565b95610120968752620000da8862000309565b94610140958652868151910120978860e05286815191012061010098818a524660a052855191888301917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528784015260608301524660808301523060a083015260a0825260c0820193828510848611176200024f578591858852835190206080523060c05251169161078f928383019160c0830190868210908211176200024f57899462001aa98739520301905ff080156200024557166101608181527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380546001600160a01b0319168317905582515f815294850191909152927f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f908290a1519261173194856200037886396080518561146f015260a0518561152a015260c05185611440015260e051856114be015251846114e40152518350505182505051816104560152f35b82513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b038211908210176200024f57604052565b5f5b8381106200029d5750505f910152565b81810151838201526020016200028d565b81601f82011215620002635780516001600160401b0381116200024f5760405192620002e5601f8301601f19166020018562000267565b8184526020828401011162000263576200030691602080850191016200028b565b90565b601f8151116200033657602081519101516020821062000327571790565b5f198260200360031b1b161790565b6044604051809263305a27a960e01b8252602060048301526200036981518092816024860152602086860191016200028b565b601f01601f19168101030190fdfe60806040526004361015610018575b61001661043d565b005b5f3560e01c806323b872dd1461007757806388b7ab6314610072578063a9059cbb1461006d578063cf09299514610068578063e3ee160e146100635763ef55bec60361000e57610421565b61038b565b610300565b6102b7565b61029a565b346100d65760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d65760206100cc6004356100b7816100da565b6024356100c3816100da565b60443591610c88565b6040519015158152f35b5f80fd5b73ffffffffffffffffffffffffffffffffffffffff8116036100d657565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60c0810190811067ffffffffffffffff82111761014157604052565b6100f8565b610100810190811067ffffffffffffffff82111761014157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761014157604052565b67ffffffffffffffff811161014157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f820112156100d6578035906101f5826101a4565b926102036040519485610163565b828452602083830101116100d657815f926020809301838601378301015290565b60e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126100d65760043561025a816100da565b91602435610267816100da565b9160443591606435916084359160a4359160c4359067ffffffffffffffff82116100d657610297916004016101de565b90565b346100d6576100166102ab36610224565b95949094939193611550565b346100d65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d65760206100cc6004356102f7816100da565b6024359061078a565b346100d65761001661031136610224565b95949094939193610f1b565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6101209101126100d657600435610354816100da565b90602435610361816100da565b9060443590606435906084359060a4359060c43560ff811681036100d6579060e435906101043590565b346100d65761001661041c6103f06103a23661031d565b60408051602081019390935282015260f89190911b7fff0000000000000000000000000000000000000000000000000000000000000016606082015297909691959294929188906061820190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101895288610163565b610f1b565b346100d6576100166104386103f06103a23661031d565b611550565b73ffffffffffffffffffffffffffffffffffffffff90337f0000000000000000000000000000000000000000000000000000000000000000831603610567575f9182357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef28600000000000000000000000000000000000000000000000000000000146104f25760046040517fd2b576ec000000000000000000000000000000000000000000000000000000008152fd5b366004116105635760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105635760043590610531826100da565b6024359367ffffffffffffffff8511610560575061055761055e939436906004016101de565b91166105aa565b565b80fd5b8280fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54165b5f808092368280378136915af43d82803e156105a6573d90f35b3d90fd5b803b156106c05773ffffffffffffffffffffffffffffffffffffffff8116907f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040515f927fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a283511561068c5750818084602061068096519101845af4903d15610683573d610663816101a4565b906106716040519283610163565b8152809360203d92013e6106ea565b50565b606092506106ea565b92505050346106985750565b807fcfc04b400000000000000000000000000000000000000000000000000000000060049252fd5b60046040517f9db85088000000000000000000000000000000000000000000000000000000008152fd5b9061072957508051156106ff57805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580610781575b61073a575090565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b15610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549190744000000000000000000000000000000000000000008316156107e75773ffffffffffffffffffffffffffffffffffffffff831661058c565b9091741000000000000000000000000000000000000000001661081c5761081061081792610846565b90336108d1565b600190565b60046040517fcd1fda9f000000000000000000000000000000000000000000000000000000008152fd5b7f0100000000000000000000000000000000000000000000000000000000000000811015610892577effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6335278d125f526004601cfd5b906040516040810181811067ffffffffffffffff82111761014157604052915460ff81161515835260081c6020830152565b919061092261091d8473ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b61089f565b8051610c415760200180517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081169084168110610bca57506109af8361098a610a2893517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b037effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6109f68573ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b9060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083549260081b169116179055565b610a7261091d8273ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b8051610b835790610b39610af284610acd60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9601517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6109f68373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b6040517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff908116931691602090a3565b6040517fcf8eb59700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602490fd5b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91821660248201529084166044820152606490fd5b6040517fcf8eb59700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602490fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54929174800000000000000000000000000000000000000000841615610ce55773ffffffffffffffffffffffffffffffffffffffff841661058c565b909192740100000000000000000000000000000000000000008116151580610d75575b610d4457741000000000000000000000000000000000000000001661081c57610d3e83610d39610817953386610dcc565b610846565b916108d1565b6040517fcf8eb597000000000000000000000000000000000000000000000000000000008152336004820152602490fd5b50610dc7610dc03373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b5460ff1690565b610d08565b91610e3b82610e188573ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8103610e6a575b50505050565b818110610ec957610ebf9291610e1891039373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70160205260405f2090565b555f808080610e64565b6064935073ffffffffffffffffffffffffffffffffffffffff604051937ffb8f41b200000000000000000000000000000000000000000000000000000000855216600484015260248301526044820152fd5b9492909593917f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54967501000000000000000000000000000000000000000000881615155f14610f815773ffffffffffffffffffffffffffffffffffffffff881661058c565b90919293949596740100000000000000000000000000000000000000008116151580611016575b610d445774100000000000000000000000000000000000000000811661081c577420000000000000000000000000000000000000000016610fec5761055e96611066565b60046040517fe283c875000000000000000000000000000000000000000000000000000000008152fd5b50611061610dc03373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b610fa8565b94959290939581421115611141578642101561111757611111610d3e94610d399361055e99611095858b611311565b6040519060208201927f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267845273ffffffffffffffffffffffffffffffffffffffff808d1660408501528b16606084015288608084015260a083015260c08201528460e082015260e0815261110881610146565b5190208861116b565b8561138f565b60046040517fa899ef93000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2ce87eeb000000000000000000000000000000000000000000000000000000008152fd5b90916042611177611429565b6040948551917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522073ffffffffffffffffffffffffffffffffffffffff5f9316806111fd575b505050156111d45750565b600490517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b90919250835191805f52602091828501518652858551146112c1575b6041855114611281575b5f6060528386527f1626ba7e00000000000000000000000000000000000000000000000000000000938481526004928382015260248101958693888552815186019081604493848601925afa503d01915afa915114165f80806111c9565b6060808601515f1a84528686015181526001848160805f825afa5183183d1517156112ad575050611223565b92509450505f9150925282525f80806111c9565b85850151601b8160ff1c0184527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060911681526001848160805f825afa5183183d1517156112ad575050611219565b73ffffffffffffffffffffffffffffffffffffffff165f527fbb0a37da742be2e3b68bdb11d195150f4243c03fb37d3cdfa756046082a3860060205260405f20905f5260205260ff60405f20541661136557565b60046040517f1dbc01d4000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff167f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a55f8281527fbb0a37da742be2e3b68bdb11d195150f4243c03fb37d3cdfa756046082a38600602052604081208482526020526040812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580a3565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016301480611527575b15611491577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815261152181610125565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614611468565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549693959094919392919075020000000000000000000000000000000000000000008816156115b65773ffffffffffffffffffffffffffffffffffffffff881661058c565b9091929394959674100000000000000000000000000000000000000000811661081c577420000000000000000000000000000000000000000016610fec573373ffffffffffffffffffffffffffffffffffffffff8616036116e45786421115611141578142101561111757611111610d3e948785611108896116b887610d399961055e9f6116448389611311565b60405196879560208701998a9260c09491979695929760e08501987fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8865273ffffffffffffffffffffffffffffffffffffffff80921660208701521660408501526060840152608083015260a08201520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610163565b6040517ffea9444200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff86166024820152604490fd6080346100c057601f61078f38819003918201601f19168301916001600160401b038311848410176100c4578084926020946040528339810103126100c057516001600160a01b0390818116908190036100c05780156100a85760018060a01b0319918260015416600155815f54938416175f5560405192167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a36106b690816100d98239f35b604051631e4fbdf760e01b81525f6004820152602490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe604060808152600480361015610013575f80fd5b5f91823560e01c908163715018a61461056557816379ba5097146104855781638da5cb5b146104345781639623609d1461023b578163ad3cb1cc1461017a578163e30c397814610127575063f2fde38b1461006c575f80fd5b346101235760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610123573573ffffffffffffffffffffffffffffffffffffffff80821680920361011f576100c3610666565b6100cb610666565b817fffffffffffffffffffffffff000000000000000000000000000000000000000060015416176001558254167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b5f80fd5b5080fd5b83903461012357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101235760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b9050823461023857807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610238575080519080820182811067ffffffffffffffff82111761020c5761020893508152600582527f352e302e3000000000000000000000000000000000000000000000000000000060208301525191829160208352602083019061060a565b0390f35b6041847f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b80fd5b905060607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103ce57813573ffffffffffffffffffffffffffffffffffffffff928382168092036103d25760249182359485168095036104305760443567ffffffffffffffff9182821161042c573660238301121561042c5781840135838111610401577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe092875193603f81601f85011601168401848110868211176103d65788528184528993929190368282018901116103d2578185928960209301838701378401015261032b610666565b803b156103ce576103749787518099819482937f4f1ef286000000000000000000000000000000000000000000000000000000008452898401528a8a840152604483019061060a565b039134905af180156103c457610388578580f35b841161039a575050525f808080808580f35b604185917f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b84513d88823e3d90fd5b8280fd5b8480fd5b878b6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b85896041877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8780fd5b8580fd5b83903461012357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101235773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b9050346103ce57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103ce576001549173ffffffffffffffffffffffffffffffffffffffff9133838516036105355750507fffffffffffffffffffffffff0000000000000000000000000000000000000000809216600155825491339083161783553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6024925051907f118cdaa70000000000000000000000000000000000000000000000000000000082523390820152fd5b833461023857807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102385761059c610666565b8073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffff0000000000000000000000000000000000000000806001541660015582549081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b91908251928382525f5b8481106106525750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201610614565b73ffffffffffffffffffffffffffffffffffffffff5f5416330361068657565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd000000000000000000000000000000000000000000000000000000000000002000000000000000000000000068898b77ebf7b55dca8a2e62d6fd74959a2930e2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000c41676f726120446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361015610018575b61001661043d565b005b5f3560e01c806323b872dd1461007757806388b7ab6314610072578063a9059cbb1461006d578063cf09299514610068578063e3ee160e146100635763ef55bec60361000e57610421565b61038b565b610300565b6102b7565b61029a565b346100d65760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d65760206100cc6004356100b7816100da565b6024356100c3816100da565b60443591610c88565b6040519015158152f35b5f80fd5b73ffffffffffffffffffffffffffffffffffffffff8116036100d657565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60c0810190811067ffffffffffffffff82111761014157604052565b6100f8565b610100810190811067ffffffffffffffff82111761014157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761014157604052565b67ffffffffffffffff811161014157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f820112156100d6578035906101f5826101a4565b926102036040519485610163565b828452602083830101116100d657815f926020809301838601378301015290565b60e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126100d65760043561025a816100da565b91602435610267816100da565b9160443591606435916084359160a4359160c4359067ffffffffffffffff82116100d657610297916004016101de565b90565b346100d6576100166102ab36610224565b95949094939193611550565b346100d65760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d65760206100cc6004356102f7816100da565b6024359061078a565b346100d65761001661031136610224565b95949094939193610f1b565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6101209101126100d657600435610354816100da565b90602435610361816100da565b9060443590606435906084359060a4359060c43560ff811681036100d6579060e435906101043590565b346100d65761001661041c6103f06103a23661031d565b60408051602081019390935282015260f89190911b7fff0000000000000000000000000000000000000000000000000000000000000016606082015297909691959294929188906061820190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101895288610163565b610f1b565b346100d6576100166104386103f06103a23661031d565b611550565b73ffffffffffffffffffffffffffffffffffffffff90337f000000000000000000000000b8fcc66d613e5f54ee6a425ddbf4a2fdbe4dedee831603610567575f9182357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef28600000000000000000000000000000000000000000000000000000000146104f25760046040517fd2b576ec000000000000000000000000000000000000000000000000000000008152fd5b366004116105635760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105635760043590610531826100da565b6024359367ffffffffffffffff8511610560575061055761055e939436906004016101de565b91166105aa565b565b80fd5b8280fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54165b5f808092368280378136915af43d82803e156105a6573d90f35b3d90fd5b803b156106c05773ffffffffffffffffffffffffffffffffffffffff8116907f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790556040515f927fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a283511561068c5750818084602061068096519101845af4903d15610683573d610663816101a4565b906106716040519283610163565b8152809360203d92013e6106ea565b50565b606092506106ea565b92505050346106985750565b807fcfc04b400000000000000000000000000000000000000000000000000000000060049252fd5b60046040517f9db85088000000000000000000000000000000000000000000000000000000008152fd5b9061072957508051156106ff57805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580610781575b61073a575090565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b15610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549190744000000000000000000000000000000000000000008316156107e75773ffffffffffffffffffffffffffffffffffffffff831661058c565b9091741000000000000000000000000000000000000000001661081c5761081061081792610846565b90336108d1565b600190565b60046040517fcd1fda9f000000000000000000000000000000000000000000000000000000008152fd5b7f0100000000000000000000000000000000000000000000000000000000000000811015610892577effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6335278d125f526004601cfd5b906040516040810181811067ffffffffffffffff82111761014157604052915460ff81161515835260081c6020830152565b919061092261091d8473ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b61089f565b8051610c415760200180517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081169084168110610bca57506109af8361098a610a2893517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b037effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6109f68573ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b9060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083549260081b169116179055565b610a7261091d8273ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b8051610b835790610b39610af284610acd60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9601517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6109f68373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b6040517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff908116931691602090a3565b6040517fcf8eb59700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602490fd5b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91821660248201529084166044820152606490fd5b6040517fcf8eb59700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602490fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54929174800000000000000000000000000000000000000000841615610ce55773ffffffffffffffffffffffffffffffffffffffff841661058c565b909192740100000000000000000000000000000000000000008116151580610d75575b610d4457741000000000000000000000000000000000000000001661081c57610d3e83610d39610817953386610dcc565b610846565b916108d1565b6040517fcf8eb597000000000000000000000000000000000000000000000000000000008152336004820152602490fd5b50610dc7610dc03373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b5460ff1690565b610d08565b91610e3b82610e188573ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8103610e6a575b50505050565b818110610ec957610ebf9291610e1891039373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70160205260405f2090565b555f808080610e64565b6064935073ffffffffffffffffffffffffffffffffffffffff604051937ffb8f41b200000000000000000000000000000000000000000000000000000000855216600484015260248301526044820152fd5b9492909593917f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54967501000000000000000000000000000000000000000000881615155f14610f815773ffffffffffffffffffffffffffffffffffffffff881661058c565b90919293949596740100000000000000000000000000000000000000008116151580611016575b610d445774100000000000000000000000000000000000000000811661081c577420000000000000000000000000000000000000000016610fec5761055e96611066565b60046040517fe283c875000000000000000000000000000000000000000000000000000000008152fd5b50611061610dc03373ffffffffffffffffffffffffffffffffffffffff165f527f455730fed596673e69db1907be2e521374ba893f1a04cc5f5dd931616cd6b70060205260405f2090565b610fa8565b94959290939581421115611141578642101561111757611111610d3e94610d399361055e99611095858b611311565b6040519060208201927f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267845273ffffffffffffffffffffffffffffffffffffffff808d1660408501528b16606084015288608084015260a083015260c08201528460e082015260e0815261110881610146565b5190208861116b565b8561138f565b60046040517fa899ef93000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2ce87eeb000000000000000000000000000000000000000000000000000000008152fd5b90916042611177611429565b6040948551917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522073ffffffffffffffffffffffffffffffffffffffff5f9316806111fd575b505050156111d45750565b600490517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b90919250835191805f52602091828501518652858551146112c1575b6041855114611281575b5f6060528386527f1626ba7e00000000000000000000000000000000000000000000000000000000938481526004928382015260248101958693888552815186019081604493848601925afa503d01915afa915114165f80806111c9565b6060808601515f1a84528686015181526001848160805f825afa5183183d1517156112ad575050611223565b92509450505f9150925282525f80806111c9565b85850151601b8160ff1c0184527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060911681526001848160805f825afa5183183d1517156112ad575050611219565b73ffffffffffffffffffffffffffffffffffffffff165f527fbb0a37da742be2e3b68bdb11d195150f4243c03fb37d3cdfa756046082a3860060205260405f20905f5260205260ff60405f20541661136557565b60046040517f1dbc01d4000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff167f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a55f8281527fbb0a37da742be2e3b68bdb11d195150f4243c03fb37d3cdfa756046082a38600602052604081208482526020526040812060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905580a3565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000efe302beaa2b3e6e1b18d08d69a9012a16301480611527575b15611491577f1b415e1fdec4058b42f2e8a1fcc859f6d3976a0b2cd9f0e9e016d07b0915d60c90565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1fff4a77785eee286dafb0db6b1c7e21126d99ba99f92d2242416147d8f70a0160408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815261152181610125565b51902090565b507f000000000000000000000000000000000000000000000000000000000000a86a4614611468565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549693959094919392919075020000000000000000000000000000000000000000008816156115b65773ffffffffffffffffffffffffffffffffffffffff881661058c565b9091929394959674100000000000000000000000000000000000000000811661081c577420000000000000000000000000000000000000000016610fec573373ffffffffffffffffffffffffffffffffffffffff8616036116e45786421115611141578142101561111757611111610d3e948785611108896116b887610d399961055e9f6116448389611311565b60405196879560208701998a9260c09491979695929760e08501987fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8865273ffffffffffffffffffffffffffffffffffffffff80921660208701521660408501526060840152608083015260a08201520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610163565b6040517ffea9444200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff86166024820152604490fd

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000002000000000000000000000000068898b77ebf7b55dca8a2e62d6fd74959a2930e2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000c41676f726120446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _params (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 00000000000000000000000068898b77ebf7b55dca8a2e62d6fd74959a2930e2
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [5] : 41676f726120446f6c6c61720000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 3100000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

1918:15635:24:-:0;;;;;;;;;-1:-1:-1;2921:65:24;;:::i;:::-;1918:15635;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;2639:95:21;1918:15635:24;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;1648:66:20;1918:15635:24;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;1918:15635:24;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;10057:28;;;1918:15635;;;:::i;:::-;;;;10057:28;;;1918:15635;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10057:28;;;;;;;;;:::i;:::-;;:::i;1918:15635::-;;;;13951:28;;;1918:15635;;;:::i;13951:28::-;;:::i;3600:538::-;1918:15635;;3653:10;3667:19;1918:15635;;3653:33;1918:15635;;3706:7;;;;;;3717:54;3706:65;3717:54;;3798:24;1918:15635;;3798:24;;;;3702:372;3927:8;3936:1;1918:15635;;;;;3927:8;1918:15635;;;;3936:1;1918:15635;;;;;:::i;:::-;;;;;;;;;3927:8;1918:15635;4047:9;3927:8;;;1918:15635;3936:1;1918:15635;;:::i;:::-;;;4047:9;:::i;:::-;3600:538::o;1918:15635::-;;;;;;;3649:483;13092:106:26;;;1918:15635:24;949:895:6;1019:819;;;;;;;;;;;;;;;;;;;;;;;;;;;4472:864:24;4637:30;;:35;4633:82;;1918:15635;;;12558:103:26;;1918:15635:24;;;;;;;;;;4671:1;5045:48;;;;;1918:15635;;5159:20;:16;;4255:25:10;;;;;4297:55;4255:25;;;;;;;;1918:15635:24;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;4255:25:10;1918:15635:24;;;;4297:55:10;:::i;:::-;;4472:864:24:o;1918:15635::-;;;-1:-1:-1;4297:55:10;:::i;5155:174:24:-;5277:9;;;;;5273:56;;5155:174;4472:864::o;5273:56::-;5299:30;;;;;;4633:82;4681:34;1918:15635;;4681:34;;;;4625:582:10;;4797:8;;-1:-1:-1;1918:15635:24;;5874:21:10;:17;;6046:142;;;;;;5870:383;6225:17;1918:15635:24;;6225:17:10;;;;4793:408;1918:15635:24;;5045:22:10;:49;;;4793:408;5041:119;;5173:17;;:::o;5041:119::-;1918:15635:24;;;;;5121:24:10;;;;1918:15635:24;5121:24:10;;;1918:15635:24;5121:24:10;5045:49;5071:18;;;:23;5045:49;;5848:913:24;13092:106:26;;;5848:913:24;14406:15:26;16138:50;;:55;14406:15;;1918:15635:24;;;6398:18;:::i;6150:605::-;15787:48:26;;14173:15;15787:48;6502:72:24;;6690:26;;;;:::i;:::-;6652:10;;6690:26;:::i;:::-;6740:4;6733:11;:::o;6502:72::-;6547:27;1918:15635;;6547:27;;;;5363:142:18;5444:8;5439:13;;;5435:36;;1918:15635:24;;5363:142:18;:::o;5435:36::-;11614:191;;;;;;1918:15635:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2198:1855:22:-;;;1918:15635:24;2396:82:22;;1918:15635:24;;;;7289:67:26;1918:15635:24;;;;;;;2396:82:22;1918:15635:24;:::i;:::-;;;2488:79:22;;2633:24;;1918:15635:24;;;;;;;;;2633:41:22;;2629:228;;1918:15635:24;3120:57:22;1918:15635:24;;3033:144:22;1918:15635:24;;;;;;;;;;;;3120:57:22;3033:60;;1918:15635:24;;;;7289:67:26;1918:15635:24;;;;;;;3033:60:22;1918:15635:24;;;;;;;;;;;;;;;3033:144:22;1918:15635:24;3465:58:22;;1918:15635:24;;;;7289:67:26;1918:15635:24;;;;;;;;;;3533:75:22;;3908:22;3823:140;3908:55;:22;1918:15635:24;2633:24:22;3989:57;3908:22;;1918:15635:24;;;;;;;;;;;3908:55:22;3823:58;;1918:15635:24;;;;7289:67:26;1918:15635:24;;;;;;;3823:140:22;1918:15635:24;;;;;;;;;;;;;;;;;;3989:57:22;2198:1855::o;3533:75::-;1918:15635:24;;3569:39:22;;;1918:15635:24;;;3569:39:22;;;1918:15635:24;;;3569:39:22;2629:228;1918:15635:24;;2695:162:22;;;1918:15635:24;;;2695:162:22;;;1918:15635:24;;;;;;;;;;;;;;;;;;3569:39:22;2488:79;1918:15635:24;;2526:41:22;;;1918:15635:24;;;2526:41:22;;;1918:15635:24;;;3569:39:22;7153:1455:24;13092:106:26;;;7153:1455:24;14495:15:26;16307:55;;:60;14495:15;;1918:15635:24;;;7676:18;:::i;7424:1178::-;15134:64:26;;;13848:15;15134:64;;:69;;7938:124:24;;;7424:1178;7917:213;;14173:15:26;15787:48;8197:72:24;;8537:26;8389:10;8409:14;8537:26;8389:10;;8409:14;;:::i;:::-;8537:26;:::i;:::-;;;:::i;7917:213::-;1918:15635;;8084:46;;;8117:10;8084:46;;;1918:15635;;;3569:39:22;7938:124:24;8042:10;7988:74;:65;8042:10;1918:15635;;;;7289:67:26;1918:15635:24;;;;;;;7988:65;1918:15635;;;;;7988:74;7938:124;;4387:744:22;;4509:77;:67;;;1918:15635:24;;;;4509:59:22;1918:15635:24;;;;;;;4509:67:22;1918:15635:24;;;;;;;;;;;;4509:77:22;1918:15635:24;4729:17:22;4708:38;;4704:421;;4387:744;;;;;:::o;4704:421::-;4766:26;;;4762:150;;4954:77;1918:15635:24;;4954:67:22;1918:15635:24;;4954:67:22;1918:15635:24;;;;4509:59:22;1918:15635:24;;;;;;;4954:77:22;1918:15635:24;4704:421:22;;;;;;4762:150;1918:15635:24;;;;;;4817:95:22;;;;1918:15635:24;4817:95:22;;;1918:15635:24;;;;;;;;;4817:95:22;10750:1823:24;;;;;;;13092:106:26;;16494:69;14615:15;16494:69;;:74;;11239:1328:24;14615:15:26;;;1918:15635:24;;;11504:18;:::i;11239:1328::-;15134:64:26;;;;;;;13848:15;15134:64;;:69;;11766:124:24;;;11239:1328;11745:213;;14173:15:26;15787:48;;12025:72:24;;14269:15:26;15961:62;12111:98:24;;12531:10;;;:::i;12111:98::-;12169:40;1918:15635;;12169:40;;;;11766:124;11870:10;11816:74;:65;11870:10;1918:15635;;;;7289:67:26;1918:15635:24;;;;;;;11816:74;11766:124;;3041:1049:20;;;;;;;3332:15;;:30;;3328:65;;3332:15;;3407:31;;3403:66;;3844:10;4062:18;3537:6;3991;3537;4062:18;3537:6;;;;;:::i;:::-;1918:15635:24;;3700:104:20;;;;1918:15635:24;1648:66:20;1918:15635:24;;;;;;;1648:66:20;;1918:15635:24;;;1648:66:20;;;1918:15635:24;1648:66:20;;;;1918:15635:24;1648:66:20;;;1918:15635:24;1648:66:20;;;1918:15635:24;1648:66:20;;;;1918:15635:24;1648:66:20;3700:104;;;;;:::i;:::-;1918:15635:24;3673:145:20;;3844:10;;:::i;:::-;3991:6;;:::i;3403:66::-;3447:22;1918:15635:24;;3447:22:20;;;;3328:65;3371:22;1918:15635:24;;3371:22:20;;;;7464:487;;;3515:233:15;7772:20:20;;:::i;:::-;3515:233:15;;;;;;;;;;;;;;;;;2181:3947:19;-1:-1:-1;2181:3947:19;;;;;;7602:306:20;;;;7585:359;;7464:487;:::o;7585:359::-;2181:3947:19;1918:15635:24;;7926:18:20;;;;2181:3947:19;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2181:3947:19;;;;;;;;;;;;;;;;8164:238:20;1918:15635:24;;-1:-1:-1;1918:15635:24;3629:64:26;1918:15635:24;;;-1:-1:-1;1918:15635:24;;-1:-1:-1;1918:15635:24;;;;;-1:-1:-1;1918:15635:24;;;8261:134:20;;8164:238::o;8261:134::-;8366:29;1918:15635:24;;8366:29:20;;;;8818:259;1918:15635:24;;9009:61:20;-1:-1:-1;1918:15635:24;;;3629:64:26;1918:15635:24;;;;;;;;;;;;;8990:4:20;1918:15635:24;;;;;;;9009:61:20;;8818:259::o;4252:222:21:-;1918:15635:24;4345:11:21;1918:15635:24;4336:4:21;4328:28;:63;;;4252:222;4324:143;;;4400:22;4393:29;:::o;4324:143::-;1918:15635:24;;4571:80:21;;;1918:15635:24;2639:95:21;1918:15635:24;;4593:11:21;1918:15635:24;2639:95:21;;1918:15635:24;4606:14:21;2639:95;;;1918:15635:24;4622:13:21;2639:95;;;1918:15635:24;4336:4:21;2639:95;;;1918:15635:24;2639:95:21;4571:80;;;;;:::i;:::-;1918:15635:24;4561:91:21;;4437:30;:::o;4328:63::-;4377:14;;4360:13;:31;4328:63;;14783:1401:24;13092:106:26;;;14783:1401:24;;;;;;;;;14717:15:26;16694:68;;:73;14717:15;;1918:15635:24;;;15533:18;:::i;15269:909::-;15787:48:26;;;;;;;14173:15;15787:48;;15637:72:24;;14269:15:26;15961:62;15723:98:24;;5174:10:20;1918:15635:24;;;5167:17:20;5163:78;;5255:15;;:30;;5251:65;;5255:15;;5330:31;;5326:66;;5766:10;5984:18;5460:6;;;5623:103;5460:6;5623:103;5460:6;5913;5460;5984:18;5460:6;;;;;:::i;:::-;1918:15635:24;;5623:103:20;;;;;;;;1648:66;;;;;;;;;;;;1918:15635:24;1940:66:20;1918:15635:24;;;;;;1648:66:20;;;1918:15635:24;;1648:66:20;;;1918:15635:24;1648:66:20;;;1918:15635:24;1648:66:20;;;1918:15635:24;1648:66:20;;;1918:15635:24;1648:66:20;1918:15635:24;1648:66:20;5623:103;;;;;;;;;:::i;5163:78::-;1918:15635:24;;5193:48:20;;;5174:10;5193:48;;;1918:15635:24;;;;;;;;;;3569:39:22

Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.