ETH Price: $2,958.91 (+0.94%)
Gas: 3 Gwei

Token

Wrapped AI Power Grid (wAIPG)
 

Overview

Max Total Supply

1,690.33769814 wAIPG

Holders

7

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
WrappedAIPG

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-06-06
*/

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

    /**
     * @dev Returns the 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/IERC20Metadata.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;


/**
 * @dev Interface for the optional metadata functions from the ERC20 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/utils/Context.sol


// 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/interfaces/draft-IERC6093.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol


// OpenZeppelin Contracts (last updated v5.0.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 ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these 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}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * 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(0)) {
            // 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(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), 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:
     * ```
     * 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/access/IAccessControl.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 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 signaling 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, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    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/introspection/IERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP 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/ERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 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/AccessControl.sol


// OpenZeppelin Contracts (last updated v5.0.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 account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => 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` to `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/security/Pausable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

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

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

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

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

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;



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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol


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

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

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

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

// File: @openzeppelin/contracts/utils/StorageSlot.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

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

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/ShortStrings.sol


// OpenZeppelin Contracts (last updated v5.0.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);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

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

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

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

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

// File: @openzeppelin/contracts/interfaces/IERC5267.sol


// 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/cryptography/EIP712.sol


// OpenZeppelin Contracts (last updated v5.0.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;
    string private _nameFallback;
    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);
    }

    /**
     * @dev See {IERC-5267}.
     */
    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/cryptography/draft-EIP712.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

// EIP-712 is Final as of 2022-08-11. This file is deprecated.


// File: wAIPG_final.sol


pragma solidity ^0.8.20;

// Importing necessary OpenZeppelin contracts for ERC20 token, access control, pausing functionality, and EIP712 standard





