ETH Price: $2,982.19 (-3.92%)
Gas: 2 Gwei

Token

Citizen Pass (CP)
 

Overview

Max Total Supply

500 CP

Holders

405

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
2 CP
0xc559dc3757dd006ce873ef831b7bb2852f272be7
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:
CitizenPass

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-01-25
*/

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


// 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/Counters.sol


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// 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/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/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/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/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/Context.sol


// OpenZeppelin Contracts (last updated v5.0.0) (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;
    }
}

// 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/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/access/Ownable.sol


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

pragma solidity ^0.8.20;


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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

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


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

pragma solidity ^0.8.20;


// 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.8;




/**
 * @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/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.20;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)

pragma solidity ^0.8.20;


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


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4906.sol)

pragma solidity ^0.8.20;



/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.20;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

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


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

pragma solidity ^0.8.20;








/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    mapping(uint256 tokenId => address) private _tokenApprovals;

    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual returns (uint256) {
        if (owner == address(0)) {
            revert ERC721InvalidOwner(address(0));
        }
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual returns (address) {
        return _requireOwned(tokenId);
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
        _requireOwned(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual {
        _approve(to, tokenId, _msgSender());
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual returns (address) {
        _requireOwned(tokenId);

        return _getApproved(tokenId);
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
        address previousOwner = _update(to, tokenId, _msgSender());
        if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
        transferFrom(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     *
     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
     */
    function _getApproved(uint256 tokenId) internal view virtual returns (address) {
        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
     * particular (ignoring whether it is owned by `owner`).
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
        return
            spender != address(0) &&
            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
    }

    /**
     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
     * the `spender` for the specific `tokenId`.
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
        if (!_isAuthorized(owner, spender, tokenId)) {
            if (owner == address(0)) {
                revert ERC721NonexistentToken(tokenId);
            } else {
                revert ERC721InsufficientApproval(spender, tokenId);
            }
        }
    }

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
     *
     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the
     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
     * remain consistent with one another.
     */
    function _increaseBalance(address account, uint128 value) internal virtual {
        unchecked {
            _balances[account] += value;
        }
    }

    /**
     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that
     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).
     *
     * Emits a {Transfer} event.
     *
     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        // Perform (optional) operator check
        if (auth != address(0)) {
            _checkAuthorized(from, auth, tokenId);
        }

        // Execute the update
        if (from != address(0)) {
            // Clear approval. No need to re-authorize or emit the Approval event
            _approve(address(0), tokenId, address(0), false);

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner != address(0)) {
            revert ERC721InvalidSender(address(0));
        }
    }

    /**
     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
        _mint(to, tokenId);
        _checkOnERC721Received(address(0), to, tokenId, data);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address previousOwner = _update(address(0), tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        }
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        } else if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
     * are aware of the ERC721 standard to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is like {safeTransferFrom} in the sense that it invokes
     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `tokenId` token must exist and be owned by `from`.
     * - `to` cannot be the zero address.
     * - `from` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId) internal {
        _safeTransfer(from, to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
        _transfer(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
     * either the owner of the token, or approved to operate on all tokens held by this owner.
     *
     * Emits an {Approval} event.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address to, uint256 tokenId, address auth) internal {
        _approve(to, tokenId, auth, true);
    }

    /**
     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
     * emitted in the context of transfers.
     */
    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
        // Avoid reading the owner unless necessary
        if (emitEvent || auth != address(0)) {
            address owner = _requireOwned(tokenId);

            // We do not use _isAuthorized because single-token approvals should not be able to call approve
            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
                revert ERC721InvalidApprover(auth);
            }

            if (emitEvent) {
                emit Approval(owner, to, tokenId);
            }
        }

        _tokenApprovals[tokenId] = to;
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Requirements:
     * - operator can't be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
        if (operator == address(0)) {
            revert ERC721InvalidOperator(operator);
        }
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
     * Returns the owner.
     *
     * Overrides to ownership logic should be done to {_ownerOf}.
     */
    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        if (owner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        }
        return owner;
    }

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
     * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
        if (to.code.length > 0) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                if (retval != IERC721Receiver.onERC721Received.selector) {
                    revert ERC721InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert ERC721InvalidReceiver(to);
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.20;




/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
 * of all the token ids in the contract as well as all token ids owned by each account.
 *
 * CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
 * interfere with enumerability and should not be used together with `ERC721Enumerable`.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
    mapping(uint256 tokenId => uint256) private _ownedTokensIndex;

    uint256[] private _allTokens;
    mapping(uint256 tokenId => uint256) private _allTokensIndex;

    /**
     * @dev An `owner`'s token query was out of bounds for `index`.
     *
     * NOTE: The owner being `address(0)` indicates a global out of bounds index.
     */
    error ERC721OutOfBoundsIndex(address owner, uint256 index);

    /**
     * @dev Batch mint is not allowed.
     */
    error ERC721EnumerableForbiddenBatchMint();

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
        if (index >= balanceOf(owner)) {
            revert ERC721OutOfBoundsIndex(owner, index);
        }
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual returns (uint256) {
        if (index >= totalSupply()) {
            revert ERC721OutOfBoundsIndex(address(0), index);
        }
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_update}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
        address previousOwner = super._update(to, tokenId, auth);

        if (previousOwner == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _removeTokenFromOwnerEnumeration(previousOwner, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }

        return previousOwner;
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = balanceOf(to) - 1;
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = balanceOf(from);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }

    /**
     * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
     */
    function _increaseBalance(address account, uint128 amount) internal virtual override {
        if (amount > 0) {
            revert ERC721EnumerableForbiddenBatchMint();
        }
        super._increaseBalance(account, amount);
    }
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721URIStorage.sol)

pragma solidity ^0.8.20;





/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is IERC4906, ERC721 {
    using Strings for uint256;

    // Interface ID as defined in ERC-4906. This does not correspond to a traditional interface ID as ERC-4906 only
    // defines events and does not include any external function.
    bytes4 private constant ERC4906_INTERFACE_ID = bytes4(0x49064906);

    // Optional mapping for token URIs
    mapping(uint256 tokenId => string) private _tokenURIs;

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireOwned(tokenId);

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via string.concat).
        if (bytes(_tokenURI).length > 0) {
            return string.concat(base, _tokenURI);
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Emits {MetadataUpdate}.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        _tokenURIs[tokenId] = _tokenURI;
        emit MetadataUpdate(tokenId);
    }
}

// File: ethereum/eth.sol


pragma solidity ^0.8.20;









