ETH Price: $2,877.59 (-9.16%)
Gas: 10 Gwei

Contract

0x247d10Dd34457f1920f50DF43F7b6488767b7392
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Set Approval For...189404512024-01-05 10:22:35181 days ago1704450155IN
0x247d10Dd...8767b7392
0 ETH0.0003603214.86042342
Set Approval For...189072352023-12-31 18:26:23186 days ago1704047183IN
0x247d10Dd...8767b7392
0 ETH0.0008232214.01856387
Set Approval For...187661572023-12-11 23:12:23206 days ago1702336343IN
0x247d10Dd...8767b7392
0 ETH0.0023794940.52001046
Set Approval For...186505722023-11-25 18:43:35222 days ago1700937815IN
0x247d10Dd...8767b7392
0 ETH0.0006299125.97902942
Transfer From183305742023-10-11 23:49:59267 days ago1697068199IN
0x247d10Dd...8767b7392
0 ETH0.000369665.48412115
Set Approval For...168621812023-03-19 13:52:11473 days ago1679233931IN
0x247d10Dd...8767b7392
0 ETH0.0003767515.53812673
Set Approval For...167133222023-02-26 15:33:11494 days ago1677425591IN
0x247d10Dd...8767b7392
0 ETH0.0013514323.04633232
Set Approval For...166439862023-02-16 21:30:11504 days ago1676583011IN
0x247d10Dd...8767b7392
0 ETH0.0010966245.2271035
Set Approval For...165938422023-02-09 21:21:11511 days ago1675977671IN
0x247d10Dd...8767b7392
0 ETH0.0029481550.27556491
Set Approval For...164864072023-01-25 21:06:11526 days ago1674680771IN
0x247d10Dd...8767b7392
0 ETH0.0011956520.36061119
Set Approval For...163502042023-01-06 20:43:23545 days ago1673037803IN
0x247d10Dd...8767b7392
0 ETH0.0016307627.77001433
Set Approval For...163066872022-12-31 18:58:35551 days ago1672513115IN
0x247d10Dd...8767b7392
0 ETH0.0010183517.34483728
Approve162728012022-12-27 1:27:47556 days ago1672104467IN
0x247d10Dd...8767b7392
0 ETH0.0008872217.7640236
Approve162727952022-12-27 1:26:35556 days ago1672104395IN
0x247d10Dd...8767b7392
0 ETH0.0008566717.15228819
Approve162727882022-12-27 1:25:11556 days ago1672104311IN
0x247d10Dd...8767b7392
0 ETH0.0012901218.47124017
Set Approval For...162560102022-12-24 17:12:47558 days ago1671901967IN
0x247d10Dd...8767b7392
0 ETH0.0010895118.55690714
Set Approval For...161952402022-12-16 5:42:35567 days ago1671169355IN
0x247d10Dd...8767b7392
0 ETH0.0002974812.26876139
Set Approval For...159827292022-11-16 12:56:59596 days ago1668603419IN
0x247d10Dd...8767b7392
0 ETH0.0007673513.08590801
Transfer From158770612022-11-01 18:46:59611 days ago1667328419IN
0x247d10Dd...8767b7392
0 ETH0.0007988611.85161043
Withdraw Payment...158332452022-10-26 15:48:35617 days ago1666799315IN
0x247d10Dd...8767b7392
0 ETH0.0012275730.70482515
Set Approval For...158314832022-10-26 9:55:11618 days ago1666778111IN
0x247d10Dd...8767b7392
0 ETH0.0002668711.0066151
Safe Transfer Fr...157841392022-10-19 19:07:23624 days ago1666206443IN
0x247d10Dd...8767b7392
0 ETH0.0034844146.49415407
Set Approval For...157700142022-10-17 19:48:47626 days ago1666036127IN
0x247d10Dd...8767b7392
0 ETH0.00154226.29619183
Set Approval For...157647812022-10-17 2:14:11627 days ago1665972851IN
0x247d10Dd...8767b7392
0 ETH0.0002975112.27023576
Safe Transfer Fr...157644392022-10-17 1:05:35627 days ago1665968735IN
0x247d10Dd...8767b7392
0 ETH0.0015787113.20694652
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
158332452022-10-26 15:48:35617 days ago1666799315
0x247d10Dd...8767b7392
48.285 ETH
Loading...
Loading

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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