// WrappedAIPG is an ERC20 token with additional features like access control and pausability
contract WrappedAIPG is ERC20, AccessControl, Pausable, EIP712 {
    // Role definition for minters using a unique hash
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    // Hash for the minting function to ensure correct function is called with EIP712
    bytes32 private constant MINT_TYPEHASH = keccak256("MintRequest(address to,uint256 amount,uint256 uuid,uint256 deadline)");
    // Account that will collect transaction fees
    address public feeAccount;
    // Initial fee percentage set at 3%
    uint256 public feePercent = 3;
    // Maximum fee percentage allowed
    uint256 public constant MAX_FEE = 5;

    // Mapping to store used UUIDs
    mapping(bytes32 => bool) private usedUUIDs;

    // Struct to define the mint request parameters
    struct MintRequest {
        address to;
        uint256 amount;
        uint256 uuid;
        uint256 deadline;
    }

    // Constructor to initialize the ERC20 token and set initial roles and fee account
    constructor() 
        ERC20("Wrapped AI Power Grid", "wAIPG") 
        EIP712("WrappedAIPowerGrid", "1") 
    {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); // Granting admin role to the contract deployer
        _grantRole(MINTER_ROLE, msg.sender); // Granting minter role to the contract deployer
        feeAccount = msg.sender; // Setting the fee account to the contract deployer initially
    }

    // Function to set the fee account, only accessible by admin
    function setFeeAccount(address _feeAccount) external onlyRole(DEFAULT_ADMIN_ROLE) {
        feeAccount = _feeAccount;
    }

    // Function to set the fee percentage, only accessible by admin and with checks for maximum fee limit
    function setFeePercent(uint256 _feePercent) external onlyRole(DEFAULT_ADMIN_ROLE) {
        require(_feePercent <= MAX_FEE, "Fee percent too high");
        feePercent = _feePercent;
    }

    // Function to transfer tokens with fee deduction
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        uint256 fee = (amount * feePercent) / 100;
        uint256 amountAfterFee = amount - fee;
        super.transfer(feeAccount, fee); // Transfer the fee
        super.transfer(recipient, amountAfterFee); // Transfer the net amount
        return true;
    }

    // Function to mint tokens using a signed request, ensuring it's within the deadline and the signature is valid
    function mint(MintRequest calldata request, uint8 v, bytes32 r, bytes32 s) public {
        require(block.timestamp <= request.deadline, "Expired deadline");
        bytes32 structHash = keccak256(abi.encode(MINT_TYPEHASH, request.to, request.amount, request.uuid, request.deadline));
        bytes32 digest = _hashTypedDataV4(structHash);
        address signer = ecrecover(digest, v, r, s);
        require(hasRole(MINTER_ROLE, signer), "Invalid signature or unauthorized");

        // Check if the UUID has already been used
        bytes32 transactionHash = keccak256(abi.encodePacked(request.to, request.amount, request.uuid, block.chainid));
        require(!usedUUIDs[transactionHash], "UUID already used");

        // Mark this UUID as used
        usedUUIDs[transactionHash] = true;

        _mint(request.to, request.amount); // Mint the full amount to the requester
    }
    
    // Function to burn tokens, reducing the total supply
    function burn(uint256 amount) public {
        _burn(msg.sender, amount); // Burn the specified amount of tokens from the caller's balance
    }

    // Function to pause the contract, only accessible by admin
    function pause() public onlyRole(DEFAULT_ADMIN_ROLE) {
        _pause();
    }

    // Function to unpause the contract, only accessible by admin
    function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) {
        _unpause();
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"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":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","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":"amount","type":"uint256"}],"name":"burn","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":"feeAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"uuid","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct WrappedAIPG.MintRequest","name":"request","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeAccount","type":"address"}],"name":"setFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feePercent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"recipient","type":"address"},{"internalType":"uint256","name":"amount","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101606040526003600a5534801562000016575f80fd5b506040518060400160405280601281526020017f577261707065644149506f7765724772696400000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601581526020017f5772617070656420414920506f776572204772696400000000000000000000008152506040518060400160405280600581526020017f774149504700000000000000000000000000000000000000000000000000000081525081600390816200010091906200075b565b5080600490816200011291906200075b565b5050505f60065f6101000a81548160ff021916908315150217905550620001446007836200026c60201b90919060201c565b6101208181525050620001626008826200026c60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a08181525050620001a1620002c160201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050620001f25f801b336200031d60201b60201c565b50620002257f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200031d60201b60201c565b503360095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000a52565b5f602083511015620002915762000289836200041960201b60201c565b9050620002bb565b82620002a3836200048360201b60201c565b5f019081620002b391906200075b565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e05161010051463060405160200162000302959493929190620008ad565b60405160208183030381529060405280519060200120905090565b5f6200033083836200048c60201b60201c565b6200040f57600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550620003ab620004f060201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001905062000413565b5f90505b92915050565b5f80829050601f815111156200046857826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016200045f919062000992565b60405180910390fd5b8051816200047690620009e3565b5f1c175f1b915050919050565b5f819050919050565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200057357607f821691505b6020821081036200058957620005886200052e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620005ed7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620005b0565b620005f98683620005b0565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620006436200063d620006378462000611565b6200061a565b62000611565b9050919050565b5f819050919050565b6200065e8362000623565b620006766200066d826200064a565b848454620005bc565b825550505050565b5f90565b6200068c6200067e565b6200069981848462000653565b505050565b5b81811015620006c057620006b45f8262000682565b6001810190506200069f565b5050565b601f8211156200070f57620006d9816200058f565b620006e484620005a1565b81016020851015620006f4578190505b6200070c6200070385620005a1565b8301826200069e565b50505b505050565b5f82821c905092915050565b5f620007315f198460080262000714565b1980831691505092915050565b5f6200074b838362000720565b9150826002028217905092915050565b6200076682620004f7565b67ffffffffffffffff81111562000782576200078162000501565b5b6200078e82546200055b565b6200079b828285620006c4565b5f60209050601f831160018114620007d1575f8415620007bc578287015190505b620007c885826200073e565b86555062000837565b601f198416620007e1866200058f565b5f5b828110156200080a57848901518255600182019150602085019450602081019050620007e3565b868310156200082a578489015162000826601f89168262000720565b8355505b6001600288020188555050505b505050505050565b5f819050919050565b62000853816200083f565b82525050565b620008648162000611565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000895826200086a565b9050919050565b620008a78162000889565b82525050565b5f60a082019050620008c25f83018862000848565b620008d1602083018762000848565b620008e0604083018662000848565b620008ef606083018562000859565b620008fe60808301846200089c565b9695505050505050565b5f82825260208201905092915050565b5f5b83811015620009375780820151818401526020810190506200091a565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6200095e82620004f7565b6200096a818562000908565b93506200097c81856020860162000918565b620009878162000942565b840191505092915050565b5f6020820190508181035f830152620009ac818462000952565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f620009da82516200083f565b80915050919050565b5f620009ef82620009b4565b82620009fb84620009be565b905062000a0881620009cd565b9250602082101562000a4b5762000a467fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802620005b0565b831692505b5050919050565b60805160a05160c05160e05161010051610120516101405161296362000aa45f395f6113be01525f61138301525f611bd001525f611baf01525f611a2601525f611a7c01525f611aa501526129635ff3fe608060405234801561000f575f80fd5b50600436106101c2575f3560e01c806370a08231116100f7578063966e2a4611610095578063bc063e1a1161006f578063bc063e1a146104e6578063d539139314610504578063d547741f14610522578063dd62ed3e1461053e576101c2565b8063966e2a461461047c578063a217fddf14610498578063a9059cbb146104b6576101c2565b80638456cb59116100d15780638456cb591461040057806384b0196e1461040a57806391d148541461042e57806395d89b411461045e576101c2565b806370a08231146103965780637ce3489b146103c65780637fd6f15c146103e2576101c2565b8063313ce5671161016457806342966c681161013e57806342966c68146103225780634b023cf81461033e5780635c975abb1461035a57806365e17c9d14610378576101c2565b8063313ce567146102de57806336568abe146102fc5780633f4ba83a14610318576101c2565b806318160ddd116101a057806318160ddd1461024457806323b872dd14610262578063248a9ca3146102925780632f2ff15d146102c2576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063095ea7b314610214575b5f80fd5b6101e060048036038101906101db9190611cc7565b61056e565b6040516101ed9190611d0c565b60405180910390f35b6101fe6105e7565b60405161020b9190611daf565b60405180910390f35b61022e60048036038101906102299190611e5c565b610677565b60405161023b9190611d0c565b60405180910390f35b61024c610699565b6040516102599190611ea9565b60405180910390f35b61027c60048036038101906102779190611ec2565b6106a2565b6040516102899190611d0c565b60405180910390f35b6102ac60048036038101906102a79190611f45565b6106d0565b6040516102b99190611f7f565b60405180910390f35b6102dc60048036038101906102d79190611f98565b6106ed565b005b6102e661070f565b6040516102f39190611ff1565b60405180910390f35b61031660048036038101906103119190611f98565b610717565b005b610320610792565b005b61033c6004803603810190610337919061200a565b6107a9565b005b61035860048036038101906103539190612035565b6107b6565b005b610362610806565b60405161036f9190611d0c565b60405180910390f35b61038061081b565b60405161038d919061206f565b60405180910390f35b6103b060048036038101906103ab9190612035565b610840565b6040516103bd9190611ea9565b60405180910390f35b6103e060048036038101906103db919061200a565b610885565b005b6103ea6108e0565b6040516103f79190611ea9565b60405180910390f35b6104086108e6565b005b6104126108fd565b6040516104259796959493929190612179565b60405180910390f35b61044860048036038101906104439190611f98565b6109a2565b6040516104559190611d0c565b60405180910390f35b610466610a06565b6040516104739190611daf565b60405180910390f35b61049660048036038101906104919190612247565b610a96565b005b6104a0610d09565b6040516104ad9190611f7f565b60405180910390f35b6104d060048036038101906104cb9190611e5c565b610d0f565b6040516104dd9190611d0c565b60405180910390f35b6104ee610d7f565b6040516104fb9190611ea9565b60405180910390f35b61050c610d84565b6040516105199190611f7f565b60405180910390f35b61053c60048036038101906105379190611f98565b610da8565b005b610558600480360381019061055391906122ab565b610dca565b6040516105659190611ea9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105e057506105df82610e4c565b5b9050919050565b6060600380546105f690612316565b80601f016020809104026020016040519081016040528092919081815260200182805461062290612316565b801561066d5780601f106106445761010080835404028352916020019161066d565b820191905f5260205f20905b81548152906001019060200180831161065057829003601f168201915b5050505050905090565b5f80610681610eb5565b905061068e818585610ebc565b600191505092915050565b5f600254905090565b5f806106ac610eb5565b90506106b9858285610ece565b6106c4858585610f60565b60019150509392505050565b5f60055f8381526020019081526020015f20600101549050919050565b6106f6826106d0565b6106ff81611050565b6107098383611064565b50505050565b5f6012905090565b61071f610eb5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610783576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61078d828261114e565b505050565b5f801b61079e81611050565b6107a6611238565b50565b6107b33382611299565b50565b5f801b6107c281611050565b8160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60065f9054906101000a900460ff16905090565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f801b61089181611050565b60058211156108d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cc90612390565b60405180910390fd5b81600a819055505050565b600a5481565b5f801b6108f281611050565b6108fa611318565b50565b5f6060805f805f606061090e61137a565b6109166113b5565b46305f801b5f67ffffffffffffffff811115610935576109346123ae565b5b6040519080825280602002602001820160405280156109635781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b606060048054610a1590612316565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190612316565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050905090565b8360600135421115610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad490612425565b60405180910390fd5b5f7f05dac90127b5beea9d6bac8bf6962ef964e99f78ca9a5ee126ed3158f14d003c855f016020810190610b119190612035565b866020013587604001358860600135604051602001610b34959493929190612443565b6040516020818303038152906040528051906020012090505f610b56826113f0565b90505f6001828787876040515f8152602001604052604051610b7b9493929190612494565b6020604051602081039080840390855afa158015610b9b573d5f803e3d5ffd5b505050602060405103519050610bd17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6826109a2565b610c10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0790612547565b60405180910390fd5b5f875f016020810190610c239190612035565b8860200135896040013546604051602001610c4194939291906125ca565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1615610cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cae90612661565b60405180910390fd5b6001600b5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610cff885f016020810190610cf59190612035565b8960200135611409565b5050505050505050565b5f801b81565b5f806064600a5484610d2191906126ac565b610d2b919061271a565b90505f8184610d3a919061274a565b9050610d6760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611488565b50610d728582611488565b5060019250505092915050565b600581565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610db1826106d0565b610dba81611050565b610dc4838361114e565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610ec983838360016114aa565b505050565b5f610ed98484610dca565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f5a5781811015610f4b578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610f429392919061277d565b60405180910390fd5b610f5984848484035f6114aa565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd0575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610fc7919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611040575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611037919061206f565b60405180910390fd5b61104b838383611679565b505050565b6110618161105c610eb5565b611892565b50565b5f61106f83836109a2565b61114457600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506110e1610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611148565b5f90505b92915050565b5f61115983836109a2565b1561122e575f60055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506111cb610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611232565b5f90505b92915050565b6112406118e3565b5f60065f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611282610eb5565b60405161128f919061206f565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611309575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611300919061206f565b60405180910390fd5b611314825f83611679565b5050565b61132061192c565b600160065f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611363610eb5565b604051611370919061206f565b60405180910390a1565b60606113b060077f000000000000000000000000000000000000000000000000000000000000000061197690919063ffffffff16565b905090565b60606113eb60087f000000000000000000000000000000000000000000000000000000000000000061197690919063ffffffff16565b905090565b5f6114026113fc611a23565b83611ad9565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611479575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611470919061206f565b60405180910390fd5b6114845f8383611679565b5050565b5f80611492610eb5565b905061149f818585610f60565b600191505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361151a575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611511919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158a575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611581919061206f565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611673578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161166a9190611ea9565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116c9578060025f8282546116bd91906127b2565b92505081905550611797565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611752578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016117499392919061277d565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117de578060025f8282540392505081905550611828565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516118859190611ea9565b60405180910390a3505050565b61189c82826109a2565b6118df5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016118d69291906127e5565b60405180910390fd5b5050565b6118eb610806565b61192a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192190612856565b60405180910390fd5b565b611934610806565b15611974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196b906128be565b60405180910390fd5b565b606060ff5f1b83146119925761198b83611b19565b9050611a1d565b81805461199e90612316565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca90612316565b8015611a155780601f106119ec57610100808354040283529160200191611a15565b820191905f5260205f20905b8154815290600101906020018083116119f857829003601f168201915b505050505090505b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611a9e57507f000000000000000000000000000000000000000000000000000000000000000046145b15611acb577f00000000000000000000000000000000000000000000000000000000000000009050611ad6565b611ad3611b8b565b90505b90565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60605f611b2583611c20565b90505f602067ffffffffffffffff811115611b4357611b426123ae565b5b6040519080825280601f01601f191660200182016040528015611b755781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001611c059594939291906128dc565b60405160208183030381529060405280519060200120905090565b5f8060ff835f1c169050601f811115611c65576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611ca681611c72565b8114611cb0575f80fd5b50565b5f81359050611cc181611c9d565b92915050565b5f60208284031215611cdc57611cdb611c6e565b5b5f611ce984828501611cb3565b91505092915050565b5f8115159050919050565b611d0681611cf2565b82525050565b5f602082019050611d1f5f830184611cfd565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611d5c578082015181840152602081019050611d41565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d8182611d25565b611d8b8185611d2f565b9350611d9b818560208601611d3f565b611da481611d67565b840191505092915050565b5f6020820190508181035f830152611dc78184611d77565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611df882611dcf565b9050919050565b611e0881611dee565b8114611e12575f80fd5b50565b5f81359050611e2381611dff565b92915050565b5f819050919050565b611e3b81611e29565b8114611e45575f80fd5b50565b5f81359050611e5681611e32565b92915050565b5f8060408385031215611e7257611e71611c6e565b5b5f611e7f85828601611e15565b9250506020611e9085828601611e48565b9150509250929050565b611ea381611e29565b82525050565b5f602082019050611ebc5f830184611e9a565b92915050565b5f805f60608486031215611ed957611ed8611c6e565b5b5f611ee686828701611e15565b9350506020611ef786828701611e15565b9250506040611f0886828701611e48565b9150509250925092565b5f819050919050565b611f2481611f12565b8114611f2e575f80fd5b50565b5f81359050611f3f81611f1b565b92915050565b5f60208284031215611f5a57611f59611c6e565b5b5f611f6784828501611f31565b91505092915050565b611f7981611f12565b82525050565b5f602082019050611f925f830184611f70565b92915050565b5f8060408385031215611fae57611fad611c6e565b5b5f611fbb85828601611f31565b9250506020611fcc85828601611e15565b9150509250929050565b5f60ff82169050919050565b611feb81611fd6565b82525050565b5f6020820190506120045f830184611fe2565b92915050565b5f6020828403121561201f5761201e611c6e565b5b5f61202c84828501611e48565b91505092915050565b5f6020828403121561204a57612049611c6e565b5b5f61205784828501611e15565b91505092915050565b61206981611dee565b82525050565b5f6020820190506120825f830184612060565b92915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6120bc81612088565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6120f481611e29565b82525050565b5f61210583836120eb565b60208301905092915050565b5f602082019050919050565b5f612127826120c2565b61213181856120cc565b935061213c836120dc565b805f5b8381101561216c57815161215388826120fa565b975061215e83612111565b92505060018101905061213f565b5085935050505092915050565b5f60e08201905061218c5f83018a6120b3565b818103602083015261219e8189611d77565b905081810360408301526121b28188611d77565b90506121c16060830187611e9a565b6121ce6080830186612060565b6121db60a0830185611f70565b81810360c08301526121ed818461211d565b905098975050505050505050565b5f80fd5b5f60808284031215612214576122136121fb565b5b81905092915050565b61222681611fd6565b8114612230575f80fd5b50565b5f813590506122418161221d565b92915050565b5f805f8060e0858703121561225f5761225e611c6e565b5b5f61226c878288016121ff565b945050608061227d87828801612233565b93505060a061228e87828801611f31565b92505060c061229f87828801611f31565b91505092959194509250565b5f80604083850312156122c1576122c0611c6e565b5b5f6122ce85828601611e15565b92505060206122df85828601611e15565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061232d57607f821691505b6020821081036123405761233f6122e9565b5b50919050565b7f4665652070657263656e7420746f6f20686967680000000000000000000000005f82015250565b5f61237a601483611d2f565b915061238582612346565b602082019050919050565b5f6020820190508181035f8301526123a78161236e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4578706972656420646561646c696e65000000000000000000000000000000005f82015250565b5f61240f601083611d2f565b915061241a826123db565b602082019050919050565b5f6020820190508181035f83015261243c81612403565b9050919050565b5f60a0820190506124565f830188611f70565b6124636020830187612060565b6124706040830186611e9a565b61247d6060830185611e9a565b61248a6080830184611e9a565b9695505050505050565b5f6080820190506124a75f830187611f70565b6124b46020830186611fe2565b6124c16040830185611f70565b6124ce6060830184611f70565b95945050505050565b7f496e76616c6964207369676e6174757265206f7220756e617574686f72697a655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f612531602183611d2f565b915061253c826124d7565b604082019050919050565b5f6020820190508181035f83015261255e81612525565b9050919050565b5f8160601b9050919050565b5f61257b82612565565b9050919050565b5f61258c82612571565b9050919050565b6125a461259f82611dee565b612582565b82525050565b5f819050919050565b6125c46125bf82611e29565b6125aa565b82525050565b5f6125d58287612593565b6014820191506125e582866125b3565b6020820191506125f582856125b3565b60208201915061260582846125b3565b60208201915081905095945050505050565b7f5555494420616c726561647920757365640000000000000000000000000000005f82015250565b5f61264b601183611d2f565b915061265682612617565b602082019050919050565b5f6020820190508181035f8301526126788161263f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126b682611e29565b91506126c183611e29565b92508282026126cf81611e29565b915082820484148315176126e6576126e561267f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61272482611e29565b915061272f83611e29565b92508261273f5761273e6126ed565b5b828204905092915050565b5f61275482611e29565b915061275f83611e29565b92508282039050818111156127775761277661267f565b5b92915050565b5f6060820190506127905f830186612060565b61279d6020830185611e9a565b6127aa6040830184611e9a565b949350505050565b5f6127bc82611e29565b91506127c783611e29565b92508282019050808211156127df576127de61267f565b5b92915050565b5f6040820190506127f85f830185612060565b6128056020830184611f70565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f612840601483611d2f565b915061284b8261280c565b602082019050919050565b5f6020820190508181035f83015261286d81612834565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6128a8601083611d2f565b91506128b382612874565b602082019050919050565b5f6020820190508181035f8301526128d58161289c565b9050919050565b5f60a0820190506128ef5f830188611f70565b6128fc6020830187611f70565b6129096040830186611f70565b6129166060830185611e9a565b6129236080830184612060565b969550505050505056fea2646970667358221220e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b64736f6c63430008140033

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106101c2575f3560e01c806370a08231116100f7578063966e2a4611610095578063bc063e1a1161006f578063bc063e1a146104e6578063d539139314610504578063d547741f14610522578063dd62ed3e1461053e576101c2565b8063966e2a461461047c578063a217fddf14610498578063a9059cbb146104b6576101c2565b80638456cb59116100d15780638456cb591461040057806384b0196e1461040a57806391d148541461042e57806395d89b411461045e576101c2565b806370a08231146103965780637ce3489b146103c65780637fd6f15c146103e2576101c2565b8063313ce5671161016457806342966c681161013e57806342966c68146103225780634b023cf81461033e5780635c975abb1461035a57806365e17c9d14610378576101c2565b8063313ce567146102de57806336568abe146102fc5780633f4ba83a14610318576101c2565b806318160ddd116101a057806318160ddd1461024457806323b872dd14610262578063248a9ca3146102925780632f2ff15d146102c2576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063095ea7b314610214575b5f80fd5b6101e060048036038101906101db9190611cc7565b61056e565b6040516101ed9190611d0c565b60405180910390f35b6101fe6105e7565b60405161020b9190611daf565b60405180910390f35b61022e60048036038101906102299190611e5c565b610677565b60405161023b9190611d0c565b60405180910390f35b61024c610699565b6040516102599190611ea9565b60405180910390f35b61027c60048036038101906102779190611ec2565b6106a2565b6040516102899190611d0c565b60405180910390f35b6102ac60048036038101906102a79190611f45565b6106d0565b6040516102b99190611f7f565b60405180910390f35b6102dc60048036038101906102d79190611f98565b6106ed565b005b6102e661070f565b6040516102f39190611ff1565b60405180910390f35b61031660048036038101906103119190611f98565b610717565b005b610320610792565b005b61033c6004803603810190610337919061200a565b6107a9565b005b61035860048036038101906103539190612035565b6107b6565b005b610362610806565b60405161036f9190611d0c565b60405180910390f35b61038061081b565b60405161038d919061206f565b60405180910390f35b6103b060048036038101906103ab9190612035565b610840565b6040516103bd9190611ea9565b60405180910390f35b6103e060048036038101906103db919061200a565b610885565b005b6103ea6108e0565b6040516103f79190611ea9565b60405180910390f35b6104086108e6565b005b6104126108fd565b6040516104259796959493929190612179565b60405180910390f35b61044860048036038101906104439190611f98565b6109a2565b6040516104559190611d0c565b60405180910390f35b610466610a06565b6040516104739190611daf565b60405180910390f35b61049660048036038101906104919190612247565b610a96565b005b6104a0610d09565b6040516104ad9190611f7f565b60405180910390f35b6104d060048036038101906104cb9190611e5c565b610d0f565b6040516104dd9190611d0c565b60405180910390f35b6104ee610d7f565b6040516104fb9190611ea9565b60405180910390f35b61050c610d84565b6040516105199190611f7f565b60405180910390f35b61053c60048036038101906105379190611f98565b610da8565b005b610558600480360381019061055391906122ab565b610dca565b6040516105659190611ea9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105e057506105df82610e4c565b5b9050919050565b6060600380546105f690612316565b80601f016020809104026020016040519081016040528092919081815260200182805461062290612316565b801561066d5780601f106106445761010080835404028352916020019161066d565b820191905f5260205f20905b81548152906001019060200180831161065057829003601f168201915b5050505050905090565b5f80610681610eb5565b905061068e818585610ebc565b600191505092915050565b5f600254905090565b5f806106ac610eb5565b90506106b9858285610ece565b6106c4858585610f60565b60019150509392505050565b5f60055f8381526020019081526020015f20600101549050919050565b6106f6826106d0565b6106ff81611050565b6107098383611064565b50505050565b5f6012905090565b61071f610eb5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610783576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61078d828261114e565b505050565b5f801b61079e81611050565b6107a6611238565b50565b6107b33382611299565b50565b5f801b6107c281611050565b8160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60065f9054906101000a900460ff16905090565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f801b61089181611050565b60058211156108d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cc90612390565b60405180910390fd5b81600a819055505050565b600a5481565b5f801b6108f281611050565b6108fa611318565b50565b5f6060805f805f606061090e61137a565b6109166113b5565b46305f801b5f67ffffffffffffffff811115610935576109346123ae565b5b6040519080825280602002602001820160405280156109635781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b606060048054610a1590612316565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190612316565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050905090565b8360600135421115610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad490612425565b60405180910390fd5b5f7f05dac90127b5beea9d6bac8bf6962ef964e99f78ca9a5ee126ed3158f14d003c855f016020810190610b119190612035565b866020013587604001358860600135604051602001610b34959493929190612443565b6040516020818303038152906040528051906020012090505f610b56826113f0565b90505f6001828787876040515f8152602001604052604051610b7b9493929190612494565b6020604051602081039080840390855afa158015610b9b573d5f803e3d5ffd5b505050602060405103519050610bd17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6826109a2565b610c10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0790612547565b60405180910390fd5b5f875f016020810190610c239190612035565b8860200135896040013546604051602001610c4194939291906125ca565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1615610cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cae90612661565b60405180910390fd5b6001600b5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610cff885f016020810190610cf59190612035565b8960200135611409565b5050505050505050565b5f801b81565b5f806064600a5484610d2191906126ac565b610d2b919061271a565b90505f8184610d3a919061274a565b9050610d6760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611488565b50610d728582611488565b5060019250505092915050565b600581565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610db1826106d0565b610dba81611050565b610dc4838361114e565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610ec983838360016114aa565b505050565b5f610ed98484610dca565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f5a5781811015610f4b578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610f429392919061277d565b60405180910390fd5b610f5984848484035f6114aa565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd0575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610fc7919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611040575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611037919061206f565b60405180910390fd5b61104b838383611679565b505050565b6110618161105c610eb5565b611892565b50565b5f61106f83836109a2565b61114457600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506110e1610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611148565b5f90505b92915050565b5f61115983836109a2565b1561122e575f60055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506111cb610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611232565b5f90505b92915050565b6112406118e3565b5f60065f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611282610eb5565b60405161128f919061206f565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611309575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611300919061206f565b60405180910390fd5b611314825f83611679565b5050565b61132061192c565b600160065f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611363610eb5565b604051611370919061206f565b60405180910390a1565b60606113b060077f577261707065644149506f77657247726964000000000000000000000000001261197690919063ffffffff16565b905090565b60606113eb60087f310000000000000000000000000000000000000000000000000000000000000161197690919063ffffffff16565b905090565b5f6114026113fc611a23565b83611ad9565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611479575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611470919061206f565b60405180910390fd5b6114845f8383611679565b5050565b5f80611492610eb5565b905061149f818585610f60565b600191505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361151a575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611511919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158a575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611581919061206f565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611673578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161166a9190611ea9565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116c9578060025f8282546116bd91906127b2565b92505081905550611797565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611752578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016117499392919061277d565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117de578060025f8282540392505081905550611828565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516118859190611ea9565b60405180910390a3505050565b61189c82826109a2565b6118df5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016118d69291906127e5565b60405180910390fd5b5050565b6118eb610806565b61192a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192190612856565b60405180910390fd5b565b611934610806565b15611974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196b906128be565b60405180910390fd5b565b606060ff5f1b83146119925761198b83611b19565b9050611a1d565b81805461199e90612316565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca90612316565b8015611a155780601f106119ec57610100808354040283529160200191611a15565b820191905f5260205f20905b8154815290600101906020018083116119f857829003601f168201915b505050505090505b92915050565b5f7f000000000000000000000000a1c0def10828a7343bb75cb5036a58570105b30373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611a9e57507f000000000000000000000000000000000000000000000000000000000000000146145b15611acb577f784e0e8df2a866b93ebb2d1d8fac3915fb8cbc0308bb0c76f7407b9d7bed06649050611ad6565b611ad3611b8b565b90505b90565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60605f611b2583611c20565b90505f602067ffffffffffffffff811115611b4357611b426123ae565b5b6040519080825280601f01601f191660200182016040528015611b755781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fe7a21fcf0b8af70ba7f6fe639866ffa7065e564f5694d61fd1bfeae2bada280c7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001611c059594939291906128dc565b60405160208183030381529060405280519060200120905090565b5f8060ff835f1c169050601f811115611c65576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611ca681611c72565b8114611cb0575f80fd5b50565b5f81359050611cc181611c9d565b92915050565b5f60208284031215611cdc57611cdb611c6e565b5b5f611ce984828501611cb3565b91505092915050565b5f8115159050919050565b611d0681611cf2565b82525050565b5f602082019050611d1f5f830184611cfd565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611d5c578082015181840152602081019050611d41565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d8182611d25565b611d8b8185611d2f565b9350611d9b818560208601611d3f565b611da481611d67565b840191505092915050565b5f6020820190508181035f830152611dc78184611d77565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611df882611dcf565b9050919050565b611e0881611dee565b8114611e12575f80fd5b50565b5f81359050611e2381611dff565b92915050565b5f819050919050565b611e3b81611e29565b8114611e45575f80fd5b50565b5f81359050611e5681611e32565b92915050565b5f8060408385031215611e7257611e71611c6e565b5b5f611e7f85828601611e15565b9250506020611e9085828601611e48565b9150509250929050565b611ea381611e29565b82525050565b5f602082019050611ebc5f830184611e9a565b92915050565b5f805f60608486031215611ed957611ed8611c6e565b5b5f611ee686828701611e15565b9350506020611ef786828701611e15565b9250506040611f0886828701611e48565b9150509250925092565b5f819050919050565b611f2481611f12565b8114611f2e575f80fd5b50565b5f81359050611f3f81611f1b565b92915050565b5f60208284031215611f5a57611f59611c6e565b5b5f611f6784828501611f31565b91505092915050565b611f7981611f12565b82525050565b5f602082019050611f925f830184611f70565b92915050565b5f8060408385031215611fae57611fad611c6e565b5b5f611fbb85828601611f31565b9250506020611fcc85828601611e15565b9150509250929050565b5f60ff82169050919050565b611feb81611fd6565b82525050565b5f6020820190506120045f830184611fe2565b92915050565b5f6020828403121561201f5761201e611c6e565b5b5f61202c84828501611e48565b91505092915050565b5f6020828403121561204a57612049611c6e565b5b5f61205784828501611e15565b91505092915050565b61206981611dee565b82525050565b5f6020820190506120825f830184612060565b92915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6120bc81612088565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6120f481611e29565b82525050565b5f61210583836120eb565b60208301905092915050565b5f602082019050919050565b5f612127826120c2565b61213181856120cc565b935061213c836120dc565b805f5b8381101561216c57815161215388826120fa565b975061215e83612111565b92505060018101905061213f565b5085935050505092915050565b5f60e08201905061218c5f83018a6120b3565b818103602083015261219e8189611d77565b905081810360408301526121b28188611d77565b90506121c16060830187611e9a565b6121ce6080830186612060565b6121db60a0830185611f70565b81810360c08301526121ed818461211d565b905098975050505050505050565b5f80fd5b5f60808284031215612214576122136121fb565b5b81905092915050565b61222681611fd6565b8114612230575f80fd5b50565b5f813590506122418161221d565b92915050565b5f805f8060e0858703121561225f5761225e611c6e565b5b5f61226c878288016121ff565b945050608061227d87828801612233565b93505060a061228e87828801611f31565b92505060c061229f87828801611f31565b91505092959194509250565b5f80604083850312156122c1576122c0611c6e565b5b5f6122ce85828601611e15565b92505060206122df85828601611e15565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061232d57607f821691505b6020821081036123405761233f6122e9565b5b50919050565b7f4665652070657263656e7420746f6f20686967680000000000000000000000005f82015250565b5f61237a601483611d2f565b915061238582612346565b602082019050919050565b5f6020820190508181035f8301526123a78161236e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4578706972656420646561646c696e65000000000000000000000000000000005f82015250565b5f61240f601083611d2f565b915061241a826123db565b602082019050919050565b5f6020820190508181035f83015261243c81612403565b9050919050565b5f60a0820190506124565f830188611f70565b6124636020830187612060565b6124706040830186611e9a565b61247d6060830185611e9a565b61248a6080830184611e9a565b9695505050505050565b5f6080820190506124a75f830187611f70565b6124b46020830186611fe2565b6124c16040830185611f70565b6124ce6060830184611f70565b95945050505050565b7f496e76616c6964207369676e6174757265206f7220756e617574686f72697a655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f612531602183611d2f565b915061253c826124d7565b604082019050919050565b5f6020820190508181035f83015261255e81612525565b9050919050565b5f8160601b9050919050565b5f61257b82612565565b9050919050565b5f61258c82612571565b9050919050565b6125a461259f82611dee565b612582565b82525050565b5f819050919050565b6125c46125bf82611e29565b6125aa565b82525050565b5f6125d58287612593565b6014820191506125e582866125b3565b6020820191506125f582856125b3565b60208201915061260582846125b3565b60208201915081905095945050505050565b7f5555494420616c726561647920757365640000000000000000000000000000005f82015250565b5f61264b601183611d2f565b915061265682612617565b602082019050919050565b5f6020820190508181035f8301526126788161263f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126b682611e29565b91506126c183611e29565b92508282026126cf81611e29565b915082820484148315176126e6576126e561267f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61272482611e29565b915061272f83611e29565b92508261273f5761273e6126ed565b5b828204905092915050565b5f61275482611e29565b915061275f83611e29565b92508282039050818111156127775761277661267f565b5b92915050565b5f6060820190506127905f830186612060565b61279d6020830185611e9a565b6127aa6040830184611e9a565b949350505050565b5f6127bc82611e29565b91506127c783611e29565b92508282019050808211156127df576127de61267f565b5b92915050565b5f6040820190506127f85f830185612060565b6128056020830184611f70565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f612840601483611d2f565b915061284b8261280c565b602082019050919050565b5f6020820190508181035f83015261286d81612834565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6128a8601083611d2f565b91506128b382612874565b602082019050919050565b5f6020820190508181035f8301526128d58161289c565b9050919050565b5f60a0820190506128ef5f830188611f70565b6128fc6020830187611f70565b6129096040830186611f70565b6129166060830185611e9a565b6129236080830184612060565b969550505050505056fea2646970667358221220e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b64736f6c63430008140033