contract CitizenPass is ERC721, ERC721URIStorage, Pausable, Ownable, AccessControl {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    address public treasury;
    address public kometWallet;
    address public collectionWallet;

    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant KOMET_ROLE = keccak256("KOMET_ROLE");

    mapping(address => uint256) public public_minted_address;

    bool internal PUBLICMINT;

    uint256 internal supply = 20;
    uint256 public feePercent = 5;
    uint256 public percentDecimal = 10;
    uint256 public mint_price = 0;
    uint256 public mint_Limit = 1;
    uint256 public totalSupply;
    string public base_url = "https://ipfs.io/ipfs/bafybeicy3cel72qi4sxkedlxjd2mot7kccg7trfz4l6djxjgasii4qkl4e/";

    mapping(address => bool) public has_paid;
    mapping(address => uint256) public amount_paid;

    event UserPaid(address indexed _user, uint256 indexed amount);

    constructor(
        address minter,
        address _treasury,
        address _komet,
        address _CollectionWallet
    ) ERC721("Citizen Pass", "CP") Ownable(msg.sender) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);

        _grantRole(PAUSER_ROLE, minter);
        _grantRole(MINTER_ROLE, minter);
        _grantRole(KOMET_ROLE, minter);

        totalSupply = 0;
        treasury = _treasury;
        kometWallet = _komet;
        collectionWallet = _CollectionWallet;
    }


    receive() external payable {
        has_paid[msg.sender] = true;
        amount_paid[msg.sender] = msg.value;

        emit UserPaid(msg.sender, msg.value);
    }


    function autoMint(address[] calldata _users)
        public
        onlyRole(MINTER_ROLE)
    {
        for (uint256 i = 0; i < _users.length; i++) {
            require(totalSupply + 1 <= supply, "supply exceed");
            _tokenIdCounter.increment();
            uint256 newItemId = _tokenIdCounter.current();
            totalSupply += 1;
            _mint(_users[i], newItemId);
            _setTokenURI(newItemId, gen_uri(newItemId));
        }
    }

    function publicMint(uint256 _amount) public payable {
        require(PUBLICMINT, "Public mint is not open");
        require(totalSupply + _amount <= supply, "token is less");
        require(
            public_minted_address[msg.sender] <= mint_Limit,
            "user exceed mint limit"
        );
        require(
            public_minted_address[msg.sender] + _amount <= mint_Limit,
            "user exceed mint limit"
        );

        require(_amount * mint_price <= msg.value, "user pass lower amount");

        for (uint256 i = 0; i < _amount; i++) {
            _tokenIdCounter.increment();
            uint256 newItemId = _tokenIdCounter.current();
            totalSupply += 1;
            public_minted_address[msg.sender] += 1;
            _mint(msg.sender, newItemId);
            _setTokenURI(newItemId, gen_uri(newItemId));
        }

        distributeFunds(payable(collectionWallet), payable(kometWallet));
    }

    function treasuryMint(uint256 _amount) public onlyRole(DEFAULT_ADMIN_ROLE) {
        require(totalSupply + _amount <= supply, "supply exceed");
        for (uint256 i = 0; i < _amount; i++) {
            _tokenIdCounter.increment();
            uint256 newItemId = _tokenIdCounter.current();

            totalSupply += 1;
            _mint(treasury, newItemId);
            _setTokenURI(newItemId, gen_uri(newItemId));
        }
    }

    function setTreasuryWallet(address _account)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        treasury = _account;
    }

    function setMintSupply(uint256 _limit) public onlyRole(MINTER_ROLE) {
        supply = _limit;
    }

    function setCollectionWallet(address _wallet)
        public
        onlyRole(MINTER_ROLE)
    {
        collectionWallet = _wallet;
    }

    function transferOwnership(address _user) public override onlyOwner {
        _revokeRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _revokeRole(MINTER_ROLE, msg.sender);
        _revokeRole(PAUSER_ROLE, msg.sender);
        _grantRole(DEFAULT_ADMIN_ROLE, _user);
        _grantRole(MINTER_ROLE, _user);
        _grantRole(PAUSER_ROLE, _user);
        _transferOwnership(_user);
    }

    function distributeFunds(
        address payable recipient1,
        address payable recipient2
    ) public payable {
        if (mint_price > 0) {
            uint256 value = msg.value;
            uint256 kometFee = ((value * feePercent) / 100) / percentDecimal;
            uint256 creator = value - kometFee;

            require(
                address(this).balance >= creator,
                "Insufficient balance to send the first transaction"
            );
            recipient1.transfer(creator);

            require(
                address(this).balance >= kometFee,
                "Insufficient balance to send the second transaction"
            );
            recipient2.transfer(kometFee);
        } else {
            uint256 kometFee = msg.value;

            require(
                address(this).balance >= kometFee,
                "Insufficient balance to send the second transaction"
            );
            recipient2.transfer(kometFee);
        }
    }

    function setMintType(
        uint256 _price,
        uint256 _perWalletLimit,
        bool _public
    ) public onlyRole(MINTER_ROLE) {
        mint_price = _price;
        mint_Limit = _perWalletLimit;
        PUBLICMINT = _public;
    }

    function setPlatFormFeeCharges(uint256 _percent, uint256 _decimal)
        public
        onlyRole(KOMET_ROLE)
    {
        feePercent = _percent;
        percentDecimal = _decimal;
    }

    function setKometWallet(address _wallet) public onlyRole(KOMET_ROLE) {
        kometWallet = _wallet;
    }

    function setBaseUrl(string calldata _uri)
        public
        onlyRole(MINTER_ROLE)
    {
        base_url = _uri;
    }

    function withdraw() external {
        require(has_paid[msg.sender], "User has not yet paid");
        has_paid[msg.sender] = false;
        bool success = payable(msg.sender).send(amount_paid[msg.sender]);
        require(success, "Ether transfer failed.");
        amount_paid[msg.sender] = 0;
    }

    function withdrawAdmin() external onlyRole(DEFAULT_ADMIN_ROLE) {
        bool success = payable(msg.sender).send(address(this).balance);
        require(success, "Ether transfer failed.");
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return gen_uri(tokenId);
    }

    function gen_uri(uint256 _tokenid) internal view returns (string memory) {
        return
            string(
                abi.encodePacked(base_url, Strings.toString(_tokenid), ".json")
            );
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, AccessControl, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"minter","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_komet","type":"address"},{"internalType":"address","name":"_CollectionWallet","type":"address"}],"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":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UserPaid","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KOMET_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amount_paid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"autoMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"base_url","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectionWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient1","type":"address"},{"internalType":"address payable","name":"recipient2","type":"address"}],"name":"distributeFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[{"internalType":"address","name":"","type":"address"}],"name":"has_paid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kometWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint_Limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint_price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"percentDecimal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"public_minted_address","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseUrl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"setCollectionWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"setKometWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setMintSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_perWalletLimit","type":"uint256"},{"internalType":"bool","name":"_public","type":"bool"}],"name":"setMintType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"},{"internalType":"uint256","name":"_decimal","type":"uint256"}],"name":"setPlatFormFeeCharges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"setTreasuryWallet","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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"treasuryMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040526014600f556005601055600a6011555f6012556001601355604051806080016040528060518152602001620051de60519139601590816200004691906200081e565b5034801562000053575f80fd5b506040516200522f3803806200522f833981810160405281019062000079919062000967565b336040518060400160405280600c81526020017f436974697a656e205061737300000000000000000000000000000000000000008152506040518060400160405280600281526020017f4350000000000000000000000000000000000000000000000000000000000000815250815f9081620000f691906200081e565b5080600190816200010891906200081e565b5050505f60075f6101000a81548160ff0219169083151502179055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000197575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016200018e9190620009e7565b60405180910390fd5b620001a8816200038e60201b60201c565b50620001bd5f801b336200045360201b60201c565b50620001f07f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200045360201b60201c565b50620002237f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336200045360201b60201c565b50620002567f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a856200045360201b60201c565b50620002897f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6856200045360201b60201c565b50620002bc7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb856200045360201b60201c565b505f60148190555082600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505062000a02565b5f600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6200046683836200054f60201b60201c565b6200054557600160085f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550620004e1620005b360201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001905062000549565b5f90505b92915050565b5f60085f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200063657607f821691505b6020821081036200064c576200064b620005f1565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620006b07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000673565b620006bc868362000673565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200070662000700620006fa84620006d4565b620006dd565b620006d4565b9050919050565b5f819050919050565b6200072183620006e6565b6200073962000730826200070d565b8484546200067f565b825550505050565b5f90565b6200074f62000741565b6200075c81848462000716565b505050565b5b818110156200078357620007775f8262000745565b60018101905062000762565b5050565b601f821115620007d2576200079c8162000652565b620007a78462000664565b81016020851015620007b7578190505b620007cf620007c68562000664565b83018262000761565b50505b505050565b5f82821c905092915050565b5f620007f45f1984600802620007d7565b1980831691505092915050565b5f6200080e8383620007e3565b9150826002028217905092915050565b6200082982620005ba565b67ffffffffffffffff811115620008455762000844620005c4565b5b6200085182546200061e565b6200085e82828562000787565b5f60209050601f83116001811462000894575f84156200087f578287015190505b6200088b858262000801565b865550620008fa565b601f198416620008a48662000652565b5f5b82811015620008cd57848901518255600182019150602085019450602081019050620008a6565b86831015620008ed5784890151620008e9601f891682620007e3565b8355505b6001600288020188555050505b505050505050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620009318262000906565b9050919050565b620009438162000925565b81146200094e575f80fd5b50565b5f81519050620009618162000938565b92915050565b5f805f806080858703121562000982576200098162000902565b5b5f620009918782880162000951565b9450506020620009a48782880162000951565b9350506040620009b78782880162000951565b9250506060620009ca8782880162000951565b91505092959194509250565b620009e18162000925565b82525050565b5f602082019050620009fc5f830184620009d6565b92915050565b6147ce8062000a105f395ff3fe6080604052600436106102e7575f3560e01c80638da5cb5b1161018f578063d5391393116100db578063eda1d5e911610094578063f2fde38b1161006e578063f2fde38b14610bd3578063fcc2ec3d14610bfb578063fccd405914610c23578063fdd46f6014610c4b576103c9565b8063eda1d5e914610b47578063ee78b83314610b83578063efdc778814610bab576103c9565b8063d539139314610a49578063d547741f14610a73578063d94f44f114610a9b578063e175bd2014610ab7578063e63ab1e914610ae1578063e985e9c514610b0b576103c9565b8063a8602fea11610148578063ba1a681f11610122578063ba1a681f1461097f578063c7c3268b146109a9578063c87b56dd146109d1578063d3fc8cdf14610a0d576103c9565b8063a8602fea14610907578063ac568e841461092f578063b88d4fde14610957576103c9565b80638da5cb5b146107fd57806391d148541461082757806395d89b4114610863578063a217fddf1461088d578063a22cb465146108b7578063a3f8013f146108df576103c9565b806333190f701161024e5780635c975abb1161020757806370a08231116101e157806370a0823114610757578063715018a61461079357806378b9f1a9146107a95780637fd6f15c146107d3576103c9565b80635c975abb146106c757806361d027b3146106f15780636352211e1461071b576103c9565b806333190f70146105d357806333a1bb261461060f57806336568abe146106395780633ccfd60b14610661578063427440f11461067757806342842e0e1461069f576103c9565b80631a4231a4116102a05780631a4231a4146104d757806323b872dd14610501578063248a9ca3146105295780632db11544146105655780632e129dbb146105815780632f2ff15d146105ab576103c9565b806301ffc9a7146103cd57806304c76af01461040957806306fdde031461041f578063081812fc14610449578063095ea7b31461048557806318160ddd146104ad576103c9565b366103c957600160165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055503460175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550343373ffffffffffffffffffffffffffffffffffffffff167f188c4d19b4fadd1889d9bd9bf0ab7c97e0719434751e6c05feac6339c1c001ec60405160405180910390a3005b5f80fd5b3480156103d8575f80fd5b506103f360048036038101906103ee91906133a1565b610c75565b60405161040091906133e6565b60405180910390f35b348015610414575f80fd5b5061041d610c86565b005b34801561042a575f80fd5b50610433610d0d565b6040516104409190613489565b60405180910390f35b348015610454575f80fd5b5061046f600480360381019061046a91906134dc565b610d9c565b60405161047c9190613546565b60405180910390f35b348015610490575f80fd5b506104ab60048036038101906104a69190613589565b610db7565b005b3480156104b8575f80fd5b506104c1610dcd565b6040516104ce91906135d6565b60405180910390f35b3480156104e2575f80fd5b506104eb610dd3565b6040516104f891906135d6565b60405180910390f35b34801561050c575f80fd5b50610527600480360381019061052291906135ef565b610dd9565b005b348015610534575f80fd5b5061054f600480360381019061054a9190613672565b610ed8565b60405161055c91906136ac565b60405180910390f35b61057f600480360381019061057a91906134dc565b610ef5565b005b34801561058c575f80fd5b50610595611202565b6040516105a29190613546565b60405180910390f35b3480156105b6575f80fd5b506105d160048036038101906105cc91906136c5565b611227565b005b3480156105de575f80fd5b506105f960048036038101906105f49190613703565b611249565b60405161060691906135d6565b60405180910390f35b34801561061a575f80fd5b5061062361125e565b6040516106309190613489565b60405180910390f35b348015610644575f80fd5b5061065f600480360381019061065a91906136c5565b6112ea565b005b34801561066c575f80fd5b50610675611365565b005b348015610682575f80fd5b5061069d6004803603810190610698919061378f565b61153b565b005b3480156106aa575f80fd5b506106c560048036038101906106c091906135ef565b611652565b005b3480156106d2575f80fd5b506106db611671565b6040516106e891906133e6565b60405180910390f35b3480156106fc575f80fd5b50610705611686565b6040516107129190613546565b60405180910390f35b348015610726575f80fd5b50610741600480360381019061073c91906134dc565b6116ab565b60405161074e9190613546565b60405180910390f35b348015610762575f80fd5b5061077d60048036038101906107789190613703565b6116bc565b60405161078a91906135d6565b60405180910390f35b34801561079e575f80fd5b506107a7611772565b005b3480156107b4575f80fd5b506107bd611785565b6040516107ca9190613546565b60405180910390f35b3480156107de575f80fd5b506107e76117aa565b6040516107f491906135d6565b60405180910390f35b348015610808575f80fd5b506108116117b0565b60405161081e9190613546565b60405180910390f35b348015610832575f80fd5b5061084d600480360381019061084891906136c5565b6117d9565b60405161085a91906133e6565b60405180910390f35b34801561086e575f80fd5b5061087761183d565b6040516108849190613489565b60405180910390f35b348015610898575f80fd5b506108a16118cd565b6040516108ae91906136ac565b60405180910390f35b3480156108c2575f80fd5b506108dd60048036038101906108d89190613804565b6118d3565b005b3480156108ea575f80fd5b5061090560048036038101906109009190613842565b6118e9565b005b348015610912575f80fd5b5061092d60048036038101906109289190613703565b611940565b005b34801561093a575f80fd5b50610955600480360381019061095091906134dc565b611990565b005b348015610962575f80fd5b5061097d600480360381019061097891906139ba565b6119c5565b005b34801561098a575f80fd5b506109936119e2565b6040516109a091906135d6565b60405180910390f35b3480156109b4575f80fd5b506109cf60048036038101906109ca9190613a8f565b6119e8565b005b3480156109dc575f80fd5b506109f760048036038101906109f291906134dc565b611a29565b604051610a049190613489565b60405180910390f35b348015610a18575f80fd5b50610a336004803603810190610a2e9190613703565b611a3b565b604051610a4091906133e6565b60405180910390f35b348015610a54575f80fd5b50610a5d611a58565b604051610a6a91906136ac565b60405180910390f35b348015610a7e575f80fd5b50610a996004803603810190610a9491906136c5565b611a7c565b005b610ab56004803603810190610ab09190613b15565b611a9e565b005b348015610ac2575f80fd5b50610acb611c8c565b604051610ad891906135d6565b60405180910390f35b348015610aec575f80fd5b50610af5611c92565b604051610b0291906136ac565b60405180910390f35b348015610b16575f80fd5b50610b316004803603810190610b2c9190613b53565b611cb6565b604051610b3e91906133e6565b60405180910390f35b348015610b52575f80fd5b50610b6d6004803603810190610b689190613703565b611d44565b604051610b7a91906135d6565b60405180910390f35b348015610b8e575f80fd5b50610ba96004803603810190610ba49190613703565b611d59565b005b348015610bb6575f80fd5b50610bd16004803603810190610bcc91906134dc565b611dc7565b005b348015610bde575f80fd5b50610bf96004803603810190610bf49190613703565b611eb5565b005b348015610c06575f80fd5b50610c216004803603810190610c1c9190613703565b611f8f565b005b348015610c2e575f80fd5b50610c496004803603810190610c449190613b91565b611ffd565b005b348015610c56575f80fd5b50610c5f61203a565b604051610c6c91906136ac565b60405180910390f35b5f610c7f8261205e565b9050919050565b5f801b610c92816120d7565b5f3373ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050905080610d09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0090613c19565b60405180910390fd5b5050565b60605f8054610d1b90613c64565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4790613c64565b8015610d925780601f10610d6957610100808354040283529160200191610d92565b820191905f5260205f20905b815481529060010190602001808311610d7557829003601f168201915b5050505050905090565b5f610da6826120eb565b50610db082612171565b9050919050565b610dc98282610dc46121aa565b6121b1565b5050565b60145481565b60125481565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e49575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610e409190613546565b60405180910390fd5b5f610e5c8383610e576121aa565b6121c3565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ed2578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610ec993929190613c94565b60405180910390fd5b50505050565b5f60085f8381526020019081526020015f20600101549050919050565b600e5f9054906101000a900460ff16610f43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3a90613d13565b60405180910390fd5b600f5481601454610f549190613d5e565b1115610f95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8c90613ddb565b60405180910390fd5b601354600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541115611017576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100e90613e43565b60405180910390fd5b60135481600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546110639190613d5e565b11156110a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109b90613e43565b60405180910390fd5b34601254826110b39190613e61565b11156110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110eb90613eec565b60405180910390fd5b5f5b818110156111b25761110860096123ce565b5f61111360096123e2565b9050600160145f8282546111279190613d5e565b925050819055506001600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461117b9190613d5e565b9250508190555061118c33826123ee565b61119e81611199836124e1565b612515565b5080806111aa90613f0a565b9150506110f6565b506111ff600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a9e565b50565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61123082610ed8565b611239816120d7565b611243838361256f565b50505050565b6017602052805f5260405f205f915090505481565b6015805461126b90613c64565b80601f016020809104026020016040519081016040528092919081815260200182805461129790613c64565b80156112e25780601f106112b9576101008083540402835291602001916112e2565b820191905f5260205f20905b8154815290600101906020018083116112c557829003601f168201915b505050505081565b6112f26121aa565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611356576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113608282612659565b505050565b60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e590613f9b565b60405180910390fd5b5f60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f3373ffffffffffffffffffffffffffffffffffffffff166108fc60175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490811502906040515f60405180830381858888f193505050509050806114f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ed90613c19565b60405180910390fd5b5f60175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611565816120d7565b5f5b8383905081101561164c57600f5460016014546115849190613d5e565b11156115c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115bc90614003565b60405180910390fd5b6115cf60096123ce565b5f6115da60096123e2565b9050600160145f8282546115ee9190613d5e565b9250508190555061162685858481811061160b5761160a614021565b5b90506020020160208101906116209190613703565b826123ee565b61163881611633836124e1565b612515565b50808061164490613f0a565b915050611567565b50505050565b61166c83838360405180602001604052805f8152506119c5565b505050565b5f60075f9054906101000a900460ff16905090565b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f6116b5826120eb565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361172d575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016117249190613546565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61177a612743565b6117835f6127ca565b565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60105481565b5f600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f60085f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60606001805461184c90613c64565b80601f016020809104026020016040519081016040528092919081815260200182805461187890613c64565b80156118c35780601f1061189a576101008083540402835291602001916118c3565b820191905f5260205f20905b8154815290600101906020018083116118a657829003601f168201915b5050505050905090565b5f801b81565b6118e56118de6121aa565b838361288f565b5050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611913816120d7565b836012819055508260138190555081600e5f6101000a81548160ff02191690831515021790555050505050565b5f801b61194c816120d7565b81600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66119ba816120d7565b81600f819055505050565b6119d0848484610dd9565b6119dc848484846129f8565b50505050565b60115481565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611a12816120d7565b828260159182611a239291906141f5565b50505050565b6060611a34826124e1565b9050919050565b6016602052805f5260405f205f915054906101000a900460ff1681565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b611a8582610ed8565b611a8e816120d7565b611a988383612659565b50505050565b5f6012541115611bfb575f3490505f601154606460105484611ac09190613e61565b611aca91906142ef565b611ad491906142ef565b90505f8183611ae3919061431f565b905080471015611b28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1f906143c2565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611b6b573d5f803e3d5ffd5b5081471015611baf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ba690614450565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f19350505050158015611bf2573d5f803e3d5ffd5b50505050611c88565b5f34905080471015611c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3990614450565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611c85573d5f803e3d5ffd5b50505b5050565b60135481565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b600d602052805f5260405f205f915090505481565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611d83816120d7565b81600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f801b611dd3816120d7565b600f5482601454611de49190613d5e565b1115611e25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1c90614003565b60405180910390fd5b5f5b82811015611eb057611e3960096123ce565b5f611e4460096123e2565b9050600160145f828254611e589190613d5e565b92505081905550611e8a600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826123ee565b611e9c81611e97836124e1565b612515565b508080611ea890613f0a565b915050611e27565b505050565b611ebd612743565b611ec95f801b33612659565b50611ef47f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633612659565b50611f1f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33612659565b50611f2c5f801b8261256f565b50611f577f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68261256f565b50611f827f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8261256f565b50611f8c816127ca565b50565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb611fb9816120d7565b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb612027816120d7565b8260108190555081601181905550505050565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb81565b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806120d057506120cf82612baa565b5b9050919050565b6120e8816120e36121aa565b612c0a565b50565b5f806120f683612c5b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361216857826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161215f91906135d6565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6121be8383836001612c94565b505050565b5f806121ce84612c5b565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461220f5761220e818486612e53565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461229a5761224e5f855f80612c94565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461231957600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b6001815f015f828254019250508190555050565b5f815f01549050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361245e575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016124559190613546565b60405180910390fd5b5f61246a83835f6121c3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146124dc575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016124d39190613546565b60405180910390fd5b505050565b606060156124ee83612f16565b6040516020016124ff929190614572565b6040516020818303038152906040529050919050565b8060065f8481526020019081526020015f20908161253391906145a0565b507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78260405161256391906135d6565b60405180910390a15050565b5f61257a83836117d9565b61264f57600160085f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506125ec6121aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050612653565b5f90505b92915050565b5f61266483836117d9565b15612739575f60085f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506126d66121aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a46001905061273d565b5f90505b92915050565b61274b6121aa565b73ffffffffffffffffffffffffffffffffffffffff166127696117b0565b73ffffffffffffffffffffffffffffffffffffffff16146127c85761278c6121aa565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016127bf9190613546565b60405180910390fd5b565b5f600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036128ff57816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016128f69190613546565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516129eb91906133e6565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612ba4578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a3b6121aa565b8685856040518563ffffffff1660e01b8152600401612a5d94939291906146c1565b6020604051808303815f875af1925050508015612a9857506040513d601f19601f82011682018060405250810190612a95919061471f565b60015b612b19573d805f8114612ac6576040519150601f19603f3d011682016040523d82523d5f602084013e612acb565b606091505b505f815103612b1157836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612b089190613546565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612ba257836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612b999190613546565b60405180910390fd5b505b50505050565b5f634906490660e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612c035750612c0282612fe0565b5b9050919050565b612c1482826117d9565b612c575780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401612c4e92919061474a565b60405180910390fd5b5050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080612ccc57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612dfe575f612cdb846120eb565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612d4557508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015612d585750612d568184611cb6565b155b15612d9a57826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401612d919190613546565b60405180910390fd5b8115612dfc57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b612e5e8383836130c1565b612f11575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ed257806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612ec991906135d6565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612f08929190614771565b60405180910390fd5b505050565b60605f6001612f2484613181565b0190505f8167ffffffffffffffff811115612f4257612f41613896565b5b6040519080825280601f01601f191660200182016040528015612f745781602001600182028036833780820191505090505b5090505f82602001820190505b600115612fd5578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612fca57612fc96142c2565b5b0494505f8503612f81575b819350505050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806130aa57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806130ba57506130b9826132d2565b5b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561317857508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061313957506131388484611cb6565b5b8061317757508273ffffffffffffffffffffffffffffffffffffffff1661315f83612171565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106131dd577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816131d3576131d26142c2565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061321a576d04ee2d6d415b85acef810000000083816132105761320f6142c2565b5b0492506020810190505b662386f26fc10000831061324957662386f26fc10000838161323f5761323e6142c2565b5b0492506010810190505b6305f5e1008310613272576305f5e1008381613268576132676142c2565b5b0492506008810190505b612710831061329757612710838161328d5761328c6142c2565b5b0492506004810190505b606483106132ba57606483816132b0576132af6142c2565b5b0492506002810190505b600a83106132c9576001810190505b80915050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6133808161334c565b811461338a575f80fd5b50565b5f8135905061339b81613377565b92915050565b5f602082840312156133b6576133b5613344565b5b5f6133c38482850161338d565b91505092915050565b5f8115159050919050565b6133e0816133cc565b82525050565b5f6020820190506133f95f8301846133d7565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561343657808201518184015260208101905061341b565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61345b826133ff565b6134658185613409565b9350613475818560208601613419565b61347e81613441565b840191505092915050565b5f6020820190508181035f8301526134a18184613451565b905092915050565b5f819050919050565b6134bb816134a9565b81146134c5575f80fd5b50565b5f813590506134d6816134b2565b92915050565b5f602082840312156134f1576134f0613344565b5b5f6134fe848285016134c8565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61353082613507565b9050919050565b61354081613526565b82525050565b5f6020820190506135595f830184613537565b92915050565b61356881613526565b8114613572575f80fd5b50565b5f813590506135838161355f565b92915050565b5f806040838503121561359f5761359e613344565b5b5f6135ac85828601613575565b92505060206135bd858286016134c8565b9150509250929050565b6135d0816134a9565b82525050565b5f6020820190506135e95f8301846135c7565b92915050565b5f805f6060848603121561360657613605613344565b5b5f61361386828701613575565b935050602061362486828701613575565b9250506040613635868287016134c8565b9150509250925092565b5f819050919050565b6136518161363f565b811461365b575f80fd5b50565b5f8135905061366c81613648565b92915050565b5f6020828403121561368757613686613344565b5b5f6136948482850161365e565b91505092915050565b6136a68161363f565b82525050565b5f6020820190506136bf5f83018461369d565b92915050565b5f80604083850312156136db576136da613344565b5b5f6136e88582860161365e565b92505060206136f985828601613575565b9150509250929050565b5f6020828403121561371857613717613344565b5b5f61372584828501613575565b91505092915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261374f5761374e61372e565b5b8235905067ffffffffffffffff81111561376c5761376b613732565b5b60208301915083602082028301111561378857613787613736565b5b9250929050565b5f80602083850312156137a5576137a4613344565b5b5f83013567ffffffffffffffff8111156137c2576137c1613348565b5b6137ce8582860161373a565b92509250509250929050565b6137e3816133cc565b81146137ed575f80fd5b50565b5f813590506137fe816137da565b92915050565b5f806040838503121561381a57613819613344565b5b5f61382785828601613575565b9250506020613838858286016137f0565b9150509250929050565b5f805f6060848603121561385957613858613344565b5b5f613866868287016134c8565b9350506020613877868287016134c8565b9250506040613888868287016137f0565b9150509250925092565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6138cc82613441565b810181811067ffffffffffffffff821117156138eb576138ea613896565b5b80604052505050565b5f6138fd61333b565b905061390982826138c3565b919050565b5f67ffffffffffffffff82111561392857613927613896565b5b61393182613441565b9050602081019050919050565b828183375f83830152505050565b5f61395e6139598461390e565b6138f4565b90508281526020810184848401111561397a57613979613892565b5b61398584828561393e565b509392505050565b5f82601f8301126139a1576139a061372e565b5b81356139b184826020860161394c565b91505092915050565b5f805f80608085870312156139d2576139d1613344565b5b5f6139df87828801613575565b94505060206139f087828801613575565b9350506040613a01878288016134c8565b925050606085013567ffffffffffffffff811115613a2257613a21613348565b5b613a2e8782880161398d565b91505092959194509250565b5f8083601f840112613a4f57613a4e61372e565b5b8235905067ffffffffffffffff811115613a6c57613a6b613732565b5b602083019150836001820283011115613a8857613a87613736565b5b9250929050565b5f8060208385031215613aa557613aa4613344565b5b5f83013567ffffffffffffffff811115613ac257613ac1613348565b5b613ace85828601613a3a565b92509250509250929050565b5f613ae482613507565b9050919050565b613af481613ada565b8114613afe575f80fd5b50565b5f81359050613b0f81613aeb565b92915050565b5f8060408385031215613b2b57613b2a613344565b5b5f613b3885828601613b01565b9250506020613b4985828601613b01565b9150509250929050565b5f8060408385031215613b6957613b68613344565b5b5f613b7685828601613575565b9250506020613b8785828601613575565b9150509250929050565b5f8060408385031215613ba757613ba6613344565b5b5f613bb4858286016134c8565b9250506020613bc5858286016134c8565b9150509250929050565b7f4574686572207472616e73666572206661696c65642e000000000000000000005f82015250565b5f613c03601683613409565b9150613c0e82613bcf565b602082019050919050565b5f6020820190508181035f830152613c3081613bf7565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613c7b57607f821691505b602082108103613c8e57613c8d613c37565b5b50919050565b5f606082019050613ca75f830186613537565b613cb460208301856135c7565b613cc16040830184613537565b949350505050565b7f5075626c6963206d696e74206973206e6f74206f70656e0000000000000000005f82015250565b5f613cfd601783613409565b9150613d0882613cc9565b602082019050919050565b5f6020820190508181035f830152613d2a81613cf1565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613d68826134a9565b9150613d73836134a9565b9250828201905080821115613d8b57613d8a613d31565b5b92915050565b7f746f6b656e206973206c657373000000000000000000000000000000000000005f82015250565b5f613dc5600d83613409565b9150613dd082613d91565b602082019050919050565b5f6020820190508181035f830152613df281613db9565b9050919050565b7f7573657220657863656564206d696e74206c696d6974000000000000000000005f82015250565b5f613e2d601683613409565b9150613e3882613df9565b602082019050919050565b5f6020820190508181035f830152613e5a81613e21565b9050919050565b5f613e6b826134a9565b9150613e76836134a9565b9250828202613e84816134a9565b91508282048414831517613e9b57613e9a613d31565b5b5092915050565b7f757365722070617373206c6f77657220616d6f756e74000000000000000000005f82015250565b5f613ed6601683613409565b9150613ee182613ea2565b602082019050919050565b5f6020820190508181035f830152613f0381613eca565b9050919050565b5f613f14826134a9565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f4657613f45613d31565b5b600182019050919050565b7f5573657220686173206e6f7420796574207061696400000000000000000000005f82015250565b5f613f85601583613409565b9150613f9082613f51565b602082019050919050565b5f6020820190508181035f830152613fb281613f79565b9050919050565b7f737570706c7920657863656564000000000000000000000000000000000000005f82015250565b5f613fed600d83613409565b9150613ff882613fb9565b602082019050919050565b5f6020820190508181035f83015261401a81613fe1565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026140b47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614079565b6140be8683614079565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6140f96140f46140ef846134a9565b6140d6565b6134a9565b9050919050565b5f819050919050565b614112836140df565b61412661411e82614100565b848454614085565b825550505050565b5f90565b61413a61412e565b614145818484614109565b505050565b5b818110156141685761415d5f82614132565b60018101905061414b565b5050565b601f8211156141ad5761417e81614058565b6141878461406a565b81016020851015614196578190505b6141aa6141a28561406a565b83018261414a565b50505b505050565b5f82821c905092915050565b5f6141cd5f19846008026141b2565b1980831691505092915050565b5f6141e583836141be565b9150826002028217905092915050565b6141ff838361404e565b67ffffffffffffffff81111561421857614217613896565b5b6142228254613c64565b61422d82828561416c565b5f601f83116001811461425a575f8415614248578287013590505b61425285826141da565b8655506142b9565b601f19841661426886614058565b5f5b8281101561428f5784890135825560018201915060208501945060208101905061426a565b868310156142ac57848901356142a8601f8916826141be565b8355505b6001600288020188555050505b50505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142f9826134a9565b9150614304836134a9565b925082614314576143136142c2565b5b828204905092915050565b5f614329826134a9565b9150614334836134a9565b925082820390508181111561434c5761434b613d31565b5b92915050565b7f496e73756666696369656e742062616c616e636520746f2073656e64207468655f8201527f206669727374207472616e73616374696f6e0000000000000000000000000000602082015250565b5f6143ac603283613409565b91506143b782614352565b604082019050919050565b5f6020820190508181035f8301526143d9816143a0565b9050919050565b7f496e73756666696369656e742062616c616e636520746f2073656e64207468655f8201527f207365636f6e64207472616e73616374696f6e00000000000000000000000000602082015250565b5f61443a603383613409565b9150614445826143e0565b604082019050919050565b5f6020820190508181035f8301526144678161442e565b9050919050565b5f81905092915050565b5f815461448481613c64565b61448e818661446e565b9450600182165f81146144a857600181146144bd576144ef565b60ff19831686528115158202860193506144ef565b6144c685614058565b5f5b838110156144e7578154818901526001820191506020810190506144c8565b838801955050505b50505092915050565b5f614502826133ff565b61450c818561446e565b935061451c818560208601613419565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61455c60058361446e565b915061456782614528565b600582019050919050565b5f61457d8285614478565b915061458982846144f8565b915061459482614550565b91508190509392505050565b6145a9826133ff565b67ffffffffffffffff8111156145c2576145c1613896565b5b6145cc8254613c64565b6145d782828561416c565b5f60209050601f831160018114614608575f84156145f6578287015190505b61460085826141da565b865550614667565b601f19841661461686614058565b5f5b8281101561463d57848901518255600182019150602085019450602081019050614618565b8683101561465a5784890151614656601f8916826141be565b8355505b6001600288020188555050505b505050505050565b5f81519050919050565b5f82825260208201905092915050565b5f6146938261466f565b61469d8185614679565b93506146ad818560208601613419565b6146b681613441565b840191505092915050565b5f6080820190506146d45f830187613537565b6146e16020830186613537565b6146ee60408301856135c7565b81810360608301526147008184614689565b905095945050505050565b5f8151905061471981613377565b92915050565b5f6020828403121561473457614733613344565b5b5f6147418482850161470b565b91505092915050565b5f60408201905061475d5f830185613537565b61476a602083018461369d565b9392505050565b5f6040820190506147845f830185613537565b61479160208301846135c7565b939250505056fea2646970667358221220828ea933287bf5c2783726ba01a4f7e7b69f5bb35cb2da4a751f5d09e0d425d964736f6c6343000814003368747470733a2f2f697066732e696f2f697066732f6261667962656963793363656c373271693473786b65646c786a64326d6f74376b636367377472667a346c36646a786a676173696934716b6c34652f000000000000000000000000192c3baa95235b84b46e76ea3fbff51b092dc0ed00000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae000000000000000000000000ef6070be0954ea67985120eef153802180ec77d800000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae

Deployed Bytecode

0x6080604052600436106102e7575f3560e01c80638da5cb5b1161018f578063d5391393116100db578063eda1d5e911610094578063f2fde38b1161006e578063f2fde38b14610bd3578063fcc2ec3d14610bfb578063fccd405914610c23578063fdd46f6014610c4b576103c9565b8063eda1d5e914610b47578063ee78b83314610b83578063efdc778814610bab576103c9565b8063d539139314610a49578063d547741f14610a73578063d94f44f114610a9b578063e175bd2014610ab7578063e63ab1e914610ae1578063e985e9c514610b0b576103c9565b8063a8602fea11610148578063ba1a681f11610122578063ba1a681f1461097f578063c7c3268b146109a9578063c87b56dd146109d1578063d3fc8cdf14610a0d576103c9565b8063a8602fea14610907578063ac568e841461092f578063b88d4fde14610957576103c9565b80638da5cb5b146107fd57806391d148541461082757806395d89b4114610863578063a217fddf1461088d578063a22cb465146108b7578063a3f8013f146108df576103c9565b806333190f701161024e5780635c975abb1161020757806370a08231116101e157806370a0823114610757578063715018a61461079357806378b9f1a9146107a95780637fd6f15c146107d3576103c9565b80635c975abb146106c757806361d027b3146106f15780636352211e1461071b576103c9565b806333190f70146105d357806333a1bb261461060f57806336568abe146106395780633ccfd60b14610661578063427440f11461067757806342842e0e1461069f576103c9565b80631a4231a4116102a05780631a4231a4146104d757806323b872dd14610501578063248a9ca3146105295780632db11544146105655780632e129dbb146105815780632f2ff15d146105ab576103c9565b806301ffc9a7146103cd57806304c76af01461040957806306fdde031461041f578063081812fc14610449578063095ea7b31461048557806318160ddd146104ad576103c9565b366103c957600160165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055503460175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550343373ffffffffffffffffffffffffffffffffffffffff167f188c4d19b4fadd1889d9bd9bf0ab7c97e0719434751e6c05feac6339c1c001ec60405160405180910390a3005b5f80fd5b3480156103d8575f80fd5b506103f360048036038101906103ee91906133a1565b610c75565b60405161040091906133e6565b60405180910390f35b348015610414575f80fd5b5061041d610c86565b005b34801561042a575f80fd5b50610433610d0d565b6040516104409190613489565b60405180910390f35b348015610454575f80fd5b5061046f600480360381019061046a91906134dc565b610d9c565b60405161047c9190613546565b60405180910390f35b348015610490575f80fd5b506104ab60048036038101906104a69190613589565b610db7565b005b3480156104b8575f80fd5b506104c1610dcd565b6040516104ce91906135d6565b60405180910390f35b3480156104e2575f80fd5b506104eb610dd3565b6040516104f891906135d6565b60405180910390f35b34801561050c575f80fd5b50610527600480360381019061052291906135ef565b610dd9565b005b348015610534575f80fd5b5061054f600480360381019061054a9190613672565b610ed8565b60405161055c91906136ac565b60405180910390f35b61057f600480360381019061057a91906134dc565b610ef5565b005b34801561058c575f80fd5b50610595611202565b6040516105a29190613546565b60405180910390f35b3480156105b6575f80fd5b506105d160048036038101906105cc91906136c5565b611227565b005b3480156105de575f80fd5b506105f960048036038101906105f49190613703565b611249565b60405161060691906135d6565b60405180910390f35b34801561061a575f80fd5b5061062361125e565b6040516106309190613489565b60405180910390f35b348015610644575f80fd5b5061065f600480360381019061065a91906136c5565b6112ea565b005b34801561066c575f80fd5b50610675611365565b005b348015610682575f80fd5b5061069d6004803603810190610698919061378f565b61153b565b005b3480156106aa575f80fd5b506106c560048036038101906106c091906135ef565b611652565b005b3480156106d2575f80fd5b506106db611671565b6040516106e891906133e6565b60405180910390f35b3480156106fc575f80fd5b50610705611686565b6040516107129190613546565b60405180910390f35b348015610726575f80fd5b50610741600480360381019061073c91906134dc565b6116ab565b60405161074e9190613546565b60405180910390f35b348015610762575f80fd5b5061077d60048036038101906107789190613703565b6116bc565b60405161078a91906135d6565b60405180910390f35b34801561079e575f80fd5b506107a7611772565b005b3480156107b4575f80fd5b506107bd611785565b6040516107ca9190613546565b60405180910390f35b3480156107de575f80fd5b506107e76117aa565b6040516107f491906135d6565b60405180910390f35b348015610808575f80fd5b506108116117b0565b60405161081e9190613546565b60405180910390f35b348015610832575f80fd5b5061084d600480360381019061084891906136c5565b6117d9565b60405161085a91906133e6565b60405180910390f35b34801561086e575f80fd5b5061087761183d565b6040516108849190613489565b60405180910390f35b348015610898575f80fd5b506108a16118cd565b6040516108ae91906136ac565b60405180910390f35b3480156108c2575f80fd5b506108dd60048036038101906108d89190613804565b6118d3565b005b3480156108ea575f80fd5b5061090560048036038101906109009190613842565b6118e9565b005b348015610912575f80fd5b5061092d60048036038101906109289190613703565b611940565b005b34801561093a575f80fd5b50610955600480360381019061095091906134dc565b611990565b005b348015610962575f80fd5b5061097d600480360381019061097891906139ba565b6119c5565b005b34801561098a575f80fd5b506109936119e2565b6040516109a091906135d6565b60405180910390f35b3480156109b4575f80fd5b506109cf60048036038101906109ca9190613a8f565b6119e8565b005b3480156109dc575f80fd5b506109f760048036038101906109f291906134dc565b611a29565b604051610a049190613489565b60405180910390f35b348015610a18575f80fd5b50610a336004803603810190610a2e9190613703565b611a3b565b604051610a4091906133e6565b60405180910390f35b348015610a54575f80fd5b50610a5d611a58565b604051610a6a91906136ac565b60405180910390f35b348015610a7e575f80fd5b50610a996004803603810190610a9491906136c5565b611a7c565b005b610ab56004803603810190610ab09190613b15565b611a9e565b005b348015610ac2575f80fd5b50610acb611c8c565b604051610ad891906135d6565b60405180910390f35b348015610aec575f80fd5b50610af5611c92565b604051610b0291906136ac565b60405180910390f35b348015610b16575f80fd5b50610b316004803603810190610b2c9190613b53565b611cb6565b604051610b3e91906133e6565b60405180910390f35b348015610b52575f80fd5b50610b6d6004803603810190610b689190613703565b611d44565b604051610b7a91906135d6565b60405180910390f35b348015610b8e575f80fd5b50610ba96004803603810190610ba49190613703565b611d59565b005b348015610bb6575f80fd5b50610bd16004803603810190610bcc91906134dc565b611dc7565b005b348015610bde575f80fd5b50610bf96004803603810190610bf49190613703565b611eb5565b005b348015610c06575f80fd5b50610c216004803603810190610c1c9190613703565b611f8f565b005b348015610c2e575f80fd5b50610c496004803603810190610c449190613b91565b611ffd565b005b348015610c56575f80fd5b50610c5f61203a565b604051610c6c91906136ac565b60405180910390f35b5f610c7f8261205e565b9050919050565b5f801b610c92816120d7565b5f3373ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050905080610d09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0090613c19565b60405180910390fd5b5050565b60605f8054610d1b90613c64565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4790613c64565b8015610d925780601f10610d6957610100808354040283529160200191610d92565b820191905f5260205f20905b815481529060010190602001808311610d7557829003601f168201915b5050505050905090565b5f610da6826120eb565b50610db082612171565b9050919050565b610dc98282610dc46121aa565b6121b1565b5050565b60145481565b60125481565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e49575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610e409190613546565b60405180910390fd5b5f610e5c8383610e576121aa565b6121c3565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ed2578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610ec993929190613c94565b60405180910390fd5b50505050565b5f60085f8381526020019081526020015f20600101549050919050565b600e5f9054906101000a900460ff16610f43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3a90613d13565b60405180910390fd5b600f5481601454610f549190613d5e565b1115610f95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8c90613ddb565b60405180910390fd5b601354600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541115611017576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100e90613e43565b60405180910390fd5b60135481600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546110639190613d5e565b11156110a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109b90613e43565b60405180910390fd5b34601254826110b39190613e61565b11156110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110eb90613eec565b60405180910390fd5b5f5b818110156111b25761110860096123ce565b5f61111360096123e2565b9050600160145f8282546111279190613d5e565b925050819055506001600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461117b9190613d5e565b9250508190555061118c33826123ee565b61119e81611199836124e1565b612515565b5080806111aa90613f0a565b9150506110f6565b506111ff600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a9e565b50565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61123082610ed8565b611239816120d7565b611243838361256f565b50505050565b6017602052805f5260405f205f915090505481565b6015805461126b90613c64565b80601f016020809104026020016040519081016040528092919081815260200182805461129790613c64565b80156112e25780601f106112b9576101008083540402835291602001916112e2565b820191905f5260205f20905b8154815290600101906020018083116112c557829003601f168201915b505050505081565b6112f26121aa565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611356576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113608282612659565b505050565b60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166113ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e590613f9b565b60405180910390fd5b5f60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f3373ffffffffffffffffffffffffffffffffffffffff166108fc60175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490811502906040515f60405180830381858888f193505050509050806114f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ed90613c19565b60405180910390fd5b5f60175f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611565816120d7565b5f5b8383905081101561164c57600f5460016014546115849190613d5e565b11156115c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115bc90614003565b60405180910390fd5b6115cf60096123ce565b5f6115da60096123e2565b9050600160145f8282546115ee9190613d5e565b9250508190555061162685858481811061160b5761160a614021565b5b90506020020160208101906116209190613703565b826123ee565b61163881611633836124e1565b612515565b50808061164490613f0a565b915050611567565b50505050565b61166c83838360405180602001604052805f8152506119c5565b505050565b5f60075f9054906101000a900460ff16905090565b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f6116b5826120eb565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361172d575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016117249190613546565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61177a612743565b6117835f6127ca565b565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60105481565b5f600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f60085f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60606001805461184c90613c64565b80601f016020809104026020016040519081016040528092919081815260200182805461187890613c64565b80156118c35780601f1061189a576101008083540402835291602001916118c3565b820191905f5260205f20905b8154815290600101906020018083116118a657829003601f168201915b5050505050905090565b5f801b81565b6118e56118de6121aa565b838361288f565b5050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611913816120d7565b836012819055508260138190555081600e5f6101000a81548160ff02191690831515021790555050505050565b5f801b61194c816120d7565b81600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66119ba816120d7565b81600f819055505050565b6119d0848484610dd9565b6119dc848484846129f8565b50505050565b60115481565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611a12816120d7565b828260159182611a239291906141f5565b50505050565b6060611a34826124e1565b9050919050565b6016602052805f5260405f205f915054906101000a900460ff1681565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b611a8582610ed8565b611a8e816120d7565b611a988383612659565b50505050565b5f6012541115611bfb575f3490505f601154606460105484611ac09190613e61565b611aca91906142ef565b611ad491906142ef565b90505f8183611ae3919061431f565b905080471015611b28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1f906143c2565b60405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611b6b573d5f803e3d5ffd5b5081471015611baf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ba690614450565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f19350505050158015611bf2573d5f803e3d5ffd5b50505050611c88565b5f34905080471015611c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3990614450565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611c85573d5f803e3d5ffd5b50505b5050565b60135481565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b600d602052805f5260405f205f915090505481565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6611d83816120d7565b81600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f801b611dd3816120d7565b600f5482601454611de49190613d5e565b1115611e25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1c90614003565b60405180910390fd5b5f5b82811015611eb057611e3960096123ce565b5f611e4460096123e2565b9050600160145f828254611e589190613d5e565b92505081905550611e8a600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826123ee565b611e9c81611e97836124e1565b612515565b508080611ea890613f0a565b915050611e27565b505050565b611ebd612743565b611ec95f801b33612659565b50611ef47f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633612659565b50611f1f7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33612659565b50611f2c5f801b8261256f565b50611f577f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68261256f565b50611f827f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8261256f565b50611f8c816127ca565b50565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb611fb9816120d7565b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb612027816120d7565b8260108190555081601181905550505050565b7fc5abefe4aed277fb344652e626c3c4fe5cdab1313b8ac46cdd6da9bbe98161cb81565b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806120d057506120cf82612baa565b5b9050919050565b6120e8816120e36121aa565b612c0a565b50565b5f806120f683612c5b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361216857826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161215f91906135d6565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6121be8383836001612c94565b505050565b5f806121ce84612c5b565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461220f5761220e818486612e53565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461229a5761224e5f855f80612c94565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461231957600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b6001815f015f828254019250508190555050565b5f815f01549050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361245e575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016124559190613546565b60405180910390fd5b5f61246a83835f6121c3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146124dc575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016124d39190613546565b60405180910390fd5b505050565b606060156124ee83612f16565b6040516020016124ff929190614572565b6040516020818303038152906040529050919050565b8060065f8481526020019081526020015f20908161253391906145a0565b507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce78260405161256391906135d6565b60405180910390a15050565b5f61257a83836117d9565b61264f57600160085f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506125ec6121aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050612653565b5f90505b92915050565b5f61266483836117d9565b15612739575f60085f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506126d66121aa565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a46001905061273d565b5f90505b92915050565b61274b6121aa565b73ffffffffffffffffffffffffffffffffffffffff166127696117b0565b73ffffffffffffffffffffffffffffffffffffffff16146127c85761278c6121aa565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016127bf9190613546565b60405180910390fd5b565b5f600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036128ff57816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016128f69190613546565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516129eb91906133e6565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612ba4578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a3b6121aa565b8685856040518563ffffffff1660e01b8152600401612a5d94939291906146c1565b6020604051808303815f875af1925050508015612a9857506040513d601f19601f82011682018060405250810190612a95919061471f565b60015b612b19573d805f8114612ac6576040519150601f19603f3d011682016040523d82523d5f602084013e612acb565b606091505b505f815103612b1157836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612b089190613546565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612ba257836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612b999190613546565b60405180910390fd5b505b50505050565b5f634906490660e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612c035750612c0282612fe0565b5b9050919050565b612c1482826117d9565b612c575780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401612c4e92919061474a565b60405180910390fd5b5050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080612ccc57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612dfe575f612cdb846120eb565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612d4557508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015612d585750612d568184611cb6565b155b15612d9a57826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401612d919190613546565b60405180910390fd5b8115612dfc57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b612e5e8383836130c1565b612f11575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ed257806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612ec991906135d6565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612f08929190614771565b60405180910390fd5b505050565b60605f6001612f2484613181565b0190505f8167ffffffffffffffff811115612f4257612f41613896565b5b6040519080825280601f01601f191660200182016040528015612f745781602001600182028036833780820191505090505b5090505f82602001820190505b600115612fd5578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612fca57612fc96142c2565b5b0494505f8503612f81575b819350505050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806130aa57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806130ba57506130b9826132d2565b5b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561317857508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061313957506131388484611cb6565b5b8061317757508273ffffffffffffffffffffffffffffffffffffffff1661315f83612171565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106131dd577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816131d3576131d26142c2565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061321a576d04ee2d6d415b85acef810000000083816132105761320f6142c2565b5b0492506020810190505b662386f26fc10000831061324957662386f26fc10000838161323f5761323e6142c2565b5b0492506010810190505b6305f5e1008310613272576305f5e1008381613268576132676142c2565b5b0492506008810190505b612710831061329757612710838161328d5761328c6142c2565b5b0492506004810190505b606483106132ba57606483816132b0576132af6142c2565b5b0492506002810190505b600a83106132c9576001810190505b80915050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6133808161334c565b811461338a575f80fd5b50565b5f8135905061339b81613377565b92915050565b5f602082840312156133b6576133b5613344565b5b5f6133c38482850161338d565b91505092915050565b5f8115159050919050565b6133e0816133cc565b82525050565b5f6020820190506133f95f8301846133d7565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561343657808201518184015260208101905061341b565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61345b826133ff565b6134658185613409565b9350613475818560208601613419565b61347e81613441565b840191505092915050565b5f6020820190508181035f8301526134a18184613451565b905092915050565b5f819050919050565b6134bb816134a9565b81146134c5575f80fd5b50565b5f813590506134d6816134b2565b92915050565b5f602082840312156134f1576134f0613344565b5b5f6134fe848285016134c8565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61353082613507565b9050919050565b61354081613526565b82525050565b5f6020820190506135595f830184613537565b92915050565b61356881613526565b8114613572575f80fd5b50565b5f813590506135838161355f565b92915050565b5f806040838503121561359f5761359e613344565b5b5f6135ac85828601613575565b92505060206135bd858286016134c8565b9150509250929050565b6135d0816134a9565b82525050565b5f6020820190506135e95f8301846135c7565b92915050565b5f805f6060848603121561360657613605613344565b5b5f61361386828701613575565b935050602061362486828701613575565b9250506040613635868287016134c8565b9150509250925092565b5f819050919050565b6136518161363f565b811461365b575f80fd5b50565b5f8135905061366c81613648565b92915050565b5f6020828403121561368757613686613344565b5b5f6136948482850161365e565b91505092915050565b6136a68161363f565b82525050565b5f6020820190506136bf5f83018461369d565b92915050565b5f80604083850312156136db576136da613344565b5b5f6136e88582860161365e565b92505060206136f985828601613575565b9150509250929050565b5f6020828403121561371857613717613344565b5b5f61372584828501613575565b91505092915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261374f5761374e61372e565b5b8235905067ffffffffffffffff81111561376c5761376b613732565b5b60208301915083602082028301111561378857613787613736565b5b9250929050565b5f80602083850312156137a5576137a4613344565b5b5f83013567ffffffffffffffff8111156137c2576137c1613348565b5b6137ce8582860161373a565b92509250509250929050565b6137e3816133cc565b81146137ed575f80fd5b50565b5f813590506137fe816137da565b92915050565b5f806040838503121561381a57613819613344565b5b5f61382785828601613575565b9250506020613838858286016137f0565b9150509250929050565b5f805f6060848603121561385957613858613344565b5b5f613866868287016134c8565b9350506020613877868287016134c8565b9250506040613888868287016137f0565b9150509250925092565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6138cc82613441565b810181811067ffffffffffffffff821117156138eb576138ea613896565b5b80604052505050565b5f6138fd61333b565b905061390982826138c3565b919050565b5f67ffffffffffffffff82111561392857613927613896565b5b61393182613441565b9050602081019050919050565b828183375f83830152505050565b5f61395e6139598461390e565b6138f4565b90508281526020810184848401111561397a57613979613892565b5b61398584828561393e565b509392505050565b5f82601f8301126139a1576139a061372e565b5b81356139b184826020860161394c565b91505092915050565b5f805f80608085870312156139d2576139d1613344565b5b5f6139df87828801613575565b94505060206139f087828801613575565b9350506040613a01878288016134c8565b925050606085013567ffffffffffffffff811115613a2257613a21613348565b5b613a2e8782880161398d565b91505092959194509250565b5f8083601f840112613a4f57613a4e61372e565b5b8235905067ffffffffffffffff811115613a6c57613a6b613732565b5b602083019150836001820283011115613a8857613a87613736565b5b9250929050565b5f8060208385031215613aa557613aa4613344565b5b5f83013567ffffffffffffffff811115613ac257613ac1613348565b5b613ace85828601613a3a565b92509250509250929050565b5f613ae482613507565b9050919050565b613af481613ada565b8114613afe575f80fd5b50565b5f81359050613b0f81613aeb565b92915050565b5f8060408385031215613b2b57613b2a613344565b5b5f613b3885828601613b01565b9250506020613b4985828601613b01565b9150509250929050565b5f8060408385031215613b6957613b68613344565b5b5f613b7685828601613575565b9250506020613b8785828601613575565b9150509250929050565b5f8060408385031215613ba757613ba6613344565b5b5f613bb4858286016134c8565b9250506020613bc5858286016134c8565b9150509250929050565b7f4574686572207472616e73666572206661696c65642e000000000000000000005f82015250565b5f613c03601683613409565b9150613c0e82613bcf565b602082019050919050565b5f6020820190508181035f830152613c3081613bf7565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613c7b57607f821691505b602082108103613c8e57613c8d613c37565b5b50919050565b5f606082019050613ca75f830186613537565b613cb460208301856135c7565b613cc16040830184613537565b949350505050565b7f5075626c6963206d696e74206973206e6f74206f70656e0000000000000000005f82015250565b5f613cfd601783613409565b9150613d0882613cc9565b602082019050919050565b5f6020820190508181035f830152613d2a81613cf1565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613d68826134a9565b9150613d73836134a9565b9250828201905080821115613d8b57613d8a613d31565b5b92915050565b7f746f6b656e206973206c657373000000000000000000000000000000000000005f82015250565b5f613dc5600d83613409565b9150613dd082613d91565b602082019050919050565b5f6020820190508181035f830152613df281613db9565b9050919050565b7f7573657220657863656564206d696e74206c696d6974000000000000000000005f82015250565b5f613e2d601683613409565b9150613e3882613df9565b602082019050919050565b5f6020820190508181035f830152613e5a81613e21565b9050919050565b5f613e6b826134a9565b9150613e76836134a9565b9250828202613e84816134a9565b91508282048414831517613e9b57613e9a613d31565b5b5092915050565b7f757365722070617373206c6f77657220616d6f756e74000000000000000000005f82015250565b5f613ed6601683613409565b9150613ee182613ea2565b602082019050919050565b5f6020820190508181035f830152613f0381613eca565b9050919050565b5f613f14826134a9565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f4657613f45613d31565b5b600182019050919050565b7f5573657220686173206e6f7420796574207061696400000000000000000000005f82015250565b5f613f85601583613409565b9150613f9082613f51565b602082019050919050565b5f6020820190508181035f830152613fb281613f79565b9050919050565b7f737570706c7920657863656564000000000000000000000000000000000000005f82015250565b5f613fed600d83613409565b9150613ff882613fb9565b602082019050919050565b5f6020820190508181035f83015261401a81613fe1565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026140b47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614079565b6140be8683614079565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6140f96140f46140ef846134a9565b6140d6565b6134a9565b9050919050565b5f819050919050565b614112836140df565b61412661411e82614100565b848454614085565b825550505050565b5f90565b61413a61412e565b614145818484614109565b505050565b5b818110156141685761415d5f82614132565b60018101905061414b565b5050565b601f8211156141ad5761417e81614058565b6141878461406a565b81016020851015614196578190505b6141aa6141a28561406a565b83018261414a565b50505b505050565b5f82821c905092915050565b5f6141cd5f19846008026141b2565b1980831691505092915050565b5f6141e583836141be565b9150826002028217905092915050565b6141ff838361404e565b67ffffffffffffffff81111561421857614217613896565b5b6142228254613c64565b61422d82828561416c565b5f601f83116001811461425a575f8415614248578287013590505b61425285826141da565b8655506142b9565b601f19841661426886614058565b5f5b8281101561428f5784890135825560018201915060208501945060208101905061426a565b868310156142ac57848901356142a8601f8916826141be565b8355505b6001600288020188555050505b50505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142f9826134a9565b9150614304836134a9565b925082614314576143136142c2565b5b828204905092915050565b5f614329826134a9565b9150614334836134a9565b925082820390508181111561434c5761434b613d31565b5b92915050565b7f496e73756666696369656e742062616c616e636520746f2073656e64207468655f8201527f206669727374207472616e73616374696f6e0000000000000000000000000000602082015250565b5f6143ac603283613409565b91506143b782614352565b604082019050919050565b5f6020820190508181035f8301526143d9816143a0565b9050919050565b7f496e73756666696369656e742062616c616e636520746f2073656e64207468655f8201527f207365636f6e64207472616e73616374696f6e00000000000000000000000000602082015250565b5f61443a603383613409565b9150614445826143e0565b604082019050919050565b5f6020820190508181035f8301526144678161442e565b9050919050565b5f81905092915050565b5f815461448481613c64565b61448e818661446e565b9450600182165f81146144a857600181146144bd576144ef565b60ff19831686528115158202860193506144ef565b6144c685614058565b5f5b838110156144e7578154818901526001820191506020810190506144c8565b838801955050505b50505092915050565b5f614502826133ff565b61450c818561446e565b935061451c818560208601613419565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61455c60058361446e565b915061456782614528565b600582019050919050565b5f61457d8285614478565b915061458982846144f8565b915061459482614550565b91508190509392505050565b6145a9826133ff565b67ffffffffffffffff8111156145c2576145c1613896565b5b6145cc8254613c64565b6145d782828561416c565b5f60209050601f831160018114614608575f84156145f6578287015190505b61460085826141da565b865550614667565b601f19841661461686614058565b5f5b8281101561463d57848901518255600182019150602085019450602081019050614618565b8683101561465a5784890151614656601f8916826141be565b8355505b6001600288020188555050505b505050505050565b5f81519050919050565b5f82825260208201905092915050565b5f6146938261466f565b61469d8185614679565b93506146ad818560208601613419565b6146b681613441565b840191505092915050565b5f6080820190506146d45f830187613537565b6146e16020830186613537565b6146ee60408301856135c7565b81810360608301526147008184614689565b905095945050505050565b5f8151905061471981613377565b92915050565b5f6020828403121561473457614733613344565b5b5f6147418482850161470b565b91505092915050565b5f60408201905061475d5f830185613537565b61476a602083018461369d565b9392505050565b5f6040820190506147845f830185613537565b61479160208301846135c7565b939250505056fea2646970667358221220828ea933287bf5c2783726ba01a4f7e7b69f5bb35cb2da4a751f5d09e0d425d964736f6c63430008140033

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

