ETH Price: $3,908.59 (+0.08%)

Token

Mortiverse (MORTI)
 

Overview

Max Total Supply

2,333 MORTI

Holders

978

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
m0bius.eth
Balance
2 MORTI
0xdaff0e93f8614d42ae3efa26657587cd4d4bbc21
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:
Mortiverse

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-10-14
*/

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

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

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

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

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

// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)

// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @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.
     *
     * _Available since v3.1._
     */
    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 `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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 up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (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; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

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

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            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 (rounding == Rounding.Up && 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 down.
     *
     * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * 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 10, 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length)
        internal
        pure
        returns (string memory)
    {
        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_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        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);
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

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

/**
 * @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);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

/**
 * @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:
 *
 * ```
 * 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}:
 *
 * ```
 * 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.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    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 override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     *
     * Format of the revert message is described in {_checkRole}.
     *
     * _Available since v4.6._
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(account),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @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 override 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 override 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 override 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 `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * May emit a {RoleGranted} event.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @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 Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

interface IBatchERC721 {
    error InvalidApprovalZeroAddress();
    error CallerNotOwnerOrApprovedOperator();
    error TransferToNonERC721ReceiverImplementer();
    error InvalidTransferToZeroAddress();
    error MintZeroTokenId();
    error TokenNotOwnedByFromAddress();
    error QueryNonExistentToken();
    error QueryBalanceOfZeroAddress();
    error QueryBurnedToken();
}

// https://eips.ethereum.org/EIPS/eip-721, http://erc721.org/


/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface IERC721 /* is ERC165 */ {
    /// @dev This emits when ownership of any NFT changes by any mechanism.
    ///  This event emits when NFTs are created (`from` == 0) and destroyed
    ///  (`to` == 0). Exception: during contract creation, any number of NFTs
    ///  may be created and assigned without emitting Transfer. At the time of
    ///  any transfer, the approved address for that NFT (if any) is reset to none.
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

    /// @dev This emits when the approved address for an NFT is changed or
    ///  reaffirmed. The zero address indicates there is no approved address.
    ///  When a Transfer event emits, this also indicates that the approved
    ///  address for that NFT (if any) is reset to none.
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

    /// @dev This emits when an operator is enabled or disabled for an owner.
    ///  The operator can manage all NFTs of the owner.
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT. When transfer is complete, this function
    ///  checks if `_to` is a smart contract (code size > 0). If so, it calls
    ///  `onERC721Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) external;

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to "".
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external;

    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
    ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
    ///  THEY MAY BE PERMANENTLY LOST
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(address _from, address _to, uint256 _tokenId) external;

    /// @notice Change or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
    ///  operator of the current owner.
    /// @param _approved The new approved NFT controller
    /// @param _tokenId The NFT to approve
    function approve(address _approved, uint256 _tokenId) external;

    /// @notice Enable or disable approval for a third party ("operator") to manage
    ///  all of `msg.sender`'s assets
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
    ///  multiple operators per owner.
    /// @param _operator Address to add to the set of authorized operators
    /// @param _approved True if the operator is approved, false to revoke approval
    function setApprovalForAll(address _operator, bool _approved) external;

    /// @notice Count all NFTs assigned to an owner
    /// @dev NFTs assigned to the zero address are considered invalid, and this
    ///  function throws for queries about the zero address.
    /// @param _owner An address for whom to query the balance
    /// @return The number of NFTs owned by `_owner`, possibly zero
    function balanceOf(address _owner) external view returns (uint256);

    /// @notice Find the owner of an NFT
    /// @dev NFTs assigned to zero address are considered invalid, and queries
    ///  about them do throw.
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 _tokenId) external view returns (address);

    /// @notice Get the approved address for a single NFT
    /// @dev Throws if `_tokenId` is not a valid NFT.
    /// @param _tokenId The NFT to find the approved address for
    /// @return The approved address for this NFT, or the zero address if there is none
    function getApproved(uint256 _tokenId) external view returns (address);

    /// @notice Query if an address is an authorized operator for another address
    /// @param _owner The address that owns the NFTs
    /// @param _operator The address that acts on behalf of the owner
    /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

interface IERC2309 {
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);
}

/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface IERC721Receiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The ERC721 smart contract calls this function on the recipient
    ///  after a `transfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param _operator The address which called `safeTransferFrom` function
    /// @param _from The address which previously owned the token
    /// @param _tokenId The NFT identifier which is being transferred
    /// @param _data Additional data with no specified format
    /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onERC721Received(
        address _operator,
        address _from,
        uint256 _tokenId,
        bytes calldata _data
    )
        external
        returns (bytes4);
}