Deployed Bytecode Sourcemap

78072:3906:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30428:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13330:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15623:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14432:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16391:249;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;31708:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32140:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14283:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33277:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;81891:84;;;:::i;:::-;;81517:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79573:125;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;36727:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78534:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14594:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79813:191;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;78607:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;81736:80;;;:::i;:::-;;76012:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;30724:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13540:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80547:899;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;30036:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80067:355;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78682:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78198:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32571:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;15162:142;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;30428:204;30513:4;30552:32;30537:47;;;:11;:47;;;;:87;;;;30588:36;30612:11;30588:23;:36::i;:::-;30537:87;30530:94;;30428:204;;;:::o;13330:91::-;13375:13;13408:5;13401:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13330:91;:::o;15623:190::-;15696:4;15713:13;15729:12;:10;:12::i;:::-;15713:28;;15752:31;15761:5;15768:7;15777:5;15752:8;:31::i;:::-;15801:4;15794:11;;;15623:190;;;;:::o;14432:99::-;14484:7;14511:12;;14504:19;;14432:99;:::o;16391:249::-;16478:4;16495:15;16513:12;:10;:12::i;:::-;16495:30;;16536:37;16552:4;16558:7;16567:5;16536:15;:37::i;:::-;16584:26;16594:4;16600:2;16604:5;16584:9;:26::i;:::-;16628:4;16621:11;;;16391:249;;;;;:::o;31708:122::-;31773:7;31800:6;:12;31807:4;31800:12;;;;;;;;;;;:22;;;31793:29;;31708:122;;;:::o;32140:138::-;32214:18;32227:4;32214:12;:18::i;:::-;30320:16;30331:4;30320:10;:16::i;:::-;32245:25:::1;32256:4;32262:7;32245:10;:25::i;:::-;;32140:138:::0;;;:::o;14283:84::-;14332:5;14357:2;14350:9;;14283:84;:::o;33277:251::-;33393:12;:10;:12::i;:::-;33371:34;;:18;:34;;;33367:104;;33429:30;;;;;;;;;;;;;;33367:104;33483:37;33495:4;33501:18;33483:11;:37::i;:::-;;33277:251;;:::o;81891:84::-;30081:4;81926:18;;30320:16;30331:4;30320:10;:16::i;:::-;81957:10:::1;:8;:10::i;:::-;81891:84:::0;:::o;81517:146::-;81565:25;81571:10;81583:6;81565:5;:25::i;:::-;81517:146;:::o;79573:125::-;30081:4;79635:18;;30320:16;30331:4;30320:10;:16::i;:::-;79679:11:::1;79666:10;;:24;;;;;;;;;;;;;;;;;;79573:125:::0;;:::o;36727:86::-;36774:4;36798:7;;;;;;;;;;;36791:14;;36727:86;:::o;78534:25::-;;;;;;;;;;;;;:::o;14594:118::-;14659:7;14686:9;:18;14696:7;14686:18;;;;;;;;;;;;;;;;14679:25;;14594:118;;;:::o;79813:191::-;30081:4;79875:18;;30320:16;30331:4;30320:10;:16::i;:::-;78716:1:::1;79914:11;:22;;79906:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;79985:11;79972:10;:24;;;;79813:191:::0;;:::o;78607:29::-;;;;:::o;81736:80::-;30081:4;81769:18;;30320:16;30331:4;30320:10;:16::i;:::-;81800:8:::1;:6;:8::i;:::-;81736:80:::0;:::o;76012:580::-;76115:13;76143:18;76176:21;76212:15;76242:25;76282:12;76309:27;76417:13;:11;:13::i;:::-;76445:16;:14;:16::i;:::-;76476:13;76512:4;76540:1;76532:10;;76571:1;76557:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76364:220;;;;;;;;;;;;;;;;;;;;;76012:580;;;;;;;:::o;30724:138::-;30801:4;30825:6;:12;30832:4;30825:12;;;;;;;;;;;:20;;:29;30846:7;30825:29;;;;;;;;;;;;;;;;;;;;;;;;;30818:36;;30724:138;;;;:::o;13540:95::-;13587:13;13620:7;13613:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13540:95;:::o;80547:899::-;80667:7;:16;;;80648:15;:35;;80640:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;80715:18;78395:81;80772:7;:10;;;;;;;;;;:::i;:::-;80784:7;:14;;;80800:7;:12;;;80814:7;:16;;;80746:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;80736:96;;;;;;80715:117;;80843:14;80860:28;80877:10;80860:16;:28::i;:::-;80843:45;;80899:14;80916:26;80926:6;80934:1;80937;80940;80916:26;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80899:43;;80961:28;78236:24;80982:6;80961:7;:28::i;:::-;80953:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;81092:23;81145:7;:10;;;;;;;;;;:::i;:::-;81157:7;:14;;;81173:7;:12;;;81187:13;81128:73;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;81118:84;;;;;;81092:110;;81222:9;:26;81232:15;81222:26;;;;;;;;;;;;;;;;;;;;;81221:27;81213:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;81347:4;81318:9;:26;81328:15;81318:26;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;81364;81370:7;:10;;;;;;;;;;:::i;:::-;81382:7;:14;;;81364:5;:33::i;:::-;80629:817;;;;80547:899;;;;:::o;30036:49::-;30081:4;30036:49;;;:::o;80067:355::-;80145:4;80162:11;80200:3;80186:10;;80177:6;:19;;;;:::i;:::-;80176:27;;;;:::i;:::-;80162:41;;80214:22;80248:3;80239:6;:12;;;;:::i;:::-;80214:37;;80262:31;80277:10;;;;;;;;;;;80289:3;80262:14;:31::i;:::-;;80324:41;80339:9;80350:14;80324;:41::i;:::-;;80410:4;80403:11;;;;80067:355;;;;:::o;78682:35::-;78716:1;78682:35;:::o;78198:62::-;78236:24;78198:62;:::o;32571:140::-;32646:18;32659:4;32646:12;:18::i;:::-;30320:16;30331:4;30320:10;:16::i;:::-;32677:26:::1;32689:4;32695:7;32677:11;:26::i;:::-;;32571:140:::0;;;:::o;15162:142::-;15242:7;15269:11;:18;15281:5;15269:18;;;;;;;;;;;;;;;:27;15288:7;15269:27;;;;;;;;;;;;;;;;15262:34;;15162:142;;;;:::o;27764:148::-;27840:4;27879:25;27864:40;;;:11;:40;;;;27857:47;;27764:148;;;:::o;4335:98::-;4388:7;4415:10;4408:17;;4335:98;:::o;20450:130::-;20535:37;20544:5;20551:7;20560:5;20567:4;20535:8;:37::i;:::-;20450:130;;;:::o;22166:487::-;22266:24;22293:25;22303:5;22310:7;22293:9;:25::i;:::-;22266:52;;22353:17;22333:16;:37;22329:317;;22410:5;22391:16;:24;22387:132;;;22470:7;22479:16;22497:5;22443:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;22387:132;22562:57;22571:5;22578:7;22606:5;22587:16;:24;22613:5;22562:8;:57::i;:::-;22329:317;22255:398;22166:487;;;:::o;17025:308::-;17125:1;17109:18;;:4;:18;;;17105:88;;17178:1;17151:30;;;;;;;;;;;:::i;:::-;;;;;;;;17105:88;17221:1;17207:16;;:2;:16;;;17203:88;;17276:1;17247:32;;;;;;;;;;;:::i;:::-;;;;;;;;17203:88;17301:24;17309:4;17315:2;17319:5;17301:7;:24::i;:::-;17025:308;;;:::o;31077:105::-;31144:30;31155:4;31161:12;:10;:12::i;:::-;31144:10;:30::i;:::-;31077:105;:::o;34154:324::-;34231:4;34253:22;34261:4;34267:7;34253;:22::i;:::-;34248:223;;34324:4;34292:6;:12;34299:4;34292:12;;;;;;;;;;;:20;;:29;34313:7;34292:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;34375:12;:10;:12::i;:::-;34348:40;;34366:7;34348:40;;34360:4;34348:40;;;;;;;;;;34410:4;34403:11;;;;34248:223;34454:5;34447:12;;34154:324;;;;;:::o;34722:325::-;34800:4;34821:22;34829:4;34835:7;34821;:22::i;:::-;34817:223;;;34892:5;34860:6;:12;34867:4;34860:12;;;;;;;;;;;:20;;:29;34881:7;34860:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;34944:12;:10;:12::i;:::-;34917:40;;34935:7;34917:40;;34929:4;34917:40;;;;;;;;;;34979:4;34972:11;;;;34817:223;35023:5;35016:12;;34722:325;;;;;:::o;37582:120::-;36591:16;:14;:16::i;:::-;37651:5:::1;37641:7;;:15;;;;;;;;;;;;;;;;;;37672:22;37681:12;:10;:12::i;:::-;37672:22;;;;;;:::i;:::-;;;;;;;;37582:120::o:0;19686:211::-;19776:1;19757:21;;:7;:21;;;19753:91;;19829:1;19802:30;;;;;;;;;;;:::i;:::-;;;;;;;;19753:91;19854:35;19862:7;19879:1;19883:5;19854:7;:35::i;:::-;19686:211;;:::o;37323:118::-;36332:19;:17;:19::i;:::-;37393:4:::1;37383:7;;:14;;;;;;;;;;;;;;;;;;37413:20;37420:12;:10;:12::i;:::-;37413:20;;;;;;:::i;:::-;;;;;;;;37323:118::o:0;76921:128::-;76967:13;77000:41;77027:13;77000:5;:26;;:41;;;;:::i;:::-;76993:48;;76921:128;:::o;77384:137::-;77433:13;77466:47;77496:16;77466:8;:29;;:47;;;;:::i;:::-;77459:54;;77384:137;:::o;75778:178::-;75855:7;75882:66;75915:20;:18;:20::i;:::-;75937:10;75882:32;:66::i;:::-;75875:73;;75778:178;;;:::o;19145:213::-;19235:1;19216:21;;:7;:21;;;19212:93;;19290:1;19261:32;;;;;;;;;;;:::i;:::-;;;;;;;;19212:93;19315:35;19331:1;19335:7;19344:5;19315:7;:35::i;:::-;19145:213;;:::o;14917:182::-;14986:4;15003:13;15019:12;:10;:12::i;:::-;15003:28;;15042:27;15052:5;15059:2;15063:5;15042:9;:27::i;:::-;15087:4;15080:11;;;14917:182;;;;:::o;21431:443::-;21561:1;21544:19;;:5;:19;;;21540:91;;21616:1;21587:32;;;;;;;;;;;:::i;:::-;;;;;;;;21540:91;21664:1;21645:21;;:7;:21;;;21641:92;;21718:1;21690:31;;;;;;;;;;;:::i;:::-;;;;;;;;21641:92;21773:5;21743:11;:18;21755:5;21743:18;;;;;;;;;;;;;;;:27;21762:7;21743:27;;;;;;;;;;;;;;;:35;;;;21793:9;21789:78;;;21840:7;21824:31;;21833:5;21824:31;;;21849:5;21824:31;;;;;;:::i;:::-;;;;;;;;21789:78;21431:443;;;;:::o;17657:1135::-;17763:1;17747:18;;:4;:18;;;17743:552;;17901:5;17885:12;;:21;;;;;;;:::i;:::-;;;;;;;;17743:552;;;17939:19;17961:9;:15;17971:4;17961:15;;;;;;;;;;;;;;;;17939:37;;18009:5;17995:11;:19;17991:117;;;18067:4;18073:11;18086:5;18042:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;17991:117;18263:5;18249:11;:19;18231:9;:15;18241:4;18231:15;;;;;;;;;;;;;;;:37;;;;17924:371;17743:552;18325:1;18311:16;;:2;:16;;;18307:435;;18493:5;18477:12;;:21;;;;;;;;;;;18307:435;;;18710:5;18693:9;:13;18703:2;18693:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;18307:435;18774:2;18759:25;;18768:4;18759:25;;;18778:5;18759:25;;;;;;:::i;:::-;;;;;;;;17657:1135;;;:::o;31318:201::-;31407:22;31415:4;31421:7;31407;:22::i;:::-;31402:110;;31486:7;31495:4;31453:47;;;;;;;;;;;;:::i;:::-;;;;;;;;31402:110;31318:201;;:::o;37071:108::-;37138:8;:6;:8::i;:::-;37130:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;37071:108::o;36886:::-;36957:8;:6;:8::i;:::-;36956:9;36948:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;36886:108::o;69148:273::-;69242:13;67094:66;69301:17;;69291:5;69272:46;69268:146;;69342:15;69351:5;69342:8;:15::i;:::-;69335:22;;;;69268:146;69397:5;69390:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69148:273;;;;;:::o;74679:268::-;74732:7;74773:11;74756:28;;74764:4;74756:28;;;:63;;;;;74805:14;74788:13;:31;74756:63;74752:188;;;74843:22;74836:29;;;;74752:188;74905:23;:21;:23::i;:::-;74898:30;;74679:268;;:::o;61171:410::-;61264:14;61376:4;61370:11;61407:10;61402:3;61395:23;61455:15;61448:4;61443:3;61439:14;61432:39;61508:10;61501:4;61496:3;61492:14;61485:34;61558:4;61553:3;61543:20;61533:30;;61344:230;61171:410;;;;:::o;67803:415::-;67862:13;67888:11;67902:16;67913:4;67902:10;:16::i;:::-;67888:30;;68008:17;68039:2;68028:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68008:34;;68133:3;68128;68121:16;68174:4;68167;68162:3;68158:14;68151:28;68207:3;68200:10;;;;67803:415;;;:::o;74955:181::-;75010:7;72871:95;75069:11;75082:14;75098:13;75121:4;75047:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;75037:91;;;;;;75030:98;;74955:181;:::o;68295:251::-;68356:7;68376:14;68429:4;68420;68393:33;;:40;68376:57;;68457:2;68448:6;:11;68444:71;;;68483:20;;;;;;;;;;;;;;68444:71;68532:6;68525:13;;;68295:251;;;:::o;88:117:1:-;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:126::-;2897:7;2937:42;2930:5;2926:54;2915:65;;2860:126;;;:::o;2992:96::-;3029:7;3058:24;3076:5;3058:24;:::i;:::-;3047:35;;2992:96;;;:::o;3094:122::-;3167:24;3185:5;3167:24;:::i;:::-;3160:5;3157:35;3147:63;;3206:1;3203;3196:12;3147:63;3094:122;:::o;3222:139::-;3268:5;3306:6;3293:20;3284:29;;3322:33;3349:5;3322:33;:::i;:::-;3222:139;;;;:::o;3367:77::-;3404:7;3433:5;3422:16;;3367:77;;;:::o;3450:122::-;3523:24;3541:5;3523:24;:::i;:::-;3516:5;3513:35;3503:63;;3562:1;3559;3552:12;3503:63;3450:122;:::o;3578:139::-;3624:5;3662:6;3649:20;3640:29;;3678:33;3705:5;3678:33;:::i;:::-;3578:139;;;;:::o;3723:474::-;3791:6;3799;3848:2;3836:9;3827:7;3823:23;3819:32;3816:119;;;3854:79;;:::i;:::-;3816:119;3974:1;3999:53;4044:7;4035:6;4024:9;4020:22;3999:53;:::i;:::-;3989:63;;3945:117;4101:2;4127:53;4172:7;4163:6;4152:9;4148:22;4127:53;:::i;:::-;4117:63;;4072:118;3723:474;;;;;:::o;4203:118::-;4290:24;4308:5;4290:24;:::i;:::-;4285:3;4278:37;4203:118;;:::o;4327:222::-;4420:4;4458:2;4447:9;4443:18;4435:26;;4471:71;4539:1;4528:9;4524:17;4515:6;4471:71;:::i;:::-;4327:222;;;;:::o;4555:619::-;4632:6;4640;4648;4697:2;4685:9;4676:7;4672:23;4668:32;4665:119;;;4703:79;;:::i;:::-;4665:119;4823:1;4848:53;4893:7;4884:6;4873:9;4869:22;4848:53;:::i;:::-;4838:63;;4794:117;4950:2;4976:53;5021:7;5012:6;5001:9;4997:22;4976:53;:::i;:::-;4966:63;;4921:118;5078:2;5104:53;5149:7;5140:6;5129:9;5125:22;5104:53;:::i;:::-;5094:63;;5049:118;4555:619;;;;;:::o;5180:77::-;5217:7;5246:5;5235:16;;5180:77;;;:::o;5263:122::-;5336:24;5354:5;5336:24;:::i;:::-;5329:5;5326:35;5316:63;;5375:1;5372;5365:12;5316:63;5263:122;:::o;5391:139::-;5437:5;5475:6;5462:20;5453:29;;5491:33;5518:5;5491:33;:::i;:::-;5391:139;;;;:::o;5536:329::-;5595:6;5644:2;5632:9;5623:7;5619:23;5615:32;5612:119;;;5650:79;;:::i;:::-;5612:119;5770:1;5795:53;5840:7;5831:6;5820:9;5816:22;5795:53;:::i;:::-;5785:63;;5741:117;5536:329;;;;:::o;5871:118::-;5958:24;5976:5;5958:24;:::i;:::-;5953:3;5946:37;5871:118;;:::o;5995:222::-;6088:4;6126:2;6115:9;6111:18;6103:26;;6139:71;6207:1;6196:9;6192:17;6183:6;6139:71;:::i;:::-;5995:222;;;;:::o;6223:474::-;6291:6;6299;6348:2;6336:9;6327:7;6323:23;6319:32;6316:119;;;6354:79;;:::i;:::-;6316:119;6474:1;6499:53;6544:7;6535:6;6524:9;6520:22;6499:53;:::i;:::-;6489:63;;6445:117;6601:2;6627:53;6672:7;6663:6;6652:9;6648:22;6627:53;:::i;:::-;6617:63;;6572:118;6223:474;;;;;:::o;6703:86::-;6738:7;6778:4;6771:5;6767:16;6756:27;;6703:86;;;:::o;6795:112::-;6878:22;6894:5;6878:22;:::i;:::-;6873:3;6866:35;6795:112;;:::o;6913:214::-;7002:4;7040:2;7029:9;7025:18;7017:26;;7053:67;7117:1;7106:9;7102:17;7093:6;7053:67;:::i;:::-;6913:214;;;;:::o;7133:329::-;7192:6;7241:2;7229:9;7220:7;7216:23;7212:32;7209:119;;;7247:79;;:::i;:::-;7209:119;7367:1;7392:53;7437:7;7428:6;7417:9;7413:22;7392:53;:::i;:::-;7382:63;;7338:117;7133:329;;;;:::o;7468:::-;7527:6;7576:2;7564:9;7555:7;7551:23;7547:32;7544:119;;;7582:79;;:::i;:::-;7544:119;7702:1;7727:53;7772:7;7763:6;7752:9;7748:22;7727:53;:::i;:::-;7717:63;;7673:117;7468:329;;;;:::o;7803:118::-;7890:24;7908:5;7890:24;:::i;:::-;7885:3;7878:37;7803:118;;:::o;7927:222::-;8020:4;8058:2;8047:9;8043:18;8035:26;;8071:71;8139:1;8128:9;8124:17;8115:6;8071:71;:::i;:::-;7927:222;;;;:::o;8155:149::-;8191:7;8231:66;8224:5;8220:78;8209:89;;8155:149;;;:::o;8310:115::-;8395:23;8412:5;8395:23;:::i;:::-;8390:3;8383:36;8310:115;;:::o;8431:114::-;8498:6;8532:5;8526:12;8516:22;;8431:114;;;:::o;8551:184::-;8650:11;8684:6;8679:3;8672:19;8724:4;8719:3;8715:14;8700:29;;8551:184;;;;:::o;8741:132::-;8808:4;8831:3;8823:11;;8861:4;8856:3;8852:14;8844:22;;8741:132;;;:::o;8879:108::-;8956:24;8974:5;8956:24;:::i;:::-;8951:3;8944:37;8879:108;;:::o;8993:179::-;9062:10;9083:46;9125:3;9117:6;9083:46;:::i;:::-;9161:4;9156:3;9152:14;9138:28;;8993:179;;;;:::o;9178:113::-;9248:4;9280;9275:3;9271:14;9263:22;;9178:113;;;:::o;9327:732::-;9446:3;9475:54;9523:5;9475:54;:::i;:::-;9545:86;9624:6;9619:3;9545:86;:::i;:::-;9538:93;;9655:56;9705:5;9655:56;:::i;:::-;9734:7;9765:1;9750:284;9775:6;9772:1;9769:13;9750:284;;;9851:6;9845:13;9878:63;9937:3;9922:13;9878:63;:::i;:::-;9871:70;;9964:60;10017:6;9964:60;:::i;:::-;9954:70;;9810:224;9797:1;9794;9790:9;9785:14;;9750:284;;;9754:14;10050:3;10043:10;;9451:608;;;9327:732;;;;:::o;10065:1215::-;10414:4;10452:3;10441:9;10437:19;10429:27;;10466:69;10532:1;10521:9;10517:17;10508:6;10466:69;:::i;:::-;10582:9;10576:4;10572:20;10567:2;10556:9;10552:18;10545:48;10610:78;10683:4;10674:6;10610:78;:::i;:::-;10602:86;;10735:9;10729:4;10725:20;10720:2;10709:9;10705:18;10698:48;10763:78;10836:4;10827:6;10763:78;:::i;:::-;10755:86;;10851:72;10919:2;10908:9;10904:18;10895:6;10851:72;:::i;:::-;10933:73;11001:3;10990:9;10986:19;10977:6;10933:73;:::i;:::-;11016;11084:3;11073:9;11069:19;11060:6;11016:73;:::i;:::-;11137:9;11131:4;11127:20;11121:3;11110:9;11106:19;11099:49;11165:108;11268:4;11259:6;11165:108;:::i;:::-;11157:116;;10065:1215;;;;;;;;;;:::o;11286:117::-;11395:1;11392;11385:12;11447:236;11524:5;11565:3;11556:6;11551:3;11547:16;11543:26;11540:113;;;11572:79;;:::i;:::-;11540:113;11671:6;11662:15;;11447:236;;;;:::o;11689:118::-;11760:22;11776:5;11760:22;:::i;:::-;11753:5;11750:33;11740:61;;11797:1;11794;11787:12;11740:61;11689:118;:::o;11813:135::-;11857:5;11895:6;11882:20;11873:29;;11911:31;11936:5;11911:31;:::i;:::-;11813:135;;;;:::o;11954:826::-;12069:6;12077;12085;12093;12142:3;12130:9;12121:7;12117:23;12113:33;12110:120;;;12149:79;;:::i;:::-;12110:120;12269:1;12294:84;12370:7;12361:6;12350:9;12346:22;12294:84;:::i;:::-;12284:94;;12240:148;12427:3;12454:51;12497:7;12488:6;12477:9;12473:22;12454:51;:::i;:::-;12444:61;;12398:117;12554:3;12581:53;12626:7;12617:6;12606:9;12602:22;12581:53;:::i;:::-;12571:63;;12525:119;12683:3;12710:53;12755:7;12746:6;12735:9;12731:22;12710:53;:::i;:::-;12700:63;;12654:119;11954:826;;;;;;;:::o;12786:474::-;12854:6;12862;12911:2;12899:9;12890:7;12886:23;12882:32;12879:119;;;12917:79;;:::i;:::-;12879:119;13037:1;13062:53;13107:7;13098:6;13087:9;13083:22;13062:53;:::i;:::-;13052:63;;13008:117;13164:2;13190:53;13235:7;13226:6;13215:9;13211:22;13190:53;:::i;:::-;13180:63;;13135:118;12786:474;;;;;:::o;13266:180::-;13314:77;13311:1;13304:88;13411:4;13408:1;13401:15;13435:4;13432:1;13425:15;13452:320;13496:6;13533:1;13527:4;13523:12;13513:22;;13580:1;13574:4;13570:12;13601:18;13591:81;;13657:4;13649:6;13645:17;13635:27;;13591:81;13719:2;13711:6;13708:14;13688:18;13685:38;13682:84;;13738:18;;:::i;:::-;13682:84;13503:269;13452:320;;;:::o;13778:170::-;13918:22;13914:1;13906:6;13902:14;13895:46;13778:170;:::o;13954:366::-;14096:3;14117:67;14181:2;14176:3;14117:67;:::i;:::-;14110:74;;14193:93;14282:3;14193:93;:::i;:::-;14311:2;14306:3;14302:12;14295:19;;13954:366;;;:::o;14326:419::-;14492:4;14530:2;14519:9;14515:18;14507:26;;14579:9;14573:4;14569:20;14565:1;14554:9;14550:17;14543:47;14607:131;14733:4;14607:131;:::i;:::-;14599:139;;14326:419;;;:::o;14751:180::-;14799:77;14796:1;14789:88;14896:4;14893:1;14886:15;14920:4;14917:1;14910:15;14937:166;15077:18;15073:1;15065:6;15061:14;15054:42;14937:166;:::o;15109:366::-;15251:3;15272:67;15336:2;15331:3;15272:67;:::i;:::-;15265:74;;15348:93;15437:3;15348:93;:::i;:::-;15466:2;15461:3;15457:12;15450:19;;15109:366;;;:::o;15481:419::-;15647:4;15685:2;15674:9;15670:18;15662:26;;15734:9;15728:4;15724:20;15720:1;15709:9;15705:17;15698:47;15762:131;15888:4;15762:131;:::i;:::-;15754:139;;15481:419;;;:::o;15906:664::-;16111:4;16149:3;16138:9;16134:19;16126:27;;16163:71;16231:1;16220:9;16216:17;16207:6;16163:71;:::i;:::-;16244:72;16312:2;16301:9;16297:18;16288:6;16244:72;:::i;:::-;16326;16394:2;16383:9;16379:18;16370:6;16326:72;:::i;:::-;16408;16476:2;16465:9;16461:18;16452:6;16408:72;:::i;:::-;16490:73;16558:3;16547:9;16543:19;16534:6;16490:73;:::i;:::-;15906:664;;;;;;;;:::o;16576:545::-;16749:4;16787:3;16776:9;16772:19;16764:27;;16801:71;16869:1;16858:9;16854:17;16845:6;16801:71;:::i;:::-;16882:68;16946:2;16935:9;16931:18;16922:6;16882:68;:::i;:::-;16960:72;17028:2;17017:9;17013:18;17004:6;16960:72;:::i;:::-;17042;17110:2;17099:9;17095:18;17086:6;17042:72;:::i;:::-;16576:545;;;;;;;:::o;17127:220::-;17267:34;17263:1;17255:6;17251:14;17244:58;17336:3;17331:2;17323:6;17319:15;17312:28;17127:220;:::o;17353:366::-;17495:3;17516:67;17580:2;17575:3;17516:67;:::i;:::-;17509:74;;17592:93;17681:3;17592:93;:::i;:::-;17710:2;17705:3;17701:12;17694:19;;17353:366;;;:::o;17725:419::-;17891:4;17929:2;17918:9;17914:18;17906:26;;17978:9;17972:4;17968:20;17964:1;17953:9;17949:17;17942:47;18006:131;18132:4;18006:131;:::i;:::-;17998:139;;17725:419;;;:::o;18150:94::-;18183:8;18231:5;18227:2;18223:14;18202:35;;18150:94;;;:::o;18250:::-;18289:7;18318:20;18332:5;18318:20;:::i;:::-;18307:31;;18250:94;;;:::o;18350:100::-;18389:7;18418:26;18438:5;18418:26;:::i;:::-;18407:37;;18350:100;;;:::o;18456:157::-;18561:45;18581:24;18599:5;18581:24;:::i;:::-;18561:45;:::i;:::-;18556:3;18549:58;18456:157;;:::o;18619:79::-;18658:7;18687:5;18676:16;;18619:79;;;:::o;18704:157::-;18809:45;18829:24;18847:5;18829:24;:::i;:::-;18809:45;:::i;:::-;18804:3;18797:58;18704:157;;:::o;18867:679::-;19063:3;19078:75;19149:3;19140:6;19078:75;:::i;:::-;19178:2;19173:3;19169:12;19162:19;;19191:75;19262:3;19253:6;19191:75;:::i;:::-;19291:2;19286:3;19282:12;19275:19;;19304:75;19375:3;19366:6;19304:75;:::i;:::-;19404:2;19399:3;19395:12;19388:19;;19417:75;19488:3;19479:6;19417:75;:::i;:::-;19517:2;19512:3;19508:12;19501:19;;19537:3;19530:10;;18867:679;;;;;;;:::o;19552:167::-;19692:19;19688:1;19680:6;19676:14;19669:43;19552:167;:::o;19725:366::-;19867:3;19888:67;19952:2;19947:3;19888:67;:::i;:::-;19881:74;;19964:93;20053:3;19964:93;:::i;:::-;20082:2;20077:3;20073:12;20066:19;;19725:366;;;:::o;20097:419::-;20263:4;20301:2;20290:9;20286:18;20278:26;;20350:9;20344:4;20340:20;20336:1;20325:9;20321:17;20314:47;20378:131;20504:4;20378:131;:::i;:::-;20370:139;;20097:419;;;:::o;20522:180::-;20570:77;20567:1;20560:88;20667:4;20664:1;20657:15;20691:4;20688:1;20681:15;20708:410;20748:7;20771:20;20789:1;20771:20;:::i;:::-;20766:25;;20805:20;20823:1;20805:20;:::i;:::-;20800:25;;20860:1;20857;20853:9;20882:30;20900:11;20882:30;:::i;:::-;20871:41;;21061:1;21052:7;21048:15;21045:1;21042:22;21022:1;21015:9;20995:83;20972:139;;21091:18;;:::i;:::-;20972:139;20756:362;20708:410;;;;:::o;21124:180::-;21172:77;21169:1;21162:88;21269:4;21266:1;21259:15;21293:4;21290:1;21283:15;21310:185;21350:1;21367:20;21385:1;21367:20;:::i;:::-;21362:25;;21401:20;21419:1;21401:20;:::i;:::-;21396:25;;21440:1;21430:35;;21445:18;;:::i;:::-;21430:35;21487:1;21484;21480:9;21475:14;;21310:185;;;;:::o;21501:194::-;21541:4;21561:20;21579:1;21561:20;:::i;:::-;21556:25;;21595:20;21613:1;21595:20;:::i;:::-;21590:25;;21639:1;21636;21632:9;21624:17;;21663:1;21657:4;21654:11;21651:37;;;21668:18;;:::i;:::-;21651:37;21501:194;;;;:::o;21701:442::-;21850:4;21888:2;21877:9;21873:18;21865:26;;21901:71;21969:1;21958:9;21954:17;21945:6;21901:71;:::i;:::-;21982:72;22050:2;22039:9;22035:18;22026:6;21982:72;:::i;:::-;22064;22132:2;22121:9;22117:18;22108:6;22064:72;:::i;:::-;21701:442;;;;;;:::o;22149:191::-;22189:3;22208:20;22226:1;22208:20;:::i;:::-;22203:25;;22242:20;22260:1;22242:20;:::i;:::-;22237:25;;22285:1;22282;22278:9;22271:16;;22306:3;22303:1;22300:10;22297:36;;;22313:18;;:::i;:::-;22297:36;22149:191;;;;:::o;22346:332::-;22467:4;22505:2;22494:9;22490:18;22482:26;;22518:71;22586:1;22575:9;22571:17;22562:6;22518:71;:::i;:::-;22599:72;22667:2;22656:9;22652:18;22643:6;22599:72;:::i;:::-;22346:332;;;;;:::o;22684:170::-;22824:22;22820:1;22812:6;22808:14;22801:46;22684:170;:::o;22860:366::-;23002:3;23023:67;23087:2;23082:3;23023:67;:::i;:::-;23016:74;;23099:93;23188:3;23099:93;:::i;:::-;23217:2;23212:3;23208:12;23201:19;;22860:366;;;:::o;23232:419::-;23398:4;23436:2;23425:9;23421:18;23413:26;;23485:9;23479:4;23475:20;23471:1;23460:9;23456:17;23449:47;23513:131;23639:4;23513:131;:::i;:::-;23505:139;;23232:419;;;:::o;23657:166::-;23797:18;23793:1;23785:6;23781:14;23774:42;23657:166;:::o;23829:366::-;23971:3;23992:67;24056:2;24051:3;23992:67;:::i;:::-;23985:74;;24068:93;24157:3;24068:93;:::i;:::-;24186:2;24181:3;24177:12;24170:19;;23829:366;;;:::o;24201:419::-;24367:4;24405:2;24394:9;24390:18;24382:26;;24454:9;24448:4;24444:20;24440:1;24429:9;24425:17;24418:47;24482:131;24608:4;24482:131;:::i;:::-;24474:139;;24201:419;;;:::o;24626:664::-;24831:4;24869:3;24858:9;24854:19;24846:27;;24883:71;24951:1;24940:9;24936:17;24927:6;24883:71;:::i;:::-;24964:72;25032:2;25021:9;25017:18;25008:6;24964:72;:::i;:::-;25046;25114:2;25103:9;25099:18;25090:6;25046:72;:::i;:::-;25128;25196:2;25185:9;25181:18;25172:6;25128:72;:::i;:::-;25210:73;25278:3;25267:9;25263:19;25254:6;25210:73;:::i;:::-;24626:664;;;;;;;;:::o

Swarm Source

ipfs://e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b
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.