000000000000000000000000192c3baa95235b84b46e76ea3fbff51b092dc0ed00000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae000000000000000000000000ef6070be0954ea67985120eef153802180ec77d800000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae

-----Decoded View---------------
Arg [0] : minter (address): 0x192C3baa95235b84b46e76ea3fbFF51b092DC0ED
Arg [1] : _treasury (address): 0x80E58970a10ba716a3229A6763E4fd0Ce0c3cDAe
Arg [2] : _komet (address): 0xEf6070BE0954eA67985120Eef153802180Ec77D8
Arg [3] : _CollectionWallet (address): 0x80E58970a10ba716a3229A6763E4fd0Ce0c3cDAe

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000192c3baa95235b84b46e76ea3fbff51b092dc0ed
Arg [1] : 00000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae
Arg [2] : 000000000000000000000000ef6070be0954ea67985120eef153802180ec77d8
Arg [3] : 00000000000000000000000080e58970a10ba716a3229a6763e4fd0ce0c3cdae


Deployed Bytecode Sourcemap

98654:7498:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100419:4;100396:8;:20;100405:10;100396:20;;;;;;;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;100460:9;100434:11;:23;100446:10;100434:23;;;;;;;;;;;;;;;:35;;;;100508:9;100496:10;100487:31;;;;;;;;;;;;98654:7498;;;;;105922:227;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105297:197;;;;;;;;;;;;;:::i;:::-;;73471:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74643:158;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74462:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;99427:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99355:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;75312:588;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;60128:122;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;101014:962;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;98865:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60560:138;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;99624:46;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99460:108;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61697:251;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;104982:307;;;;;;;;;;;;;:::i;:::-;;100536:470;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;75971:134;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;49078:86;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98835:23;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73284:120;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73009:213;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;52405:103;;;;;;;;;;;;;:::i;:::-;;98898:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99278:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51730:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;59144:138;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73631:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;58456:49;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74873:146;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;104272:247;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102437:142;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102587:102;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;76176:211;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;99314:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104846:128;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;105502:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99577:40;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99007:62;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60991:140;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103246:1018;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;99391:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98938:62;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;75090:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;99145:56;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;102697:143;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;101984:445;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102848:390;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;104729:109;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;104527:194;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;99076:60;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105922:227;106076:4;106105:36;106129:11;106105:23;:36::i;:::-;106098:43;;105922:227;;;:::o;105297:197::-;58501:4;105340:18;;58740:16;58751:4;58740:10;:16::i;:::-;105371:12:::1;105394:10;105386:24;;:47;105411:21;105386:47;;;;;;;;;;;;;;;;;;;;;;;105371:62;;105452:7;105444:42;;;;;;;;;;;;:::i;:::-;;;;;;;;;105360:134;105297:197:::0;:::o;73471:91::-;73516:13;73549:5;73542:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73471:91;:::o;74643:158::-;74710:7;74730:22;74744:7;74730:13;:22::i;:::-;;74772:21;74785:7;74772:12;:21::i;:::-;74765:28;;74643:158;;;:::o;74462:115::-;74534:35;74543:2;74547:7;74556:12;:10;:12::i;:::-;74534:8;:35::i;:::-;74462:115;;:::o;99427:26::-;;;;:::o;99355:29::-;;;;:::o;75312:588::-;75421:1;75407:16;;:2;:16;;;75403:89;;75477:1;75447:33;;;;;;;;;;;:::i;:::-;;;;;;;;75403:89;75713:21;75737:34;75745:2;75749:7;75758:12;:10;:12::i;:::-;75737:7;:34::i;:::-;75713:58;;75803:4;75786:21;;:13;:21;;;75782:111;;75852:4;75858:7;75867:13;75831:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;75782:111;75392:508;75312:588;;;:::o;60128:122::-;60193:7;60220:6;:12;60227:4;60220:12;;;;;;;;;;;:22;;;60213:29;;60128:122;;;:::o;101014:962::-;101085:10;;;;;;;;;;;101077:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;101167:6;;101156:7;101142:11;;:21;;;;:::i;:::-;:31;;101134:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;101261:10;;101224:21;:33;101246:10;101224:33;;;;;;;;;;;;;;;;:47;;101202:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;101401:10;;101390:7;101354:21;:33;101376:10;101354:33;;;;;;;;;;;;;;;;:43;;;;:::i;:::-;:57;;101332:129;;;;;;;;;;;;:::i;:::-;;;;;;;;;101506:9;101492:10;;101482:7;:20;;;;:::i;:::-;:33;;101474:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;101560:9;101555:337;101579:7;101575:1;:11;101555:337;;;101608:27;:15;:25;:27::i;:::-;101650:17;101670:25;:15;:23;:25::i;:::-;101650:45;;101725:1;101710:11;;:16;;;;;;;:::i;:::-;;;;;;;;101778:1;101741:21;:33;101763:10;101741:33;;;;;;;;;;;;;;;;:38;;;;;;;:::i;:::-;;;;;;;;101794:28;101800:10;101812:9;101794:5;:28::i;:::-;101837:43;101850:9;101861:18;101869:9;101861:7;:18::i;:::-;101837:12;:43::i;:::-;101593:299;101588:3;;;;;:::i;:::-;;;;101555:337;;;;101904:64;101928:16;;;;;;;;;;;101955:11;;;;;;;;;;;101904:15;:64::i;:::-;101014:962;:::o;98865:26::-;;;;;;;;;;;;;:::o;60560:138::-;60634:18;60647:4;60634:12;:18::i;:::-;58740:16;58751:4;58740:10;:16::i;:::-;60665:25:::1;60676:4;60682:7;60665:10;:25::i;:::-;;60560:138:::0;;;:::o;99624:46::-;;;;;;;;;;;;;;;;;:::o;99460:108::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;61697:251::-;61813:12;:10;:12::i;:::-;61791:34;;:18;:34;;;61787:104;;61849:30;;;;;;;;;;;;;;61787:104;61903:37;61915:4;61921:18;61903:11;:37::i;:::-;;61697:251;;:::o;104982:307::-;105030:8;:20;105039:10;105030:20;;;;;;;;;;;;;;;;;;;;;;;;;105022:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;105110:5;105087:8;:20;105096:10;105087:20;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;105126:12;105149:10;105141:24;;:49;105166:11;:23;105178:10;105166:23;;;;;;;;;;;;;;;;105141:49;;;;;;;;;;;;;;;;;;;;;;;105126:64;;105209:7;105201:42;;;;;;;;;;;;:::i;:::-;;;;;;;;;105280:1;105254:11;:23;105266:10;105254:23;;;;;;;;;;;;;;;:27;;;;105011:278;104982:307::o;100536:470::-;99045:24;58740:16;58751:4;58740:10;:16::i;:::-;100649:9:::1;100644:355;100668:6;;:13;;100664:1;:17;100644:355;;;100730:6;;100725:1;100711:11;;:15;;;;:::i;:::-;:25;;100703:51;;;;;;;;;;;;:::i;:::-;;;;;;;;;100769:27;:15;:25;:27::i;:::-;100811:17;100831:25;:15;:23;:25::i;:::-;100811:45;;100886:1;100871:11;;:16;;;;;;;:::i;:::-;;;;;;;;100902:27;100908:6;;100915:1;100908:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;100919;100902:5;:27::i;:::-;100944:43;100957:9;100968:18;100976:9;100968:7;:18::i;:::-;100944:12;:43::i;:::-;100688:311;100683:3;;;;;:::i;:::-;;;;100644:355;;;;100536:470:::0;;;:::o;75971:134::-;76058:39;76075:4;76081:2;76085:7;76058:39;;;;;;;;;;;;:16;:39::i;:::-;75971:134;;;:::o;49078:86::-;49125:4;49149:7;;;;;;;;;;;49142:14;;49078:86;:::o;98835:23::-;;;;;;;;;;;;;:::o;73284:120::-;73347:7;73374:22;73388:7;73374:13;:22::i;:::-;73367:29;;73284:120;;;:::o;73009:213::-;73072:7;73113:1;73096:19;;:5;:19;;;73092:89;;73166:1;73139:30;;;;;;;;;;;:::i;:::-;;;;;;;;73092:89;73198:9;:16;73208:5;73198:16;;;;;;;;;;;;;;;;73191:23;;73009:213;;;:::o;52405:103::-;51616:13;:11;:13::i;:::-;52470:30:::1;52497:1;52470:18;:30::i;:::-;52405:103::o:0;98898:31::-;;;;;;;;;;;;;:::o;99278:29::-;;;;:::o;51730:87::-;51776:7;51803:6;;;;;;;;;;;51796:13;;51730:87;:::o;59144:138::-;59221:4;59245:6;:12;59252:4;59245:12;;;;;;;;;;;:20;;:29;59266:7;59245:29;;;;;;;;;;;;;;;;;;;;;;;;;59238:36;;59144:138;;;;:::o;73631:95::-;73678:13;73711:7;73704:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73631:95;:::o;58456:49::-;58501:4;58456:49;;;:::o;74873:146::-;74959:52;74978:12;:10;:12::i;:::-;74992:8;75002;74959:18;:52::i;:::-;74873:146;;:::o;104272:247::-;99045:24;58740:16;58751:4;58740:10;:16::i;:::-;104435:6:::1;104422:10;:19;;;;104465:15;104452:10;:28;;;;104504:7;104491:10;;:20;;;;;;;;;;;;;;;;;;104272:247:::0;;;;:::o;102437:142::-;58501:4;102516:18;;58740:16;58751:4;58740:10;:16::i;:::-;102563:8:::1;102552;;:19;;;;;;;;;;;;;;;;;;102437:142:::0;;:::o;102587:102::-;99045:24;58740:16;58751:4;58740:10;:16::i;:::-;102675:6:::1;102666;:15;;;;102587:102:::0;;:::o;76176:211::-;76290:31;76303:4;76309:2;76313:7;76290:12;:31::i;:::-;76332:47;76355:4;76361:2;76365:7;76374:4;76332:22;:47::i;:::-;76176:211;;;;:::o;99314:34::-;;;;:::o;104846:128::-;99045:24;58740:16;58751:4;58740:10;:16::i;:::-;104962:4:::1;;104951:8;:15;;;;;;;:::i;:::-;;104846:128:::0;;;:::o;105502:189::-;105629:13;105667:16;105675:7;105667;:16::i;:::-;105660:23;;105502:189;;;:::o;99577:40::-;;;;;;;;;;;;;;;;;;;;;;:::o;99007:62::-;99045:24;99007:62;:::o;60991:140::-;61066:18;61079:4;61066:12;:18::i;:::-;58740:16;58751:4;58740:10;:16::i;:::-;61097:26:::1;61109:4;61115:7;61097:11;:26::i;:::-;;60991:140:::0;;;:::o;103246:1018::-;103395:1;103382:10;;:14;103378:879;;;103413:13;103429:9;103413:25;;103453:16;103503:14;;103496:3;103482:10;;103474:5;:18;;;;:::i;:::-;103473:26;;;;:::i;:::-;103472:45;;;;:::i;:::-;103453:64;;103532:15;103558:8;103550:5;:16;;;;:::i;:::-;103532:34;;103634:7;103609:21;:32;;103583:144;;;;;;;;;;;;:::i;:::-;;;;;;;;;103742:10;:19;;:28;103762:7;103742:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103838:8;103813:21;:33;;103787:146;;;;;;;;;;;;:::i;:::-;;;;;;;;;103948:10;:19;;:29;103968:8;103948:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103398:591;;;103378:879;;;104010:16;104029:9;104010:28;;104106:8;104081:21;:33;;104055:146;;;;;;;;;;;;:::i;:::-;;;;;;;;;104216:10;:19;;:29;104236:8;104216:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103995:262;103378:879;103246:1018;;:::o;99391:29::-;;;;:::o;98938:62::-;98976:24;98938:62;:::o;75090:155::-;75178:4;75202:18;:25;75221:5;75202:25;;;;;;;;;;;;;;;:35;75228:8;75202:35;;;;;;;;;;;;;;;;;;;;;;;;;75195:42;;75090:155;;;;:::o;99145:56::-;;;;;;;;;;;;;;;;;:::o;102697:143::-;99045:24;58740:16;58751:4;58740:10;:16::i;:::-;102825:7:::1;102806:16;;:26;;;;;;;;;;;;;;;;;;102697:143:::0;;:::o;101984:445::-;58501:4;102039:18;;58740:16;58751:4;58740:10;:16::i;:::-;102103:6:::1;;102092:7;102078:11;;:21;;;;:::i;:::-;:31;;102070:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;102143:9;102138:284;102162:7;102158:1;:11;102138:284;;;102191:27;:15;:25;:27::i;:::-;102233:17;102253:25;:15;:23;:25::i;:::-;102233:45;;102310:1;102295:11;;:16;;;;;;;:::i;:::-;;;;;;;;102326:26;102332:8;;;;;;;;;;;102342:9;102326:5;:26::i;:::-;102367:43;102380:9;102391:18;102399:9;102391:7;:18::i;:::-;102367:12;:43::i;:::-;102176:246;102171:3;;;;;:::i;:::-;;;;102138:284;;;;101984:445:::0;;:::o;102848:390::-;51616:13;:11;:13::i;:::-;102927:43:::1;58501:4;102939:18:::0;::::1;102959:10;102927:11;:43::i;:::-;;102981:36;99045:24;103006:10;102981:11;:36::i;:::-;;103028;98976:24;103053:10;103028:11;:36::i;:::-;;103075:37;58501:4;103086:18:::0;::::1;103106:5;103075:10;:37::i;:::-;;103123:30;99045:24;103147:5;103123:10;:30::i;:::-;;103164;98976:24;103188:5;103164:10;:30::i;:::-;;103205:25;103224:5;103205:18;:25::i;:::-;102848:390:::0;:::o;104729:109::-;99113:23;58740:16;58751:4;58740:10;:16::i;:::-;104823:7:::1;104809:11;;:21;;;;;;;;;;;;;;;;;;104729:109:::0;;:::o;104527:194::-;99113:23;58740:16;58751:4;58740:10;:16::i;:::-;104669:8:::1;104656:10;:21;;;;104705:8;104688:14;:25;;;;104527:194:::0;;;:::o;99076:60::-;99113:23;99076:60;:::o;58848:204::-;58933:4;58972:32;58957:47;;;:11;:47;;;;:87;;;;59008:36;59032:11;59008:23;:36::i;:::-;58957:87;58950:94;;58848:204;;;:::o;59497:105::-;59564:30;59575:4;59581:12;:10;:12::i;:::-;59564:10;:30::i;:::-;59497:105;:::o;87626:247::-;87689:7;87709:13;87725:17;87734:7;87725:8;:17::i;:::-;87709:33;;87774:1;87757:19;;:5;:19;;;87753:90;;87823:7;87800:31;;;;;;;;;;;:::i;:::-;;;;;;;;87753:90;87860:5;87853:12;;;87626:247;;;:::o;77149:129::-;77219:7;77246:15;:24;77262:7;77246:24;;;;;;;;;;;;;;;;;;;;;77239:31;;77149:129;;;:::o;35917:98::-;35970:7;35997:10;35990:17;;35917:98;:::o;85858:122::-;85939:33;85948:2;85952:7;85961:4;85967;85939:8;:33::i;:::-;85858:122;;;:::o;80111:824::-;80197:7;80217:12;80232:17;80241:7;80232:8;:17::i;:::-;80217:32;;80328:1;80312:18;;:4;:18;;;80308:88;;80347:37;80364:4;80370;80376:7;80347:16;:37::i;:::-;80308:88;80459:1;80443:18;;:4;:18;;;80439:263;;80561:48;80578:1;80582:7;80599:1;80603:5;80561:8;:48::i;:::-;80674:1;80655:9;:15;80665:4;80655:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;80439:263;80732:1;80718:16;;:2;:16;;;80714:111;;80797:1;80780:9;:13;80790:2;80780:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;80714:111;80856:2;80837:7;:16;80845:7;80837:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;80895:7;80891:2;80876:27;;80885:4;80876:27;;;;;;;;;;;;80923:4;80916:11;;;80111:824;;;;;:::o;4601:127::-;4708:1;4690:7;:14;;;:19;;;;;;;;;;;4601:127;:::o;4479:114::-;4544:7;4571;:14;;;4564:21;;4479:114;;;:::o;81271:335::-;81353:1;81339:16;;:2;:16;;;81335:89;;81409:1;81379:33;;;;;;;;;;;:::i;:::-;;;;;;;;81335:89;81434:21;81458:32;81466:2;81470:7;81487:1;81458:7;:32::i;:::-;81434:56;;81530:1;81505:27;;:13;:27;;;81501:98;;81584:1;81556:31;;;;;;;;;;;:::i;:::-;;;;;;;;81501:98;81324:282;81271:335;;:::o;105699:215::-;105757:13;105845:8;105855:26;105872:8;105855:16;:26::i;:::-;105828:63;;;;;;;;;:::i;:::-;;;;;;;;;;;;;105783:123;;105699:215;;;:::o;98402:170::-;98516:9;98494:10;:19;98505:7;98494:19;;;;;;;;;;;:31;;;;;;:::i;:::-;;98541:23;98556:7;98541:23;;;;;;:::i;:::-;;;;;;;;98402:170;;:::o;62574:324::-;62651:4;62673:22;62681:4;62687:7;62673;:22::i;:::-;62668:223;;62744:4;62712:6;:12;62719:4;62712:12;;;;;;;;;;;:20;;:29;62733:7;62712:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;62795:12;:10;:12::i;:::-;62768:40;;62786:7;62768:40;;62780:4;62768:40;;;;;;;;;;62830:4;62823:11;;;;62668:223;62874:5;62867:12;;62574:324;;;;;:::o;63142:325::-;63220:4;63241:22;63249:4;63255:7;63241;:22::i;:::-;63237:223;;;63312:5;63280:6;:12;63287:4;63280:12;;;;;;;;;;;:20;;:29;63301:7;63280:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;63364:12;:10;:12::i;:::-;63337:40;;63355:7;63337:40;;63349:4;63337:40;;;;;;;;;;63399:4;63392:11;;;;63237:223;63443:5;63436:12;;63142:325;;;;;:::o;51895:166::-;51966:12;:10;:12::i;:::-;51955:23;;:7;:5;:7::i;:::-;:23;;;51951:103;;52029:12;:10;:12::i;:::-;52002:40;;;;;;;;;;;:::i;:::-;;;;;;;;51951:103;51895:166::o;53043:191::-;53117:16;53136:6;;;;;;;;;;;53117:25;;53162:8;53153:6;;:17;;;;;;;;;;;;;;;;;;53217:8;53186:40;;53207:8;53186:40;;;;;;;;;;;;53106:128;53043:191;:::o;87065:318::-;87193:1;87173:22;;:8;:22;;;87169:93;;87241:8;87219:31;;;;;;;;;;;:::i;:::-;;;;;;;;87169:93;87310:8;87272:18;:25;87291:5;87272:25;;;;;;;;;;;;;;;:35;87298:8;87272:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;87356:8;87334:41;;87349:5;87334:41;;;87366:8;87334:41;;;;;;:::i;:::-;;;;;;;;87065:318;;;:::o;88423:799::-;88557:1;88540:2;:14;;;:18;88536:679;;;88595:2;88579:36;;;88616:12;:10;:12::i;:::-;88630:4;88636:7;88645:4;88579:71;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;88575:629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88910:1;88893:6;:13;:18;88889:300;;88965:2;88943:25;;;;;;;;;;;:::i;:::-;;;;;;;;88889:300;89139:6;89133:13;89124:6;89120:2;89116:15;89109:38;88575:629;88708:41;;;88698:51;;;:6;:51;;;;88694:132;;88803:2;88781:25;;;;;;;;;;;:::i;:::-;;;;;;;;88694:132;88651:190;88536:679;88423:799;;;;:::o;97387:209::-;97489:4;97202:10;97195:18;;97513:35;;;:11;:35;;;;:75;;;;97552:36;97576:11;97552:23;:36::i;:::-;97513:75;97506:82;;97387:209;;;:::o;59738:201::-;59827:22;59835:4;59841:7;59827;:22::i;:::-;59822:110;;59906:7;59915:4;59873:47;;;;;;;;;;;;:::i;:::-;;;;;;;;59822:110;59738:201;;:::o;76911:117::-;76977:7;77004;:16;77012:7;77004:16;;;;;;;;;;;;;;;;;;;;;76997:23;;76911:117;;;:::o;86168:678::-;86330:9;:31;;;;86359:1;86343:18;;:4;:18;;;;86330:31;86326:471;;;86378:13;86394:22;86408:7;86394:13;:22::i;:::-;86378:38;;86563:1;86547:18;;:4;:18;;;;:35;;;;;86578:4;86569:13;;:5;:13;;;;86547:35;:69;;;;;86587:29;86604:5;86611:4;86587:16;:29::i;:::-;86586:30;86547:69;86543:144;;;86666:4;86644:27;;;;;;;;;;;:::i;:::-;;;;;;;;86543:144;86707:9;86703:83;;;86762:7;86758:2;86742:28;;86751:5;86742:28;;;;;;;;;;;;86703:83;86363:434;86326:471;86836:2;86809:15;:24;86825:7;86809:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;86168:678;;;;:::o;78318:376::-;78431:38;78445:5;78452:7;78461;78431:13;:38::i;:::-;78426:261;;78507:1;78490:19;;:5;:19;;;78486:190;;78560:7;78537:31;;;;;;;;;;;:::i;:::-;;;;;;;;78486:190;78643:7;78652;78616:44;;;;;;;;;;;;:::i;:::-;;;;;;;;78426:261;78318:376;;;:::o;32687:718::-;32743:13;32794:14;32831:1;32811:17;32822:5;32811:10;:17::i;:::-;:21;32794:38;;32847:20;32881:6;32870:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32847:41;;32903:11;33032:6;33028:2;33024:15;33016:6;33012:28;33005:35;;33069:290;33076:4;33069:290;;;33101:5;;;;;;;;33243:10;33238:2;33231:5;33227:14;33222:32;33217:3;33209:46;33301:2;33292:11;;;;;;:::i;:::-;;;;;33335:1;33326:5;:10;33069:290;33322:21;33069:290;33380:6;33373:13;;;;;32687:718;;;:::o;72640:305::-;72742:4;72794:25;72779:40;;;:11;:40;;;;:105;;;;72851:33;72836:48;;;:11;:48;;;;72779:105;:158;;;;72901:36;72925:11;72901:23;:36::i;:::-;72779:158;72759:178;;72640:305;;;:::o;77598:276::-;77701:4;77757:1;77738:21;;:7;:21;;;;:128;;;;;77786:7;77777:16;;:5;:16;;;:52;;;;77797:32;77814:5;77821:7;77797:16;:32::i;:::-;77777:52;:88;;;;77858:7;77833:32;;:21;77846:7;77833:12;:21::i;:::-;:32;;;77777:88;77738:128;77718:148;;77598:276;;;;;:::o;29091:948::-;29144:7;29164:14;29181:1;29164:18;;29231:8;29222:5;:17;29218:106;;29269:8;29260:17;;;;;;:::i;:::-;;;;;29306:2;29296:12;;;;29218:106;29351:8;29342:5;:17;29338:106;;29389:8;29380:17;;;;;;:::i;:::-;;;;;29426:2;29416:12;;;;29338:106;29471:8;29462:5;:17;29458:106;;29509:8;29500:17;;;;;;:::i;:::-;;;;;29546:2;29536:12;;;;29458:106;29591:7;29582:5;:16;29578:103;;29628:7;29619:16;;;;;;:::i;:::-;;;;;29664:1;29654:11;;;;29578:103;29708:7;29699:5;:16;29695:103;;29745:7;29736:16;;;;;;:::i;:::-;;;;;29781:1;29771:11;;;;29695:103;29825:7;29816:5;:16;29812:103;;29862:7;29853:16;;;;;;:::i;:::-;;;;;29898:1;29888:11;;;;29812:103;29942:7;29933:5;:16;29929:68;;29980:1;29970:11;;;;29929:68;30025:6;30018:13;;;29091:948;;;:::o;56185:148::-;56261:4;56300:25;56285:40;;;:11;:40;;;;56278:47;;56185:148;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310: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:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:77::-;5904:7;5933:5;5922:16;;5867:77;;;:::o;5950:122::-;6023:24;6041:5;6023:24;:::i;:::-;6016:5;6013:35;6003:63;;6062:1;6059;6052:12;6003:63;5950:122;:::o;6078:139::-;6124:5;6162:6;6149:20;6140:29;;6178:33;6205:5;6178:33;:::i;:::-;6078:139;;;;:::o;6223:329::-;6282:6;6331:2;6319:9;6310:7;6306:23;6302:32;6299:119;;;6337:79;;:::i;:::-;6299:119;6457:1;6482:53;6527:7;6518:6;6507:9;6503:22;6482:53;:::i;:::-;6472:63;;6428:117;6223:329;;;;:::o;6558:118::-;6645:24;6663:5;6645:24;:::i;:::-;6640:3;6633:37;6558:118;;:::o;6682:222::-;6775:4;6813:2;6802:9;6798:18;6790:26;;6826:71;6894:1;6883:9;6879:17;6870:6;6826:71;:::i;:::-;6682:222;;;;:::o;6910:474::-;6978:6;6986;7035:2;7023:9;7014:7;7010:23;7006:32;7003:119;;;7041:79;;:::i;:::-;7003:119;7161:1;7186:53;7231:7;7222:6;7211:9;7207:22;7186:53;:::i;:::-;7176:63;;7132:117;7288:2;7314:53;7359:7;7350:6;7339:9;7335:22;7314:53;:::i;:::-;7304:63;;7259:118;6910:474;;;;;:::o;7390:329::-;7449:6;7498:2;7486:9;7477:7;7473:23;7469:32;7466:119;;;7504:79;;:::i;:::-;7466:119;7624:1;7649:53;7694:7;7685:6;7674:9;7670:22;7649:53;:::i;:::-;7639:63;;7595:117;7390:329;;;;:::o;7725:117::-;7834:1;7831;7824:12;7848:117;7957:1;7954;7947:12;7971:117;8080:1;8077;8070:12;8111:568;8184:8;8194:6;8244:3;8237:4;8229:6;8225:17;8221:27;8211:122;;8252:79;;:::i;:::-;8211:122;8365:6;8352:20;8342:30;;8395:18;8387:6;8384:30;8381:117;;;8417:79;;:::i;:::-;8381:117;8531:4;8523:6;8519:17;8507:29;;8585:3;8577:4;8569:6;8565:17;8555:8;8551:32;8548:41;8545:128;;;8592:79;;:::i;:::-;8545:128;8111:568;;;;;:::o;8685:559::-;8771:6;8779;8828:2;8816:9;8807:7;8803:23;8799:32;8796:119;;;8834:79;;:::i;:::-;8796:119;8982:1;8971:9;8967:17;8954:31;9012:18;9004:6;9001:30;8998:117;;;9034:79;;:::i;:::-;8998:117;9147:80;9219:7;9210:6;9199:9;9195:22;9147:80;:::i;:::-;9129:98;;;;8925:312;8685:559;;;;;:::o;9250:116::-;9320:21;9335:5;9320:21;:::i;:::-;9313:5;9310:32;9300:60;;9356:1;9353;9346:12;9300:60;9250:116;:::o;9372:133::-;9415:5;9453:6;9440:20;9431:29;;9469:30;9493:5;9469:30;:::i;:::-;9372:133;;;;:::o;9511:468::-;9576:6;9584;9633:2;9621:9;9612:7;9608:23;9604:32;9601:119;;;9639:79;;:::i;:::-;9601:119;9759:1;9784:53;9829:7;9820:6;9809:9;9805:22;9784:53;:::i;:::-;9774:63;;9730:117;9886:2;9912:50;9954:7;9945:6;9934:9;9930:22;9912:50;:::i;:::-;9902:60;;9857:115;9511:468;;;;;:::o;9985:613::-;10059:6;10067;10075;10124:2;10112:9;10103:7;10099:23;10095:32;10092:119;;;10130:79;;:::i;:::-;10092:119;10250:1;10275:53;10320:7;10311:6;10300:9;10296:22;10275:53;:::i;:::-;10265:63;;10221:117;10377:2;10403:53;10448:7;10439:6;10428:9;10424:22;10403:53;:::i;:::-;10393:63;;10348:118;10505:2;10531:50;10573:7;10564:6;10553:9;10549:22;10531:50;:::i;:::-;10521:60;;10476:115;9985:613;;;;;:::o;10604:117::-;10713:1;10710;10703:12;10727:180;10775:77;10772:1;10765:88;10872:4;10869:1;10862:15;10896:4;10893:1;10886:15;10913:281;10996:27;11018:4;10996:27;:::i;:::-;10988:6;10984:40;11126:6;11114:10;11111:22;11090:18;11078:10;11075:34;11072:62;11069:88;;;11137:18;;:::i;:::-;11069:88;11177:10;11173:2;11166:22;10956:238;10913:281;;:::o;11200:129::-;11234:6;11261:20;;:::i;:::-;11251:30;;11290:33;11318:4;11310:6;11290:33;:::i;:::-;11200:129;;;:::o;11335:307::-;11396:4;11486:18;11478:6;11475:30;11472:56;;;11508:18;;:::i;:::-;11472:56;11546:29;11568:6;11546:29;:::i;:::-;11538:37;;11630:4;11624;11620:15;11612:23;;11335:307;;;:::o;11648:146::-;11745:6;11740:3;11735;11722:30;11786:1;11777:6;11772:3;11768:16;11761:27;11648:146;;;:::o;11800:423::-;11877:5;11902:65;11918:48;11959:6;11918:48;:::i;:::-;11902:65;:::i;:::-;11893:74;;11990:6;11983:5;11976:21;12028:4;12021:5;12017:16;12066:3;12057:6;12052:3;12048:16;12045:25;12042:112;;;12073:79;;:::i;:::-;12042:112;12163:54;12210:6;12205:3;12200;12163:54;:::i;:::-;11883:340;11800:423;;;;;:::o;12242:338::-;12297:5;12346:3;12339:4;12331:6;12327:17;12323:27;12313:122;;12354:79;;:::i;:::-;12313:122;12471:6;12458:20;12496:78;12570:3;12562:6;12555:4;12547:6;12543:17;12496:78;:::i;:::-;12487:87;;12303:277;12242:338;;;;:::o;12586:943::-;12681:6;12689;12697;12705;12754:3;12742:9;12733:7;12729:23;12725:33;12722:120;;;12761:79;;:::i;:::-;12722:120;12881:1;12906:53;12951:7;12942:6;12931:9;12927:22;12906:53;:::i;:::-;12896:63;;12852:117;13008:2;13034:53;13079:7;13070:6;13059:9;13055:22;13034:53;:::i;:::-;13024:63;;12979:118;13136:2;13162:53;13207:7;13198:6;13187:9;13183:22;13162:53;:::i;:::-;13152:63;;13107:118;13292:2;13281:9;13277:18;13264:32;13323:18;13315:6;13312:30;13309:117;;;13345:79;;:::i;:::-;13309:117;13450:62;13504:7;13495:6;13484:9;13480:22;13450:62;:::i;:::-;13440:72;;13235:287;12586:943;;;;;;;:::o;13549:553::-;13607:8;13617:6;13667:3;13660:4;13652:6;13648:17;13644:27;13634:122;;13675:79;;:::i;:::-;13634:122;13788:6;13775:20;13765:30;;13818:18;13810:6;13807:30;13804:117;;;13840:79;;:::i;:::-;13804:117;13954:4;13946:6;13942:17;13930:29;;14008:3;14000:4;13992:6;13988:17;13978:8;13974:32;13971:41;13968:128;;;14015:79;;:::i;:::-;13968:128;13549:553;;;;;:::o;14108:529::-;14179:6;14187;14236:2;14224:9;14215:7;14211:23;14207:32;14204:119;;;14242:79;;:::i;:::-;14204:119;14390:1;14379:9;14375:17;14362:31;14420:18;14412:6;14409:30;14406:117;;;14442:79;;:::i;:::-;14406:117;14555:65;14612:7;14603:6;14592:9;14588:22;14555:65;:::i;:::-;14537:83;;;;14333:297;14108:529;;;;;:::o;14643:104::-;14688:7;14717:24;14735:5;14717:24;:::i;:::-;14706:35;;14643:104;;;:::o;14753:138::-;14834:32;14860:5;14834:32;:::i;:::-;14827:5;14824:43;14814:71;;14881:1;14878;14871:12;14814:71;14753:138;:::o;14897:155::-;14951:5;14989:6;14976:20;14967:29;;15005:41;15040:5;15005:41;:::i;:::-;14897:155;;;;:::o;15058:506::-;15142:6;15150;15199:2;15187:9;15178:7;15174:23;15170:32;15167:119;;;15205:79;;:::i;:::-;15167:119;15325:1;15350:61;15403:7;15394:6;15383:9;15379:22;15350:61;:::i;:::-;15340:71;;15296:125;15460:2;15486:61;15539:7;15530:6;15519:9;15515:22;15486:61;:::i;:::-;15476:71;;15431:126;15058:506;;;;;:::o;15570:474::-;15638:6;15646;15695:2;15683:9;15674:7;15670:23;15666:32;15663:119;;;15701:79;;:::i;:::-;15663:119;15821:1;15846:53;15891:7;15882:6;15871:9;15867:22;15846:53;:::i;:::-;15836:63;;15792:117;15948:2;15974:53;16019:7;16010:6;15999:9;15995:22;15974:53;:::i;:::-;15964:63;;15919:118;15570:474;;;;;:::o;16050:::-;16118:6;16126;16175:2;16163:9;16154:7;16150:23;16146:32;16143:119;;;16181:79;;:::i;:::-;16143:119;16301:1;16326:53;16371:7;16362:6;16351:9;16347:22;16326:53;:::i;:::-;16316:63;;16272:117;16428:2;16454:53;16499:7;16490:6;16479:9;16475:22;16454:53;:::i;:::-;16444:63;;16399:118;16050:474;;;;;:::o;16530:172::-;16670:24;16666:1;16658:6;16654:14;16647:48;16530:172;:::o;16708:366::-;16850:3;16871:67;16935:2;16930:3;16871:67;:::i;:::-;16864:74;;16947:93;17036:3;16947:93;:::i;:::-;17065:2;17060:3;17056:12;17049:19;;16708:366;;;:::o;17080:419::-;17246:4;17284:2;17273:9;17269:18;17261:26;;17333:9;17327:4;17323:20;17319:1;17308:9;17304:17;17297:47;17361:131;17487:4;17361:131;:::i;:::-;17353:139;;17080:419;;;:::o;17505:180::-;17553:77;17550:1;17543:88;17650:4;17647:1;17640:15;17674:4;17671:1;17664:15;17691:320;17735:6;17772:1;17766:4;17762:12;17752:22;;17819:1;17813:4;17809:12;17840:18;17830:81;;17896:4;17888:6;17884:17;17874:27;;17830:81;17958:2;17950:6;17947:14;17927:18;17924:38;17921:84;;17977:18;;:::i;:::-;17921:84;17742:269;17691:320;;;:::o;18017:442::-;18166:4;18204:2;18193:9;18189:18;18181:26;;18217:71;18285:1;18274:9;18270:17;18261:6;18217:71;:::i;:::-;18298:72;18366:2;18355:9;18351:18;18342:6;18298:72;:::i;:::-;18380;18448:2;18437:9;18433:18;18424:6;18380:72;:::i;:::-;18017:442;;;;;;:::o;18465:173::-;18605:25;18601:1;18593:6;18589:14;18582:49;18465:173;:::o;18644:366::-;18786:3;18807:67;18871:2;18866:3;18807:67;:::i;:::-;18800:74;;18883:93;18972:3;18883:93;:::i;:::-;19001:2;18996:3;18992:12;18985:19;;18644:366;;;:::o;19016:419::-;19182:4;19220:2;19209:9;19205:18;19197:26;;19269:9;19263:4;19259:20;19255:1;19244:9;19240:17;19233:47;19297:131;19423:4;19297:131;:::i;:::-;19289:139;;19016:419;;;:::o;19441:180::-;19489:77;19486:1;19479:88;19586:4;19583:1;19576:15;19610:4;19607:1;19600:15;19627:191;19667:3;19686:20;19704:1;19686:20;:::i;:::-;19681:25;;19720:20;19738:1;19720:20;:::i;:::-;19715:25;;19763:1;19760;19756:9;19749:16;;19784:3;19781:1;19778:10;19775:36;;;19791:18;;:::i;:::-;19775:36;19627:191;;;;:::o;19824:163::-;19964:15;19960:1;19952:6;19948:14;19941:39;19824:163;:::o;19993:366::-;20135:3;20156:67;20220:2;20215:3;20156:67;:::i;:::-;20149:74;;20232:93;20321:3;20232:93;:::i;:::-;20350:2;20345:3;20341:12;20334:19;;19993:366;;;:::o;20365:419::-;20531:4;20569:2;20558:9;20554:18;20546:26;;20618:9;20612:4;20608:20;20604:1;20593:9;20589:17;20582:47;20646:131;20772:4;20646:131;:::i;:::-;20638:139;;20365:419;;;:::o;20790:172::-;20930:24;20926:1;20918:6;20914:14;20907:48;20790:172;:::o;20968:366::-;21110:3;21131:67;21195:2;21190:3;21131:67;:::i;:::-;21124:74;;21207:93;21296:3;21207:93;:::i;:::-;21325:2;21320:3;21316:12;21309:19;;20968:366;;;:::o;21340:419::-;21506:4;21544:2;21533:9;21529:18;21521:26;;21593:9;21587:4;21583:20;21579:1;21568:9;21564:17;21557:47;21621:131;21747:4;21621:131;:::i;:::-;21613:139;;21340:419;;;:::o;21765:410::-;21805:7;21828:20;21846:1;21828:20;:::i;:::-;21823:25;;21862:20;21880:1;21862:20;:::i;:::-;21857:25;;21917:1;21914;21910:9;21939:30;21957:11;21939:30;:::i;:::-;21928:41;;22118:1;22109:7;22105:15;22102:1;22099:22;22079:1;22072:9;22052:83;22029:139;;22148:18;;:::i;:::-;22029:139;21813:362;21765:410;;;;:::o;22181:172::-;22321:24;22317:1;22309:6;22305:14;22298:48;22181:172;:::o;22359:366::-;22501:3;22522:67;22586:2;22581:3;22522:67;:::i;:::-;22515:74;;22598:93;22687:3;22598:93;:::i;:::-;22716:2;22711:3;22707:12;22700:19;;22359:366;;;:::o;22731:419::-;22897:4;22935:2;22924:9;22920:18;22912:26;;22984:9;22978:4;22974:20;22970:1;22959:9;22955:17;22948:47;23012:131;23138:4;23012:131;:::i;:::-;23004:139;;22731:419;;;:::o;23156:233::-;23195:3;23218:24;23236:5;23218:24;:::i;:::-;23209:33;;23264:66;23257:5;23254:77;23251:103;;23334:18;;:::i;:::-;23251:103;23381:1;23374:5;23370:13;23363:20;;23156:233;;;:::o;23395:171::-;23535:23;23531:1;23523:6;23519:14;23512:47;23395:171;:::o;23572:366::-;23714:3;23735:67;23799:2;23794:3;23735:67;:::i;:::-;23728:74;;23811:93;23900:3;23811:93;:::i;:::-;23929:2;23924:3;23920:12;23913:19;;23572:366;;;:::o;23944:419::-;24110:4;24148:2;24137:9;24133:18;24125:26;;24197:9;24191:4;24187:20;24183:1;24172:9;24168:17;24161:47;24225:131;24351:4;24225:131;:::i;:::-;24217:139;;23944:419;;;:::o;24369:163::-;24509:15;24505:1;24497:6;24493:14;24486:39;24369:163;:::o;24538:366::-;24680:3;24701:67;24765:2;24760:3;24701:67;:::i;:::-;24694:74;;24777:93;24866:3;24777:93;:::i;:::-;24895:2;24890:3;24886:12;24879:19;;24538:366;;;:::o;24910:419::-;25076:4;25114:2;25103:9;25099:18;25091:26;;25163:9;25157:4;25153:20;25149:1;25138:9;25134:17;25127:47;25191:131;25317:4;25191:131;:::i;:::-;25183:139;;24910:419;;;:::o;25335:180::-;25383:77;25380:1;25373:88;25480:4;25477:1;25470:15;25504:4;25501:1;25494:15;25521:97;25580:6;25608:3;25598:13;;25521:97;;;;:::o;25624:141::-;25673:4;25696:3;25688:11;;25719:3;25716:1;25709:14;25753:4;25750:1;25740:18;25732:26;;25624:141;;;:::o;25771:93::-;25808:6;25855:2;25850;25843:5;25839:14;25835:23;25825:33;;25771:93;;;:::o;25870:107::-;25914:8;25964:5;25958:4;25954:16;25933:37;;25870:107;;;;:::o;25983:393::-;26052:6;26102:1;26090:10;26086:18;26125:97;26155:66;26144:9;26125:97;:::i;:::-;26243:39;26273:8;26262:9;26243:39;:::i;:::-;26231:51;;26315:4;26311:9;26304:5;26300:21;26291:30;;26364:4;26354:8;26350:19;26343:5;26340:30;26330:40;;26059:317;;25983:393;;;;;:::o;26382:60::-;26410:3;26431:5;26424:12;;26382:60;;;:::o;26448:142::-;26498:9;26531:53;26549:34;26558:24;26576:5;26558:24;:::i;:::-;26549:34;:::i;:::-;26531:53;:::i;:::-;26518:66;;26448:142;;;:::o;26596:75::-;26639:3;26660:5;26653:12;;26596:75;;;:::o;26677:269::-;26787:39;26818:7;26787:39;:::i;:::-;26848:91;26897:41;26921:16;26897:41;:::i;:::-;26889:6;26882:4;26876:11;26848:91;:::i;:::-;26842:4;26835:105;26753:193;26677:269;;;:::o;26952:73::-;26997:3;26952:73;:::o;27031:189::-;27108:32;;:::i;:::-;27149:65;27207:6;27199;27193:4;27149:65;:::i;:::-;27084:136;27031:189;;:::o;27226:186::-;27286:120;27303:3;27296:5;27293:14;27286:120;;;27357:39;27394:1;27387:5;27357:39;:::i;:::-;27330:1;27323:5;27319:13;27310:22;;27286:120;;;27226:186;;:::o;27418:543::-;27519:2;27514:3;27511:11;27508:446;;;27553:38;27585:5;27553:38;:::i;:::-;27637:29;27655:10;27637:29;:::i;:::-;27627:8;27623:44;27820:2;27808:10;27805:18;27802:49;;;27841:8;27826:23;;27802:49;27864:80;27920:22;27938:3;27920:22;:::i;:::-;27910:8;27906:37;27893:11;27864:80;:::i;:::-;27523:431;;27508:446;27418:543;;;:::o;27967:117::-;28021:8;28071:5;28065:4;28061:16;28040:37;;27967:117;;;;:::o;28090:169::-;28134:6;28167:51;28215:1;28211:6;28203:5;28200:1;28196:13;28167:51;:::i;:::-;28163:56;28248:4;28242;28238:15;28228:25;;28141:118;28090:169;;;;:::o;28264:295::-;28340:4;28486:29;28511:3;28505:4;28486:29;:::i;:::-;28478:37;;28548:3;28545:1;28541:11;28535:4;28532:21;28524:29;;28264:295;;;;:::o;28564:1403::-;28688:44;28728:3;28723;28688:44;:::i;:::-;28797:18;28789:6;28786:30;28783:56;;;28819:18;;:::i;:::-;28783:56;28863:38;28895:4;28889:11;28863:38;:::i;:::-;28948:67;29008:6;29000;28994:4;28948:67;:::i;:::-;29042:1;29071:2;29063:6;29060:14;29088:1;29083:632;;;;29759:1;29776:6;29773:84;;;29832:9;29827:3;29823:19;29810:33;29801:42;;29773:84;29883:67;29943:6;29936:5;29883:67;:::i;:::-;29877:4;29870:81;29732:229;29053:908;;29083:632;29135:4;29131:9;29123:6;29119:22;29169:37;29201:4;29169:37;:::i;:::-;29228:1;29242:215;29256:7;29253:1;29250:14;29242:215;;;29342:9;29337:3;29333:19;29320:33;29312:6;29305:49;29393:1;29385:6;29381:14;29371:24;;29440:2;29429:9;29425:18;29412:31;;29279:4;29276:1;29272:12;29267:17;;29242:215;;;29485:6;29476:7;29473:19;29470:186;;;29550:9;29545:3;29541:19;29528:33;29593:48;29635:4;29627:6;29623:17;29612:9;29593:48;:::i;:::-;29585:6;29578:64;29493:163;29470:186;29702:1;29698;29690:6;29686:14;29682:22;29676:4;29669:36;29090:625;;;29053:908;;28663:1304;;;28564:1403;;;:::o;29973:180::-;30021:77;30018:1;30011:88;30118:4;30115:1;30108:15;30142:4;30139:1;30132:15;30159:185;30199:1;30216:20;30234:1;30216:20;:::i;:::-;30211:25;;30250:20;30268:1;30250:20;:::i;:::-;30245:25;;30289:1;30279:35;;30294:18;;:::i;:::-;30279:35;30336:1;30333;30329:9;30324:14;;30159:185;;;;:::o;30350:194::-;30390:4;30410:20;30428:1;30410:20;:::i;:::-;30405:25;;30444:20;30462:1;30444:20;:::i;:::-;30439:25;;30488:1;30485;30481:9;30473:17;;30512:1;30506:4;30503:11;30500:37;;;30517:18;;:::i;:::-;30500:37;30350:194;;;;:::o;30550:237::-;30690:34;30686:1;30678:6;30674:14;30667:58;30759:20;30754:2;30746:6;30742:15;30735:45;30550:237;:::o;30793:366::-;30935:3;30956:67;31020:2;31015:3;30956:67;:::i;:::-;30949:74;;31032:93;31121:3;31032:93;:::i;:::-;31150:2;31145:3;31141:12;31134:19;;30793:366;;;:::o;31165:419::-;31331:4;31369:2;31358:9;31354:18;31346:26;;31418:9;31412:4;31408:20;31404:1;31393:9;31389:17;31382:47;31446:131;31572:4;31446:131;:::i;:::-;31438:139;;31165:419;;;:::o;31590:238::-;31730:34;31726:1;31718:6;31714:14;31707:58;31799:21;31794:2;31786:6;31782:15;31775:46;31590:238;:::o;31834:366::-;31976:3;31997:67;32061:2;32056:3;31997:67;:::i;:::-;31990:74;;32073:93;32162:3;32073:93;:::i;:::-;32191:2;32186:3;32182:12;32175:19;;31834:366;;;:::o;32206:419::-;32372:4;32410:2;32399:9;32395:18;32387:26;;32459:9;32453:4;32449:20;32445:1;32434:9;32430:17;32423:47;32487:131;32613:4;32487:131;:::i;:::-;32479:139;;32206:419;;;:::o;32631:148::-;32733:11;32770:3;32755:18;;32631:148;;;;:::o;32809:874::-;32912:3;32949:5;32943:12;32978:36;33004:9;32978:36;:::i;:::-;33030:89;33112:6;33107:3;33030:89;:::i;:::-;33023:96;;33150:1;33139:9;33135:17;33166:1;33161:166;;;;33341:1;33336:341;;;;33128:549;;33161:166;33245:4;33241:9;33230;33226:25;33221:3;33214:38;33307:6;33300:14;33293:22;33285:6;33281:35;33276:3;33272:45;33265:52;;33161:166;;33336:341;33403:38;33435:5;33403:38;:::i;:::-;33463:1;33477:154;33491:6;33488:1;33485:13;33477:154;;;33565:7;33559:14;33555:1;33550:3;33546:11;33539:35;33615:1;33606:7;33602:15;33591:26;;33513:4;33510:1;33506:12;33501:17;;33477:154;;;33660:6;33655:3;33651:16;33644:23;;33343:334;;33128:549;;32916:767;;32809:874;;;;:::o;33689:390::-;33795:3;33823:39;33856:5;33823:39;:::i;:::-;33878:89;33960:6;33955:3;33878:89;:::i;:::-;33871:96;;33976:65;34034:6;34029:3;34022:4;34015:5;34011:16;33976:65;:::i;:::-;34066:6;34061:3;34057:16;34050:23;;33799:280;33689:390;;;;:::o;34085:155::-;34225:7;34221:1;34213:6;34209:14;34202:31;34085:155;:::o;34246:400::-;34406:3;34427:84;34509:1;34504:3;34427:84;:::i;:::-;34420:91;;34520:93;34609:3;34520:93;:::i;:::-;34638:1;34633:3;34629:11;34622:18;;34246:400;;;:::o;34652:695::-;34930:3;34952:92;35040:3;35031:6;34952:92;:::i;:::-;34945:99;;35061:95;35152:3;35143:6;35061:95;:::i;:::-;35054:102;;35173:148;35317:3;35173:148;:::i;:::-;35166:155;;35338:3;35331:10;;34652:695;;;;;:::o;35353:1395::-;35470:37;35503:3;35470:37;:::i;:::-;35572:18;35564:6;35561:30;35558:56;;;35594:18;;:::i;:::-;35558:56;35638:38;35670:4;35664:11;35638:38;:::i;:::-;35723:67;35783:6;35775;35769:4;35723:67;:::i;:::-;35817:1;35841:4;35828:17;;35873:2;35865:6;35862:14;35890:1;35885:618;;;;36547:1;36564:6;36561:77;;;36613:9;36608:3;36604:19;36598:26;36589:35;;36561:77;36664:67;36724:6;36717:5;36664:67;:::i;:::-;36658:4;36651:81;36520:222;35855:887;;35885:618;35937:4;35933:9;35925:6;35921:22;35971:37;36003:4;35971:37;:::i;:::-;36030:1;36044:208;36058:7;36055:1;36052:14;36044:208;;;36137:9;36132:3;36128:19;36122:26;36114:6;36107:42;36188:1;36180:6;36176:14;36166:24;;36235:2;36224:9;36220:18;36207:31;;36081:4;36078:1;36074:12;36069:17;;36044:208;;;36280:6;36271:7;36268:19;36265:179;;;36338:9;36333:3;36329:19;36323:26;36381:48;36423:4;36415:6;36411:17;36400:9;36381:48;:::i;:::-;36373:6;36366:64;36288:156;36265:179;36490:1;36486;36478:6;36474:14;36470:22;36464:4;36457:36;35892:611;;;35855:887;;35445:1303;;;35353:1395;;:::o;36754:98::-;36805:6;36839:5;36833:12;36823:22;;36754:98;;;:::o;36858:168::-;36941:11;36975:6;36970:3;36963:19;37015:4;37010:3;37006:14;36991:29;;36858:168;;;;:::o;37032:373::-;37118:3;37146:38;37178:5;37146:38;:::i;:::-;37200:70;37263:6;37258:3;37200:70;:::i;:::-;37193:77;;37279:65;37337:6;37332:3;37325:4;37318:5;37314:16;37279:65;:::i;:::-;37369:29;37391:6;37369:29;:::i;:::-;37364:3;37360:39;37353:46;;37122:283;37032:373;;;;:::o;37411:640::-;37606:4;37644:3;37633:9;37629:19;37621:27;;37658:71;37726:1;37715:9;37711:17;37702:6;37658:71;:::i;:::-;37739:72;37807:2;37796:9;37792:18;37783:6;37739:72;:::i;:::-;37821;37889:2;37878:9;37874:18;37865:6;37821:72;:::i;:::-;37940:9;37934:4;37930:20;37925:2;37914:9;37910:18;37903:48;37968:76;38039:4;38030:6;37968:76;:::i;:::-;37960:84;;37411:640;;;;;;;:::o;38057:141::-;38113:5;38144:6;38138:13;38129:22;;38160:32;38186:5;38160:32;:::i;:::-;38057:141;;;;:::o;38204:349::-;38273:6;38322:2;38310:9;38301:7;38297:23;38293:32;38290:119;;;38328:79;;:::i;:::-;38290:119;38448:1;38473:63;38528:7;38519:6;38508:9;38504:22;38473:63;:::i;:::-;38463:73;;38419:127;38204:349;;;;:::o;38559:332::-;38680:4;38718:2;38707:9;38703:18;38695:26;;38731:71;38799:1;38788:9;38784:17;38775:6;38731:71;:::i;:::-;38812:72;38880:2;38869:9;38865:18;38856:6;38812:72;:::i;:::-;38559:332;;;;;:::o;38897:::-;39018:4;39056:2;39045:9;39041:18;39033:26;;39069:71;39137:1;39126:9;39122:17;39113:6;39069:71;:::i;:::-;39150:72;39218:2;39207:9;39203:18;39194:6;39150:72;:::i;:::-;38897:332;;;;;:::o

Swarm Source

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