contract BatchERC721 is IERC165, IERC721, IERC2309, IBatchERC721 {
    bytes4 private constant ERC165_INTERFACE_ID = 0x01ffc9a7;
    bytes4 private constant ERC721_INTERFACE_ID = 0x80ac58cd;
    bytes4 private constant ERC721_RECEIVER_INTERFACE_ID = 0x150b7a02;
    bytes4 private constant ERC721_METADATA_INTERFACE_ID = 0x5b5e139f;

    string public baseURI;
    string internal uriExtension;
    string private _name;
    string private _symbol;

    uint256 private nextTokenId;
    uint256 private startingTokenId;
    uint256 private burnCounter;

    mapping(uint256 => address) private tokenOwnersOrdered;
    mapping(uint256 => bool) private unorderedOwner;
    mapping(uint256 => address) private tokenOwners;
    mapping(uint256 => address) private tokenOperators;
    mapping(uint256 => bool) private burnedTokens;
    mapping(address => uint256) private balances;
    mapping(address => mapping(address => bool)) private operators;

    constructor(
        string memory name_,
        string memory symbol_,
        uint256 startingTokenId_
    ) {
        _name = name_;
        _symbol = symbol_;
        nextTokenId = startingTokenId = startingTokenId_;
    }

    /// @notice Change or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
    ///  operator of the current owner.
    /// @param _approved The new approved NFT controller
    /// @param _tokenId The NFT to approve
    function approve(address _approved, uint256 _tokenId) external {
        _beforeSetApproval(_approved, true);
        if (_approved == address(0)) revert InvalidApprovalZeroAddress();
        address owner = ownerOf(_tokenId);
        if (
            owner != msg.sender &&
            !operators[msg.sender][_approved] &&
            tokenOperators[_tokenId] != msg.sender
        ) revert CallerNotOwnerOrApprovedOperator();

        if (!unorderedOwner[_tokenId]) {
            tokenOwners[_tokenId] = owner;
            unorderedOwner[_tokenId] = true;
        }
        tokenOperators[_tokenId] = _approved;

        emit Approval(msg.sender, _approved, _tokenId);
        _afterSetApproval(_approved, true);
    }

    /// @notice Enable or disable approval for a third party ("operator") to manage
    ///  all of `msg.sender`'s assets
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
    ///  multiple operators per owner.
    /// @param _operator Address to add to the set of authorized operators
    /// @param _approved True if the operator is approved, false to revoke approval
    function setApprovalForAll(address _operator, bool _approved) external {
        _beforeSetApproval(_operator, _approved);
        operators[msg.sender][_operator] = _approved;

        emit ApprovalForAll(msg.sender, _operator, _approved);
        _afterSetApproval(_operator, _approved);
    }

    /// @notice Get the approved address for a single NFT
    /// @dev Throws if `_tokenId` is not a valid NFT.
    /// @param _tokenId The NFT to find the approved address for
    /// @return The approved address for this NFT, or the zero address if there is none
    function getApproved(uint256 _tokenId) external view returns (address) {
        return ownerOf(_tokenId);
    }

    /// @notice Query if an address is an authorized operator for another address
    /// @param _owner The address that owns the NFTs
    /// @param _operator The address that acts on behalf of the owner
    /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
    function isApprovedForAll(address _owner, address _operator)
        external
        view
        returns (bool)
    {
        return operators[_owner][_operator];
    }

    /// @notice Name for NFTs in this contract
    function name() external view returns (string memory) {
        return _name;
    }

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI(uint256 _tokenId)
        external
        view
        virtual
        returns (string memory)
    {
        if (_tokenId < startingTokenId || _tokenId > nextTokenId - 1)
            revert QueryNonExistentToken();
        return
            bytes(baseURI).length > 0
                ? string.concat(
                    baseURI,
                    Strings.toString(_tokenId),
                    uriExtension
                )
                : "";
    }

    /// @notice Count NFTs tracked by this contract
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function totalSupply() external view returns (uint256) {
        return nextTokenId - startingTokenId - burnCounter;
    }

    /// @notice Count all NFTs assigned to an owner
    /// @dev NFTs assigned to the zero address are considered invalid, and this
    ///  function throws for queries about the zero address.
    /// @param _owner An address for whom to query the balance
    /// @return The number of NFTs owned by `_owner`, possibly zero
    function balanceOf(address _owner) external view returns (uint256) {
        if (_owner == address(0)) revert QueryBalanceOfZeroAddress();
        return balances[_owner];
    }

    /// @notice Verify whether a token exists and has not been burned
    /// @param _tokenId The token id
    /// @return bool
    function exists(uint256 _tokenId) external view returns (bool) {
        return
            _tokenId >= startingTokenId &&
            _tokenId < nextTokenId &&
            !burnedTokens[_tokenId];
    }

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to "".
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public {
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT. When transfer is complete, this function
    ///  checks if `_to` is a smart contract (code size > 0). If so, it calls
    ///  `onERC721Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory data
    ) public {
        transferFrom(_from, _to, _tokenId);
        if (_to.code.length > 0) {
            _checkERC721Received(_from, _to, _tokenId, data);
        }
    }

    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
    ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
    ///  THEY MAY BE PERMANENTLY LOST
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public {
        if (_tokenId < startingTokenId || _tokenId > nextTokenId - 1)
            revert QueryNonExistentToken();
        address owner = ownerOf(_tokenId);

        if (owner != _from) revert TokenNotOwnedByFromAddress();
        if (
            owner != msg.sender &&
            !operators[_from][msg.sender] &&
            tokenOperators[_tokenId] != msg.sender
        ) revert CallerNotOwnerOrApprovedOperator();
        if (_to == address(0)) revert InvalidTransferToZeroAddress();

        _beforeTokenTransfer(_from, _to, _tokenId);

        balances[_from] -= 1;
        balances[_to] += 1;

        tokenOperators[_tokenId] = address(0);
        tokenOwners[_tokenId] = _to;
        unorderedOwner[_tokenId] = true;

        emit Transfer(_from, _to, _tokenId);

        _afterTokenTransfer(_from, _to, _tokenId);
    }

    /// @notice Find the owner of an NFT
    /// @dev NFTs assigned to zero address are considered invalid, and queries
    ///  about them do throw.
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 _tokenId) public view returns (address) {
        if (_tokenId < startingTokenId || _tokenId > nextTokenId)
            revert QueryNonExistentToken();
        if (burnedTokens[_tokenId]) revert QueryBurnedToken();
        return
            unorderedOwner[_tokenId]
                ? tokenOwners[_tokenId]
                : _ownerOf(_tokenId);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        returns (bool)
    {
        return
            interfaceId == ERC165_INTERFACE_ID ||
            interfaceId == ERC721_INTERFACE_ID ||
            interfaceId == ERC721_RECEIVER_INTERFACE_ID ||
            interfaceId == ERC721_METADATA_INTERFACE_ID;
    }

    /// @notice Find the owner of an NFT
    /// @dev Does not revert if token is burned, this is used to query via multi-call
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function unsafeOwnerOf(uint256 _tokenId) public view returns (address) {
        if (burnedTokens[_tokenId]) return address(0);
        return
            unorderedOwner[_tokenId]
                ? tokenOwners[_tokenId]
                : _ownerOf(_tokenId);
    }

    function _mint2309(address _to, uint256 _quantity) internal {
        if (_to == address(0)) revert InvalidTransferToZeroAddress();
        if (_quantity == 0) revert MintZeroTokenId();
        unchecked {
            balances[_to] += _quantity;
            uint256 newTotal = nextTokenId + _quantity;

            tokenOwnersOrdered[nextTokenId] = _to;
            nextTokenId = newTotal;
        }

        emit ConsecutiveTransfer(
            startingTokenId,
            nextTokenId - 1,
            address(0),
            _to
        );
    }

    /// @notice Same as calling {_mint} and then checking for IERC721Receiver
    function safeMint(address _to, uint256 _quantity) internal {
        safeMint(_to, _quantity, "");
    }

    /// @notice Same as calling {_mint} and then checking for IERC721Receiver
    function safeMint(
        address _to,
        uint256 _quantity,
        bytes memory _data
    ) internal {
        _mint(_to, _quantity);
        uint256 currentTokenId = nextTokenId - 1;
        unchecked {
            if (_to.code.length != 0) {
                uint256 tokenId = nextTokenId - _quantity - 1;
                do {
                    if (
                        !_checkERC721Received(address(0), _to, ++tokenId, _data)
                    ) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (tokenId < currentTokenId);
            }
        }
    }

    /// @notice Mint a quantity of NFTs to an address
    /// @dev Saves the first token id minted by the address to a map of
    ///      used to verify ownership initially.
    ///      {tokenOwnersOrdered} will be used to find the owner unless the token
    ///      has been transfered. In that case, it will be available in {tokenOwners} instead.
    ///      This is done to reduce gas requirements of minting while keeping on-chain lookups
    ///      cheaper as tokens are transfered around. It helps with the burning of tokens.
    /// @param _to Receiver address
    /// @param _quantity The quantity to be minted
    function _mint(address _to, uint256 _quantity) internal {
        if (_to == address(0)) revert InvalidTransferToZeroAddress();
        if (_quantity == 0) revert MintZeroTokenId();
        unchecked {
            balances[_to] += _quantity;
            uint256 newTotal = nextTokenId + _quantity;

            for (uint256 i = nextTokenId; i < newTotal; i++) {
                emit Transfer(address(0), _to, i);
            }

            tokenOwnersOrdered[nextTokenId] = _to;
            nextTokenId = newTotal;
        }
    }

    /// @notice Same as calling {_burn} without a from address or approval check
    function _burn(uint256 _tokenId) internal {
        _burn(_tokenId, msg.sender);
    }

    /// @notice Same as calling {_burn} without approval check
    function _burn(uint256 _tokenId, address _from) internal {
        _burn(_tokenId, _from, false);
    }

    /// @notice Burn an NFT
    /// @dev Checks ownership of the token
    /// @param _tokenId The token id
    /// @param _from The owner address
    /// @param _approvalCheck Check if the caller is owner or an approved operator
    function _burn(
        uint256 _tokenId,
        address _from,
        bool _approvalCheck
    ) internal {
        if (_tokenId < startingTokenId || _tokenId > nextTokenId - 1)
            revert QueryNonExistentToken();
        address owner = ownerOf(_tokenId);
        if (owner != _from) revert TokenNotOwnedByFromAddress();
        if (_approvalCheck) {
            if (
                owner != msg.sender &&
                !operators[_from][msg.sender] &&
                tokenOperators[_tokenId] != msg.sender
            ) revert CallerNotOwnerOrApprovedOperator();
        }

        balances[_from]--;
        burnCounter++;
        burnedTokens[_tokenId] = true;

        tokenOperators[_tokenId] = address(0);

        emit Transfer(_from, address(0), _tokenId);
    }

    /// @notice Before Approval Hook
    /// @param _operator Operator
    /// @param _approved Approved
    /* solhint-disable no-empty-blocks */
    function _beforeSetApproval(address _operator, bool _approved)
        internal
        virtual
    {}

    /* solhint-disable no-empty-blocks */

    /// @notice Before Approval Hook
    /// @param _operator Operator
    /// @param _approved Approved
    /* solhint-disable no-empty-blocks */
    function _afterSetApproval(address _operator, bool _approved)
        internal
        virtual
    {}

    /* solhint-disable no-empty-blocks */

    /// @notice Before Token Transfer Hook
    /// @param from Token owner
    /// @param to Receiver
    /// @param tokenId The token id
    /* solhint-disable no-empty-blocks */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /* solhint-disable no-empty-blocks */

    /// @notice After Token Transfer Hook
    /// @param from Token owner
    /// @param to Receiver
    /// @param tokenId The token id
    /* solhint-disable no-empty-blocks */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /* solhint-disable no-empty-blocks */

    /// @notice Checking if the receiving contract implements IERC721Receiver
    /// @param from Token owner
    /// @param to Receiver
    /// @param tokenId The token id
    /// @param _data Extra data
    function _checkERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal returns (bool) {
        try
            IERC721Receiver(to).onERC721Received(
                msg.sender,
                from,
                tokenId,
                _data
            )
        returns (bytes4 retval) {
            return retval == IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    /// @notice Count NFTs minted by this contract
    /// @dev Includes burned tokens
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function _totalMinted() internal view returns (uint256) {
        return nextTokenId - startingTokenId;
    }

    /// @notice Find the owner of an NFT
    /// @dev This function should only be called from {ownerOf(_tokenId)}
    ///      This iterates through the original minters since they are ordered
    ///      If an owner is address(0), it keeps looking for the owner by checking the
    ///      previous tokens. If minter A minted 10, then the first token will have the address
    ///      and the rest will have address(0)
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function _ownerOf(uint256 _tokenId)
        internal
        view
        virtual
        returns (address)
    {
        uint256 curr = _tokenId;
        unchecked {
            address owner;
            // Invariant:
            // There will always be an ownership that has an address and is not burned
            // before an ownership that does not have an address and is not burned.
            // Hence, curr will not underflow.
            while (owner == address(0)) {
                if (!unorderedOwner[curr]) {
                    owner = tokenOwnersOrdered[curr];
                }
                curr--;
            }
            return owner;
        }
    }
}

interface IOperatorFilter {
    function mayTransfer(address operator) external view returns (bool);
}

abstract contract ERC721OperatorFilter is BatchERC721, Ownable, AccessControl {
    IOperatorFilter private operatorFilter_;

    constructor(
        string memory name_,
        string memory symbol_,
        uint256 startingTokenId_,
        address filter
    ) Ownable() BatchERC721(name_, symbol_, startingTokenId_) AccessControl() {
        operatorFilter_ = IOperatorFilter(filter);
    }

    function setOperatorFilter(IOperatorFilter filter) public onlyRole(DEFAULT_ADMIN_ROLE) {
        operatorFilter_ = filter;
    }

    function operatorFilter() public view returns (IOperatorFilter) {
        return operatorFilter_;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(BatchERC721, AccessControl)
        returns (bool)
    {
        return
            interfaceId == type(AccessControl).interfaceId ||
            BatchERC721.supportsInterface(interfaceId);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(BatchERC721) {
        if (
            from != address(0) &&
            to != address(0) &&
            !_mayTransfer(msg.sender, tokenId)
        ) {
            revert("ERC721OperatorFilter: illegal operator");
        }
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function _beforeSetApproval(address _operator, bool _approved) internal virtual override {
        if(_approved && !_mayOperate(_operator)) revert("ERC721OperatorFilter: illegal operator");
        super._beforeSetApproval(_operator, _approved);
    }

    function _mayOperate(address operator)
        private
        view
        returns (bool)
    {
        IOperatorFilter filter = operatorFilter_;
        return filter.mayTransfer(operator);
    }

    function _mayTransfer(address operator, uint256 tokenId)
        private
        view
        returns (bool)
    {
        IOperatorFilter filter = operatorFilter_;
        if (address(filter) == address(0)) return true;
        if (operator == ownerOf(tokenId)) return true;
        return filter.mayTransfer(msg.sender);
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

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

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol)

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

interface IMortiverse {
    error InvalidETHQuantity();
    error MaxSupply();
    error NonExistentTokenURI();
    error WithdrawTransfer();
    error NotInAllowlist();
    error ExceedsMintAllowance();
    error InvalidURI();
    error LengthsMismatch();
    error NotAllowlistPhase();
    error NotPublicPhase();
    error PublicSaleMustStartAfterAllowlist();
    error NewAllowanceLowerThanActual();
    error IllegalOperator();
}

contract Mortiverse is
    ERC721OperatorFilter,
    ERC2981,
    IMortiverse
{
    struct SaleConfig {
        uint128 allowlist;
        uint128 publicSale;
    }

    enum Phase {
        CLOSED,
        ALLOWLIST,
        PUBLIC,
        OVER
    }

    uint256 public constant TOTAL_SUPPLY = 5555;
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

    string public contractURI = "ipfs://QmR2y7P2m9cbmtc31LskvVcbn2qxJPWNE4EvrioJJjPukJ";

    uint256 public price = 0.029 ether;
    uint256 public mintAllowance = 2;

    bytes32 public allowlistMerkleRoot;

    mapping(address => uint256) private mints;

    SaleConfig public saleConfig;

    modifier isMintable(uint256 quantity) {
        if (price * quantity != msg.value) {
            revert InvalidETHQuantity();
        }
        if (_totalMinted() + quantity > TOTAL_SUPPLY) {
            revert MaxSupply();
        }
        if (mints[msg.sender] + quantity > mintAllowance) {
            revert ExceedsMintAllowance();
        }
        _;
    }

    constructor(
        address owner_,
        address manager_,
        uint256 initialQty_,
        address filter_
    ) ERC721OperatorFilter("Mortiverse", "MORTI", 1, filter_) {
        baseURI = "ipfs://QmWpxg6xzYgZhdzoejrp8HFxUppr8sPQaV6kE5XasfuZeX/";
        uriExtension = ".json";
        _grantRole(DEFAULT_ADMIN_ROLE, owner_);
        _grantRole(DEFAULT_ADMIN_ROLE, manager_);
        _grantRole(MANAGER_ROLE, owner_);
        _grantRole(MANAGER_ROLE, manager_);
        _setDefaultRoyalty(owner_, 750);
        saleConfig = SaleConfig(1665763200, 1665777600);
        if(initialQty_ > 0) {
            _mint2309(owner_, initialQty_);
        }
        _transferOwnership(manager_);
    }

    function allowlistMint(bytes32[] calldata merkleProof, uint256 quantity)
        external
        payable
        isMintable(quantity)
    {
        if (currentPhase() != Phase.ALLOWLIST) revert NotAllowlistPhase();
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
        if (!MerkleProof.verify(merkleProof, allowlistMerkleRoot, leaf)) {
            revert NotInAllowlist();
        }
        mints[msg.sender] += quantity;
        safeMint(msg.sender, quantity);
    }

    function mint(uint256 quantity) external payable isMintable(quantity) {
        if (currentPhase() != Phase.PUBLIC) revert NotPublicPhase();
        mints[msg.sender] += quantity;
        safeMint(msg.sender, quantity);
    }

    function ownerMint(address recipient, uint256 quantity)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        safeMint(recipient, quantity);
    }

    function airdrop(
        address[] calldata receivers,
        uint256[] calldata quantities
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        if (receivers.length != quantities.length) revert LengthsMismatch();
        uint256 total;
        for (uint256 i = 0; i < quantities.length; i++) {
            total += quantities[i];
        }
        if (_totalMinted() + total > TOTAL_SUPPLY) revert MaxSupply();
        for (uint256 i = 0; i < receivers.length; i++) {
            safeMint(receivers[i], quantities[i]);
        }
    }

    function setContractURI(string calldata _contractURI)
        external
        onlyRole(MANAGER_ROLE)
    {
        if (bytes(_contractURI).length == 0) {
            revert InvalidURI();
        }
        contractURI = _contractURI;
    }

    function setBaseURI(string calldata _baseURI)
        external
        onlyRole(MANAGER_ROLE)
    {
        if (bytes(_baseURI).length == 0) {
            revert InvalidURI();
        }
        baseURI = _baseURI;
    }

    function setURIExtension(string calldata _extension)
        external
        onlyRole(MANAGER_ROLE)
    {
        if (bytes(_extension).length == 0) {
            uriExtension = "";
        }
        uriExtension = _extension;
    }

    function setSaleConfig(uint128 allowlistTimestamp, uint128 publicTimestamp)
        external
        onlyRole(MANAGER_ROLE)
    {
        if (allowlistTimestamp >= publicTimestamp)
            revert PublicSaleMustStartAfterAllowlist();
        saleConfig = SaleConfig(allowlistTimestamp, publicTimestamp);
    }

    function setAllowlistRoot(bytes32 merkleRoot)
        external
        onlyRole(MANAGER_ROLE)
    {
        allowlistMerkleRoot = merkleRoot;
    }

    function setDefaultAdmin() external onlyOwner {
        _grantRole(DEFAULT_ADMIN_ROLE, owner());
    }

    function withdrawPayments(address payable payee)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        uint256 balance = address(this).balance;
        (bool transferTx, ) = payee.call{value: balance}(""); // solhint-disable-line avoid-low-level-calls
        if (!transferTx) {
            revert WithdrawTransfer();
        }
    }

    /// @notice Sets the royalty information that all ids in this contract will default to.
    /// @dev Explain to a developer any extra details
    /// @param receiver cannot be the zero address.
    /// @param feeNumerator cannot be greater than the fee denominator.
    function setDefaultRoyalty(address receiver, uint96 feeNumerator)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    // @notice Sets the royalty information that token ids.
    /// @dev to Resets royalty information set _feeNumerator to 0
    /// @param tokenId the specific token id to Sets the royalty information for
    /// @param receiver the address that will receive the royalty
    /// @param feeNumerator cannot be greater than the fee denominator other case revert with InvalidFeeNumerator
    function setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        _setTokenRoyalty(tokenId, receiver, feeNumerator);
    }

    function setMintAllowance(uint256 allowance) external onlyRole(MANAGER_ROLE) {
        if(allowance <= mintAllowance) revert NewAllowanceLowerThanActual();
        mintAllowance = allowance;
    }

    function setPrice(uint256 newPrice) external onlyRole(MANAGER_ROLE) {
        price = newPrice;
    }

    // solhint-disable not-rely-on-time
    function currentPhase() public view returns (Phase) {
        if (_totalMinted() == TOTAL_SUPPLY) {
            return Phase.OVER;
        } else if (block.timestamp > saleConfig.publicSale) {
            return Phase.PUBLIC;
        } else if (block.timestamp > saleConfig.allowlist) {
            return Phase.ALLOWLIST;
        } else {
            return Phase.CLOSED;
        }
    }
    // solhint-enable

    function userAllowance(address user) public view returns (uint256) {
        return mintAllowance - mints[user];
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721OperatorFilter, ERC2981)
        returns (bool)
    {
        return
            interfaceId == 0x2a55205a || // ERC165 Interface ID for ERC2981
            ERC721OperatorFilter.supportsInterface(interfaceId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"manager_","type":"address"},{"internalType":"uint256","name":"initialQty_","type":"uint256"},{"internalType":"address","name":"filter_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotOwnerOrApprovedOperator","type":"error"},{"inputs":[],"name":"ExceedsMintAllowance","type":"error"},{"inputs":[],"name":"IllegalOperator","type":"error"},{"inputs":[],"name":"InvalidApprovalZeroAddress","type":"error"},{"inputs":[],"name":"InvalidETHQuantity","type":"error"},{"inputs":[],"name":"InvalidTransferToZeroAddress","type":"error"},{"inputs":[],"name":"InvalidURI","type":"error"},{"inputs":[],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"MaxSupply","type":"error"},{"inputs":[],"name":"MintZeroTokenId","type":"error"},{"inputs":[],"name":"NewAllowanceLowerThanActual","type":"error"},{"inputs":[],"name":"NonExistentTokenURI","type":"error"},{"inputs":[],"name":"NotAllowlistPhase","type":"error"},{"inputs":[],"name":"NotInAllowlist","type":"error"},{"inputs":[],"name":"NotPublicPhase","type":"error"},{"inputs":[],"name":"PublicSaleMustStartAfterAllowlist","type":"error"},{"inputs":[],"name":"QueryBalanceOfZeroAddress","type":"error"},{"inputs":[],"name":"QueryBurnedToken","type":"error"},{"inputs":[],"name":"QueryNonExistentToken","type":"error"},{"inputs":[],"name":"TokenNotOwnedByFromAddress","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"WithdrawTransfer","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":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"}],"name":"ConsecutiveTransfer","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":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"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowlistMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"allowlistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","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":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPhase","outputs":[{"internalType":"enum Mortiverse.Phase","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintAllowance","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":"operatorFilter","outputs":[{"internalType":"contract IOperatorFilter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","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":"account","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":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"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":[],"name":"saleConfig","outputs":[{"internalType":"uint128","name":"allowlist","type":"uint128"},{"internalType":"uint128","name":"publicSale","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"setAllowlistRoot","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":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_contractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setDefaultAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"allowance","type":"uint256"}],"name":"setMintAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOperatorFilter","name":"filter","type":"address"}],"name":"setOperatorFilter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"allowlistTimestamp","type":"uint128"},{"internalType":"uint128","name":"publicTimestamp","type":"uint128"}],"name":"setSaleConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_extension","type":"string"}],"name":"setURIExtension","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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unsafeOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"payee","type":"address"}],"name":"withdrawPayments","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e060405260356080818152906200388960a039601390620000229082620005a3565b5066670758aa7c800060145560026015553480156200004057600080fd5b50604051620039143803806200391483398101604081905262000063916200068c565b6040518060400160405280600a8152602001694d6f727469766572736560b01b815250604051806040016040528060058152602001644d4f52544960d81b8152506001838383838260029081620000bb9190620005a3565b506003620000ca8382620005a3565b50600581905560045550620000e190503362000215565b601080546001600160a01b0319166001600160a01b0392909216919091179055505060408051606081019091526036808252909150620038de60208301396000906200012e9082620005a3565b50604080518082019091526005815264173539b7b760d91b60208201526001906200015a9082620005a3565b506200016860008562000267565b6200017560008462000267565b62000190600080516020620038be8339815191528562000267565b620001ab600080516020620038be8339815191528462000267565b620001b9846102ee620002f2565b6040805180820190915263634987808152636349bfc0602090910152736349bfc00000000000000000000000006349878060185581156200020057620002008483620003f7565b6200020b8362000215565b5050505062000702565b600e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b620002738282620004d1565b620002ee576000828152600f602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620002ad3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6127106001600160601b0382161115620003665760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084015b60405180910390fd5b6001600160a01b038216620003be5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016200035d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601155565b6001600160a01b0382166200041f5760405163163ae22d60e11b815260040160405180910390fd5b80600003620004415760405163eb1d0cf560e01b815260040160405180910390fd5b6001600160a01b0382166000818152600c6020908152604080832080548601905560048054808552600790935290832080546001600160a01b0319168517905590840190819055600554907fdeaa91b6123d068f5821d0fb0678463d1a8a6079fe8af5de3ce5e896dcf9133d90620004bc90600190620006e0565b60405190815260200160405180910390a45050565b6000828152600f602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200052957607f821691505b6020821081036200054a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200059e57600081815260208120601f850160051c81016020861015620005795750805b601f850160051c820191505b818110156200059a5782815560010162000585565b5050505b505050565b81516001600160401b03811115620005bf57620005bf620004fe565b620005d781620005d0845462000514565b8462000550565b602080601f8311600181146200060f5760008415620005f65750858301515b600019600386901b1c1916600185901b1785556200059a565b600085815260208120601f198616915b8281101562000640578886015182559484019460019091019084016200061f565b50858210156200065f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200068757600080fd5b919050565b60008060008060808587031215620006a357600080fd5b620006ae856200066f565b9350620006be602086016200066f565b925060408501519150620006d5606086016200066f565b905092959194509250565b81810381811115620004f857634e487b7160e01b600052601160045260246000fd5b61317780620007126000396000f3fe60806040526004361061031a5760003560e01c806367243482116101ab57806395d89b41116100f7578063c87b56dd11610095578063e8a3d4851161006f578063e8a3d48514610952578063e985e9c514610967578063ec87621c146109b0578063f2fde38b146109d257600080fd5b8063c87b56dd146108f2578063d547741f14610912578063d783925b1461093257600080fd5b8063a217fddf116100d1578063a217fddf1461087d578063a22cb46514610892578063acf080d1146108b2578063b88d4fde146108d257600080fd5b806395d89b411461083f578063a035b1fe14610854578063a0712d681461086a57600080fd5b80638e0acd121161016457806390aa0b0f1161013e57806390aa0b0f1461079457806391b7f5ed146107df57806391d14854146107ff578063938e3d7b1461081f57600080fd5b80638e0acd121461073e578063902d55a51461075e578063907097511461077457600080fd5b80636724348214610698578063689843e0146106b85780636c0360eb146106d657806370a08231146106eb578063715018a61461070b5780638da5cb5b1461072057600080fd5b80632a55205a1161026a57806342842e0e116102235780634f558e79116101fd5780634f558e791461061857806355f804b3146106385780635944c753146106585780636352211e1461067857600080fd5b806342842e0e146105b85780634777a597146105d8578063484b973c146105f857600080fd5b80632a55205a146104ee5780632f2ff15d1461052d57806331b3eb941461054d57806336568abe1461056d57806338a59d971461058d578063396876bd146105a257600080fd5b8063095ea7b3116102d757806318160ddd116102b157806318160ddd1461047357806323b872dd14610488578063248a9ca3146104a8578063293108e0146104d857600080fd5b8063095ea7b3146104125780630c6b2cbf146104325780631338a83f1461046057600080fd5b806301ffc9a71461031f57806304392a4c1461035457806304634d8d14610376578063055ad42e1461039657806306fdde03146103b8578063081812fc146103da575b600080fd5b34801561032b57600080fd5b5061033f61033a3660046126b9565b6109f2565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b5061037461036f3660046126f2565b610a1d565b005b34801561038257600080fd5b50610374610391366004612751565b610a9a565b3480156103a257600080fd5b506103ab610ab4565b60405161034b9190612793565b3480156103c457600080fd5b506103cd610b0b565b60405161034b919061280b565b3480156103e657600080fd5b506103fa6103f536600461281e565b610b9d565b6040516001600160a01b03909116815260200161034b565b34801561041e57600080fd5b5061037461042d366004612837565b610ba8565b34801561043e57600080fd5b5061045261044d366004612863565b610d12565b60405190815260200161034b565b61037461046e3660046128c5565b610d38565b34801561047f57600080fd5b50610452610ede565b34801561049457600080fd5b506103746104a3366004612911565b610f02565b3480156104b457600080fd5b506104526104c336600461281e565b6000908152600f602052604090206001015490565b3480156104e457600080fd5b5061045260165481565b3480156104fa57600080fd5b5061050e610509366004612952565b61110c565b604080516001600160a01b03909316835260208301919091520161034b565b34801561053957600080fd5b50610374610548366004612974565b6111ba565b34801561055957600080fd5b50610374610568366004612863565b6111df565b34801561057957600080fd5b50610374610588366004612974565b61125e565b34801561059957600080fd5b506103746112e1565b3480156105ae57600080fd5b5061045260155481565b3480156105c457600080fd5b506103746105d3366004612911565b611307565b3480156105e457600080fd5b506103fa6105f336600461281e565b611322565b34801561060457600080fd5b50610374610613366004612837565b611381565b34801561062457600080fd5b5061033f61063336600461281e565b611396565b34801561064457600080fd5b506103746106533660046129a4565b6113c9565b34801561066457600080fd5b50610374610673366004612a16565b611410565b34801561068457600080fd5b506103fa61069336600461281e565b611426565b3480156106a457600080fd5b506103746106b3366004612a54565b611486565b3480156106c457600080fd5b506010546001600160a01b03166103fa565b3480156106e257600080fd5b506103cd611599565b3480156106f757600080fd5b50610452610706366004612863565b611627565b34801561071757600080fd5b5061037461166b565b34801561072c57600080fd5b50600e546001600160a01b03166103fa565b34801561074a57600080fd5b5061037461075936600461281e565b61167d565b34801561076a57600080fd5b506104526115b381565b34801561078057600080fd5b5061037461078f3660046129a4565b61169b565b3480156107a057600080fd5b506018546107bf906001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161034b565b3480156107eb57600080fd5b506103746107fa36600461281e565b6116e7565b34801561080b57600080fd5b5061033f61081a366004612974565b611705565b34801561082b57600080fd5b5061037461083a3660046129a4565b611730565b34801561084b57600080fd5b506103cd611777565b34801561086057600080fd5b5061045260145481565b61037461087836600461281e565b611786565b34801561088957600080fd5b50610452600081565b34801561089e57600080fd5b506103746108ad366004612ace565b61188e565b3480156108be57600080fd5b506103746108cd36600461281e565b611904565b3480156108de57600080fd5b506103746108ed366004612b12565b611944565b3480156108fe57600080fd5b506103cd61090d36600461281e565b61196b565b34801561091e57600080fd5b5061037461092d366004612974565b611a06565b34801561093e57600080fd5b5061037461094d366004612863565b611a2b565b34801561095e57600080fd5b506103cd611a59565b34801561097357600080fd5b5061033f610982366004612bf2565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205460ff1690565b3480156109bc57600080fd5b5061045260008051602061312283398151915281565b3480156109de57600080fd5b506103746109ed366004612863565b611a66565b600063152a902d60e11b6001600160e01b031983161480610a175750610a1782611adf565b92915050565b600080516020613122833981519152610a3581611b04565b816001600160801b0316836001600160801b031610610a6757604051636de2dbdf60e01b815260040160405180910390fd5b50604080518082019091526001600160801b03928316808252919092166020909201829052600160801b90910217601855565b6000610aa581611b04565b610aaf8383611b0e565b505050565b60006115b3610ac1611bc8565b03610acc5750600390565b601854600160801b90046001600160801b0316421115610aec5750600290565b6018546001600160801b0316421115610b055750600190565b50600090565b606060028054610b1a90612c20565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4690612c20565b8015610b935780601f10610b6857610100808354040283529160200191610b93565b820191906000526020600020905b815481529060010190602001808311610b7657829003601f168201915b5050505050905090565b6000610a1782611426565b610bb3826001611bda565b6001600160a01b038216610bda576040516306c8ec8f60e31b815260040160405180910390fd5b6000610be582611426565b90506001600160a01b0381163314801590610c245750336000908152600d602090815260408083206001600160a01b038716845290915290205460ff16155b8015610c4757506000828152600a60205260409020546001600160a01b03163314155b15610c655760405163449de15f60e11b815260040160405180910390fd5b60008281526008602052604090205460ff16610cb857600082815260096020908152604080832080546001600160a01b0319166001600160a01b03861617905560089091529020805460ff191660011790555b6000828152600a602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b6001600160a01b038116600090815260176020526040812054601554610a179190612c70565b803481601454610d489190612c83565b14610d66576040516303b59b0160e61b815260040160405180910390fd5b6115b381610d72611bc8565b610d7c9190612c9a565b1115610d9b57604051632cdb04a160e21b815260040160405180910390fd5b60155433600090815260176020526040902054610db9908390612c9a565b1115610dd857604051637335356360e01b815260040160405180910390fd5b6001610de2610ab4565b6003811115610df357610df361277d565b14610e115760405163bb8f723160e01b815260040160405180910390fd5b6040516bffffffffffffffffffffffff193360601b166020820152600090603401604051602081830303815290604052805190602001209050610e8b858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506016549150849050611c0a565b610ea8576040516315ebf2b560e21b815260040160405180910390fd5b3360009081526017602052604081208054859290610ec7908490612c9a565b90915550610ed790503384611c20565b5050505050565b6000600654600554600454610ef39190612c70565b610efd9190612c70565b905090565b600554811080610f1f57506001600454610f1c9190612c70565b81115b15610f3d57604051635f22452f60e01b815260040160405180910390fd5b6000610f4882611426565b9050836001600160a01b0316816001600160a01b031614610f7c576040516311f1e70d60e11b815260040160405180910390fd5b6001600160a01b0381163314801590610fb957506001600160a01b0384166000908152600d6020908152604080832033845290915290205460ff16155b8015610fdc57506000828152600a60205260409020546001600160a01b03163314155b15610ffa5760405163449de15f60e11b815260040160405180910390fd5b6001600160a01b0383166110215760405163163ae22d60e11b815260040160405180910390fd5b61102c848484611c3a565b6001600160a01b0384166000908152600c60205260408120805460019290611055908490612c70565b90915550506001600160a01b0383166000908152600c60205260408120805460019290611083908490612c9a565b90915550506000828152600a6020908152604080832080546001600160a01b03199081169091556009835281842080546001600160a01b038981169190931681179091556008909352818420805460ff1916600117905590518593918816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a45b50505050565b60008281526012602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916111815750604080518082019091526011546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906111a0906001600160601b031687612c83565b6111aa9190612cc3565b91519350909150505b9250929050565b6000828152600f60205260409020600101546111d581611b04565b610aaf8383611c8a565b60006111ea81611b04565b60405147906000906001600160a01b0385169083908381818185875af1925050503d8060008114611237576040519150601f19603f3d011682016040523d82523d6000602084013e61123c565b606091505b50509050806111065760405163d23a9e8960e01b815260040160405180910390fd5b6001600160a01b03811633146112d35760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6112dd8282611d10565b5050565b6112e9611d77565b6113056000611300600e546001600160a01b031690565b611c8a565b565b610aaf83838360405180602001604052806000815250611944565b6000818152600b602052604081205460ff161561134157506000919050565b60008281526008602052604090205460ff166113655761136082611dd1565b610a17565b506000908152600960205260409020546001600160a01b031690565b600061138c81611b04565b610aaf8383611c20565b600060055482101580156113ab575060045482105b8015610a175750506000908152600b602052604090205460ff161590565b6000805160206131228339815191526113e181611b04565b600082900361140357604051633ba0191160e01b815260040160405180910390fd5b6000611106838583612d25565b600061141b81611b04565b611106848484611e27565b6000600554821080611439575060045482115b1561145757604051635f22452f60e01b815260040160405180910390fd5b6000828152600b602052604090205460ff16156113415760405162846fdf60e41b815260040160405180910390fd5b600061149181611b04565b8382146114b15760405163586cb9e160e01b815260040160405180910390fd5b6000805b838110156114f5578484828181106114cf576114cf612de5565b90506020020135826114e19190612c9a565b9150806114ed81612dfb565b9150506114b5565b506115b381611502611bc8565b61150c9190612c9a565b111561152b57604051632cdb04a160e21b815260040160405180910390fd5b60005b858110156115905761157e87878381811061154b5761154b612de5565b90506020020160208101906115609190612863565b86868481811061157257611572612de5565b90506020020135611c20565b8061158881612dfb565b91505061152e565b50505050505050565b600080546115a690612c20565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290612c20565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b505050505081565b60006001600160a01b03821661164f576040516280526360e51b815260040160405180910390fd5b506001600160a01b03166000908152600c602052604090205490565b611673611d77565b6113056000611ef2565b60008051602061312283398151915261169581611b04565b50601655565b6000805160206131228339815191526116b381611b04565b60008290036116da576040805160208101909152600081526001906116d89082612e14565b505b6001611106838583612d25565b6000805160206131228339815191526116ff81611b04565b50601455565b6000918252600f602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061312283398151915261174881611b04565b600082900361176a57604051633ba0191160e01b815260040160405180910390fd5b6013611106838583612d25565b606060038054610b1a90612c20565b8034816014546117969190612c83565b146117b4576040516303b59b0160e61b815260040160405180910390fd5b6115b3816117c0611bc8565b6117ca9190612c9a565b11156117e957604051632cdb04a160e21b815260040160405180910390fd5b60155433600090815260176020526040902054611807908390612c9a565b111561182657604051637335356360e01b815260040160405180910390fd5b6002611830610ab4565b60038111156118415761184161277d565b1461185f5760405163275b660b60e01b815260040160405180910390fd5b336000908152601760205260408120805484929061187e908490612c9a565b909155506112dd90503383611c20565b6118988282611bda565b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60008051602061312283398151915261191c81611b04565b601554821161193e57604051634a000f7b60e11b815260040160405180910390fd5b50601555565b61194f848484610f02565b6001600160a01b0383163b1561110657610ed784848484611f44565b606060055482108061198a575060016004546119879190612c70565b82115b156119a857604051635f22452f60e01b815260040160405180910390fd5b60008080546119b690612c20565b9050116119d25760405180602001604052806000815250610a17565b60006119dd83612030565b60016040516020016119f193929190612f47565b60405160208183030381529060405292915050565b6000828152600f6020526040902060010154611a2181611b04565b610aaf8383611d10565b6000611a3681611b04565b50601080546001600160a01b0319166001600160a01b0392909216919091179055565b601380546115a690612c20565b611a6e611d77565b6001600160a01b038116611ad35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016112ca565b611adc81611ef2565b50565b60006001600160e01b0319821663da8def7360e01b1480610a175750610a1782612131565b611adc813361219d565b6127106001600160601b0382161115611b395760405162461bcd60e51b81526004016112ca90612f7a565b6001600160a01b038216611b8f5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016112ca565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601155565b6000600554600454610efd9190612c70565b808015611bed5750611beb826121f6565b155b156112dd5760405162461bcd60e51b81526004016112ca90612fc4565b600082611c178584612267565b14949350505050565b6112dd8282604051806020016040528060008152506122b4565b6001600160a01b03831615801590611c5a57506001600160a01b03821615155b8015611c6d5750611c6b3382612327565b155b15610aaf5760405162461bcd60e51b81526004016112ca90612fc4565b611c948282611705565b6112dd576000828152600f602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611ccc3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611d1a8282611705565b156112dd576000828152600f602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600e546001600160a01b031633146113055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016112ca565b600081815b6001600160a01b038116611e205760008281526008602052604090205460ff16611e1457506000818152600760205260409020546001600160a01b03165b60001990910190611dd6565b9392505050565b6127106001600160601b0382161115611e525760405162461bcd60e51b81526004016112ca90612f7a565b6001600160a01b038216611ea85760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d6574657273000000000060448201526064016112ca565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752601290529190942093519051909116600160a01b029116179055565b600e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611f7990339089908890889060040161300a565b6020604051808303816000875af1925050508015611fb4575060408051601f3d908101601f19168201909252611fb191810190613047565b60015b612012573d808015611fe2576040519150601f19603f3d011682016040523d82523d6000602084013e611fe7565b606091505b50805160000361200a576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b6060816000036120575750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612081578061206b81612dfb565b915061207a9050600a83612cc3565b915061205b565b60008167ffffffffffffffff81111561209c5761209c612afc565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090505b8415612028576120db600183612c70565b91506120e8600a86613064565b6120f3906030612c9a565b60f81b81838151811061210857612108612de5565b60200101906001600160f81b031916908160001a90535061212a600a86612cc3565b94506120ca565b60006001600160e01b031982166301ffc9a760e01b148061216257506001600160e01b031982166380ac58cd60e01b145b8061217d57506001600160e01b03198216630a85bd0160e11b145b80610a1757506001600160e01b03198216635b5e139f60e01b1492915050565b6121a78282611705565b6112dd576121b4816123d8565b6121bf8360206123ea565b6040516020016121d0929190613078565b60408051601f198184030181529082905262461bcd60e51b82526112ca9160040161280b565b601054604051630c962cb760e11b81526001600160a01b0383811660048301526000921690819063192c596e90602401602060405180830381865afa158015612243573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2091906130ed565b600081815b84518110156122ac576122988286838151811061228b5761228b612de5565b6020026020010151612586565b9150806122a481612dfb565b91505061226c565b509392505050565b6122be83836125b5565b600060016004546122cf9190612c70565b90506001600160a01b0384163b1561110657600454839003600019015b6001016122fc6000868386611f44565b612319576040516368d2bf6b60e11b815260040160405180910390fd5b8181106122ec575050505050565b6010546000906001600160a01b031680612345576001915050610a17565b61234e83611426565b6001600160a01b0316846001600160a01b031603612370576001915050610a17565b604051630c962cb760e11b81523360048201526001600160a01b0382169063192c596e90602401602060405180830381865afa1580156123b4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202891906130ed565b6060610a176001600160a01b03831660145b606060006123f9836002612c83565b612404906002612c9a565b67ffffffffffffffff81111561241c5761241c612afc565b6040519080825280601f01601f191660200182016040528015612446576020820181803683370190505b509050600360fc1b8160008151811061246157612461612de5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061249057612490612de5565b60200101906001600160f81b031916908160001a90535060006124b4846002612c83565b6124bf906001612c9a565b90505b6001811115612537576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106124f3576124f3612de5565b1a60f81b82828151811061250957612509612de5565b60200101906001600160f81b031916908160001a90535060049490941c936125308161310a565b90506124c2565b508315611e205760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016112ca565b60008183106125a2576000828152602084905260409020611e20565b6000838152602083905260409020611e20565b6001600160a01b0382166125dc5760405163163ae22d60e11b815260040160405180910390fd5b806000036125fd5760405163eb1d0cf560e01b815260040160405180910390fd5b6001600160a01b0382166000908152600c60205260409020805482019055600454808201905b8181101561266b5760405181906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600101612623565b5060048054600090815260076020526040902080546001600160a01b0319166001600160a01b03959095169490941790935590915550565b6001600160e01b031981168114611adc57600080fd5b6000602082840312156126cb57600080fd5b8135611e20816126a3565b80356001600160801b03811681146126ed57600080fd5b919050565b6000806040838503121561270557600080fd5b61270e836126d6565b915061271c602084016126d6565b90509250929050565b6001600160a01b0381168114611adc57600080fd5b80356001600160601b03811681146126ed57600080fd5b6000806040838503121561276457600080fd5b823561276f81612725565b915061271c6020840161273a565b634e487b7160e01b600052602160045260246000fd5b60208101600483106127b557634e487b7160e01b600052602160045260246000fd5b91905290565b60005b838110156127d65781810151838201526020016127be565b50506000910152565b600081518084526127f78160208601602086016127bb565b601f01601f19169290920160200192915050565b602081526000611e2060208301846127df565b60006020828403121561283057600080fd5b5035919050565b6000806040838503121561284a57600080fd5b823561285581612725565b946020939093013593505050565b60006020828403121561287557600080fd5b8135611e2081612725565b60008083601f84011261289257600080fd5b50813567ffffffffffffffff8111156128aa57600080fd5b6020830191508360208260051b85010111156111b357600080fd5b6000806000604084860312156128da57600080fd5b833567ffffffffffffffff8111156128f157600080fd5b6128fd86828701612880565b909790965060209590950135949350505050565b60008060006060848603121561292657600080fd5b833561293181612725565b9250602084013561294181612725565b929592945050506040919091013590565b6000806040838503121561296557600080fd5b50508035926020909101359150565b6000806040838503121561298757600080fd5b82359150602083013561299981612725565b809150509250929050565b600080602083850312156129b757600080fd5b823567ffffffffffffffff808211156129cf57600080fd5b818501915085601f8301126129e357600080fd5b8135818111156129f257600080fd5b866020828501011115612a0457600080fd5b60209290920196919550909350505050565b600080600060608486031215612a2b57600080fd5b833592506020840135612a3d81612725565b9150612a4b6040850161273a565b90509250925092565b60008060008060408587031215612a6a57600080fd5b843567ffffffffffffffff80821115612a8257600080fd5b612a8e88838901612880565b90965094506020870135915080821115612aa757600080fd5b50612ab487828801612880565b95989497509550505050565b8015158114611adc57600080fd5b60008060408385031215612ae157600080fd5b8235612aec81612725565b9150602083013561299981612ac0565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215612b2857600080fd5b8435612b3381612725565b93506020850135612b4381612725565b925060408501359150606085013567ffffffffffffffff80821115612b6757600080fd5b818701915087601f830112612b7b57600080fd5b813581811115612b8d57612b8d612afc565b604051601f8201601f19908116603f01168101908382118183101715612bb557612bb5612afc565b816040528281528a6020848701011115612bce57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215612c0557600080fd5b8235612c1081612725565b9150602083013561299981612725565b600181811c90821680612c3457607f821691505b602082108103612c5457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a1757610a17612c5a565b8082028115828204841417610a1757610a17612c5a565b80820180821115610a1757610a17612c5a565b634e487b7160e01b600052601260045260246000fd5b600082612cd257612cd2612cad565b500490565b601f821115610aaf57600081815260208120601f850160051c81016020861015612cfe5750805b601f850160051c820191505b81811015612d1d57828155600101612d0a565b505050505050565b67ffffffffffffffff831115612d3d57612d3d612afc565b612d5183612d4b8354612c20565b83612cd7565b6000601f841160018114612d855760008515612d6d5750838201355b600019600387901b1c1916600186901b178355610ed7565b600083815260209020601f19861690835b82811015612db65786850135825560209485019460019092019101612d96565b5086821015612dd35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0d57612e0d612c5a565b5060010190565b815167ffffffffffffffff811115612e2e57612e2e612afc565b612e4281612e3c8454612c20565b84612cd7565b602080601f831160018114612e775760008415612e5f5750858301515b600019600386901b1c1916600185901b178555612d1d565b600085815260208120601f198616915b82811015612ea657888601518255948401946001909101908401612e87565b5085821015612ec45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008154612ee181612c20565b60018281168015612ef95760018114612f0e57612f3d565b60ff1984168752821515830287019450612f3d565b8560005260208060002060005b85811015612f345781548a820152908401908201612f1b565b50505082870194505b5050505092915050565b6000612f538286612ed4565b8451612f638183602089016127bb565b612f6f81830186612ed4565b979650505050505050565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b60208082526026908201527f4552433732314f70657261746f7246696c7465723a20696c6c6567616c206f7060408201526532b930ba37b960d11b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061303d908301846127df565b9695505050505050565b60006020828403121561305957600080fd5b8151611e20816126a3565b60008261307357613073612cad565b500690565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516130b08160178501602088016127bb565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516130e18160288401602088016127bb565b01602801949350505050565b6000602082840312156130ff57600080fd5b8151611e2081612ac0565b60008161311957613119612c5a565b50600019019056fe241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08a2646970667358221220a53af23e2b1925c6a3a7b52e02f5af2ac1c122618fdbf083126e77b7ff2b6de164736f6c63430008110033697066733a2f2f516d5232793750326d3963626d746333314c736b765663626e3271784a50574e4534457672696f4a4a6a50756b4a241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08697066733a2f2f516d5770786736787a59675a68647a6f656a72703848467855707072387350516156366b453558617366755a65582f000000000000000000000000d4746f083df2d2e06734466d863e170881897e7100000000000000000000000098a3fba3036c9ed0ad4b28eacd9d939d7e3e1366000000000000000000000000000000000000000000000000000000000000022b00000000000000000000000046db79ad52f4ab71a7176c011ec9c79172873fe8

Deployed Bytecode

0x60806040526004361061031a5760003560e01c806367243482116101ab57806395d89b41116100f7578063c87b56dd11610095578063e8a3d4851161006f578063e8a3d48514610952578063e985e9c514610967578063ec87621c146109b0578063f2fde38b146109d257600080fd5b8063c87b56dd146108f2578063d547741f14610912578063d783925b1461093257600080fd5b8063a217fddf116100d1578063a217fddf1461087d578063a22cb46514610892578063acf080d1146108b2578063b88d4fde146108d257600080fd5b806395d89b411461083f578063a035b1fe14610854578063a0712d681461086a57600080fd5b80638e0acd121161016457806390aa0b0f1161013e57806390aa0b0f1461079457806391b7f5ed146107df57806391d14854146107ff578063938e3d7b1461081f57600080fd5b80638e0acd121461073e578063902d55a51461075e578063907097511461077457600080fd5b80636724348214610698578063689843e0146106b85780636c0360eb146106d657806370a08231146106eb578063715018a61461070b5780638da5cb5b1461072057600080fd5b80632a55205a1161026a57806342842e0e116102235780634f558e79116101fd5780634f558e791461061857806355f804b3146106385780635944c753146106585780636352211e1461067857600080fd5b806342842e0e146105b85780634777a597146105d8578063484b973c146105f857600080fd5b80632a55205a146104ee5780632f2ff15d1461052d57806331b3eb941461054d57806336568abe1461056d57806338a59d971461058d578063396876bd146105a257600080fd5b8063095ea7b3116102d757806318160ddd116102b157806318160ddd1461047357806323b872dd14610488578063248a9ca3146104a8578063293108e0146104d857600080fd5b8063095ea7b3146104125780630c6b2cbf146104325780631338a83f1461046057600080fd5b806301ffc9a71461031f57806304392a4c1461035457806304634d8d14610376578063055ad42e1461039657806306fdde03146103b8578063081812fc146103da575b600080fd5b34801561032b57600080fd5b5061033f61033a3660046126b9565b6109f2565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b5061037461036f3660046126f2565b610a1d565b005b34801561038257600080fd5b50610374610391366004612751565b610a9a565b3480156103a257600080fd5b506103ab610ab4565b60405161034b9190612793565b3480156103c457600080fd5b506103cd610b0b565b60405161034b919061280b565b3480156103e657600080fd5b506103fa6103f536600461281e565b610b9d565b6040516001600160a01b03909116815260200161034b565b34801561041e57600080fd5b5061037461042d366004612837565b610ba8565b34801561043e57600080fd5b5061045261044d366004612863565b610d12565b60405190815260200161034b565b61037461046e3660046128c5565b610d38565b34801561047f57600080fd5b50610452610ede565b34801561049457600080fd5b506103746104a3366004612911565b610f02565b3480156104b457600080fd5b506104526104c336600461281e565b6000908152600f602052604090206001015490565b3480156104e457600080fd5b5061045260165481565b3480156104fa57600080fd5b5061050e610509366004612952565b61110c565b604080516001600160a01b03909316835260208301919091520161034b565b34801561053957600080fd5b50610374610548366004612974565b6111ba565b34801561055957600080fd5b50610374610568366004612863565b6111df565b34801561057957600080fd5b50610374610588366004612974565b61125e565b34801561059957600080fd5b506103746112e1565b3480156105ae57600080fd5b5061045260155481565b3480156105c457600080fd5b506103746105d3366004612911565b611307565b3480156105e457600080fd5b506103fa6105f336600461281e565b611322565b34801561060457600080fd5b50610374610613366004612837565b611381565b34801561062457600080fd5b5061033f61063336600461281e565b611396565b34801561064457600080fd5b506103746106533660046129a4565b6113c9565b34801561066457600080fd5b50610374610673366004612a16565b611410565b34801561068457600080fd5b506103fa61069336600461281e565b611426565b3480156106a457600080fd5b506103746106b3366004612a54565b611486565b3480156106c457600080fd5b506010546001600160a01b03166103fa565b3480156106e257600080fd5b506103cd611599565b3480156106f757600080fd5b50610452610706366004612863565b611627565b34801561071757600080fd5b5061037461166b565b34801561072c57600080fd5b50600e546001600160a01b03166103fa565b34801561074a57600080fd5b5061037461075936600461281e565b61167d565b34801561076a57600080fd5b506104526115b381565b34801561078057600080fd5b5061037461078f3660046129a4565b61169b565b3480156107a057600080fd5b506018546107bf906001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161034b565b3480156107eb57600080fd5b506103746107fa36600461281e565b6116e7565b34801561080b57600080fd5b5061033f61081a366004612974565b611705565b34801561082b57600080fd5b5061037461083a3660046129a4565b611730565b34801561084b57600080fd5b506103cd611777565b34801561086057600080fd5b5061045260145481565b61037461087836600461281e565b611786565b34801561088957600080fd5b50610452600081565b34801561089e57600080fd5b506103746108ad366004612ace565b61188e565b3480156108be57600080fd5b506103746108cd36600461281e565b611904565b3480156108de57600080fd5b506103746108ed366004612b12565b611944565b3480156108fe57600080fd5b506103cd61090d36600461281e565b61196b565b34801561091e57600080fd5b5061037461092d366004612974565b611a06565b34801561093e57600080fd5b5061037461094d366004612863565b611a2b565b34801561095e57600080fd5b506103cd611a59565b34801561097357600080fd5b5061033f610982366004612bf2565b6001600160a01b039182166000908152600d6020908152604080832093909416825291909152205460ff1690565b3480156109bc57600080fd5b5061045260008051602061312283398151915281565b3480156109de57600080fd5b506103746109ed366004612863565b611a66565b600063152a902d60e11b6001600160e01b031983161480610a175750610a1782611adf565b92915050565b600080516020613122833981519152610a3581611b04565b816001600160801b0316836001600160801b031610610a6757604051636de2dbdf60e01b815260040160405180910390fd5b50604080518082019091526001600160801b03928316808252919092166020909201829052600160801b90910217601855565b6000610aa581611b04565b610aaf8383611b0e565b505050565b60006115b3610ac1611bc8565b03610acc5750600390565b601854600160801b90046001600160801b0316421115610aec5750600290565b6018546001600160801b0316421115610b055750600190565b50600090565b606060028054610b1a90612c20565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4690612c20565b8015610b935780601f10610b6857610100808354040283529160200191610b93565b820191906000526020600020905b815481529060010190602001808311610b7657829003601f168201915b5050505050905090565b6000610a1782611426565b610bb3826001611bda565b6001600160a01b038216610bda576040516306c8ec8f60e31b815260040160405180910390fd5b6000610be582611426565b90506001600160a01b0381163314801590610c245750336000908152600d602090815260408083206001600160a01b038716845290915290205460ff16155b8015610c4757506000828152600a60205260409020546001600160a01b03163314155b15610c655760405163449de15f60e11b815260040160405180910390fd5b60008281526008602052604090205460ff16610cb857600082815260096020908152604080832080546001600160a01b0319166001600160a01b03861617905560089091529020805460ff191660011790555b6000828152600a602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a4505050565b6001600160a01b038116600090815260176020526040812054601554610a179190612c70565b803481601454610d489190612c83565b14610d66576040516303b59b0160e61b815260040160405180910390fd5b6115b381610d72611bc8565b610d7c9190612c9a565b1115610d9b57604051632cdb04a160e21b815260040160405180910390fd5b60155433600090815260176020526040902054610db9908390612c9a565b1115610dd857604051637335356360e01b815260040160405180910390fd5b6001610de2610ab4565b6003811115610df357610df361277d565b14610e115760405163bb8f723160e01b815260040160405180910390fd5b6040516bffffffffffffffffffffffff193360601b166020820152600090603401604051602081830303815290604052805190602001209050610e8b858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506016549150849050611c0a565b610ea8576040516315ebf2b560e21b815260040160405180910390fd5b3360009081526017602052604081208054859290610ec7908490612c9a565b90915550610ed790503384611c20565b5050505050565b6000600654600554600454610ef39190612c70565b610efd9190612c70565b905090565b600554811080610f1f57506001600454610f1c9190612c70565b81115b15610f3d57604051635f22452f60e01b815260040160405180910390fd5b6000610f4882611426565b9050836001600160a01b0316816001600160a01b031614610f7c576040516311f1e70d60e11b815260040160405180910390fd5b6001600160a01b0381163314801590610fb957506001600160a01b0384166000908152600d6020908152604080832033845290915290205460ff16155b8015610fdc57506000828152600a60205260409020546001600160a01b03163314155b15610ffa5760405163449de15f60e11b815260040160405180910390fd5b6001600160a01b0383166110215760405163163ae22d60e11b815260040160405180910390fd5b61102c848484611c3a565b6001600160a01b0384166000908152600c60205260408120805460019290611055908490612c70565b90915550506001600160a01b0383166000908152600c60205260408120805460019290611083908490612c9a565b90915550506000828152600a6020908152604080832080546001600160a01b03199081169091556009835281842080546001600160a01b038981169190931681179091556008909352818420805460ff1916600117905590518593918816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a45b50505050565b60008281526012602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916111815750604080518082019091526011546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906111a0906001600160601b031687612c83565b6111aa9190612cc3565b91519350909150505b9250929050565b6000828152600f60205260409020600101546111d581611b04565b610aaf8383611c8a565b60006111ea81611b04565b60405147906000906001600160a01b0385169083908381818185875af1925050503d8060008114611237576040519150601f19603f3d011682016040523d82523d6000602084013e61123c565b606091505b50509050806111065760405163d23a9e8960e01b815260040160405180910390fd5b6001600160a01b03811633146112d35760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6112dd8282611d10565b5050565b6112e9611d77565b6113056000611300600e546001600160a01b031690565b611c8a565b565b610aaf83838360405180602001604052806000815250611944565b6000818152600b602052604081205460ff161561134157506000919050565b60008281526008602052604090205460ff166113655761136082611dd1565b610a17565b506000908152600960205260409020546001600160a01b031690565b600061138c81611b04565b610aaf8383611c20565b600060055482101580156113ab575060045482105b8015610a175750506000908152600b602052604090205460ff161590565b6000805160206131228339815191526113e181611b04565b600082900361140357604051633ba0191160e01b815260040160405180910390fd5b6000611106838583612d25565b600061141b81611b04565b611106848484611e27565b6000600554821080611439575060045482115b1561145757604051635f22452f60e01b815260040160405180910390fd5b6000828152600b602052604090205460ff16156113415760405162846fdf60e41b815260040160405180910390fd5b600061149181611b04565b8382146114b15760405163586cb9e160e01b815260040160405180910390fd5b6000805b838110156114f5578484828181106114cf576114cf612de5565b90506020020135826114e19190612c9a565b9150806114ed81612dfb565b9150506114b5565b506115b381611502611bc8565b61150c9190612c9a565b111561152b57604051632cdb04a160e21b815260040160405180910390fd5b60005b858110156115905761157e87878381811061154b5761154b612de5565b90506020020160208101906115609190612863565b86868481811061157257611572612de5565b90506020020135611c20565b8061158881612dfb565b91505061152e565b50505050505050565b600080546115a690612c20565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290612c20565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b505050505081565b60006001600160a01b03821661164f576040516280526360e51b815260040160405180910390fd5b506001600160a01b03166000908152600c602052604090205490565b611673611d77565b6113056000611ef2565b60008051602061312283398151915261169581611b04565b50601655565b6000805160206131228339815191526116b381611b04565b60008290036116da576040805160208101909152600081526001906116d89082612e14565b505b6001611106838583612d25565b6000805160206131228339815191526116ff81611b04565b50601455565b6000918252600f602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60008051602061312283398151915261174881611b04565b600082900361176a57604051633ba0191160e01b815260040160405180910390fd5b6013611106838583612d25565b606060038054610b1a90612c20565b8034816014546117969190612c83565b146117b4576040516303b59b0160e61b815260040160405180910390fd5b6115b3816117c0611bc8565b6117ca9190612c9a565b11156117e957604051632cdb04a160e21b815260040160405180910390fd5b60155433600090815260176020526040902054611807908390612c9a565b111561182657604051637335356360e01b815260040160405180910390fd5b6002611830610ab4565b60038111156118415761184161277d565b1461185f5760405163275b660b60e01b815260040160405180910390fd5b336000908152601760205260408120805484929061187e908490612c9a565b909155506112dd90503383611c20565b6118988282611bda565b336000818152600d602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60008051602061312283398151915261191c81611b04565b601554821161193e57604051634a000f7b60e11b815260040160405180910390fd5b50601555565b61194f848484610f02565b6001600160a01b0383163b1561110657610ed784848484611f44565b606060055482108061198a575060016004546119879190612c70565b82115b156119a857604051635f22452f60e01b815260040160405180910390fd5b60008080546119b690612c20565b9050116119d25760405180602001604052806000815250610a17565b60006119dd83612030565b60016040516020016119f193929190612f47565b60405160208183030381529060405292915050565b6000828152600f6020526040902060010154611a2181611b04565b610aaf8383611d10565b6000611a3681611b04565b50601080546001600160a01b0319166001600160a01b0392909216919091179055565b601380546115a690612c20565b611a6e611d77565b6001600160a01b038116611ad35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016112ca565b611adc81611ef2565b50565b60006001600160e01b0319821663da8def7360e01b1480610a175750610a1782612131565b611adc813361219d565b6127106001600160601b0382161115611b395760405162461bcd60e51b81526004016112ca90612f7a565b6001600160a01b038216611b8f5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016112ca565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217601155565b6000600554600454610efd9190612c70565b808015611bed5750611beb826121f6565b155b156112dd5760405162461bcd60e51b81526004016112ca90612fc4565b600082611c178584612267565b14949350505050565b6112dd8282604051806020016040528060008152506122b4565b6001600160a01b03831615801590611c5a57506001600160a01b03821615155b8015611c6d5750611c6b3382612327565b155b15610aaf5760405162461bcd60e51b81526004016112ca90612fc4565b611c948282611705565b6112dd576000828152600f602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611ccc3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611d1a8282611705565b156112dd576000828152600f602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600e546001600160a01b031633146113055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016112ca565b600081815b6001600160a01b038116611e205760008281526008602052604090205460ff16611e1457506000818152600760205260409020546001600160a01b03165b60001990910190611dd6565b9392505050565b6127106001600160601b0382161115611e525760405162461bcd60e51b81526004016112ca90612f7a565b6001600160a01b038216611ea85760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d6574657273000000000060448201526064016112ca565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752601290529190942093519051909116600160a01b029116179055565b600e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611f7990339089908890889060040161300a565b6020604051808303816000875af1925050508015611fb4575060408051601f3d908101601f19168201909252611fb191810190613047565b60015b612012573d808015611fe2576040519150601f19603f3d011682016040523d82523d6000602084013e611fe7565b606091505b50805160000361200a576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b6060816000036120575750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612081578061206b81612dfb565b915061207a9050600a83612cc3565b915061205b565b60008167ffffffffffffffff81111561209c5761209c612afc565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090505b8415612028576120db600183612c70565b91506120e8600a86613064565b6120f3906030612c9a565b60f81b81838151811061210857612108612de5565b60200101906001600160f81b031916908160001a90535061212a600a86612cc3565b94506120ca565b60006001600160e01b031982166301ffc9a760e01b148061216257506001600160e01b031982166380ac58cd60e01b145b8061217d57506001600160e01b03198216630a85bd0160e11b145b80610a1757506001600160e01b03198216635b5e139f60e01b1492915050565b6121a78282611705565b6112dd576121b4816123d8565b6121bf8360206123ea565b6040516020016121d0929190613078565b60408051601f198184030181529082905262461bcd60e51b82526112ca9160040161280b565b601054604051630c962cb760e11b81526001600160a01b0383811660048301526000921690819063192c596e90602401602060405180830381865afa158015612243573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2091906130ed565b600081815b84518110156122ac576122988286838151811061228b5761228b612de5565b6020026020010151612586565b9150806122a481612dfb565b91505061226c565b509392505050565b6122be83836125b5565b600060016004546122cf9190612c70565b90506001600160a01b0384163b1561110657600454839003600019015b6001016122fc6000868386611f44565b612319576040516368d2bf6b60e11b815260040160405180910390fd5b8181106122ec575050505050565b6010546000906001600160a01b031680612345576001915050610a17565b61234e83611426565b6001600160a01b0316846001600160a01b031603612370576001915050610a17565b604051630c962cb760e11b81523360048201526001600160a01b0382169063192c596e90602401602060405180830381865afa1580156123b4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202891906130ed565b6060610a176001600160a01b03831660145b606060006123f9836002612c83565b612404906002612c9a565b67ffffffffffffffff81111561241c5761241c612afc565b6040519080825280601f01601f191660200182016040528015612446576020820181803683370190505b509050600360fc1b8160008151811061246157612461612de5565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061249057612490612de5565b60200101906001600160f81b031916908160001a90535060006124b4846002612c83565b6124bf906001612c9a565b90505b6001811115612537576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106124f3576124f3612de5565b1a60f81b82828151811061250957612509612de5565b60200101906001600160f81b031916908160001a90535060049490941c936125308161310a565b90506124c2565b508315611e205760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016112ca565b60008183106125a2576000828152602084905260409020611e20565b6000838152602083905260409020611e20565b6001600160a01b0382166125dc5760405163163ae22d60e11b815260040160405180910390fd5b806000036125fd5760405163eb1d0cf560e01b815260040160405180910390fd5b6001600160a01b0382166000908152600c60205260409020805482019055600454808201905b8181101561266b5760405181906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600101612623565b5060048054600090815260076020526040902080546001600160a01b0319166001600160a01b03959095169490941790935590915550565b6001600160e01b031981168114611adc57600080fd5b6000602082840312156126cb57600080fd5b8135611e20816126a3565b80356001600160801b03811681146126ed57600080fd5b919050565b6000806040838503121561270557600080fd5b61270e836126d6565b915061271c602084016126d6565b90509250929050565b6001600160a01b0381168114611adc57600080fd5b80356001600160601b03811681146126ed57600080fd5b6000806040838503121561276457600080fd5b823561276f81612725565b915061271c6020840161273a565b634e487b7160e01b600052602160045260246000fd5b60208101600483106127b557634e487b7160e01b600052602160045260246000fd5b91905290565b60005b838110156127d65781810151838201526020016127be565b50506000910152565b600081518084526127f78160208601602086016127bb565b601f01601f19169290920160200192915050565b602081526000611e2060208301846127df565b60006020828403121561283057600080fd5b5035919050565b6000806040838503121561284a57600080fd5b823561285581612725565b946020939093013593505050565b60006020828403121561287557600080fd5b8135611e2081612725565b60008083601f84011261289257600080fd5b50813567ffffffffffffffff8111156128aa57600080fd5b6020830191508360208260051b85010111156111b357600080fd5b6000806000604084860312156128da57600080fd5b833567ffffffffffffffff8111156128f157600080fd5b6128fd86828701612880565b909790965060209590950135949350505050565b60008060006060848603121561292657600080fd5b833561293181612725565b9250602084013561294181612725565b929592945050506040919091013590565b6000806040838503121561296557600080fd5b50508035926020909101359150565b6000806040838503121561298757600080fd5b82359150602083013561299981612725565b809150509250929050565b600080602083850312156129b757600080fd5b823567ffffffffffffffff808211156129cf57600080fd5b818501915085601f8301126129e357600080fd5b8135818111156129f257600080fd5b866020828501011115612a0457600080fd5b60209290920196919550909350505050565b600080600060608486031215612a2b57600080fd5b833592506020840135612a3d81612725565b9150612a4b6040850161273a565b90509250925092565b60008060008060408587031215612a6a57600080fd5b843567ffffffffffffffff80821115612a8257600080fd5b612a8e88838901612880565b90965094506020870135915080821115612aa757600080fd5b50612ab487828801612880565b95989497509550505050565b8015158114611adc57600080fd5b60008060408385031215612ae157600080fd5b8235612aec81612725565b9150602083013561299981612ac0565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215612b2857600080fd5b8435612b3381612725565b93506020850135612b4381612725565b925060408501359150606085013567ffffffffffffffff80821115612b6757600080fd5b818701915087601f830112612b7b57600080fd5b813581811115612b8d57612b8d612afc565b604051601f8201601f19908116603f01168101908382118183101715612bb557612bb5612afc565b816040528281528a6020848701011115612bce57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215612c0557600080fd5b8235612c1081612725565b9150602083013561299981612725565b600181811c90821680612c3457607f821691505b602082108103612c5457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a1757610a17612c5a565b8082028115828204841417610a1757610a17612c5a565b80820180821115610a1757610a17612c5a565b634e487b7160e01b600052601260045260246000fd5b600082612cd257612cd2612cad565b500490565b601f821115610aaf57600081815260208120601f850160051c81016020861015612cfe5750805b601f850160051c820191505b81811015612d1d57828155600101612d0a565b505050505050565b67ffffffffffffffff831115612d3d57612d3d612afc565b612d5183612d4b8354612c20565b83612cd7565b6000601f841160018114612d855760008515612d6d5750838201355b600019600387901b1c1916600186901b178355610ed7565b600083815260209020601f19861690835b82811015612db65786850135825560209485019460019092019101612d96565b5086821015612dd35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052603260045260246000fd5b600060018201612e0d57612e0d612c5a565b5060010190565b815167ffffffffffffffff811115612e2e57612e2e612afc565b612e4281612e3c8454612c20565b84612cd7565b602080601f831160018114612e775760008415612e5f5750858301515b600019600386901b1c1916600185901b178555612d1d565b600085815260208120601f198616915b82811015612ea657888601518255948401946001909101908401612e87565b5085821015612ec45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008154612ee181612c20565b60018281168015612ef95760018114612f0e57612f3d565b60ff1984168752821515830287019450612f3d565b8560005260208060002060005b85811015612f345781548a820152908401908201612f1b565b50505082870194505b5050505092915050565b6000612f538286612ed4565b8451612f638183602089016127bb565b612f6f81830186612ed4565b979650505050505050565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b60208082526026908201527f4552433732314f70657261746f7246696c7465723a20696c6c6567616c206f7060408201526532b930ba37b960d11b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061303d908301846127df565b9695505050505050565b60006020828403121561305957600080fd5b8151611e20816126a3565b60008261307357613073612cad565b500690565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516130b08160178501602088016127bb565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516130e18160288401602088016127bb565b01602801949350505050565b6000602082840312156130ff57600080fd5b8151611e2081612ac0565b60008161311957613119612c5a565b50600019019056fe241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08a2646970667358221220a53af23e2b1925c6a3a7b52e02f5af2ac1c122618fdbf083126e77b7ff2b6de164736f6c63430008110033

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

000000000000000000000000d4746f083df2d2e06734466d863e170881897e7100000000000000000000000098a3fba3036c9ed0ad4b28eacd9d939d7e3e1366000000000000000000000000000000000000000000000000000000000000022b00000000000000000000000046db79ad52f4ab71a7176c011ec9c79172873fe8

-----Decoded View---------------
Arg [0] : owner_ (address): 0xd4746f083DF2D2e06734466D863E170881897E71
Arg [1] : manager_ (address): 0x98A3fbA3036C9ed0Ad4b28EacD9d939D7e3e1366
Arg [2] : initialQty_ (uint256): 555
Arg [3] : filter_ (address): 0x46Db79ad52f4AB71A7176C011Ec9C79172873fE8

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000d4746f083df2d2e06734466d863e170881897e71
Arg [1] : 00000000000000000000000098a3fba3036c9ed0ad4b28eacd9d939d7e3e1366
Arg [2] : 000000000000000000000000000000000000000000000000000000000000022b
Arg [3] : 00000000000000000000000046db79ad52f4ab71a7176c011ec9c79172873fe8


Deployed Bytecode Sourcemap

75254:7333:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82245:339;;;;;;;;;;-1:-1:-1;82245:339:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;82245:339:0;;;;;;;;79275:319;;;;;;;;;;-1:-1:-1;79275:319:0;;;;;:::i;:::-;;:::i;:::-;;80512:188;;;;;;;;;;-1:-1:-1;80512:188:0;;;;;:::i;:::-;;:::i;81688:398::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;42983:85::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;42330:114::-;;;;;;;;;;-1:-1:-1;42330:114:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3274:32:1;;;3256:51;;3244:2;3229:18;42330:114:0;3110:203:1;40611:738:0;;;;;;;;;;-1:-1:-1;40611:738:0;;;;;:::i;:::-;;:::i;82117:120::-;;;;;;;;;;-1:-1:-1;82117:120:0;;;;;:::i;:::-;;:::i;:::-;;;4036:25:1;;;4024:2;4009:18;82117:120:0;3890:177:1;77061:498:0;;;;;;:::i;:::-;;:::i;44223:124::-;;;;;;;;;;;;;:::i;47519:967::-;;;;;;;;;;-1:-1:-1;47519:967:0;;;;;:::i;:::-;;:::i;27688:131::-;;;;;;;;;;-1:-1:-1;27688:131:0;;;;;:::i;:::-;27762:7;27789:12;;;:6;:12;;;;;:22;;;;27688:131;75826:34;;;;;;;;;;;;;;;;62847:442;;;;;;;;;;-1:-1:-1;62847:442:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6227:32:1;;;6209:51;;6291:2;6276:18;;6269:34;;;;6182:18;62847:442:0;6035:274:1;28129:147:0;;;;;;;;;;-1:-1:-1;28129:147:0;;;;;:::i;:::-;;:::i;79874:356::-;;;;;;;;;;-1:-1:-1;79874:356:0;;;;;:::i;:::-;;:::i;29273:218::-;;;;;;;;;;-1:-1:-1;29273:218:0;;;;;:::i;:::-;;:::i;79762:104::-;;;;;;;;;;;;;:::i;75785:32::-;;;;;;;;;;;;;;;;45578:174;;;;;;;;;;-1:-1:-1;45578:174:0;;;;;:::i;:::-;;:::i;49814:269::-;;;;;;;;;;-1:-1:-1;49814:269:0;;;;;:::i;:::-;;:::i;77804:165::-;;;;;;;;;;-1:-1:-1;77804:165:0;;;;;:::i;:::-;;:::i;45003:208::-;;;;;;;;;;-1:-1:-1;45003:208:0;;;;;:::i;:::-;;:::i;78791:227::-;;;;;;;;;;-1:-1:-1;78791:227:0;;;;;:::i;:::-;;:::i;81100:221::-;;;;;;;;;;-1:-1:-1;81100:221:0;;;;;:::i;:::-;;:::i;48751:383::-;;;;;;;;;;-1:-1:-1;48751:383:0;;;;;:::i;:::-;;:::i;77977:551::-;;;;;;;;;;-1:-1:-1;77977:551:0;;;;;:::i;:::-;;:::i;58791:105::-;;;;;;;;;;-1:-1:-1;58873:15:0;;-1:-1:-1;;;;;58873:15:0;58791:105;;39377:21;;;;;;;;;;;;;:::i;44684:180::-;;;;;;;;;;-1:-1:-1;44684:180:0;;;;;:::i;:::-;;:::i;2667:103::-;;;;;;;;;;;;;:::i;2019:87::-;;;;;;;;;;-1:-1:-1;2092:6:0;;-1:-1:-1;;;;;2092:6:0;2019:87;;79602:152;;;;;;;;;;-1:-1:-1;79602:152:0;;;;;:::i;:::-;;:::i;75529:43::-;;;;;;;;;;;;75568:4;75529:43;;79026:241;;;;;;;;;;-1:-1:-1;79026:241:0;;;;;:::i;:::-;;:::i;75919:28::-;;;;;;;;;;-1:-1:-1;75919:28:0;;;;-1:-1:-1;;;;;75919:28:0;;;;-1:-1:-1;;;75919:28:0;;;;;;;;;-1:-1:-1;;;;;9138:15:1;;;9120:34;;9190:15;;;;9185:2;9170:18;;9163:43;9040:18;75919:28:0;8893:319:1;81536:103:0;;;;;;;;;;-1:-1:-1;81536:103:0;;;;;:::i;:::-;;:::i;26161:147::-;;;;;;;;;;-1:-1:-1;26161:147:0;;;;;:::i;:::-;;:::i;78536:247::-;;;;;;;;;;-1:-1:-1;78536:247:0;;;;;:::i;:::-;;:::i;43139:89::-;;;;;;;;;;;;;:::i;75744:34::-;;;;;;;;;;;;;;;;77567:229;;;;;;:::i;:::-;;:::i;25266:49::-;;;;;;;;;;-1:-1:-1;25266:49:0;25311:4;25266:49;;41752:301;;;;;;;;;;-1:-1:-1;41752:301:0;;;;;:::i;:::-;;:::i;81329:199::-;;;;;;;;;;-1:-1:-1;81329:199:0;;;;;:::i;:::-;;:::i;46617:304::-;;;;;;;;;;-1:-1:-1;46617:304:0;;;;;:::i;:::-;;:::i;43507:491::-;;;;;;;;;;-1:-1:-1;43507:491:0;;;;;:::i;:::-;;:::i;28569:149::-;;;;;;;;;;-1:-1:-1;28569:149:0;;;;;:::i;:::-;;:::i;58653:130::-;;;;;;;;;;-1:-1:-1;58653:130:0;;;;;:::i;:::-;;:::i;75652:83::-;;;;;;;;;;;;;:::i;42751:176::-;;;;;;;;;;-1:-1:-1;42751:176:0;;;;;:::i;:::-;-1:-1:-1;;;;;42891:17:0;;;42862:4;42891:17;;;:9;:17;;;;;;;;:28;;;;;;;;;;;;;;;42751:176;75579:64;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;75579:64:0;;2925:201;;;;;;;;;;-1:-1:-1;2925:201:0;;;;;:::i;:::-;;:::i;82245:339::-;82406:4;-1:-1:-1;;;;;;;;;82448:25:0;;;;:128;;;82525:51;82564:11;82525:38;:51::i;:::-;82428:148;82245:339;-1:-1:-1;;82245:339:0:o;79275:319::-;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;79443:15:::1;-1:-1:-1::0;;;;;79421:37:0::1;:18;-1:-1:-1::0;;;;;79421:37:0::1;;79417:98;;79480:35;;-1:-1:-1::0;;;79480:35:0::1;;;;;;;;;;;79417:98;-1:-1:-1::0;79539:47:0::1;::::0;;;;::::1;::::0;;;-1:-1:-1;;;;;79539:47:0;;::::1;::::0;;;;;;::::1;;::::0;;::::1;::::0;;;-1:-1:-1;;;79526:60:0;;::::1;;:10;:60:::0;79275:319::o;80512:188::-;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;80650:42:::1;80669:8;80679:12;80650:18;:42::i;:::-;80512:188:::0;;;:::o;81688:398::-;81733:5;75568:4;81755:14;:12;:14::i;:::-;:30;81751:328;;-1:-1:-1;81809:10:0;;81688:398::o;81751:328::-;81859:10;:21;-1:-1:-1;;;81859:21:0;;-1:-1:-1;;;;;81859:21:0;81841:15;:39;81837:242;;;-1:-1:-1;81904:12:0;;81688:398::o;81837:242::-;81956:10;:20;-1:-1:-1;;;;;81956:20:0;81938:15;:38;81934:145;;;-1:-1:-1;82000:15:0;;81688:398::o;81934:145::-;-1:-1:-1;82055:12:0;;81688:398::o;42983:85::-;43022:13;43055:5;43048:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42983:85;:::o;42330:114::-;42392:7;42419:17;42427:8;42419:7;:17::i;40611:738::-;40685:35;40704:9;40715:4;40685:18;:35::i;:::-;-1:-1:-1;;;;;40735:23:0;;40731:64;;40767:28;;-1:-1:-1;;;40767:28:0;;;;;;;;;;;40731:64;40806:13;40822:17;40830:8;40822:7;:17::i;:::-;40806:33;-1:-1:-1;;;;;;40868:19:0;;40877:10;40868:19;;;;:69;;-1:-1:-1;40915:10:0;40905:21;;;;:9;:21;;;;;;;;-1:-1:-1;;;;;40905:32:0;;;;;;;;;;;;40904:33;40868:69;:124;;;;-1:-1:-1;40954:24:0;;;;:14;:24;;;;;;-1:-1:-1;;;;;40954:24:0;40982:10;40954:38;;40868:124;40850:195;;;41011:34;;-1:-1:-1;;;41011:34:0;;;;;;;;;;;40850:195;41063:24;;;;:14;:24;;;;;;;;41058:133;;41104:21;;;;:11;:21;;;;;;;;:29;;-1:-1:-1;;;;;;41104:29:0;-1:-1:-1;;;;;41104:29:0;;;;;41148:14;:24;;;;;:31;;-1:-1:-1;;41148:31:0;-1:-1:-1;41148:31:0;;;41058:133;41201:24;;;;:14;:24;;;;;;:36;;-1:-1:-1;;;;;;41201:36:0;-1:-1:-1;;;;;41201:36:0;;;;;;;;41255:41;;41201:24;;41264:10;;41255:41;;41201:24;41255:41;80512:188;;;:::o;82117:120::-;-1:-1:-1;;;;;82218:11:0;;82175:7;82218:11;;;:5;:11;;;;;;82202:13;;:27;;82218:11;82202:27;:::i;77061:498::-;77189:8;76029:9;76017:8;76009:5;;:16;;;;:::i;:::-;:29;76005:89;;76062:20;;-1:-1:-1;;;76062:20:0;;;;;;;;;;;76005:89;75568:4;76125:8;76108:14;:12;:14::i;:::-;:25;;;;:::i;:::-;:40;76104:91;;;76172:11;;-1:-1:-1;;;76172:11:0;;;;;;;;;;;76104:91;76240:13;;76215:10;76209:17;;;;:5;:17;;;;;;:28;;76229:8;;76209:28;:::i;:::-;:44;76205:106;;;76277:22;;-1:-1:-1;;;76277:22:0;;;;;;;;;;;76205:106;77237:15:::1;77219:14;:12;:14::i;:::-;:33;;;;;;;;:::i;:::-;;77215:65;;77261:19;;-1:-1:-1::0;;;77261:19:0::1;;;;;;;;;;;77215:65;77316:28;::::0;-1:-1:-1;;77333:10:0::1;12901:2:1::0;12897:15;12893:53;77316:28:0::1;::::0;::::1;12881:66:1::0;77291:12:0::1;::::0;12963::1;;77316:28:0::1;;;;;;;;;;;;77306:39;;;;;;77291:54;;77361:58;77380:11;;77361:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;77393:19:0::1;::::0;;-1:-1:-1;77414:4:0;;-1:-1:-1;77361:18:0::1;:58::i;:::-;77356:115;;77443:16;;-1:-1:-1::0;;;77443:16:0::1;;;;;;;;;;;77356:115;77487:10;77481:17;::::0;;;:5:::1;:17;::::0;;;;:29;;77502:8;;77481:17;:29:::1;::::0;77502:8;;77481:29:::1;:::i;:::-;::::0;;;-1:-1:-1;77521:30:0::1;::::0;-1:-1:-1;77530:10:0::1;77542:8:::0;77521::::1;:30::i;:::-;77204:355;77061:498:::0;;;;:::o;44223:124::-;44269:7;44328:11;;44310:15;;44296:11;;:29;;;;:::i;:::-;:43;;;;:::i;:::-;44289:50;;44223:124;:::o;47519:967::-;47654:15;;47643:8;:26;:56;;;;47698:1;47684:11;;:15;;;;:::i;:::-;47673:8;:26;47643:56;47639:105;;;47721:23;;-1:-1:-1;;;47721:23:0;;;;;;;;;;;47639:105;47755:13;47771:17;47779:8;47771:7;:17::i;:::-;47755:33;;47814:5;-1:-1:-1;;;;;47805:14:0;:5;-1:-1:-1;;;;;47805:14:0;;47801:55;;47828:28;;-1:-1:-1;;;47828:28:0;;;;;;;;;;;47801:55;-1:-1:-1;;;;;47885:19:0;;47894:10;47885:19;;;;:65;;-1:-1:-1;;;;;;47922:16:0;;;;;;:9;:16;;;;;;;;47939:10;47922:28;;;;;;;;;;47921:29;47885:65;:120;;;;-1:-1:-1;47967:24:0;;;;:14;:24;;;;;;-1:-1:-1;;;;;47967:24:0;47995:10;47967:38;;47885:120;47867:191;;;48024:34;;-1:-1:-1;;;48024:34:0;;;;;;;;;;;47867:191;-1:-1:-1;;;;;48073:17:0;;48069:60;;48099:30;;-1:-1:-1;;;48099:30:0;;;;;;;;;;;48069:60;48142:42;48163:5;48170:3;48175:8;48142:20;:42::i;:::-;-1:-1:-1;;;;;48197:15:0;;;;;;:8;:15;;;;;:20;;48216:1;;48197:15;:20;;48216:1;;48197:20;:::i;:::-;;;;-1:-1:-1;;;;;;;48228:13:0;;;;;;:8;:13;;;;;:18;;48245:1;;48228:13;:18;;48245:1;;48228:18;:::i;:::-;;;;-1:-1:-1;;48294:1:0;48259:24;;;:14;:24;;;;;;;;:37;;-1:-1:-1;;;;;;48259:37:0;;;;;;48307:11;:21;;;;;:27;;-1:-1:-1;;;;;48307:27:0;;;;;;;;;;;;48345:14;:24;;;;;;:31;;-1:-1:-1;;48345:31:0;48259:37;48345:31;;;48394:30;;48274:8;;48394:30;;;;;;;48437:41;47628:858;47519:967;;;:::o;62847:442::-;62944:7;63002:27;;;:17;:27;;;;;;;;62973:56;;;;;;;;;-1:-1:-1;;;;;62973:56:0;;;;;-1:-1:-1;;;62973:56:0;;;-1:-1:-1;;;;;62973:56:0;;;;;;;;62944:7;;63042:92;;-1:-1:-1;63093:29:0;;;;;;;;;63103:19;63093:29;-1:-1:-1;;;;;63093:29:0;;;;-1:-1:-1;;;63093:29:0;;-1:-1:-1;;;;;63093:29:0;;;;;63042:92;63184:23;;;;63146:21;;63655:5;;63171:36;;-1:-1:-1;;;;;63171:36:0;:10;:36;:::i;:::-;63170:58;;;;:::i;:::-;63249:16;;;-1:-1:-1;63146:82:0;;-1:-1:-1;;62847:442:0;;;;;;:::o;28129:147::-;27762:7;27789:12;;;:6;:12;;;;;:22;;;25757:16;25768:4;25757:10;:16::i;:::-;28243:25:::1;28254:4;28260:7;28243:10;:25::i;79874:356::-:0;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;80067:30:::1;::::0;80013:21:::1;::::0;79995:15:::1;::::0;-1:-1:-1;;;;;80067:10:0;::::1;::::0;80013:21;;79995:15;80067:30;79995:15;80067:30;80013:21;80067:10;:30:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80045:52;;;80159:10;80154:69;;80193:18;;-1:-1:-1::0;;;80193:18:0::1;;;;;;;;;;;29273:218:::0;-1:-1:-1;;;;;29369:23:0;;808:10;29369:23;29361:83;;;;-1:-1:-1;;;29361:83:0;;13655:2:1;29361:83:0;;;13637:21:1;13694:2;13674:18;;;13667:30;13733:34;13713:18;;;13706:62;-1:-1:-1;;;13784:18:1;;;13777:45;13839:19;;29361:83:0;;;;;;;;;29457:26;29469:4;29475:7;29457:11;:26::i;:::-;29273:218;;:::o;79762:104::-;1905:13;:11;:13::i;:::-;79819:39:::1;25311:4;79850:7;2092:6:::0;;-1:-1:-1;;;;;2092:6:0;;2019:87;79850:7:::1;79819:10;:39::i;:::-;79762:104::o:0;45578:174::-;45702:42;45719:5;45726:3;45731:8;45702:42;;;;;;;;;;;;:16;:42::i;49814:269::-;49876:7;49900:22;;;:12;:22;;;;;;;;49896:45;;;-1:-1:-1;49939:1:0;;49814:269;-1:-1:-1;49814:269:0:o;49896:45::-;49972:24;;;;:14;:24;;;;;;;;:103;;50057:18;50066:8;50057;:18::i;:::-;49972:103;;;-1:-1:-1;50016:21:0;;;;:11;:21;;;;;;-1:-1:-1;;;;;50016:21:0;;49814:269::o;77804:165::-;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;77932:29:::1;77941:9;77952:8;77932;:29::i;45003:208::-:0;45060:4;45109:15;;45097:8;:27;;:66;;;;;45152:11;;45141:8;:22;45097:66;:106;;;;-1:-1:-1;;45181:22:0;;;;:12;:22;;;;;;;;45180:23;;45003:208::o;78791:227::-;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;78933:1:::1;78907:27:::0;;;78903:79:::1;;78958:12;;-1:-1:-1::0;;;78958:12:0::1;;;;;;;;;;;78903:79;78992:7;:18;79002:8:::0;;78992:7;:18:::1;:::i;81100:221::-:0;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;81264:49:::1;81281:7;81290:8;81300:12;81264:16;:49::i;48751:383::-:0;48807:7;48842:15;;48831:8;:26;:52;;;;48872:11;;48861:8;:22;48831:52;48827:101;;;48905:23;;-1:-1:-1;;;48905:23:0;;;;;;;;;;;48827:101;48943:22;;;;:12;:22;;;;;;;;48939:53;;;48974:18;;-1:-1:-1;;;48974:18:0;;;;;;;;;;;77977:551;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;78133:37;;::::1;78129:67;;78179:17;;-1:-1:-1::0;;;78179:17:0::1;;;;;;;;;;;78129:67;78207:13;::::0;78231:97:::1;78251:21:::0;;::::1;78231:97;;;78303:10;;78314:1;78303:13;;;;;;;:::i;:::-;;;;;;;78294:22;;;;;:::i;:::-;::::0;-1:-1:-1;78274:3:0;::::1;::::0;::::1;:::i;:::-;;;;78231:97;;;;75568:4;78359:5;78342:14;:12;:14::i;:::-;:22;;;;:::i;:::-;:37;78338:61;;;78388:11;;-1:-1:-1::0;;;78388:11:0::1;;;;;;;;;;;78338:61;78415:9;78410:111;78430:20:::0;;::::1;78410:111;;;78472:37;78481:9;;78491:1;78481:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;78495:10;;78506:1;78495:13;;;;;;;:::i;:::-;;;;;;;78472:8;:37::i;:::-;78452:3:::0;::::1;::::0;::::1;:::i;:::-;;;;78410:111;;;;78118:410;77977:551:::0;;;;;:::o;39377:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;44684:180::-;44742:7;-1:-1:-1;;;;;44766:20:0;;44762:60;;44795:27;;-1:-1:-1;;;44795:27:0;;;;;;;;;;;44762:60;-1:-1:-1;;;;;;44840:16:0;;;;;:8;:16;;;;;;;44684:180::o;2667:103::-;1905:13;:11;:13::i;:::-;2732:30:::1;2759:1;2732:18;:30::i;79602:152::-:0;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;-1:-1:-1;79714:19:0::1;:32:::0;79602:152::o;79026:241::-;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;79177:1:::1;79149:29:::0;;;79145:79:::1;;79195:17;::::0;;::::1;::::0;::::1;::::0;;;-1:-1:-1;79195:17:0;;:12:::1;::::0;:17:::1;::::0;:12;:17:::1;:::i;:::-;;79145:79;79234:12;:25;79249:10:::0;;79234:12;:25:::1;:::i;81536:103::-:0;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;-1:-1:-1;81615:5:0::1;:16:::0;81536:103::o;26161:147::-;26247:4;26271:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;26271:29:0;;;;;;;;;;;;;;;26161:147::o;78536:247::-;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;78690:1:::1;78660:31:::0;;;78656:83:::1;;78715:12;;-1:-1:-1::0;;;78715:12:0::1;;;;;;;;;;;78656:83;78749:11;:26;78763:12:::0;;78749:11;:26:::1;:::i;43139:89::-:0;43180:13;43213:7;43206:14;;;;;:::i;77567:229::-;77627:8;76029:9;76017:8;76009:5;;:16;;;;:::i;:::-;:29;76005:89;;76062:20;;-1:-1:-1;;;76062:20:0;;;;;;;;;;;76005:89;75568:4;76125:8;76108:14;:12;:14::i;:::-;:25;;;;:::i;:::-;:40;76104:91;;;76172:11;;-1:-1:-1;;;76172:11:0;;;;;;;;;;;76104:91;76240:13;;76215:10;76209:17;;;;:5;:17;;;;;;:28;;76229:8;;76209:28;:::i;:::-;:44;76205:106;;;76277:22;;-1:-1:-1;;;76277:22:0;;;;;;;;;;;76205:106;77670:12:::1;77652:14;:12;:14::i;:::-;:30;;;;;;;;:::i;:::-;;77648:59;;77691:16;;-1:-1:-1::0;;;77691:16:0::1;;;;;;;;;;;77648:59;77724:10;77718:17;::::0;;;:5:::1;:17;::::0;;;;:29;;77739:8;;77718:17;:29:::1;::::0;77739:8;;77718:29:::1;:::i;:::-;::::0;;;-1:-1:-1;77758:30:0::1;::::0;-1:-1:-1;77767:10:0::1;77779:8:::0;77758::::1;:30::i;41752:301::-:0;41834:40;41853:9;41864;41834:18;:40::i;:::-;41895:10;41885:21;;;;:9;:21;;;;;;;;-1:-1:-1;;;;;41885:32:0;;;;;;;;;;;;:44;;-1:-1:-1;;41885:44:0;;;;;;;;;;41947:48;;540:41:1;;;41885:32:0;;41895:10;41947:48;;513:18:1;41947:48:0;;;;;;;29273:218;;:::o;81329:199::-;-1:-1:-1;;;;;;;;;;;25757:16:0;25768:4;25757:10;:16::i;:::-;81433:13:::1;;81420:9;:26;81417:67;;81455:29;;-1:-1:-1::0;;;81455:29:0::1;;;;;;;;;;;81417:67;-1:-1:-1::0;81495:13:0::1;:25:::0;81329:199::o;46617:304::-;46769:34;46782:5;46789:3;46794:8;46769:12;:34::i;:::-;-1:-1:-1;;;;;46818:15:0;;;:19;46814:100;;46854:48;46875:5;46882:3;46887:8;46897:4;46854:20;:48::i;43507:491::-;43610:13;43656:15;;43645:8;:26;:56;;;;43700:1;43686:11;;:15;;;;:::i;:::-;43675:8;:26;43645:56;43641:105;;;43723:23;;-1:-1:-1;;;43723:23:0;;;;;;;;;;;43641:105;43801:1;43783:7;43777:21;;;;;:::i;:::-;;;:25;:213;;;;;;;;;;;;;;;;;43858:7;43888:26;43905:8;43888:16;:26::i;:::-;43937:12;43822:146;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;43757:233;43507:491;-1:-1:-1;;43507:491:0:o;28569:149::-;27762:7;27789:12;;;:6;:12;;;;;:22;;;25757:16;25768:4;25757:10;:16::i;:::-;28684:26:::1;28696:4;28702:7;28684:11;:26::i;58653:130::-:0;25311:4;25757:16;25311:4;25757:10;:16::i;:::-;-1:-1:-1;58751:15:0::1;:24:::0;;-1:-1:-1;;;;;;58751:24:0::1;-1:-1:-1::0;;;;;58751:24:0;;;::::1;::::0;;;::::1;::::0;;58653:130::o;75652:83::-;;;;;;;:::i;2925:201::-;1905:13;:11;:13::i;:::-;-1:-1:-1;;;;;3014:22:0;::::1;3006:73;;;::::0;-1:-1:-1;;;3006:73:0;;18959:2:1;3006:73:0::1;::::0;::::1;18941:21:1::0;18998:2;18978:18;;;18971:30;19037:34;19017:18;;;19010:62;-1:-1:-1;;;19088:18:1;;;19081:36;19134:19;;3006:73:0::1;18757:402:1::0;3006:73:0::1;3090:28;3109:8;3090:18;:28::i;:::-;2925:201:::0;:::o;58904:313::-;59062:4;-1:-1:-1;;;;;;59104:46:0;;-1:-1:-1;;;59104:46:0;;:105;;;59167:42;59197:11;59167:29;:42::i;26612:105::-;26679:30;26690:4;808:10;26679;:30::i;63939:332::-;63655:5;-1:-1:-1;;;;;64042:33:0;;;;64034:88;;;;-1:-1:-1;;;64034:88:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;64141:22:0;;64133:60;;;;-1:-1:-1;;;64133:60:0;;19777:2:1;64133:60:0;;;19759:21:1;19816:2;19796:18;;;19789:30;19855:27;19835:18;;;19828:55;19900:18;;64133:60:0;19575:349:1;64133:60:0;64228:35;;;;;;;;;-1:-1:-1;;;;;64228:35:0;;;;;;-1:-1:-1;;;;;64228:35:0;;;;;;;;;;-1:-1:-1;;;64206:57:0;;;;:19;:57;63939:332::o;56774:111::-;56821:7;56862:15;;56848:11;;:29;;;;:::i;59660:254::-;59763:9;:36;;;;;59777:22;59789:9;59777:11;:22::i;:::-;59776:23;59763:36;59760:89;;;59801:48;;-1:-1:-1;;;59801:48:0;;;;;;;:::i;66463:190::-;66588:4;66641;66612:25;66625:5;66632:4;66612:12;:25::i;:::-;:33;;66463:190;-1:-1:-1;;;;66463:190:0:o;50744:106::-;50814:28;50823:3;50828:9;50814:28;;;;;;;;;;;;:8;:28::i;59225:427::-;-1:-1:-1;;;;;59400:18:0;;;;;;:51;;-1:-1:-1;;;;;;59435:16:0;;;;59400:51;:102;;;;;59469:33;59482:10;59494:7;59469:12;:33::i;:::-;59468:34;59400:102;59382:207;;;59529:48;;-1:-1:-1;;;59529:48:0;;;;;;;:::i;30870:238::-;30954:22;30962:4;30968:7;30954;:22::i;:::-;30949:152;;30993:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;30993:29:0;;;;;;;;;:36;;-1:-1:-1;;30993:36:0;31025:4;30993:36;;;31076:12;808:10;;728:98;31076:12;-1:-1:-1;;;;;31049:40:0;31067:7;-1:-1:-1;;;;;31049:40:0;31061:4;31049:40;;;;;;;;;;30870:238;;:::o;31288:239::-;31372:22;31380:4;31386:7;31372;:22::i;:::-;31368:152;;;31443:5;31411:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;31411:29:0;;;;;;;;;;:37;;-1:-1:-1;;31411:37:0;;;31468:40;808:10;;31411:12;;31468:40;;31443:5;31468:40;31288:239;;:::o;2184:132::-;2092:6;;-1:-1:-1;;;;;2092:6:0;808:10;2248:23;2240:68;;;;-1:-1:-1;;;2240:68:0;;20538:2:1;2240:68:0;;;20520:21:1;;;20557:18;;;20550:30;20616:34;20596:18;;;20589:62;20668:18;;2240:68:0;20336:356:1;57427:697:0;57530:7;57570:8;57530:7;57890:189;-1:-1:-1;;;;;57897:19:0;;57890:189;;57942:20;;;;:14;:20;;;;;;;;57937:102;;-1:-1:-1;57995:24:0;;;;:18;:24;;;;;;-1:-1:-1;;;;;57995:24:0;57937:102;-1:-1:-1;;58057:6:0;;;;57890:189;;;58100:5;57427:697;-1:-1:-1;;;57427:697:0:o;64722:390::-;63655:5;-1:-1:-1;;;;;64874:33:0;;;;64866:88;;;;-1:-1:-1;;;64866:88:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;64973:22:0;;64965:62;;;;-1:-1:-1;;;64965:62:0;;20899:2:1;64965:62:0;;;20881:21:1;20938:2;20918:18;;;20911:30;20977:29;20957:18;;;20950:57;21024:18;;64965:62:0;20697:351:1;64965:62:0;65069:35;;;;;;;;-1:-1:-1;;;;;65069:35:0;;;;;-1:-1:-1;;;;;65069:35:0;;;;;;;;;;-1:-1:-1;65040:26:0;;;:17;:26;;;;;;:64;;;;;;;-1:-1:-1;;;65040:64:0;;;;;;64722:390::o;3286:191::-;3379:6;;;-1:-1:-1;;;;;3396:17:0;;;-1:-1:-1;;;;;;3396:17:0;;;;;;;3429:40;;3379:6;;;3396:17;3379:6;;3429:40;;3360:16;;3429:40;3349:128;3286:191;:::o;55752:761::-;55940:153;;-1:-1:-1;;;55940:153:0;;55906:4;;-1:-1:-1;;;;;55940:36:0;;;;;:153;;55995:10;;56024:4;;56047:7;;56073:5;;55940:153;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55940:153:0;;;;;;;;-1:-1:-1;;55940:153:0;;;;;;;;;;;;:::i;:::-;;;55923:583;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56264:6;:13;56281:1;56264:18;56260:235;;56310:40;;-1:-1:-1;;;56310:40:0;;;;;;;;;;;56260:235;56453:6;56447:13;56438:6;56434:2;56430:15;56423:38;55923:583;-1:-1:-1;;;;;;56149:55:0;-1:-1:-1;;;56149:55:0;;-1:-1:-1;55923:583:0;55752:761;;;;;;:::o;19614:723::-;19670:13;19891:5;19900:1;19891:10;19887:53;;-1:-1:-1;;19918:10:0;;;;;;;;;;;;-1:-1:-1;;;19918:10:0;;;;;19614:723::o;19887:53::-;19965:5;19950:12;20006:78;20013:9;;20006:78;;20039:8;;;;:::i;:::-;;-1:-1:-1;20062:10:0;;-1:-1:-1;20070:2:0;20062:10;;:::i;:::-;;;20006:78;;;20094:19;20126:6;20116:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20116:17:0;;20094:39;;20144:154;20151:10;;20144:154;;20178:11;20188:1;20178:11;;:::i;:::-;;-1:-1:-1;20247:10:0;20255:2;20247:5;:10;:::i;:::-;20234:24;;:2;:24;:::i;:::-;20221:39;;20204:6;20211;20204:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;20204:56:0;;;;;;;;-1:-1:-1;20275:11:0;20284:2;20275:11;;:::i;:::-;;;20144:154;;49206:367;49318:4;-1:-1:-1;;;;;;49360:34:0;;-1:-1:-1;;;49360:34:0;;:85;;-1:-1:-1;;;;;;;49411:34:0;;-1:-1:-1;;;49411:34:0;49360:85;:145;;;-1:-1:-1;;;;;;;49462:43:0;;-1:-1:-1;;;49462:43:0;49360:145;:205;;;-1:-1:-1;;;;;;;49522:43:0;;-1:-1:-1;;;49522:43:0;49340:225;49206:367;-1:-1:-1;;49206:367:0:o;27007:492::-;27096:22;27104:4;27110:7;27096;:22::i;:::-;27091:401;;27284:28;27304:7;27284:19;:28::i;:::-;27385:38;27413:4;27420:2;27385:19;:38::i;:::-;27189:257;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;27189:257:0;;;;;;;;;;-1:-1:-1;;;27135:345:0;;;;;;;:::i;59922:204::-;60057:15;;60090:28;;-1:-1:-1;;;60090:28:0;;-1:-1:-1;;;;;3274:32:1;;;60090:28:0;;;3256:51:1;60010:4:0;;60057:15;;;;60090:18;;3229::1;;60090:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;67330:296::-;67413:7;67456:4;67413:7;67471:118;67495:5;:12;67491:1;:16;67471:118;;;67544:33;67554:12;67568:5;67574:1;67568:8;;;;;;;;:::i;:::-;;;;;;;67544:9;:33::i;:::-;67529:48;-1:-1:-1;67509:3:0;;;;:::i;:::-;;;;67471:118;;;-1:-1:-1;67606:12:0;67330:296;-1:-1:-1;;;67330:296:0:o;50937:661::-;51061:21;51067:3;51072:9;51061:5;:21::i;:::-;51093:22;51132:1;51118:11;;:15;;;;:::i;:::-;51093:40;-1:-1:-1;;;;;;51173:15:0;;;:20;51169:411;;51232:11;;:23;;;-1:-1:-1;;51232:27:0;51278:287;51373:9;;51335:55;51364:1;51368:3;51373:9;51384:5;51335:20;:55::i;:::-;51304:208;;51448:40;;-1:-1:-1;;;51448:40:0;;;;;;;;;;;51304:208;51549:14;51539:7;:24;51278:287;;51195:385;51050:548;50937:661;;;:::o;60134:337::-;60287:15;;60240:4;;-1:-1:-1;;;;;60287:15:0;;60313:46;;60355:4;60348:11;;;;;60313:46;60386:16;60394:7;60386;:16::i;:::-;-1:-1:-1;;;;;60374:28:0;:8;-1:-1:-1;;;;;60374:28:0;;60370:45;;60411:4;60404:11;;;;;60370:45;60433:30;;-1:-1:-1;;;60433:30:0;;60452:10;60433:30;;;3256:51:1;-1:-1:-1;;;;;60433:18:0;;;;;3229::1;;60433:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;21555:151::-;21613:13;21646:52;-1:-1:-1;;;;;21658:22:0;;19505:2;20915:483;21017:13;21048:19;21080:10;21084:6;21080:1;:10;:::i;:::-;:14;;21093:1;21080:14;:::i;:::-;21070:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21070:25:0;;21048:47;;-1:-1:-1;;;21106:6:0;21113:1;21106:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;21106:15:0;;;;;;;;;-1:-1:-1;;;21132:6:0;21139:1;21132:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;21132:15:0;;;;;;;;-1:-1:-1;21163:9:0;21175:10;21179:6;21175:1;:10;:::i;:::-;:14;;21188:1;21175:14;:::i;:::-;21163:26;;21158:135;21195:1;21191;:5;21158:135;;;-1:-1:-1;;;21243:5:0;21251:3;21243:11;21230:25;;;;;;;:::i;:::-;;;;21218:6;21225:1;21218:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;21218:37:0;;;;;;;;-1:-1:-1;21280:1:0;21270:11;;;;;21198:3;;;:::i;:::-;;;21158:135;;;-1:-1:-1;21311:10:0;;21303:55;;;;-1:-1:-1;;;21303:55:0;;23328:2:1;21303:55:0;;;23310:21:1;;;23347:18;;;23340:30;23406:34;23386:18;;;23379:62;23458:18;;21303:55:0;23126:356:1;74370:149:0;74433:7;74464:1;74460;:5;:51;;74595:13;74689:15;;;74725:4;74718:15;;;74772:4;74756:21;;74460:51;;;74595:13;74689:15;;;74725:4;74718:15;;;74772:4;74756:21;;74468:20;74527:268;52240:544;-1:-1:-1;;;;;52311:17:0;;52307:60;;52337:30;;-1:-1:-1;;;52337:30:0;;;;;;;;;;;52307:60;52382:9;52395:1;52382:14;52378:44;;52405:17;;-1:-1:-1;;;52405:17:0;;;;;;;;;;;52378:44;-1:-1:-1;;;;;52458:13:0;;;;;;:8;:13;;;;;:26;;;;;;52518:11;;:23;;;;52558:117;52592:8;52588:1;:12;52558:117;;;52631:28;;52657:1;;-1:-1:-1;;;;;52631:28:0;;;52648:1;;52631:28;;52648:1;;52631:28;52602:3;;52558:117;;;-1:-1:-1;52710:11:0;;;52691:31;;;;:18;:31;;;;;:37;;-1:-1:-1;;;;;;52691:37:0;-1:-1:-1;;;;;52691:37:0;;;;;;;;;;;52743:22;;;-1:-1:-1;52240:544:0:o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:188::-;660:20;;-1:-1:-1;;;;;709:46:1;;699:57;;689:85;;770:1;767;760:12;689:85;592:188;;;:::o;785:260::-;853:6;861;914:2;902:9;893:7;889:23;885:32;882:52;;;930:1;927;920:12;882:52;953:29;972:9;953:29;:::i;:::-;943:39;;1001:38;1035:2;1024:9;1020:18;1001:38;:::i;:::-;991:48;;785:260;;;;;:::o;1050:131::-;-1:-1:-1;;;;;1125:31:1;;1115:42;;1105:70;;1171:1;1168;1161:12;1186:179;1253:20;;-1:-1:-1;;;;;1302:38:1;;1292:49;;1282:77;;1355:1;1352;1345:12;1370:319;1437:6;1445;1498:2;1486:9;1477:7;1473:23;1469:32;1466:52;;;1514:1;1511;1504:12;1466:52;1553:9;1540:23;1572:31;1597:5;1572:31;:::i;:::-;1622:5;-1:-1:-1;1646:37:1;1679:2;1664:18;;1646:37;:::i;1694:127::-;1755:10;1750:3;1746:20;1743:1;1736:31;1786:4;1783:1;1776:15;1810:4;1807:1;1800:15;1826:338;1968:2;1953:18;;2001:1;1990:13;;1980:144;;2046:10;2041:3;2037:20;2034:1;2027:31;2081:4;2078:1;2071:15;2109:4;2106:1;2099:15;1980:144;2133:25;;;1826:338;:::o;2169:250::-;2254:1;2264:113;2278:6;2275:1;2272:13;2264:113;;;2354:11;;;2348:18;2335:11;;;2328:39;2300:2;2293:10;2264:113;;;-1:-1:-1;;2411:1:1;2393:16;;2386:27;2169:250::o;2424:271::-;2466:3;2504:5;2498:12;2531:6;2526:3;2519:19;2547:76;2616:6;2609:4;2604:3;2600:14;2593:4;2586:5;2582:16;2547:76;:::i;:::-;2677:2;2656:15;-1:-1:-1;;2652:29:1;2643:39;;;;2684:4;2639:50;;2424:271;-1:-1:-1;;2424:271:1:o;2700:220::-;2849:2;2838:9;2831:21;2812:4;2869:45;2910:2;2899:9;2895:18;2887:6;2869:45;:::i;2925:180::-;2984:6;3037:2;3025:9;3016:7;3012:23;3008:32;3005:52;;;3053:1;3050;3043:12;3005:52;-1:-1:-1;3076:23:1;;2925:180;-1:-1:-1;2925:180:1:o;3318:315::-;3386:6;3394;3447:2;3435:9;3426:7;3422:23;3418:32;3415:52;;;3463:1;3460;3453:12;3415:52;3502:9;3489:23;3521:31;3546:5;3521:31;:::i;:::-;3571:5;3623:2;3608:18;;;;3595:32;;-1:-1:-1;;;3318:315:1:o;3638:247::-;3697:6;3750:2;3738:9;3729:7;3725:23;3721:32;3718:52;;;3766:1;3763;3756:12;3718:52;3805:9;3792:23;3824:31;3849:5;3824:31;:::i;4072:367::-;4135:8;4145:6;4199:3;4192:4;4184:6;4180:17;4176:27;4166:55;;4217:1;4214;4207:12;4166:55;-1:-1:-1;4240:20:1;;4283:18;4272:30;;4269:50;;;4315:1;4312;4305:12;4269:50;4352:4;4344:6;4340:17;4328:29;;4412:3;4405:4;4395:6;4392:1;4388:14;4380:6;4376:27;4372:38;4369:47;4366:67;;;4429:1;4426;4419:12;4444:505;4539:6;4547;4555;4608:2;4596:9;4587:7;4583:23;4579:32;4576:52;;;4624:1;4621;4614:12;4576:52;4664:9;4651:23;4697:18;4689:6;4686:30;4683:50;;;4729:1;4726;4719:12;4683:50;4768:70;4830:7;4821:6;4810:9;4806:22;4768:70;:::i;:::-;4857:8;;4742:96;;-1:-1:-1;4939:2:1;4924:18;;;;4911:32;;4444:505;-1:-1:-1;;;;4444:505:1:o;4954:456::-;5031:6;5039;5047;5100:2;5088:9;5079:7;5075:23;5071:32;5068:52;;;5116:1;5113;5106:12;5068:52;5155:9;5142:23;5174:31;5199:5;5174:31;:::i;:::-;5224:5;-1:-1:-1;5281:2:1;5266:18;;5253:32;5294:33;5253:32;5294:33;:::i;:::-;4954:456;;5346:7;;-1:-1:-1;;;5400:2:1;5385:18;;;;5372:32;;4954:456::o;5782:248::-;5850:6;5858;5911:2;5899:9;5890:7;5886:23;5882:32;5879:52;;;5927:1;5924;5917:12;5879:52;-1:-1:-1;;5950:23:1;;;6020:2;6005:18;;;5992:32;;-1:-1:-1;5782:248:1:o;6314:315::-;6382:6;6390;6443:2;6431:9;6422:7;6418:23;6414:32;6411:52;;;6459:1;6456;6449:12;6411:52;6495:9;6482:23;6472:33;;6555:2;6544:9;6540:18;6527:32;6568:31;6593:5;6568:31;:::i;:::-;6618:5;6608:15;;;6314:315;;;;;:::o;6894:592::-;6965:6;6973;7026:2;7014:9;7005:7;7001:23;6997:32;6994:52;;;7042:1;7039;7032:12;6994:52;7082:9;7069:23;7111:18;7152:2;7144:6;7141:14;7138:34;;;7168:1;7165;7158:12;7138:34;7206:6;7195:9;7191:22;7181:32;;7251:7;7244:4;7240:2;7236:13;7232:27;7222:55;;7273:1;7270;7263:12;7222:55;7313:2;7300:16;7339:2;7331:6;7328:14;7325:34;;;7355:1;7352;7345:12;7325:34;7400:7;7395:2;7386:6;7382:2;7378:15;7374:24;7371:37;7368:57;;;7421:1;7418;7411:12;7368:57;7452:2;7444:11;;;;;7474:6;;-1:-1:-1;6894:592:1;;-1:-1:-1;;;;6894:592:1:o;7491:387::-;7567:6;7575;7583;7636:2;7624:9;7615:7;7611:23;7607:32;7604:52;;;7652:1;7649;7642:12;7604:52;7688:9;7675:23;7665:33;;7748:2;7737:9;7733:18;7720:32;7761:31;7786:5;7761:31;:::i;:::-;7811:5;-1:-1:-1;7835:37:1;7868:2;7853:18;;7835:37;:::i;:::-;7825:47;;7491:387;;;;;:::o;7883:773::-;8005:6;8013;8021;8029;8082:2;8070:9;8061:7;8057:23;8053:32;8050:52;;;8098:1;8095;8088:12;8050:52;8138:9;8125:23;8167:18;8208:2;8200:6;8197:14;8194:34;;;8224:1;8221;8214:12;8194:34;8263:70;8325:7;8316:6;8305:9;8301:22;8263:70;:::i;:::-;8352:8;;-1:-1:-1;8237:96:1;-1:-1:-1;8440:2:1;8425:18;;8412:32;;-1:-1:-1;8456:16:1;;;8453:36;;;8485:1;8482;8475:12;8453:36;;8524:72;8588:7;8577:8;8566:9;8562:24;8524:72;:::i;:::-;7883:773;;;;-1:-1:-1;8615:8:1;-1:-1:-1;;;;7883:773:1:o;9217:118::-;9303:5;9296:13;9289:21;9282:5;9279:32;9269:60;;9325:1;9322;9315:12;9340:382;9405:6;9413;9466:2;9454:9;9445:7;9441:23;9437:32;9434:52;;;9482:1;9479;9472:12;9434:52;9521:9;9508:23;9540:31;9565:5;9540:31;:::i;:::-;9590:5;-1:-1:-1;9647:2:1;9632:18;;9619:32;9660:30;9619:32;9660:30;:::i;9727:127::-;9788:10;9783:3;9779:20;9776:1;9769:31;9819:4;9816:1;9809:15;9843:4;9840:1;9833:15;9859:1266;9954:6;9962;9970;9978;10031:3;10019:9;10010:7;10006:23;10002:33;9999:53;;;10048:1;10045;10038:12;9999:53;10087:9;10074:23;10106:31;10131:5;10106:31;:::i;:::-;10156:5;-1:-1:-1;10213:2:1;10198:18;;10185:32;10226:33;10185:32;10226:33;:::i;:::-;10278:7;-1:-1:-1;10332:2:1;10317:18;;10304:32;;-1:-1:-1;10387:2:1;10372:18;;10359:32;10410:18;10440:14;;;10437:34;;;10467:1;10464;10457:12;10437:34;10505:6;10494:9;10490:22;10480:32;;10550:7;10543:4;10539:2;10535:13;10531:27;10521:55;;10572:1;10569;10562:12;10521:55;10608:2;10595:16;10630:2;10626;10623:10;10620:36;;;10636:18;;:::i;:::-;10711:2;10705:9;10679:2;10765:13;;-1:-1:-1;;10761:22:1;;;10785:2;10757:31;10753:40;10741:53;;;10809:18;;;10829:22;;;10806:46;10803:72;;;10855:18;;:::i;:::-;10895:10;10891:2;10884:22;10930:2;10922:6;10915:18;10970:7;10965:2;10960;10956;10952:11;10948:20;10945:33;10942:53;;;10991:1;10988;10981:12;10942:53;11047:2;11042;11038;11034:11;11029:2;11021:6;11017:15;11004:46;11092:1;11087:2;11082;11074:6;11070:15;11066:24;11059:35;11113:6;11103:16;;;;;;;9859:1266;;;;;;;:::o;11406:388::-;11474:6;11482;11535:2;11523:9;11514:7;11510:23;11506:32;11503:52;;;11551:1;11548;11541:12;11503:52;11590:9;11577:23;11609:31;11634:5;11609:31;:::i;:::-;11659:5;-1:-1:-1;11716:2:1;11701:18;;11688:32;11729:33;11688:32;11729:33;:::i;11799:380::-;11878:1;11874:12;;;;11921;;;11942:61;;11996:4;11988:6;11984:17;11974:27;;11942:61;12049:2;12041:6;12038:14;12018:18;12015:38;12012:161;;12095:10;12090:3;12086:20;12083:1;12076:31;12130:4;12127:1;12120:15;12158:4;12155:1;12148:15;12012:161;;11799:380;;;:::o;12184:127::-;12245:10;12240:3;12236:20;12233:1;12226:31;12276:4;12273:1;12266:15;12300:4;12297:1;12290:15;12316:128;12383:9;;;12404:11;;;12401:37;;;12418:18;;:::i;12449:168::-;12522:9;;;12553;;12570:15;;;12564:22;;12550:37;12540:71;;12591:18;;:::i;12622:125::-;12687:9;;;12708:10;;;12705:36;;;12721:18;;:::i;12986:127::-;13047:10;13042:3;13038:20;13035:1;13028:31;13078:4;13075:1;13068:15;13102:4;13099:1;13092:15;13118:120;13158:1;13184;13174:35;;13189:18;;:::i;:::-;-1:-1:-1;13223:9:1;;13118:120::o;13995:545::-;14097:2;14092:3;14089:11;14086:448;;;14133:1;14158:5;14154:2;14147:17;14203:4;14199:2;14189:19;14273:2;14261:10;14257:19;14254:1;14250:27;14244:4;14240:38;14309:4;14297:10;14294:20;14291:47;;;-1:-1:-1;14332:4:1;14291:47;14387:2;14382:3;14378:12;14375:1;14371:20;14365:4;14361:31;14351:41;;14442:82;14460:2;14453:5;14450:13;14442:82;;;14505:17;;;14486:1;14475:13;14442:82;;;14446:3;;;13995:545;;;:::o;14716:1206::-;14840:18;14835:3;14832:27;14829:53;;;14862:18;;:::i;:::-;14891:94;14981:3;14941:38;14973:4;14967:11;14941:38;:::i;:::-;14935:4;14891:94;:::i;:::-;15011:1;15036:2;15031:3;15028:11;15053:1;15048:616;;;;15708:1;15725:3;15722:93;;;-1:-1:-1;15781:19:1;;;15768:33;15722:93;-1:-1:-1;;14673:1:1;14669:11;;;14665:24;14661:29;14651:40;14697:1;14693:11;;;14648:57;15828:78;;15021:895;;15048:616;13942:1;13935:14;;;13979:4;13966:18;;-1:-1:-1;;15084:17:1;;;15185:9;15207:229;15221:7;15218:1;15215:14;15207:229;;;15310:19;;;15297:33;15282:49;;15417:4;15402:20;;;;15370:1;15358:14;;;;15237:12;15207:229;;;15211:3;15464;15455:7;15452:16;15449:159;;;15588:1;15584:6;15578:3;15572;15569:1;15565:11;15561:21;15557:34;15553:39;15540:9;15535:3;15531:19;15518:33;15514:79;15506:6;15499:95;15449:159;;;15651:1;15645:3;15642:1;15638:11;15634:19;15628:4;15621:33;15021:895;;14716:1206;;;:::o;15927:127::-;15988:10;15983:3;15979:20;15976:1;15969:31;16019:4;16016:1;16009:15;16043:4;16040:1;16033:15;16059:135;16098:3;16119:17;;;16116:43;;16139:18;;:::i;:::-;-1:-1:-1;16186:1:1;16175:13;;16059:135::o;16199:1352::-;16325:3;16319:10;16352:18;16344:6;16341:30;16338:56;;;16374:18;;:::i;:::-;16403:97;16493:6;16453:38;16485:4;16479:11;16453:38;:::i;:::-;16447:4;16403:97;:::i;:::-;16555:4;;16619:2;16608:14;;16636:1;16631:663;;;;17338:1;17355:6;17352:89;;;-1:-1:-1;17407:19:1;;;17401:26;17352:89;-1:-1:-1;;14673:1:1;14669:11;;;14665:24;14661:29;14651:40;14697:1;14693:11;;;14648:57;17454:81;;16601:944;;16631:663;13942:1;13935:14;;;13979:4;13966:18;;-1:-1:-1;;16667:20:1;;;16785:236;16799:7;16796:1;16793:14;16785:236;;;16888:19;;;16882:26;16867:42;;16980:27;;;;16948:1;16936:14;;;;16815:19;;16785:236;;;16789:3;17049:6;17040:7;17037:19;17034:201;;;17110:19;;;17104:26;-1:-1:-1;;17193:1:1;17189:14;;;17205:3;17185:24;17181:37;17177:42;17162:58;17147:74;;17034:201;-1:-1:-1;;;;;17281:1:1;17265:14;;;17261:22;17248:36;;-1:-1:-1;16199:1352:1:o;17556:722::-;17606:3;17647:5;17641:12;17676:36;17702:9;17676:36;:::i;:::-;17731:1;17748:18;;;17775:133;;;;17922:1;17917:355;;;;17741:531;;17775:133;-1:-1:-1;;17808:24:1;;17796:37;;17881:14;;17874:22;17862:35;;17853:45;;;-1:-1:-1;17775:133:1;;17917:355;17948:5;17945:1;17938:16;17977:4;18022:2;18019:1;18009:16;18047:1;18061:165;18075:6;18072:1;18069:13;18061:165;;;18153:14;;18140:11;;;18133:35;18196:16;;;;18090:10;;18061:165;;;18065:3;;;18255:6;18250:3;18246:16;18239:23;;17741:531;;;;;17556:722;;;;:::o;18283:469::-;18504:3;18532:38;18566:3;18558:6;18532:38;:::i;:::-;18599:6;18593:13;18615:65;18673:6;18669:2;18662:4;18654:6;18650:17;18615:65;:::i;:::-;18696:50;18738:6;18734:2;18730:15;18722:6;18696:50;:::i;:::-;18689:57;18283:469;-1:-1:-1;;;;;;;18283:469:1:o;19164:406::-;19366:2;19348:21;;;19405:2;19385:18;;;19378:30;19444:34;19439:2;19424:18;;19417:62;-1:-1:-1;;;19510:2:1;19495:18;;19488:40;19560:3;19545:19;;19164:406::o;19929:402::-;20131:2;20113:21;;;20170:2;20150:18;;;20143:30;20209:34;20204:2;20189:18;;20182:62;-1:-1:-1;;;20275:2:1;20260:18;;20253:36;20321:3;20306:19;;19929:402::o;21053:489::-;-1:-1:-1;;;;;21322:15:1;;;21304:34;;21374:15;;21369:2;21354:18;;21347:43;21421:2;21406:18;;21399:34;;;21469:3;21464:2;21449:18;;21442:31;;;21247:4;;21490:46;;21516:19;;21508:6;21490:46;:::i;:::-;21482:54;21053:489;-1:-1:-1;;;;;;21053:489:1:o;21547:249::-;21616:6;21669:2;21657:9;21648:7;21644:23;21640:32;21637:52;;;21685:1;21682;21675:12;21637:52;21717:9;21711:16;21736:30;21760:5;21736:30;:::i;21801:112::-;21833:1;21859;21849:35;;21864:18;;:::i;:::-;-1:-1:-1;21898:9:1;;21801:112::o;21918:812::-;22329:25;22324:3;22317:38;22299:3;22384:6;22378:13;22400:75;22468:6;22463:2;22458:3;22454:12;22447:4;22439:6;22435:17;22400:75;:::i;:::-;-1:-1:-1;;;22534:2:1;22494:16;;;22526:11;;;22519:40;22584:13;;22606:76;22584:13;22668:2;22660:11;;22653:4;22641:17;;22606:76;:::i;:::-;22702:17;22721:2;22698:26;;21918:812;-1:-1:-1;;;;21918:812:1:o;22735:245::-;22802:6;22855:2;22843:9;22834:7;22830:23;22826:32;22823:52;;;22871:1;22868;22861:12;22823:52;22903:9;22897:16;22922:28;22944:5;22922:28;:::i;22985:136::-;23024:3;23052:5;23042:39;;23061:18;;:::i;:::-;-1:-1:-1;;;23097:18:1;;22985:136::o

Swarm Source

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