BNB Price: $611.75 (-0.96%)
 

Overview

Max Total Supply

27,201,049.914274ARK

Holders

620,864 ( 0.043%)

Market

Price

$14.74 @ 0.024095 BNB (-0.98%)

Onchain Market Cap

$400,943,475.74

Circulating Supply Market Cap

$0.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
2.780369348165574548 ARK

Value
$40.98 ( ~0.0669880568285721 BNB) [0.0000%]
0x055fec03bb1b3156b28abe0700d1e465bd3916f9
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

ARK DEFAI is a decentralized system combining AI, DAO governance, and modular blockchain architecture. AI agents automate decisions, DAOs ensure community control, and modular design allows flexibility.

Market

Volume (24H):$6,830,302.00
Market Capitalization:$0.00
Circulating Supply:0.00 ARK
Market Data Source: Coinmarketcap


Update? Click here to update the token ICO / general information

Contract Source Code Verified (Exact Match)

Contract Name:
ARK

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
cancun EvmVersion, MIT license
/**
 *Submitted for verification at BscScan.com on 2025-08-26
*/

// Sources flattened with hardhat v2.24.2 https://hardhat.org

// SPDX-License-Identifier: MIT

// File @openzeppelin/contracts/access/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted to signal this.
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        external
        view
        returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: 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 @openzeppelin/contracts/utils/introspection/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File @openzeppelin/contracts/utils/introspection/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        returns (bool)
    {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File @openzeppelin/contracts/access/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IAccessControl).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        public
        view
        virtual
        returns (bool)
    {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account)
        public
        virtual
        onlyRole(getRoleAdmin(role))
    {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account)
        public
        virtual
        onlyRole(getRoleAdmin(role))
    {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation)
        public
        virtual
    {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account)
        internal
        virtual
        returns (bool)
    {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account)
        internal
        virtual
        returns (bool)
    {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

// File @openzeppelin/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 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 ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-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 ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 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 @openzeppelin/contracts/token/ERC20/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);
}

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// File @openzeppelin/contracts/token/ERC20/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both values are immutable: they can only be set once during construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender)
        public
        view
        virtual
        returns (uint256)
    {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value)
        public
        virtual
        returns (bool)
    {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(
        address from,
        address to,
        uint256 value
    ) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(
        address from,
        address to,
        uint256 value
    ) internal virtual {
        if (from == address(this)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(this)) {
            revert ERC20InvalidReceiver(address(this));
        }
        _update(address(this), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(
        address owner,
        address spender,
        uint256 value
    ) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(
        address owner,
        address spender,
        uint256 value,
        bool emitEvent
    ) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 value
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(
                    spender,
                    currentAllowance,
                    value
                );
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys a `value` amount of tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 value) public virtual {
        _burn(_msgSender(), value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, deducting from
     * the caller's allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `value`.
     */
    function burnFrom(address account, uint256 value) public virtual {
        _spendAllowance(account, _msgSender(), value);
        _burn(account, value);
    }
}

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// File @openzeppelin/contracts/utils/cryptography/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (
            address recovered,
            RecoverError err,
            bytes32 errArg
        )
    {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly ("memory-safe") {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (
                address(0),
                RecoverError.InvalidSignatureLength,
                bytes32(signature.length)
            );
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (address)
    {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            signature
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    )
        internal
        pure
        returns (
            address recovered,
            RecoverError err,
            bytes32 errArg
        )
    {
        unchecked {
            bytes32 s = vs &
                bytes32(
                    0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                );
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            r,
            vs
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        internal
        pure
        returns (
            address recovered,
            RecoverError err,
            bytes32 errArg
        )
    {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (
            uint256(s) >
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
        ) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(
            hash,
            v,
            r,
            s
        );
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

// File @openzeppelin/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

// File @openzeppelin/contracts/utils/math/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 *
 * _Available since v5.1._
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

// File @openzeppelin/contracts/utils/math/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Return the 512-bit addition of two uint256.
     *
     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
     */
    function add512(uint256 a, uint256 b)
        internal
        pure
        returns (uint256 high, uint256 low)
    {
        assembly ("memory-safe") {
            low := add(a, b)
            high := lt(low, a)
        }
    }

    /**
     * @dev Return the 512-bit multiplication of two uint256.
     *
     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
     */
    function mul512(uint256 a, uint256 b)
        internal
        pure
        returns (uint256 high, uint256 low)
    {
        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
        // variables such that product = high * 2²⁵⁶ + low.
        assembly ("memory-safe") {
            let mm := mulmod(a, b, not(0))
            low := mul(a, b)
            high := sub(sub(mm, low), lt(mm, low))
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b)
        internal
        pure
        returns (bool success, uint256 result)
    {
        unchecked {
            uint256 c = a + b;
            success = c >= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b)
        internal
        pure
        returns (bool success, uint256 result)
    {
        unchecked {
            uint256 c = a - b;
            success = c <= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
     */
    function tryMul(uint256 a, uint256 b)
        internal
        pure
        returns (bool success, uint256 result)
    {
        unchecked {
            uint256 c = a * b;
            assembly ("memory-safe") {
                // Only true when the multiplication doesn't overflow
                // (c / a == b) || (a == 0)
                success := or(eq(div(c, a), b), iszero(a))
            }
            // equivalent to: success ? c : 0
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
     */
    function tryDiv(uint256 a, uint256 b)
        internal
        pure
        returns (bool success, uint256 result)
    {
        unchecked {
            success = b > 0;
            assembly ("memory-safe") {
                // The `DIV` opcode returns zero when the denominator is 0.
                result := div(a, b)
            }
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
     */
    function tryMod(uint256 a, uint256 b)
        internal
        pure
        returns (bool success, uint256 result)
    {
        unchecked {
            success = b > 0;
            assembly ("memory-safe") {
                // The `MOD` opcode returns zero when the denominator is 0.
                result := mod(a, b)
            }
        }
    }

    /**
     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingAdd(uint256 a, uint256 b)
        internal
        pure
        returns (uint256)
    {
        (bool success, uint256 result) = tryAdd(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
     */
    function saturatingSub(uint256 a, uint256 b)
        internal
        pure
        returns (uint256)
    {
        (, uint256 result) = trySub(a, b);
        return result;
    }

    /**
     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingMul(uint256 a, uint256 b)
        internal
        pure
        returns (uint256)
    {
        (bool success, uint256 result) = tryMul(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(
        bool condition,
        uint256 a,
        uint256 b
    ) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

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

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(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.
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    /**
     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     *
     * 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 {
            (uint256 high, uint256 low) = mul512(x, y);

            // Handle non-overflow cases, 256 by 256 division.
            if (high == 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 low / denominator;
            }

            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
            if (denominator <= high) {
                Panic.panic(
                    ternary(
                        denominator == 0,
                        Panic.DIVISION_BY_ZERO,
                        Panic.UNDER_OVERFLOW
                    )
                );
            }

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

            // Make division exact by subtracting the remainder from [high low].
            uint256 remainder;
            assembly ("memory-safe") {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                high := sub(high, gt(remainder, low))
                low := sub(low, 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 ("memory-safe") {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [high low] by twos.
                low := div(low, twos)

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

            // Shift in bits from high into low.
            low |= high * twos;

            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
            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⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

            // 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²⁵⁶. Since the preconditions guarantee that the outcome is
            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
            // is no longer required.
            result = low * inverse;
            return result;
        }
    }

    /**
     * @dev 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) {
        return
            mulDiv(x, y, denominator) +
            SafeCast.toUint(
                unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0
            );
    }

    /**
     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
     */
    function mulShr(
        uint256 x,
        uint256 y,
        uint8 n
    ) internal pure returns (uint256 result) {
        unchecked {
            (uint256 high, uint256 low) = mul512(x, y);
            if (high >= 1 << n) {
                Panic.panic(Panic.UNDER_OVERFLOW);
            }
            return (high << (256 - n)) | (low >> n);
        }
    }

    /**
     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.
     */
    function mulShr(
        uint256 x,
        uint256 y,
        uint8 n,
        Rounding rounding
    ) internal pure returns (uint256) {
        return
            mulShr(x, y, n) +
            SafeCast.toUint(
                unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0
            );
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
     *
     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
     *
     * NOTE: this function does NOT check that `p` is a prime greater than `2`.
     */
    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(
        uint256 b,
        uint256 e,
        uint256 m
    ) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(
        uint256 b,
        uint256 e,
        uint256 m
    ) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(
                gas(),
                0x05,
                dataPtr,
                mload(result),
                dataPtr,
                mLen
            )
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev 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 +
                SafeCast.toUint(
                    unsignedRoundsUp(rounding) && result * result < a
                );
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // If upper 8 bits of 16-bit half set, add 8 to result
        r |= SafeCast.toUint((x >> r) > 0xff) << 3;
        // If upper 4 bits of 8-bit half set, add 4 to result
        r |= SafeCast.toUint((x >> r) > 0xf) << 2;

        // Shifts value right by the current result and use it as an index into this lookup table:
        //
        // | x (4 bits) |  index  | table[index] = MSB position |
        // |------------|---------|-----------------------------|
        // |    0000    |    0    |        table[0] = 0         |
        // |    0001    |    1    |        table[1] = 0         |
        // |    0010    |    2    |        table[2] = 1         |
        // |    0011    |    3    |        table[3] = 1         |
        // |    0100    |    4    |        table[4] = 2         |
        // |    0101    |    5    |        table[5] = 2         |
        // |    0110    |    6    |        table[6] = 2         |
        // |    0111    |    7    |        table[7] = 2         |
        // |    1000    |    8    |        table[8] = 3         |
        // |    1001    |    9    |        table[9] = 3         |
        // |    1010    |   10    |        table[10] = 3        |
        // |    1011    |   11    |        table[11] = 3        |
        // |    1100    |   12    |        table[12] = 3        |
        // |    1101    |   13    |        table[13] = 3        |
        // |    1110    |   14    |        table[14] = 3        |
        // |    1111    |   15    |        table[15] = 3        |
        //
        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
        assembly ("memory-safe") {
            r := or(
                r,
                byte(
                    shr(r, x),
                    0x0000010102020202030303030303030300000000000000000000000000000000
                )
            )
        }
    }

    /**
     * @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 +
                SafeCast.toUint(
                    unsignedRoundsUp(rounding) && 1 << result < value
                );
        }
    }

    /**
     * @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 +
                SafeCast.toUint(
                    unsignedRoundsUp(rounding) && 10**result < value
                );
        }
    }

    /**
     * @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 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
    }

    /**
     * @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 +
                SafeCast.toUint(
                    unsignedRoundsUp(rounding) && 1 << (result << 3) < value
                );
        }
    }

    /**
     * @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 @openzeppelin/contracts/utils/math/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(
        bool condition,
        int256 a,
        int256 b
    ) internal pure returns (int256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

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

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return ternary(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 {
            // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
            // taking advantage of the most significant (or "sign" bit) in two's complement representation.
            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
            int256 mask = n >> 255;

            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
            return uint256((n + mask) ^ mask);
        }
    }
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

/**
 * @dev String operations.
 */
library Strings {
    using SafeCast for *;

    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;
    uint256 private constant SPECIAL_CHARS_LOOKUP =
        (1 << 0x08) | // backspace
            (1 << 0x09) | // tab
            (1 << 0x0a) | // newline
            (1 << 0x0c) | // form feed
            (1 << 0x0d) | // carriage return
            (1 << 0x22) | // double quote
            (1 << 0x5c); // backslash

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

    /**
     * @dev The string being parsed contains characters that are not in scope of the given base.
     */
    error StringsInvalidChar();

    /**
     * @dev The string being parsed is not a properly formatted address.
     */
    error StringsInvalidAddressFormat();

    /**
     * @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;
            assembly ("memory-safe") {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                assembly ("memory-safe") {
                    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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
     * representation, according to EIP-55.
     */
    function toChecksumHexString(address addr)
        internal
        pure
        returns (string memory)
    {
        bytes memory buffer = bytes(toHexString(addr));

        // hash the hex part of buffer (skip length + 2 bytes, length 40)
        uint256 hashValue;
        assembly ("memory-safe") {
            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
        }

        for (uint256 i = 41; i > 1; --i) {
            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
                // case shift by xoring with 0x20
                buffer[i] ^= 0x20;
            }
            hashValue >>= 4;
        }
        return string(buffer);
    }

    /**
     * @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));
    }

    /**
     * @dev Parse a decimal string and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(string memory input) internal pure returns (uint256) {
        return parseUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(string memory input)
        internal
        pure
        returns (bool success, uint256 value)
    {
        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        uint256 result = 0;
        for (uint256 i = begin; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 9) return (false, 0);
            result *= 10;
            result += chr;
        }
        return (true, result);
    }

    /**
     * @dev Parse a decimal string and returns the value as a `int256`.
     *
     * Requirements:
     * - The string must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(string memory input) internal pure returns (int256) {
        return parseInt(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (int256) {
        (bool success, int256 value) = tryParseInt(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
     * the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(string memory input)
        internal
        pure
        returns (bool success, int256 value)
    {
        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
    }

    uint256 private constant ABS_MIN_INT256 = 2**255;

    /**
     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character or if the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, int256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseIntUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseIntUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, int256 value) {
        bytes memory buffer = bytes(input);

        // Check presence of a negative sign.
        bytes1 sign = begin == end
            ? bytes1(0)
            : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        bool positiveSign = sign == bytes1("+");
        bool negativeSign = sign == bytes1("-");
        uint256 offset = (positiveSign || negativeSign).toUint();

        (bool absSuccess, uint256 absValue) = tryParseUint(
            input,
            begin + offset,
            end
        );

        if (absSuccess && absValue < ABS_MIN_INT256) {
            return (true, negativeSign ? -int256(absValue) : int256(absValue));
        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
            return (true, type(int256).min);
        } else return (false, 0);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(string memory input) internal pure returns (uint256) {
        return parseHexUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseHexUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(string memory input)
        internal
        pure
        returns (bool success, uint256 value)
    {
        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
     * invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseHexUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseHexUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        // skip 0x prefix if present
        bool hasPrefix = (end > begin + 1) &&
            bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 offset = hasPrefix.toUint() * 2;

        uint256 result = 0;
        for (uint256 i = begin + offset; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 15) return (false, 0);
            result *= 16;
            unchecked {
                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
                // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
                result += chr;
            }
        }
        return (true, result);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(string memory input) internal pure returns (address) {
        return parseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (address) {
        (bool success, address value) = tryParseAddress(input, begin, end);
        if (!success) revert StringsInvalidAddressFormat();
        return value;
    }

    /**
     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
     * formatted address. See {parseAddress-string} requirements.
     */
    function tryParseAddress(string memory input)
        internal
        pure
        returns (bool success, address value)
    {
        return tryParseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
     * formatted address. See {parseAddress-string-uint256-uint256} requirements.
     */
    function tryParseAddress(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, address value) {
        if (end > bytes(input).length || begin > end)
            return (false, address(0));

        bool hasPrefix = (end > begin + 1) &&
            bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;

        // check that input is the correct length
        if (end - begin == expectedLength) {
            // length guarantees that this does not overflow, and value is at most type(uint160).max
            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(
                input,
                begin,
                end
            );
            return (s, address(uint160(v)));
        } else {
            return (false, address(0));
        }
    }

    function _tryParseChr(bytes1 chr) private pure returns (uint8) {
        uint8 value = uint8(chr);

        // Try to parse `chr`:
        // - Case 1: [0-9]
        // - Case 2: [a-f]
        // - Case 3: [A-F]
        // - otherwise not supported
        unchecked {
            if (value > 47 && value < 58) value -= 48;
            else if (value > 96 && value < 103) value -= 87;
            else if (value > 64 && value < 71) value -= 55;
            else return type(uint8).max;
        }

        return value;
    }

    /**
     * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
     *
     * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
     *
     * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
     * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
     * characters that are not in this range, but other tooling may provide different results.
     */
    function escapeJSON(string memory input)
        internal
        pure
        returns (string memory)
    {
        bytes memory buffer = bytes(input);
        bytes memory output = new bytes(2 * buffer.length); // worst case scenario
        uint256 outputLength = 0;

        for (uint256 i; i < buffer.length; ++i) {
            bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
            if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
                output[outputLength++] = "\\";
                if (char == 0x08) output[outputLength++] = "b";
                else if (char == 0x09) output[outputLength++] = "t";
                else if (char == 0x0a) output[outputLength++] = "n";
                else if (char == 0x0c) output[outputLength++] = "f";
                else if (char == 0x0d) output[outputLength++] = "r";
                else if (char == 0x5c) output[outputLength++] = "\\";
                else if (char == 0x22) {
                    // solhint-disable-next-line quotes
                    output[outputLength++] = '"';
                }
            } else {
                output[outputLength++] = char;
            }
        }
        // write the actual length and deallocate unused memory
        assembly ("memory-safe") {
            mstore(output, outputLength)
            mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
        }

        return string(output);
    }

    /**
     * @dev Reads a bytes32 from a bytes array without bounds checking.
     *
     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
     * assembly block as such would prevent some optimizations.
     */
    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset)
        private
        pure
        returns (bytes32 value)
    {
        // This is not memory safe in the general case, but all calls to this private function are within bounds.
        assembly ("memory-safe") {
            value := mload(add(buffer, add(0x20, offset)))
        }
    }
}

// File @openzeppelin/contracts/utils/cryptography/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;

/**
 * @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[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
 * specifications.
 */
library MessageHashUtils {
    /**
     * @dev Returns the keccak256 digest of an ERC-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://ethereum.org/en/developers/docs/apis/json-rpc/#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)
    {
        assembly ("memory-safe") {
            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 ERC-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://ethereum.org/en/developers/docs/apis/json-rpc/#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 ERC-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 Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
     */
    function toDataWithIntendedValidatorHash(
        address validator,
        bytes32 messageHash
    ) internal pure returns (bytes32 digest) {
        assembly ("memory-safe") {
            mstore(0x00, hex"19_00")
            mstore(0x02, shl(96, validator))
            mstore(0x16, messageHash)
            digest := keccak256(0x00, 0x36)
        }
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-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)
    {
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.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 ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     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;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 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)
    {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

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

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

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

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot)
        internal
        pure
        returns (Int256Slot storage r)
    {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot)
        internal
        pure
        returns (StringSlot storage r)
    {
        assembly ("memory-safe") {
            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)
    {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot)
        internal
        pure
        returns (BytesSlot storage r)
    {
        assembly ("memory-safe") {
            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)
    {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;

// | 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);
        assembly ("memory-safe") {
            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 {toShortStringWithFallback}.
     */
    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
     * {toShortStringWithFallback}.
     *
     * 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 @openzeppelin/contracts/utils/cryptography/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.20;

/**
 * @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].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable
 */
abstract contract EIP712 is IERC5267 {
    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;
    // slither-disable-next-line constable-states
    string private _nameFallback;
    // slither-disable-next-line constable-states
    string private _versionFallback;

    /**
     * @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.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @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
        virtual
        returns (bytes32)
    {
        return
            MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @inheritdoc IERC5267
     */
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _EIP712Name(),
            _EIP712Version(),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }

    /**
     * @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.toStringWithFallback(_nameFallback);
    }

    /**
     * @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.toStringWithFallback(_versionFallback);
    }
}

// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;

/**
 * @dev Provides tracking nonces for addresses. Nonces will only increment.
 */
abstract contract Nonces {
    /**
     * @dev The nonce used for an `account` is not the expected current nonce.
     */
    error InvalidAccountNonce(address account, uint256 currentNonce);

    mapping(address => uint256) private _nonces;

    /**
     * @dev Returns the next unused nonce for an address.
     */
    function nonces(address owner) public view virtual returns (uint256) {
        return _nonces[owner];
    }

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256) {
        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
        // decremented or reset. This guarantees that the nonce never overflows.
        unchecked {
            // It is important to do x++ and not ++x here.
            return _nonces[owner]++;
        }
    }

    /**
     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.
     */
    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {
        uint256 current = _useNonce(owner);
        if (nonce != current) {
            revert InvalidAccountNonce(owner, current);
        }
    }
}

// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
    bytes32 private constant PERMIT_TYPEHASH =
        keccak256(
            "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
        );

    /**
     * @dev Permit deadline has expired.
     */
    error ERC2612ExpiredSignature(uint256 deadline);

    /**
     * @dev Mismatched signature.
     */
    error ERC2612InvalidSigner(address signer, address owner);

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC-20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @inheritdoc IERC20Permit
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        if (block.timestamp > deadline) {
            revert ERC2612ExpiredSignature(deadline);
        }

        bytes32 structHash = keccak256(
            abi.encode(
                PERMIT_TYPEHASH,
                owner,
                spender,
                value,
                _useNonce(owner),
                deadline
            )
        );

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        if (signer != owner) {
            revert ERC2612InvalidSigner(signer, owner);
        }

        _approve(owner, spender, value);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    function nonces(address owner)
        public
        view
        virtual
        override(IERC20Permit, Nonces)
        returns (uint256)
    {
        return super.nonces(owner);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {
        return _domainSeparatorV4();
    }
}

// File contracts/pERC20.sol

// Original license: SPDX_License_Identifier: MIT
pragma solidity ^0.8.22;

contract ARK is ERC20Burnable, ERC20Permit {
    mapping(address => bool) public longGovernanceList;
    mapping(address => bool) public shortGovernanceList;
    mapping(address => bool) public whitelist;
    address public governance;
    address public oracle;
    address public rbs;
    address public treasury;
    uint256 public longGovernanceRatio;
    uint256 public shortGovernanceRatio;
    uint256 public constant BPS_100 = 10000; // 100%

    constructor() ERC20("ARK", "ARK") ERC20Permit("ARK") {
        governance = msg.sender;
        oracle = 0x615a2a799c49AF74E91b4C3Ca5eaD68897c07A81;
        rbs = 0x23876D9F06F8290F119Fb39B7FDCf93A08e2D616;

        treasury = 0xd9D1c7dCf7CB6181A61ed0E70F64fe7Ddd4B9495;
        longGovernanceRatio = 9999;

        // mint initial supply to treasury
        _mint(0xf7B2f3Fc7d5107c2bF3776B5C02a818F33F9453e, 1_150_000 ether);
    }

    modifier onlyGovernance() {
        require(msg.sender == governance, "unauthorized access");
        _;
    }

    function setBuyRates(uint256 _taxRate) external onlyGovernance {
        require(_taxRate >= 0 && _taxRate <= BPS_100, "invalid tax rate");
        longGovernanceRatio = _taxRate;
        emit BuyRateChanged(longGovernanceRatio);
    }

    function setSellRates(uint256 _taxRate) external onlyGovernance {
        require(_taxRate >= 0 && _taxRate <= BPS_100, "invalid tax rate");
        shortGovernanceRatio = _taxRate;
        emit SellRateChanged(shortGovernanceRatio);
    }

    function setTreasuryAddress(address _treasury) external onlyGovernance {
        treasury = _treasury;
        emit TreasuryAddressChanged(treasury);
    }

    function addWhitelist(address _addr) external onlyGovernance {
        whitelist[_addr] = true;
        emit WhitelistAdded(_addr);
    }

    function removeWhitelist(address _addr) external onlyGovernance {
        whitelist[_addr] = false;
        emit WhitelistRemoved(_addr);
    }

    function setLongGovernanceList(address _taxAddress, bool state)
        external
        onlyGovernance
    {
        longGovernanceList[_taxAddress] = state;
        emit LongGovernanceSet(_taxAddress, longGovernanceList[_taxAddress]);
    }

    function setShortGovernanceList(address _taxAddress, bool state)
        external
        onlyGovernance
    {
        shortGovernanceList[_taxAddress] = state;
        emit ShortGovernanceSet(_taxAddress, shortGovernanceList[_taxAddress]);
    }

    function _collectGovernance(
        address from,
        address to,
        uint256 value
    ) internal returns (uint256) {
        uint256 tax = 0;

        // if treasury address is not set, tax = 0
        if (treasury == address(0)) {
            return tax;
        }

        if (longGovernanceList[from] && !whitelist[from] && !whitelist[to]) {
            // buy tax, `from` address is taxed
            tax = (value * longGovernanceRatio) / BPS_100;
            _transfer(from, treasury, tax);
        }
        // handle LP pool sell event
        else if (
            shortGovernanceList[to] && !whitelist[from] && !whitelist[to]
        ) {
            // sell tax, `to` address is taxed
            tax = (value * shortGovernanceRatio) / BPS_100;
            _transfer(from, treasury, tax);
        }

        return tax;
    }

    function transfer(address to, uint256 value)
        public
        override
        returns (bool)
    {
        address owner = _msgSender();

        uint256 tax = _collectGovernance(owner, to, value);

        _transfer(owner, to, value - tax);
        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) public override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);

        uint256 tax = _collectGovernance(from, to, value);

        _transfer(from, to, value - tax);
        return true;
    }

    function mint(address to, uint256 amount) public {
        require(
            msg.sender == oracle || msg.sender == rbs,
            "unauthorized access"
        );
        _mint(to, amount);
    }

    function transferGovernance(address newGovernance) external onlyGovernance {
        governance = newGovernance;
    }

    event BuyRateChanged(uint256 newRate);
    event SellRateChanged(uint256 newRate);
    event TreasuryAddressChanged(address newTreasury);
    event WhitelistAdded(address newAccount);
    event WhitelistRemoved(address newAccount);
    event LongGovernanceSet(address account, bool state);
    event ShortGovernanceSet(address account, bool state);
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","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":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"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":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"BuyRateChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"LongGovernanceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRate","type":"uint256"}],"name":"SellRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"ShortGovernanceSet","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":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAccount","type":"address"}],"name":"WhitelistAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAccount","type":"address"}],"name":"WhitelistRemoved","type":"event"},{"inputs":[],"name":"BPS_100","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"addWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"longGovernanceList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"longGovernanceRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rbs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"removeWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taxRate","type":"uint256"}],"name":"setBuyRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taxAddress","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setLongGovernanceList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taxRate","type":"uint256"}],"name":"setSellRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taxAddress","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setShortGovernanceList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shortGovernanceList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shortGovernanceRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","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":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGovernance","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

61016060405234801562000011575f80fd5b506040518060400160405280600381526020017f41524b0000000000000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f41524b00000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f41524b00000000000000000000000000000000000000000000000000000000008152508160039081620000fc919062000973565b5080600490816200010e919062000973565b505050620001276005836200033d60201b90919060201c565b6101208181525050620001456006826200033d60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a08181525050620001846200039260201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff168152505050505033600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073615a2a799c49af74e91b4c3ca5ead68897c07a81600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507323876d9f06f8290f119fb39b7fdcf93a08e2d616600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073d9d1c7dcf7cb6181a61ed0e70f64fe7ddd4b9495600e5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061270f600f819055506200033773f7b2f3fc7d5107c2bf3776b5c02a818f33f9453e69f3859ffa9ede12c00000620003ee60201b60201c565b62000d42565b5f60208351101562000362576200035a836200047860201b60201c565b90506200038c565b826200037483620004e260201b60201c565b5f01908162000384919062000973565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e051610100514630604051602001620003d395949392919062000ac5565b60405160208183030381529060405280519060200120905090565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036200046157306040517fec442f0500000000000000000000000000000000000000000000000000000000815260040162000458919062000b20565b60405180910390fd5b62000474308383620004eb60201b60201c565b5050565b5f80829050601f81511115620004c757826040517f305a27a9000000000000000000000000000000000000000000000000000000008152600401620004be919062000bc5565b60405180910390fd5b805181620004d59062000c16565b5f1c175f1b915050919050565b5f819050919050565b3073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200053f578060025f82825462000532919062000cb2565b9250508190555062000610565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015620005cb578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401620005c29392919062000cec565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000659578060025f8282540392505081905550620006a3565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405162000702919062000d27565b60405180910390a3505050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200078b57607f821691505b602082108103620007a157620007a062000746565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620008057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620007c8565b620008118683620007c8565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200085b620008556200084f8462000829565b62000832565b62000829565b9050919050565b5f819050919050565b62000876836200083b565b6200088e620008858262000862565b848454620007d4565b825550505050565b5f90565b620008a462000896565b620008b18184846200086b565b505050565b5b81811015620008d857620008cc5f826200089a565b600181019050620008b7565b5050565b601f8211156200092757620008f181620007a7565b620008fc84620007b9565b810160208510156200090c578190505b620009246200091b85620007b9565b830182620008b6565b50505b505050565b5f82821c905092915050565b5f620009495f19846008026200092c565b1980831691505092915050565b5f62000963838362000938565b9150826002028217905092915050565b6200097e826200070f565b67ffffffffffffffff8111156200099a576200099962000719565b5b620009a6825462000773565b620009b3828285620008dc565b5f60209050601f831160018114620009e9575f8415620009d4578287015190505b620009e0858262000956565b86555062000a4f565b601f198416620009f986620007a7565b5f5b8281101562000a2257848901518255600182019150602085019450602081019050620009fb565b8683101562000a42578489015162000a3e601f89168262000938565b8355505b6001600288020188555050505b505050505050565b5f819050919050565b62000a6b8162000a57565b82525050565b62000a7c8162000829565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000aad8262000a82565b9050919050565b62000abf8162000aa1565b82525050565b5f60a08201905062000ada5f83018862000a60565b62000ae9602083018762000a60565b62000af8604083018662000a60565b62000b07606083018562000a71565b62000b16608083018462000ab4565b9695505050505050565b5f60208201905062000b355f83018462000ab4565b92915050565b5f82825260208201905092915050565b5f5b8381101562000b6a57808201518184015260208101905062000b4d565b5f8484015250505050565b5f601f19601f8301169050919050565b5f62000b91826200070f565b62000b9d818562000b3b565b935062000baf81856020860162000b4b565b62000bba8162000b75565b840191505092915050565b5f6020820190508181035f83015262000bdf818462000b85565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f62000c0d825162000a57565b80915050919050565b5f62000c228262000be7565b8262000c2e8462000bf1565b905062000c3b8162000c00565b9250602082101562000c7e5762000c797fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802620007c8565b831692505b5050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f62000cbe8262000829565b915062000ccb8362000829565b925082820190508082111562000ce65762000ce562000c85565b5b92915050565b5f60608201905062000d015f83018662000ab4565b62000d10602083018562000a71565b62000d1f604083018462000a71565b949350505050565b5f60208201905062000d3c5f83018462000a71565b92915050565b60805160a05160c05160e05161010051610120516101405161312e62000d945f395f611d7a01525f611d3f01525f61227301525f61225201525f611b3f01525f611b9501525f611bbe015261312e5ff3fe608060405234801561000f575f80fd5b5060043610610204575f3560e01c80637c39e12211610118578063a9059cbb116100ab578063d505accf1161007a578063d505accf146105de578063dc3f973d146105fa578063dd62ed3e1461062a578063e66315ce1461065a578063f80f5dd51461067857610204565b8063a9059cbb14610558578063c5e067ec14610588578063cf81982a146105a6578063d38bfff4146105c257610204565b806384b0196e116100e757806384b0196e146104c857806384c42b24146104ec57806395d89b411461050a5780639b19251a1461052857610204565b80637c39e1221461042c5780637dc0d1d01461044a5780637ecebe00146104685780638404051c1461049857610204565b806342966c681161019b578063670f730b1161016a578063670f730b1461038c57806370a08231146103a857806374c6bf41146103d857806378c8cda7146103f457806379cc67901461041057610204565b806342966c68146103185780635aa6e6751461033457806361d027b3146103525780636605bfda1461037057610204565b806323b872dd116101d757806323b872dd14610290578063313ce567146102c05780633644e515146102de57806340c10f19146102fc57610204565b806306fdde0314610208578063095ea7b31461022657806318160ddd1461025657806318330eef14610274575b5f80fd5b610210610694565b60405161021d9190612743565b60405180910390f35b610240600480360381019061023b91906127f4565b610724565b60405161024d919061284c565b60405180910390f35b61025e610746565b60405161026b9190612874565b60405180910390f35b61028e6004803603810190610289919061288d565b61074f565b005b6102aa60048036038101906102a591906128b8565b610872565b6040516102b7919061284c565b60405180910390f35b6102c86108ba565b6040516102d59190612923565b60405180910390f35b6102e66108c2565b6040516102f39190612954565b60405180910390f35b610316600480360381019061031191906127f4565b6108d0565b005b610332600480360381019061032d919061288d565b6109c4565b005b61033c6109d8565b604051610349919061297c565b60405180910390f35b61035a6109fd565b604051610367919061297c565b60405180910390f35b61038a60048036038101906103859190612995565b610a22565b005b6103a660048036038101906103a191906129ea565b610b4c565b005b6103c260048036038101906103bd9190612995565b610cb5565b6040516103cf9190612874565b60405180910390f35b6103f260048036038101906103ed919061288d565b610cfa565b005b61040e60048036038101906104099190612995565b610e1d565b005b61042a600480360381019061042591906127f4565b610f3a565b005b610434610f5a565b6040516104419190612874565b60405180910390f35b610452610f60565b60405161045f919061297c565b60405180910390f35b610482600480360381019061047d9190612995565b610f85565b60405161048f9190612874565b60405180910390f35b6104b260048036038101906104ad9190612995565b610f96565b6040516104bf919061284c565b60405180910390f35b6104d0610fb3565b6040516104e39796959493929190612b19565b60405180910390f35b6104f4611058565b6040516105019190612874565b60405180910390f35b61051261105e565b60405161051f9190612743565b60405180910390f35b610542600480360381019061053d9190612995565b6110ee565b60405161054f919061284c565b60405180910390f35b610572600480360381019061056d91906127f4565b61110b565b60405161057f919061284c565b60405180910390f35b610590611147565b60405161059d919061297c565b60405180910390f35b6105c060048036038101906105bb91906129ea565b61116c565b005b6105dc60048036038101906105d79190612995565b6112d5565b005b6105f860048036038101906105f39190612bef565b6113a7565b005b610614600480360381019061060f9190612995565b6114ec565b604051610621919061284c565b60405180910390f35b610644600480360381019061063f9190612c8c565b611509565b6040516106519190612874565b60405180910390f35b61066261158b565b60405161066f9190612874565b60405180910390f35b610692600480360381019061068d9190612995565b611591565b005b6060600380546106a390612cf7565b80601f01602080910402602001604051908101604052809291908181526020018280546106cf90612cf7565b801561071a5780601f106106f15761010080835404028352916020019161071a565b820191905f5260205f20905b8154815290600101906020018083116106fd57829003601f168201915b5050505050905090565b5f8061072e6116af565b905061073b8185856116b6565b600191505092915050565b5f600254905090565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d590612d71565b60405180910390fd5b5f81101580156107f057506127108111155b61082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082690612dd9565b60405180910390fd5b80600f819055507fe69bd2eb7089e3c126252ddfeb1f833595cda52cb6286f43e5939c3ee7cb9135600f546040516108679190612874565b60405180910390a150565b5f8061087c6116af565b90506108898582856116c8565b5f61089586868661175b565b90506108ad868683876108a89190612e24565b611a4c565b6001925050509392505050565b5f6012905090565b5f6108cb611b3c565b905090565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109775750600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6109b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ad90612d71565b60405180910390fd5b6109c08282611bf2565b5050565b6109d56109cf6116af565b82611c71565b50565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ab1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa890612d71565b60405180910390fd5b80600e5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f9073dfac663173e64aa95665faedae52e2246f9bcdd3890fbfaf6733b46bba13600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610b41919061297c565b60405180910390a150565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd290612d71565b60405180910390fd5b8060085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f787f6bd9c5e005ded0ea8f79fe1e532aca8cd7a2129f87513b7e2749ebaf1a778260085f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16604051610ca9929190612e57565b60405180910390a15050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8090612d71565b60405180910390fd5b5f8110158015610d9b57506127108111155b610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd190612dd9565b60405180910390fd5b806010819055507f699aa66599ea05213d852039f080c1b0e852ad059ef903b7eb4703a3adf45f7c601054604051610e129190612874565b60405180910390a150565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610eac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea390612d71565b60405180910390fd5b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507fde8cf212af7ce38b2840785a2768d97ff2dbf3c21b516961cec0061e134c2a1e81604051610f2f919061297c565b60405180910390a150565b610f4c82610f466116af565b836116c8565b610f568282611c71565b5050565b61271081565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610f8f82611cf0565b9050919050565b6009602052805f5260405f205f915054906101000a900460ff1681565b5f6060805f805f6060610fc4611d36565b610fcc611d71565b46305f801b5f67ffffffffffffffff811115610feb57610fea612e7e565b5b6040519080825280602002602001820160405280156110195781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600f5481565b60606004805461106d90612cf7565b80601f016020809104026020016040519081016040528092919081815260200182805461109990612cf7565b80156110e45780601f106110bb576101008083540402835291602001916110e4565b820191905f5260205f20905b8154815290600101906020018083116110c757829003601f168201915b5050505050905090565b600a602052805f5260405f205f915054906101000a900460ff1681565b5f806111156116af565b90505f61112382868661175b565b905061113b828683876111369190612e24565b611a4c565b60019250505092915050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f290612d71565b60405180910390fd5b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f590b660adbb74506c0344cf64b7af80788b3e832a91f8b14076e6cfe9fe6b5648260095f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166040516112c9929190612e57565b60405180910390a15050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611364576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135b90612d71565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b834211156113ec57836040517f627913020000000000000000000000000000000000000000000000000000000081526004016113e39190612874565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861141a8c611dac565b8960405160200161143096959493929190612eab565b6040516020818303038152906040528051906020012090505f61145282611dff565b90505f61146182878787611e18565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114d557808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016114cc929190612f0a565b60405180910390fd5b6114e08a8a8a6116b6565b50505050505050505050565b6008602052805f5260405f205f915054906101000a900460ff1681565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b60105481565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161790612d71565b60405180910390fd5b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f4790a4adb426ca2345bb5108f6e454eae852a7bf687544cd66a7270dff3a41d6816040516116a4919061297c565b60405180910390a150565b5f33905090565b6116c38383836001611e46565b505050565b5f6116d38484611509565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156117555781811015611746578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161173d93929190612f31565b60405180910390fd5b61175484848484035f611e46565b5b50505050565b5f805f90505f73ffffffffffffffffffffffffffffffffffffffff16600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036117bd5780915050611a45565b60085f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16801561185a5750600a5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b80156118ad5750600a5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b1561190057612710600f54846118c39190612f66565b6118cd9190612fd4565b90506118fb85600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611a4c565b611a40565b60095f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16801561199d5750600a5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b80156119f05750600a5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b15611a3f5761271060105484611a069190612f66565b611a109190612fd4565b9050611a3e85600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611a4c565b5b5b809150505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abc575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611ab3919061297c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b2c575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611b23919061297c565b60405180910390fd5b611b37838383612015565b505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611bb757507f000000000000000000000000000000000000000000000000000000000000000046145b15611be4577f00000000000000000000000000000000000000000000000000000000000000009050611bef565b611bec61222e565b90505b90565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c6257306040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611c59919061297c565b60405180910390fd5b611c6d308383612015565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611ce1575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611cd8919061297c565b60405180910390fd5b611cec825f83612015565b5050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6060611d6c60057f00000000000000000000000000000000000000000000000000000000000000006122c390919063ffffffff16565b905090565b6060611da760067f00000000000000000000000000000000000000000000000000000000000000006122c390919063ffffffff16565b905090565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f611e11611e0b611b3c565b83612370565b9050919050565b5f805f80611e28888888886123b0565b925092509250611e388282612497565b829350505050949350505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611eb6575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611ead919061297c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611f26575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611f1d919061297c565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550801561200f578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516120069190612874565b60405180910390a35b50505050565b3073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612065578060025f8282546120599190613004565b92505081905550612133565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156120ee578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016120e593929190612f31565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361217a578060025f82825403925050819055506121c4565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516122219190612874565b60405180910390a3505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000046306040516020016122a8959493929190613037565b60405160208183030381529060405280519060200120905090565b606060ff5f1b83146122df576122d8836125f9565b905061236a565b8180546122eb90612cf7565b80601f016020809104026020016040519081016040528092919081815260200182805461231790612cf7565b80156123625780601f1061233957610100808354040283529160200191612362565b820191905f5260205f20905b81548152906001019060200180831161234557829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c11156123ec575f60038592509250925061248d565b5f6001888888886040515f815260200160405260405161240f9493929190613088565b6020604051602081039080840390855afa15801561242f573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612480575f60015f801b9350935093505061248d565b805f805f1b935093509350505b9450945094915050565b5f60038111156124aa576124a96130cb565b5b8260038111156124bd576124bc6130cb565b5b03156125f557600160038111156124d7576124d66130cb565b5b8260038111156124ea576124e96130cb565b5b03612521576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612535576125346130cb565b5b826003811115612548576125476130cb565b5b0361258c57805f1c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016125839190612874565b60405180910390fd5b60038081111561259f5761259e6130cb565b5b8260038111156125b2576125b16130cb565b5b036125f457806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016125eb9190612954565b60405180910390fd5b5b5050565b60605f6126058361266b565b90505f602067ffffffffffffffff81111561262357612622612e7e565b5b6040519080825280601f01601f1916602001820160405280156126555781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f8060ff835f1c169050601f8111156126b0576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156126f05780820151818401526020810190506126d5565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612715826126b9565b61271f81856126c3565b935061272f8185602086016126d3565b612738816126fb565b840191505092915050565b5f6020820190508181035f83015261275b818461270b565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61279082612767565b9050919050565b6127a081612786565b81146127aa575f80fd5b50565b5f813590506127bb81612797565b92915050565b5f819050919050565b6127d3816127c1565b81146127dd575f80fd5b50565b5f813590506127ee816127ca565b92915050565b5f806040838503121561280a57612809612763565b5b5f612817858286016127ad565b9250506020612828858286016127e0565b9150509250929050565b5f8115159050919050565b61284681612832565b82525050565b5f60208201905061285f5f83018461283d565b92915050565b61286e816127c1565b82525050565b5f6020820190506128875f830184612865565b92915050565b5f602082840312156128a2576128a1612763565b5b5f6128af848285016127e0565b91505092915050565b5f805f606084860312156128cf576128ce612763565b5b5f6128dc868287016127ad565b93505060206128ed868287016127ad565b92505060406128fe868287016127e0565b9150509250925092565b5f60ff82169050919050565b61291d81612908565b82525050565b5f6020820190506129365f830184612914565b92915050565b5f819050919050565b61294e8161293c565b82525050565b5f6020820190506129675f830184612945565b92915050565b61297681612786565b82525050565b5f60208201905061298f5f83018461296d565b92915050565b5f602082840312156129aa576129a9612763565b5b5f6129b7848285016127ad565b91505092915050565b6129c981612832565b81146129d3575f80fd5b50565b5f813590506129e4816129c0565b92915050565b5f8060408385031215612a00576129ff612763565b5b5f612a0d858286016127ad565b9250506020612a1e858286016129d6565b9150509250929050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612a5c81612a28565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612a94816127c1565b82525050565b5f612aa58383612a8b565b60208301905092915050565b5f602082019050919050565b5f612ac782612a62565b612ad18185612a6c565b9350612adc83612a7c565b805f5b83811015612b0c578151612af38882612a9a565b9750612afe83612ab1565b925050600181019050612adf565b5085935050505092915050565b5f60e082019050612b2c5f83018a612a53565b8181036020830152612b3e818961270b565b90508181036040830152612b52818861270b565b9050612b616060830187612865565b612b6e608083018661296d565b612b7b60a0830185612945565b81810360c0830152612b8d8184612abd565b905098975050505050505050565b612ba481612908565b8114612bae575f80fd5b50565b5f81359050612bbf81612b9b565b92915050565b612bce8161293c565b8114612bd8575f80fd5b50565b5f81359050612be981612bc5565b92915050565b5f805f805f805f60e0888a031215612c0a57612c09612763565b5b5f612c178a828b016127ad565b9750506020612c288a828b016127ad565b9650506040612c398a828b016127e0565b9550506060612c4a8a828b016127e0565b9450506080612c5b8a828b01612bb1565b93505060a0612c6c8a828b01612bdb565b92505060c0612c7d8a828b01612bdb565b91505092959891949750929550565b5f8060408385031215612ca257612ca1612763565b5b5f612caf858286016127ad565b9250506020612cc0858286016127ad565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612d0e57607f821691505b602082108103612d2157612d20612cca565b5b50919050565b7f756e617574686f72697a656420616363657373000000000000000000000000005f82015250565b5f612d5b6013836126c3565b9150612d6682612d27565b602082019050919050565b5f6020820190508181035f830152612d8881612d4f565b9050919050565b7f696e76616c6964207461782072617465000000000000000000000000000000005f82015250565b5f612dc36010836126c3565b9150612dce82612d8f565b602082019050919050565b5f6020820190508181035f830152612df081612db7565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612e2e826127c1565b9150612e39836127c1565b9250828203905081811115612e5157612e50612df7565b5b92915050565b5f604082019050612e6a5f83018561296d565b612e77602083018461283d565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f60c082019050612ebe5f830189612945565b612ecb602083018861296d565b612ed8604083018761296d565b612ee56060830186612865565b612ef26080830185612865565b612eff60a0830184612865565b979650505050505050565b5f604082019050612f1d5f83018561296d565b612f2a602083018461296d565b9392505050565b5f606082019050612f445f83018661296d565b612f516020830185612865565b612f5e6040830184612865565b949350505050565b5f612f70826127c1565b9150612f7b836127c1565b9250828202612f89816127c1565b91508282048414831517612fa057612f9f612df7565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612fde826127c1565b9150612fe9836127c1565b925082612ff957612ff8612fa7565b5b828204905092915050565b5f61300e826127c1565b9150613019836127c1565b925082820190508082111561303157613030612df7565b5b92915050565b5f60a08201905061304a5f830188612945565b6130576020830187612945565b6130646040830186612945565b6130716060830185612865565b61307e608083018461296d565b9695505050505050565b5f60808201905061309b5f830187612945565b6130a86020830186612914565b6130b56040830185612945565b6130c26060830184612945565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffdfea26469706673582212207c74f56d12efb45bd5d41bf7f12ca1a2d6591d7c1aa565b9913c48611dca3b1364736f6c63430008180033

Deployed Bytecode

0x608060405234801561000f575f80fd5b5060043610610204575f3560e01c80637c39e12211610118578063a9059cbb116100ab578063d505accf1161007a578063d505accf146105de578063dc3f973d146105fa578063dd62ed3e1461062a578063e66315ce1461065a578063f80f5dd51461067857610204565b8063a9059cbb14610558578063c5e067ec14610588578063cf81982a146105a6578063d38bfff4146105c257610204565b806384b0196e116100e757806384b0196e146104c857806384c42b24146104ec57806395d89b411461050a5780639b19251a1461052857610204565b80637c39e1221461042c5780637dc0d1d01461044a5780637ecebe00146104685780638404051c1461049857610204565b806342966c681161019b578063670f730b1161016a578063670f730b1461038c57806370a08231146103a857806374c6bf41146103d857806378c8cda7146103f457806379cc67901461041057610204565b806342966c68146103185780635aa6e6751461033457806361d027b3146103525780636605bfda1461037057610204565b806323b872dd116101d757806323b872dd14610290578063313ce567146102c05780633644e515146102de57806340c10f19146102fc57610204565b806306fdde0314610208578063095ea7b31461022657806318160ddd1461025657806318330eef14610274575b5f80fd5b610210610694565b60405161021d9190612743565b60405180910390f35b610240600480360381019061023b91906127f4565b610724565b60405161024d919061284c565b60405180910390f35b61025e610746565b60405161026b9190612874565b60405180910390f35b61028e6004803603810190610289919061288d565b61074f565b005b6102aa60048036038101906102a591906128b8565b610872565b6040516102b7919061284c565b60405180910390f35b6102c86108ba565b6040516102d59190612923565b60405180910390f35b6102e66108c2565b6040516102f39190612954565b60405180910390f35b610316600480360381019061031191906127f4565b6108d0565b005b610332600480360381019061032d919061288d565b6109c4565b005b61033c6109d8565b604051610349919061297c565b60405180910390f35b61035a6109fd565b604051610367919061297c565b60405180910390f35b61038a60048036038101906103859190612995565b610a22565b005b6103a660048036038101906103a191906129ea565b610b4c565b005b6103c260048036038101906103bd9190612995565b610cb5565b6040516103cf9190612874565b60405180910390f35b6103f260048036038101906103ed919061288d565b610cfa565b005b61040e60048036038101906104099190612995565b610e1d565b005b61042a600480360381019061042591906127f4565b610f3a565b005b610434610f5a565b6040516104419190612874565b60405180910390f35b610452610f60565b60405161045f919061297c565b60405180910390f35b610482600480360381019061047d9190612995565b610f85565b60405161048f9190612874565b60405180910390f35b6104b260048036038101906104ad9190612995565b610f96565b6040516104bf919061284c565b60405180910390f35b6104d0610fb3565b6040516104e39796959493929190612b19565b60405180910390f35b6104f4611058565b6040516105019190612874565b60405180910390f35b61051261105e565b60405161051f9190612743565b60405180910390f35b610542600480360381019061053d9190612995565b6110ee565b60405161054f919061284c565b60405180910390f35b610572600480360381019061056d91906127f4565b61110b565b60405161057f919061284c565b60405180910390f35b610590611147565b60405161059d919061297c565b60405180910390f35b6105c060048036038101906105bb91906129ea565b61116c565b005b6105dc60048036038101906105d79190612995565b6112d5565b005b6105f860048036038101906105f39190612bef565b6113a7565b005b610614600480360381019061060f9190612995565b6114ec565b604051610621919061284c565b60405180910390f35b610644600480360381019061063f9190612c8c565b611509565b6040516106519190612874565b60405180910390f35b61066261158b565b60405161066f9190612874565b60405180910390f35b610692600480360381019061068d9190612995565b611591565b005b6060600380546106a390612cf7565b80601f01602080910402602001604051908101604052809291908181526020018280546106cf90612cf7565b801561071a5780601f106106f15761010080835404028352916020019161071a565b820191905f5260205f20905b8154815290600101906020018083116106fd57829003601f168201915b5050505050905090565b5f8061072e6116af565b905061073b8185856116b6565b600191505092915050565b5f600254905090565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d590612d71565b60405180910390fd5b5f81101580156107f057506127108111155b61082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082690612dd9565b60405180910390fd5b80600f819055507fe69bd2eb7089e3c126252ddfeb1f833595cda52cb6286f43e5939c3ee7cb9135600f546040516108679190612874565b60405180910390a150565b5f8061087c6116af565b90506108898582856116c8565b5f61089586868661175b565b90506108ad868683876108a89190612e24565b611a4c565b6001925050509392505050565b5f6012905090565b5f6108cb611b3c565b905090565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109775750600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6109b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ad90612d71565b60405180910390fd5b6109c08282611bf2565b5050565b6109d56109cf6116af565b82611c71565b50565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ab1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa890612d71565b60405180910390fd5b80600e5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f9073dfac663173e64aa95665faedae52e2246f9bcdd3890fbfaf6733b46bba13600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610b41919061297c565b60405180910390a150565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd290612d71565b60405180910390fd5b8060085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f787f6bd9c5e005ded0ea8f79fe1e532aca8cd7a2129f87513b7e2749ebaf1a778260085f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16604051610ca9929190612e57565b60405180910390a15050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8090612d71565b60405180910390fd5b5f8110158015610d9b57506127108111155b610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd190612dd9565b60405180910390fd5b806010819055507f699aa66599ea05213d852039f080c1b0e852ad059ef903b7eb4703a3adf45f7c601054604051610e129190612874565b60405180910390a150565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610eac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea390612d71565b60405180910390fd5b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507fde8cf212af7ce38b2840785a2768d97ff2dbf3c21b516961cec0061e134c2a1e81604051610f2f919061297c565b60405180910390a150565b610f4c82610f466116af565b836116c8565b610f568282611c71565b5050565b61271081565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610f8f82611cf0565b9050919050565b6009602052805f5260405f205f915054906101000a900460ff1681565b5f6060805f805f6060610fc4611d36565b610fcc611d71565b46305f801b5f67ffffffffffffffff811115610feb57610fea612e7e565b5b6040519080825280602002602001820160405280156110195781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600f5481565b60606004805461106d90612cf7565b80601f016020809104026020016040519081016040528092919081815260200182805461109990612cf7565b80156110e45780601f106110bb576101008083540402835291602001916110e4565b820191905f5260205f20905b8154815290600101906020018083116110c757829003601f168201915b5050505050905090565b600a602052805f5260405f205f915054906101000a900460ff1681565b5f806111156116af565b90505f61112382868661175b565b905061113b828683876111369190612e24565b611a4c565b60019250505092915050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f290612d71565b60405180910390fd5b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f590b660adbb74506c0344cf64b7af80788b3e832a91f8b14076e6cfe9fe6b5648260095f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166040516112c9929190612e57565b60405180910390a15050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611364576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135b90612d71565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b834211156113ec57836040517f627913020000000000000000000000000000000000000000000000000000000081526004016113e39190612874565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861141a8c611dac565b8960405160200161143096959493929190612eab565b6040516020818303038152906040528051906020012090505f61145282611dff565b90505f61146182878787611e18565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114d557808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016114cc929190612f0a565b60405180910390fd5b6114e08a8a8a6116b6565b50505050505050505050565b6008602052805f5260405f205f915054906101000a900460ff1681565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b60105481565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161790612d71565b60405180910390fd5b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f4790a4adb426ca2345bb5108f6e454eae852a7bf687544cd66a7270dff3a41d6816040516116a4919061297c565b60405180910390a150565b5f33905090565b6116c38383836001611e46565b505050565b5f6116d38484611509565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156117555781811015611746578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161173d93929190612f31565b60405180910390fd5b61175484848484035f611e46565b5b50505050565b5f805f90505f73ffffffffffffffffffffffffffffffffffffffff16600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036117bd5780915050611a45565b60085f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16801561185a5750600a5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b80156118ad5750600a5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b1561190057612710600f54846118c39190612f66565b6118cd9190612fd4565b90506118fb85600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611a4c565b611a40565b60095f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16801561199d5750600a5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b80156119f05750600a5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16155b15611a3f5761271060105484611a069190612f66565b611a109190612fd4565b9050611a3e85600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611a4c565b5b5b809150505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abc575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611ab3919061297c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b2c575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611b23919061297c565b60405180910390fd5b611b37838383612015565b505050565b5f7f000000000000000000000000cae117ca6bc8a341d2e7207f30e180f0e5618b9d73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611bb757507f000000000000000000000000000000000000000000000000000000000000003846145b15611be4577f7bcd65fb9e70fa6ee2e316d43621b3d5c3152abffea4cd9f0592f6bc745eb8e49050611bef565b611bec61222e565b90505b90565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c6257306040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611c59919061297c565b60405180910390fd5b611c6d308383612015565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611ce1575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611cd8919061297c565b60405180910390fd5b611cec825f83612015565b5050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6060611d6c60057f41524b00000000000000000000000000000000000000000000000000000000036122c390919063ffffffff16565b905090565b6060611da760067f31000000000000000000000000000000000000000000000000000000000000016122c390919063ffffffff16565b905090565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f611e11611e0b611b3c565b83612370565b9050919050565b5f805f80611e28888888886123b0565b925092509250611e388282612497565b829350505050949350505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611eb6575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611ead919061297c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611f26575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611f1d919061297c565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550801561200f578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516120069190612874565b60405180910390a35b50505050565b3073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612065578060025f8282546120599190613004565b92505081905550612133565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156120ee578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016120e593929190612f31565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361217a578060025f82825403925050819055506121c4565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516122219190612874565b60405180910390a3505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f297e671db5cfa180eb0f44754f808501aedf0061a602ea53714819dde27d87497fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016122a8959493929190613037565b60405160208183030381529060405280519060200120905090565b606060ff5f1b83146122df576122d8836125f9565b905061236a565b8180546122eb90612cf7565b80601f016020809104026020016040519081016040528092919081815260200182805461231790612cf7565b80156123625780601f1061233957610100808354040283529160200191612362565b820191905f5260205f20905b81548152906001019060200180831161234557829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c11156123ec575f60038592509250925061248d565b5f6001888888886040515f815260200160405260405161240f9493929190613088565b6020604051602081039080840390855afa15801561242f573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612480575f60015f801b9350935093505061248d565b805f805f1b935093509350505b9450945094915050565b5f60038111156124aa576124a96130cb565b5b8260038111156124bd576124bc6130cb565b5b03156125f557600160038111156124d7576124d66130cb565b5b8260038111156124ea576124e96130cb565b5b03612521576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612535576125346130cb565b5b826003811115612548576125476130cb565b5b0361258c57805f1c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016125839190612874565b60405180910390fd5b60038081111561259f5761259e6130cb565b5b8260038111156125b2576125b16130cb565b5b036125f457806040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004016125eb9190612954565b60405180910390fd5b5b5050565b60605f6126058361266b565b90505f602067ffffffffffffffff81111561262357612622612e7e565b5b6040519080825280601f01601f1916602001820160405280156126555781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f8060ff835f1c169050601f8111156126b0576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156126f05780820151818401526020810190506126d5565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612715826126b9565b61271f81856126c3565b935061272f8185602086016126d3565b612738816126fb565b840191505092915050565b5f6020820190508181035f83015261275b818461270b565b905092915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61279082612767565b9050919050565b6127a081612786565b81146127aa575f80fd5b50565b5f813590506127bb81612797565b92915050565b5f819050919050565b6127d3816127c1565b81146127dd575f80fd5b50565b5f813590506127ee816127ca565b92915050565b5f806040838503121561280a57612809612763565b5b5f612817858286016127ad565b9250506020612828858286016127e0565b9150509250929050565b5f8115159050919050565b61284681612832565b82525050565b5f60208201905061285f5f83018461283d565b92915050565b61286e816127c1565b82525050565b5f6020820190506128875f830184612865565b92915050565b5f602082840312156128a2576128a1612763565b5b5f6128af848285016127e0565b91505092915050565b5f805f606084860312156128cf576128ce612763565b5b5f6128dc868287016127ad565b93505060206128ed868287016127ad565b92505060406128fe868287016127e0565b9150509250925092565b5f60ff82169050919050565b61291d81612908565b82525050565b5f6020820190506129365f830184612914565b92915050565b5f819050919050565b61294e8161293c565b82525050565b5f6020820190506129675f830184612945565b92915050565b61297681612786565b82525050565b5f60208201905061298f5f83018461296d565b92915050565b5f602082840312156129aa576129a9612763565b5b5f6129b7848285016127ad565b91505092915050565b6129c981612832565b81146129d3575f80fd5b50565b5f813590506129e4816129c0565b92915050565b5f8060408385031215612a00576129ff612763565b5b5f612a0d858286016127ad565b9250506020612a1e858286016129d6565b9150509250929050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612a5c81612a28565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612a94816127c1565b82525050565b5f612aa58383612a8b565b60208301905092915050565b5f602082019050919050565b5f612ac782612a62565b612ad18185612a6c565b9350612adc83612a7c565b805f5b83811015612b0c578151612af38882612a9a565b9750612afe83612ab1565b925050600181019050612adf565b5085935050505092915050565b5f60e082019050612b2c5f83018a612a53565b8181036020830152612b3e818961270b565b90508181036040830152612b52818861270b565b9050612b616060830187612865565b612b6e608083018661296d565b612b7b60a0830185612945565b81810360c0830152612b8d8184612abd565b905098975050505050505050565b612ba481612908565b8114612bae575f80fd5b50565b5f81359050612bbf81612b9b565b92915050565b612bce8161293c565b8114612bd8575f80fd5b50565b5f81359050612be981612bc5565b92915050565b5f805f805f805f60e0888a031215612c0a57612c09612763565b5b5f612c178a828b016127ad565b9750506020612c288a828b016127ad565b9650506040612c398a828b016127e0565b9550506060612c4a8a828b016127e0565b9450506080612c5b8a828b01612bb1565b93505060a0612c6c8a828b01612bdb565b92505060c0612c7d8a828b01612bdb565b91505092959891949750929550565b5f8060408385031215612ca257612ca1612763565b5b5f612caf858286016127ad565b9250506020612cc0858286016127ad565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612d0e57607f821691505b602082108103612d2157612d20612cca565b5b50919050565b7f756e617574686f72697a656420616363657373000000000000000000000000005f82015250565b5f612d5b6013836126c3565b9150612d6682612d27565b602082019050919050565b5f6020820190508181035f830152612d8881612d4f565b9050919050565b7f696e76616c6964207461782072617465000000000000000000000000000000005f82015250565b5f612dc36010836126c3565b9150612dce82612d8f565b602082019050919050565b5f6020820190508181035f830152612df081612db7565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612e2e826127c1565b9150612e39836127c1565b9250828203905081811115612e5157612e50612df7565b5b92915050565b5f604082019050612e6a5f83018561296d565b612e77602083018461283d565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f60c082019050612ebe5f830189612945565b612ecb602083018861296d565b612ed8604083018761296d565b612ee56060830186612865565b612ef26080830185612865565b612eff60a0830184612865565b979650505050505050565b5f604082019050612f1d5f83018561296d565b612f2a602083018461296d565b9392505050565b5f606082019050612f445f83018661296d565b612f516020830185612865565b612f5e6040830184612865565b949350505050565b5f612f70826127c1565b9150612f7b836127c1565b9250828202612f89816127c1565b91508282048414831517612fa057612f9f612df7565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612fde826127c1565b9150612fe9836127c1565b925082612ff957612ff8612fa7565b5b828204905092915050565b5f61300e826127c1565b9150613019836127c1565b925082820190508082111561303157613030612df7565b5b92915050565b5f60a08201905061304a5f830188612945565b6130576020830187612945565b6130646040830186612945565b6130716060830185612865565b61307e608083018461296d565b9695505050505050565b5f60808201905061309b5f830187612945565b6130a86020830186612914565b6130b56040830185612945565b6130c26060830184612945565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffdfea26469706673582212207c74f56d12efb45bd5d41bf7f12ca1a2d6591d7c1aa565b9913c48611dca3b1364736f6c63430008180033

Deployed Bytecode Sourcemap

172673:4755:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26651:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28985:222;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;27753:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173711:239;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;176367:354;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;27604:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172441:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;176729:206;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;37054:89;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;172886:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172971:23;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;174209:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;174677:248;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;27915:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173958:243;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;174523:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;37472:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173084:39;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172918:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172133:195;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172780:51;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166532:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;173001:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;26861:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172838:41;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;176073:286;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172946:18;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;174933:252;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;176943:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;171238:836;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;172723:50;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28483:183;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173042:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;174375:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;26651:91;26696:13;26729:5;26722:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26651:91;:::o;28985:222::-;29085:4;29107:13;29123:12;:10;:12::i;:::-;29107:28;;29146:31;29155:5;29162:7;29171:5;29146:8;:31::i;:::-;29195:4;29188:11;;;28985:222;;;;:::o;27753:99::-;27805:7;27832:12;;27825:19;;27753:99;:::o;173711:239::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;173805:1:::1;173793:8;:13;;:36;;;;;173118:5;173810:8;:19;;173793:36;173785:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;173883:8;173861:19;:30;;;;173907:35;173922:19;;173907:35;;;;;;:::i;:::-;;;;;;;;173711:239:::0;:::o;176367:354::-;176489:4;176506:15;176524:12;:10;:12::i;:::-;176506:30;;176547:37;176563:4;176569:7;176578:5;176547:15;:37::i;:::-;176597:11;176611:35;176630:4;176636:2;176640:5;176611:18;:35::i;:::-;176597:49;;176659:32;176669:4;176675:2;176687:3;176679:5;:11;;;;:::i;:::-;176659:9;:32::i;:::-;176709:4;176702:11;;;;176367:354;;;;;:::o;27604:84::-;27653:5;27678:2;27671:9;;27604:84;:::o;172441:114::-;172500:7;172527:20;:18;:20::i;:::-;172520:27;;172441:114;:::o;176729:206::-;176825:6;;;;;;;;;;;176811:20;;:10;:20;;;:41;;;;176849:3;;;;;;;;;;;176835:17;;:10;:17;;;176811:41;176789:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;176910:17;176916:2;176920:6;176910:5;:17::i;:::-;176729:206;;:::o;37054:89::-;37109:26;37115:12;:10;:12::i;:::-;37129:5;37109;:26::i;:::-;37054:89;:::o;172886:25::-;;;;;;;;;;;;;:::o;172971:23::-;;;;;;;;;;;;;:::o;174209:158::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;174302:9:::1;174291:8;;:20;;;;;;;;;;;;;;;;;;174327:32;174350:8;;;;;;;;;;;174327:32;;;;;;:::i;:::-;;;;;;;;174209:158:::0;:::o;174677:248::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;174833:5:::1;174799:18;:31;174818:11;174799:31;;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;;;174854:63;174872:11;174885:18;:31;174904:11;174885:31;;;;;;;;;;;;;;;;;;;;;;;;;174854:63;;;;;;;:::i;:::-;;;;;;;;174677:248:::0;;:::o;27915:118::-;27980:7;28007:9;:18;28017:7;28007:18;;;;;;;;;;;;;;;;28000:25;;27915:118;;;:::o;173958:243::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;174053:1:::1;174041:8;:13;;:36;;;;;173118:5;174058:8;:19;;174041:36;174033:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;174132:8;174109:20;:31;;;;174156:37;174172:20;;174156:37;;;;;;:::i;:::-;;;;;;;;173958:243:::0;:::o;174523:146::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;174617:5:::1;174598:9;:16;174608:5;174598:16;;;;;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;174638:23;174655:5;174638:23;;;;;;:::i;:::-;;;;;;;;174523:146:::0;:::o;37472:161::-;37548:45;37564:7;37573:12;:10;:12::i;:::-;37587:5;37548:15;:45::i;:::-;37604:21;37610:7;37619:5;37604;:21::i;:::-;37472:161;;:::o;173084:39::-;173118:5;173084:39;:::o;172918:21::-;;;;;;;;;;;;;:::o;172133:195::-;172269:7;172301:19;172314:5;172301:12;:19::i;:::-;172294:26;;172133:195;;;:::o;172780:51::-;;;;;;;;;;;;;;;;;;;;;;:::o;166532:580::-;166635:13;166663:18;166696:21;166732:15;166762:25;166802:12;166829:27;166937:13;:11;:13::i;:::-;166965:16;:14;:16::i;:::-;166996:13;167032:4;167060:1;167052:10;;167091:1;167077:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;166884:220;;;;;;;;;;;;;;;;;;;;;166532:580;;;;;;;:::o;173001:34::-;;;;:::o;26861:95::-;26908:13;26941:7;26934:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26861:95;:::o;172838:41::-;;;;;;;;;;;;;;;;;;;;;;:::o;176073:286::-;176170:4;176192:13;176208:12;:10;:12::i;:::-;176192:28;;176233:11;176247:36;176266:5;176273:2;176277:5;176247:18;:36::i;:::-;176233:50;;176296:33;176306:5;176313:2;176325:3;176317:5;:11;;;;:::i;:::-;176296:9;:33::i;:::-;176347:4;176340:11;;;;176073:286;;;;:::o;172946:18::-;;;;;;;;;;;;;:::o;174933:252::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;175091:5:::1;175056:19;:32;175076:11;175056:32;;;;;;;;;;;;;;;;:40;;;;;;;;;;;;;;;;;;175112:65;175131:11;175144:19;:32;175164:11;175144:32;;;;;;;;;;;;;;;;;;;;;;;;;175112:65;;;;;;;:::i;:::-;;;;;;;;174933:252:::0;;:::o;176943:120::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;177042:13:::1;177029:10;;:26;;;;;;;;;;;;;;;;;;176943:120:::0;:::o;171238:836::-;171468:8;171450:15;:26;171446:99;;;171524:8;171500:33;;;;;;;;;;;:::i;:::-;;;;;;;;171446:99;171557:18;170533:119;171665:5;171689:7;171715:5;171739:16;171749:5;171739:9;:16::i;:::-;171774:8;171602:195;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;171578:230;;;;;;171557:251;;171821:12;171836:28;171853:10;171836:16;:28::i;:::-;171821:43;;171877:14;171894:28;171908:4;171914:1;171917;171920;171894:13;:28::i;:::-;171877:45;;171947:5;171937:15;;:6;:15;;;171933:90;;171997:6;172005:5;171976:35;;;;;;;;;;;;:::i;:::-;;;;;;;;171933:90;172035:31;172044:5;172051:7;172060:5;172035:8;:31::i;:::-;171435:639;;;171238:836;;;;;;;:::o;172723:50::-;;;;;;;;;;;;;;;;;;;;;;:::o;28483:183::-;28599:7;28631:11;:18;28643:5;28631:18;;;;;;;;;;;;;;;:27;28650:7;28631:27;;;;;;;;;;;;;;;;28624:34;;28483:183;;;;:::o;173042:35::-;;;;:::o;174375:140::-;173649:10;;;;;;;;;;;173635:24;;:10;:24;;;173627:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;174466:4:::1;174447:9;:16;174457:5;174447:16;;;;;;;;;;;;;;;;:23;;;;;;;;;;;;;;;;;;174486:21;174501:5;174486:21;;;;;;:::i;:::-;;;;;;;;174375:140:::0;:::o;4508:98::-;4561:7;4588:10;4581:17;;4508:98;:::o;33990:164::-;34109:37;34118:5;34125:7;34134:5;34141:4;34109:8;:37::i;:::-;33990:164;;;:::o;35799:602::-;35933:24;35960:25;35970:5;35977:7;35960:9;:25::i;:::-;35933:52;;36019:17;36000:16;:36;35996:398;;;36076:5;36057:16;:24;36053:214;;;36158:7;36188:16;36227:5;36109:142;;;;;;;;;;;;;:::i;:::-;;;;;;;;36053:214;36310:57;36319:5;36326:7;36354:5;36335:16;:24;36361:5;36310:8;:57::i;:::-;35996:398;35922:479;35799:602;;;:::o;175193:872::-;175314:7;175334:11;175348:1;175334:15;;175438:1;175418:22;;:8;;;;;;;;;;;:22;;;175414:65;;175464:3;175457:10;;;;;175414:65;175495:18;:24;175514:4;175495:24;;;;;;;;;;;;;;;;;;;;;;;;;:44;;;;;175524:9;:15;175534:4;175524:15;;;;;;;;;;;;;;;;;;;;;;;;;175523:16;175495:44;:62;;;;;175544:9;:13;175554:2;175544:13;;;;;;;;;;;;;;;;;;;;;;;;;175543:14;175495:62;175491:544;;;173118:5;175638:19;;175630:5;:27;;;;:::i;:::-;175629:39;;;;:::i;:::-;175623:45;;175683:30;175693:4;175699:8;;;;;;;;;;;175709:3;175683:9;:30::i;:::-;175491:544;;;175796:19;:23;175816:2;175796:23;;;;;;;;;;;;;;;;;;;;;;;;;:43;;;;;175824:9;:15;175834:4;175824:15;;;;;;;;;;;;;;;;;;;;;;;;;175823:16;175796:43;:61;;;;;175844:9;:13;175854:2;175844:13;;;;;;;;;;;;;;;;;;;;;;;;;175843:14;175796:61;175778:257;;;173118:5;175947:20;;175939:5;:28;;;;:::i;:::-;175938:40;;;;:::i;:::-;175932:46;;175993:30;176003:4;176009:8;;;;;;;;;;;176019:3;175993:9;:30::i;:::-;175778:257;175491:544;176054:3;176047:10;;;175193:872;;;;;;:::o;30485:342::-;30619:1;30603:18;;:4;:18;;;30599:88;;30672:1;30645:30;;;;;;;;;;;:::i;:::-;;;;;;;;30599:88;30715:1;30701:16;;:2;:16;;;30697:88;;30770:1;30741:32;;;;;;;;;;;:::i;:::-;;;;;;;;30697:88;30795:24;30803:4;30809:2;30813:5;30795:7;:24::i;:::-;30485:342;;;:::o;164977:268::-;165030:7;165071:11;165054:28;;165062:4;165054:28;;;:63;;;;;165103:14;165086:13;:31;165054:63;165050:188;;;165141:22;165134:29;;;;165050:188;165203:23;:21;:23::i;:::-;165196:30;;164977:268;;:::o;32676:222::-;32766:4;32747:24;;:7;:24;;;32743:99;;32824:4;32795:35;;;;;;;;;;;:::i;:::-;;;;;;;;32743:99;32852:38;32868:4;32875:7;32884:5;32852:7;:38::i;:::-;32676:222;;:::o;33226:211::-;33316:1;33297:21;;:7;:21;;;33293:91;;33369:1;33342:30;;;;;;;;;;;:::i;:::-;;;;;;;;33293:91;33394:35;33402:7;33419:1;33423:5;33394:7;:35::i;:::-;33226:211;;:::o;168673:109::-;168733:7;168760;:14;168768:5;168760:14;;;;;;;;;;;;;;;;168753:21;;168673:109;;;:::o;167441:128::-;167487:13;167520:41;167547:13;167520:5;:26;;:41;;;;:::i;:::-;167513:48;;167441:128;:::o;167904:137::-;167953:13;167986:47;168016:16;167986:8;:29;;:47;;;;:::i;:::-;167979:54;;167904:137;:::o;168903:402::-;168963:7;169270;:14;169278:5;169270:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;169263:23;;168903:402;;;:::o;166245:232::-;166358:7;166403:66;166436:20;:18;:20::i;:::-;166458:10;166403:32;:66::i;:::-;166383:86;;166245:232;;;:::o;49306:370::-;49434:7;49455:17;49474:18;49494:16;49514:88;49539:4;49558:1;49574;49590;49514:10;:88::i;:::-;49454:148;;;;;;49613:28;49625:5;49632:8;49613:11;:28::i;:::-;49659:9;49652:16;;;;;49306:370;;;;;;:::o;35021:486::-;35194:1;35177:19;;:5;:19;;;35173:91;;35249:1;35220:32;;;;;;;;;;;:::i;:::-;;;;;;;;35173:91;35297:1;35278:21;;:7;:21;;;35274:92;;35351:1;35323:31;;;;;;;;;;;:::i;:::-;;;;;;;;35274:92;35406:5;35376:11;:18;35388:5;35376:18;;;;;;;;;;;;;;;:27;35395:7;35376:27;;;;;;;;;;;;;;;:35;;;;35426:9;35422:78;;;35473:7;35457:31;;35466:5;35457:31;;;35482:5;35457:31;;;;;;:::i;:::-;;;;;;;;35422:78;35021:486;;;;:::o;31151:1172::-;31291:4;31275:21;;:4;:21;;;31271:555;;31432:5;31416:12;;:21;;;;;;;:::i;:::-;;;;;;;;31271:555;;;31470:19;31492:9;:15;31502:4;31492:15;;;;;;;;;;;;;;;;31470:37;;31540:5;31526:11;:19;31522:117;;;31598:4;31604:11;31617:5;31573:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;31522:117;31794:5;31780:11;:19;31762:9;:15;31772:4;31762:15;;;;;;;;;;;;;;;:37;;;;31455:371;31271:555;31856:1;31842:16;;:2;:16;;;31838:435;;32024:5;32008:12;;:21;;;;;;;;;;;31838:435;;;32241:5;32224:9;:13;32234:2;32224:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;31838:435;32305:2;32290:25;;32299:4;32290:25;;;32309:5;32290:25;;;;;;:::i;:::-;;;;;;;;31151:1172;;;:::o;165253:350::-;165308:7;163043:119;165441:11;165475:14;165512:13;165556:4;165376:204;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;165348:247;;;;;;165328:267;;165253:350;:::o;159995:305::-;160116:13;157902:66;160180:17;;160170:5;160151:46;160147:146;;160221:15;160230:5;160221:8;:15::i;:::-;160214:22;;;;160147:146;160276:5;160269:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159995:305;;;;;:::o;151311:414::-;151431:14;151520:4;151514:11;151551:10;151546:3;151539:23;151599:15;151592:4;151587:3;151583:14;151576:39;151652:10;151645:4;151640:3;151636:14;151629:34;151702:4;151697:3;151687:20;151677:30;;151488:230;151311:414;;;;:::o;47471:1696::-;47643:17;47675:16;47706:14;48675:66;48657:1;48649:10;;:92;48631:203;;;48784:1;48788:30;48820:1;48768:54;;;;;;;;48631:203;48931:14;48948:24;48958:4;48964:1;48967;48970;48948:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48931:41;;49005:1;48987:20;;:6;:20;;;48983:115;;49040:1;49044:29;49083:1;49075:10;;49024:62;;;;;;;;;48983:115;49118:6;49126:20;49156:1;49148:10;;49110:49;;;;;;;47471:1696;;;;;;;;;:::o;49814:542::-;49910:20;49901:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;49897:452;49947:7;49897:452;50008:29;49999:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;49995:354;;50061:23;;;;;;;;;;;;;;49995:354;50115:35;50106:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;50102:247;;50210:8;50202:17;;50174:46;;;;;;;;;;;:::i;:::-;;;;;;;;50102:247;50251:30;50242:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;50238:111;;50328:8;50305:32;;;;;;;;;;;:::i;:::-;;;;;;;;50238:111;49814:542;;;:::o;158643:387::-;158702:13;158728:11;158742:16;158753:4;158742:10;:16::i;:::-;158728:30;;158848:17;158879:2;158868:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158848:34;;158945:3;158940;158933:16;158986:4;158979;158974:3;158970:14;158963:28;159019:3;159012:10;;;;158643:387;;;:::o;159107:251::-;159168:7;159188:14;159241:4;159232;159205:33;;:40;159188:57;;159269:2;159260:6;:11;159256:71;;;159295:20;;;;;;;;;;;;;;159256:71;159344:6;159337:13;;;159107:251;;;:::o;7:99:1:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1430:117::-;1539:1;1536;1529:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:118::-;3533:24;3551:5;3533:24;:::i;:::-;3528:3;3521:37;3446:118;;:::o;3570:222::-;3663:4;3701:2;3690:9;3686:18;3678:26;;3714:71;3782:1;3771:9;3767:17;3758:6;3714:71;:::i;:::-;3570:222;;;;:::o;3798:329::-;3857:6;3906:2;3894:9;3885:7;3881:23;3877:32;3874:119;;;3912:79;;:::i;:::-;3874:119;4032:1;4057:53;4102:7;4093:6;4082:9;4078:22;4057:53;:::i;:::-;4047:63;;4003:117;3798:329;;;;:::o;4133:619::-;4210:6;4218;4226;4275:2;4263:9;4254:7;4250:23;4246:32;4243:119;;;4281:79;;:::i;:::-;4243:119;4401:1;4426:53;4471:7;4462:6;4451:9;4447:22;4426:53;:::i;:::-;4416:63;;4372:117;4528:2;4554:53;4599:7;4590:6;4579:9;4575:22;4554:53;:::i;:::-;4544:63;;4499:118;4656:2;4682:53;4727:7;4718:6;4707:9;4703:22;4682:53;:::i;:::-;4672:63;;4627:118;4133:619;;;;;:::o;4758:86::-;4793:7;4833:4;4826:5;4822:16;4811:27;;4758:86;;;:::o;4850:112::-;4933:22;4949:5;4933:22;:::i;:::-;4928:3;4921:35;4850:112;;:::o;4968:214::-;5057:4;5095:2;5084:9;5080:18;5072:26;;5108:67;5172:1;5161:9;5157:17;5148:6;5108:67;:::i;:::-;4968:214;;;;:::o;5188:77::-;5225:7;5254:5;5243:16;;5188:77;;;:::o;5271:118::-;5358:24;5376:5;5358:24;:::i;:::-;5353:3;5346:37;5271:118;;:::o;5395:222::-;5488:4;5526:2;5515:9;5511:18;5503:26;;5539:71;5607:1;5596:9;5592:17;5583:6;5539:71;:::i;:::-;5395:222;;;;:::o;5623:118::-;5710:24;5728:5;5710:24;:::i;:::-;5705:3;5698:37;5623:118;;:::o;5747:222::-;5840:4;5878:2;5867:9;5863:18;5855:26;;5891:71;5959:1;5948:9;5944:17;5935:6;5891:71;:::i;:::-;5747:222;;;;:::o;5975:329::-;6034:6;6083:2;6071:9;6062:7;6058:23;6054:32;6051:119;;;6089:79;;:::i;:::-;6051:119;6209:1;6234:53;6279:7;6270:6;6259:9;6255:22;6234:53;:::i;:::-;6224:63;;6180:117;5975:329;;;;:::o;6310:116::-;6380:21;6395:5;6380:21;:::i;:::-;6373:5;6370:32;6360:60;;6416:1;6413;6406:12;6360:60;6310:116;:::o;6432:133::-;6475:5;6513:6;6500:20;6491:29;;6529:30;6553:5;6529:30;:::i;:::-;6432:133;;;;:::o;6571:468::-;6636:6;6644;6693:2;6681:9;6672:7;6668:23;6664:32;6661:119;;;6699:79;;:::i;:::-;6661:119;6819:1;6844:53;6889:7;6880:6;6869:9;6865:22;6844:53;:::i;:::-;6834:63;;6790:117;6946:2;6972:50;7014:7;7005:6;6994:9;6990:22;6972:50;:::i;:::-;6962:60;;6917:115;6571:468;;;;;:::o;7045:149::-;7081:7;7121:66;7114:5;7110:78;7099:89;;7045:149;;;:::o;7200:115::-;7285:23;7302:5;7285:23;:::i;:::-;7280:3;7273:36;7200:115;;:::o;7321:114::-;7388:6;7422:5;7416:12;7406:22;;7321:114;;;:::o;7441:184::-;7540:11;7574:6;7569:3;7562:19;7614:4;7609:3;7605:14;7590:29;;7441:184;;;;:::o;7631:132::-;7698:4;7721:3;7713:11;;7751:4;7746:3;7742:14;7734:22;;7631:132;;;:::o;7769:108::-;7846:24;7864:5;7846:24;:::i;:::-;7841:3;7834:37;7769:108;;:::o;7883:179::-;7952:10;7973:46;8015:3;8007:6;7973:46;:::i;:::-;8051:4;8046:3;8042:14;8028:28;;7883:179;;;;:::o;8068:113::-;8138:4;8170;8165:3;8161:14;8153:22;;8068:113;;;:::o;8217:732::-;8336:3;8365:54;8413:5;8365:54;:::i;:::-;8435:86;8514:6;8509:3;8435:86;:::i;:::-;8428:93;;8545:56;8595:5;8545:56;:::i;:::-;8624:7;8655:1;8640:284;8665:6;8662:1;8659:13;8640:284;;;8741:6;8735:13;8768:63;8827:3;8812:13;8768:63;:::i;:::-;8761:70;;8854:60;8907:6;8854:60;:::i;:::-;8844:70;;8700:224;8687:1;8684;8680:9;8675:14;;8640:284;;;8644:14;8940:3;8933:10;;8341:608;;;8217:732;;;;:::o;8955:1215::-;9304:4;9342:3;9331:9;9327:19;9319:27;;9356:69;9422:1;9411:9;9407:17;9398:6;9356:69;:::i;:::-;9472:9;9466:4;9462:20;9457:2;9446:9;9442:18;9435:48;9500:78;9573:4;9564:6;9500:78;:::i;:::-;9492:86;;9625:9;9619:4;9615:20;9610:2;9599:9;9595:18;9588:48;9653:78;9726:4;9717:6;9653:78;:::i;:::-;9645:86;;9741:72;9809:2;9798:9;9794:18;9785:6;9741:72;:::i;:::-;9823:73;9891:3;9880:9;9876:19;9867:6;9823:73;:::i;:::-;9906;9974:3;9963:9;9959:19;9950:6;9906:73;:::i;:::-;10027:9;10021:4;10017:20;10011:3;10000:9;9996:19;9989:49;10055:108;10158:4;10149:6;10055:108;:::i;:::-;10047:116;;8955:1215;;;;;;;;;;:::o;10176:118::-;10247:22;10263:5;10247:22;:::i;:::-;10240:5;10237:33;10227:61;;10284:1;10281;10274:12;10227:61;10176:118;:::o;10300:135::-;10344:5;10382:6;10369:20;10360:29;;10398:31;10423:5;10398:31;:::i;:::-;10300:135;;;;:::o;10441:122::-;10514:24;10532:5;10514:24;:::i;:::-;10507:5;10504:35;10494:63;;10553:1;10550;10543:12;10494:63;10441:122;:::o;10569:139::-;10615:5;10653:6;10640:20;10631:29;;10669:33;10696:5;10669:33;:::i;:::-;10569:139;;;;:::o;10714:1199::-;10825:6;10833;10841;10849;10857;10865;10873;10922:3;10910:9;10901:7;10897:23;10893:33;10890:120;;;10929:79;;:::i;:::-;10890:120;11049:1;11074:53;11119:7;11110:6;11099:9;11095:22;11074:53;:::i;:::-;11064:63;;11020:117;11176:2;11202:53;11247:7;11238:6;11227:9;11223:22;11202:53;:::i;:::-;11192:63;;11147:118;11304:2;11330:53;11375:7;11366:6;11355:9;11351:22;11330:53;:::i;:::-;11320:63;;11275:118;11432:2;11458:53;11503:7;11494:6;11483:9;11479:22;11458:53;:::i;:::-;11448:63;;11403:118;11560:3;11587:51;11630:7;11621:6;11610:9;11606:22;11587:51;:::i;:::-;11577:61;;11531:117;11687:3;11714:53;11759:7;11750:6;11739:9;11735:22;11714:53;:::i;:::-;11704:63;;11658:119;11816:3;11843:53;11888:7;11879:6;11868:9;11864:22;11843:53;:::i;:::-;11833:63;;11787:119;10714:1199;;;;;;;;;;:::o;11919:474::-;11987:6;11995;12044:2;12032:9;12023:7;12019:23;12015:32;12012:119;;;12050:79;;:::i;:::-;12012:119;12170:1;12195:53;12240:7;12231:6;12220:9;12216:22;12195:53;:::i;:::-;12185:63;;12141:117;12297:2;12323:53;12368:7;12359:6;12348:9;12344:22;12323:53;:::i;:::-;12313:63;;12268:118;11919:474;;;;;:::o;12399:180::-;12447:77;12444:1;12437:88;12544:4;12541:1;12534:15;12568:4;12565:1;12558:15;12585:320;12629:6;12666:1;12660:4;12656:12;12646:22;;12713:1;12707:4;12703:12;12734:18;12724:81;;12790:4;12782:6;12778:17;12768:27;;12724:81;12852:2;12844:6;12841:14;12821:18;12818:38;12815:84;;12871:18;;:::i;:::-;12815:84;12636:269;12585:320;;;:::o;12911:169::-;13051:21;13047:1;13039:6;13035:14;13028:45;12911:169;:::o;13086:366::-;13228:3;13249:67;13313:2;13308:3;13249:67;:::i;:::-;13242:74;;13325:93;13414:3;13325:93;:::i;:::-;13443:2;13438:3;13434:12;13427:19;;13086:366;;;:::o;13458:419::-;13624:4;13662:2;13651:9;13647:18;13639:26;;13711:9;13705:4;13701:20;13697:1;13686:9;13682:17;13675:47;13739:131;13865:4;13739:131;:::i;:::-;13731:139;;13458:419;;;:::o;13883:166::-;14023:18;14019:1;14011:6;14007:14;14000:42;13883:166;:::o;14055:366::-;14197:3;14218:67;14282:2;14277:3;14218:67;:::i;:::-;14211:74;;14294:93;14383:3;14294:93;:::i;:::-;14412:2;14407:3;14403:12;14396:19;;14055:366;;;:::o;14427:419::-;14593:4;14631:2;14620:9;14616:18;14608:26;;14680:9;14674:4;14670:20;14666:1;14655:9;14651:17;14644:47;14708:131;14834:4;14708:131;:::i;:::-;14700:139;;14427:419;;;:::o;14852:180::-;14900:77;14897:1;14890:88;14997:4;14994:1;14987:15;15021:4;15018:1;15011:15;15038:194;15078:4;15098:20;15116:1;15098:20;:::i;:::-;15093:25;;15132:20;15150:1;15132:20;:::i;:::-;15127:25;;15176:1;15173;15169:9;15161:17;;15200:1;15194:4;15191:11;15188:37;;;15205:18;;:::i;:::-;15188:37;15038:194;;;;:::o;15238:320::-;15353:4;15391:2;15380:9;15376:18;15368:26;;15404:71;15472:1;15461:9;15457:17;15448:6;15404:71;:::i;:::-;15485:66;15547:2;15536:9;15532:18;15523:6;15485:66;:::i;:::-;15238:320;;;;;:::o;15564:180::-;15612:77;15609:1;15602:88;15709:4;15706:1;15699:15;15733:4;15730:1;15723:15;15750:775;15983:4;16021:3;16010:9;16006:19;15998:27;;16035:71;16103:1;16092:9;16088:17;16079:6;16035:71;:::i;:::-;16116:72;16184:2;16173:9;16169:18;16160:6;16116:72;:::i;:::-;16198;16266:2;16255:9;16251:18;16242:6;16198:72;:::i;:::-;16280;16348:2;16337:9;16333:18;16324:6;16280:72;:::i;:::-;16362:73;16430:3;16419:9;16415:19;16406:6;16362:73;:::i;:::-;16445;16513:3;16502:9;16498:19;16489:6;16445:73;:::i;:::-;15750:775;;;;;;;;;:::o;16531:332::-;16652:4;16690:2;16679:9;16675:18;16667:26;;16703:71;16771:1;16760:9;16756:17;16747:6;16703:71;:::i;:::-;16784:72;16852:2;16841:9;16837:18;16828:6;16784:72;:::i;:::-;16531:332;;;;;:::o;16869:442::-;17018:4;17056:2;17045:9;17041:18;17033:26;;17069:71;17137:1;17126:9;17122:17;17113:6;17069:71;:::i;:::-;17150:72;17218:2;17207:9;17203:18;17194:6;17150:72;:::i;:::-;17232;17300:2;17289:9;17285:18;17276:6;17232:72;:::i;:::-;16869:442;;;;;;:::o;17317:410::-;17357:7;17380:20;17398:1;17380:20;:::i;:::-;17375:25;;17414:20;17432:1;17414:20;:::i;:::-;17409:25;;17469:1;17466;17462:9;17491:30;17509:11;17491:30;:::i;:::-;17480:41;;17670:1;17661:7;17657:15;17654:1;17651:22;17631:1;17624:9;17604:83;17581:139;;17700:18;;:::i;:::-;17581:139;17365:362;17317:410;;;;:::o;17733:180::-;17781:77;17778:1;17771:88;17878:4;17875:1;17868:15;17902:4;17899:1;17892:15;17919:185;17959:1;17976:20;17994:1;17976:20;:::i;:::-;17971:25;;18010:20;18028:1;18010:20;:::i;:::-;18005:25;;18049:1;18039:35;;18054:18;;:::i;:::-;18039:35;18096:1;18093;18089:9;18084:14;;17919:185;;;;:::o;18110:191::-;18150:3;18169:20;18187:1;18169:20;:::i;:::-;18164:25;;18203:20;18221:1;18203:20;:::i;:::-;18198:25;;18246:1;18243;18239:9;18232:16;;18267:3;18264:1;18261:10;18258:36;;;18274:18;;:::i;:::-;18258:36;18110:191;;;;:::o;18307:664::-;18512:4;18550:3;18539:9;18535:19;18527:27;;18564:71;18632:1;18621:9;18617:17;18608:6;18564:71;:::i;:::-;18645:72;18713:2;18702:9;18698:18;18689:6;18645:72;:::i;:::-;18727;18795:2;18784:9;18780:18;18771:6;18727:72;:::i;:::-;18809;18877:2;18866:9;18862:18;18853:6;18809:72;:::i;:::-;18891:73;18959:3;18948:9;18944:19;18935:6;18891:73;:::i;:::-;18307:664;;;;;;;;:::o;18977:545::-;19150:4;19188:3;19177:9;19173:19;19165:27;;19202:71;19270:1;19259:9;19255:17;19246:6;19202:71;:::i;:::-;19283:68;19347:2;19336:9;19332:18;19323:6;19283:68;:::i;:::-;19361:72;19429:2;19418:9;19414:18;19405:6;19361:72;:::i;:::-;19443;19511:2;19500:9;19496:18;19487:6;19443:72;:::i;:::-;18977:545;;;;;;;:::o;19528:180::-;19576:77;19573:1;19566:88;19673:4;19670:1;19663:15;19697:4;19694:1;19687:15

Swarm Source

ipfs://7c74f56d12efb45bd5d41bf7f12ca1a2d6591d7c1aa565b9913c48611dca3b13
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.