ETH Price: $3,488.64 (+2.35%)
Gas: 3.55 Gwei

Token

Soseiki Diary (SDC)
 

Overview

Max Total Supply

1,888 SDC

Holders

818

Total Transfers

-

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Soseiki

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-12-16
*/

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

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

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

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

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

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

pragma solidity ^0.8.0;

/**
 * @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 * 8) < value ? 1 : 0);
        }
    }
}

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

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

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _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) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length)
        internal
        pure
        returns (string memory)
    {
        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] = _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);
    }
}

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

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return
            functionCallWithValue(
                target,
                data,
                0,
                "Address: low-level call failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                "Address: low-level call with value failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            "Address: insufficient balance for call"
        );
        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data)
        internal
        view
        returns (bytes memory)
    {
        return
            functionStaticCall(
                target,
                data,
                "Address: low-level static call failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return
            functionDelegateCall(
                target,
                data,
                "Address: low-level delegate call failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return
            verifyCallResultFromTarget(
                target,
                success,
                returndata,
                errorMessage
            );
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage)
        private
        pure
    {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

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

// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

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

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

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

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

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            owner != address(0),
            "ERC721: address zero is not a valid owner"
        );
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

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

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

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

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

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

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner or approved for all"
        );

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: caller is not token owner or approved"
        );

        _transfer(from, to, tokenId);
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: caller is not token owner or approved"
        );
        _safeTransfer(from, to, tokenId, data);
    }

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

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        virtual
        returns (bool)
    {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner ||
            isApprovedForAll(owner, spender) ||
            getApproved(tokenId) == spender);
    }

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

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

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

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

        _beforeTokenTransfer(owner, address(0), tokenId, 1);

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(
            ERC721.ownerOf(tokenId) == from,
            "ERC721: transfer from incorrect owner"
        );
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(
            ERC721.ownerOf(tokenId) == from,
            "ERC721: transfer from incorrect owner"
        );

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try
                IERC721Receiver(to).onERC721Received(
                    _msgSender(),
                    from,
                    tokenId,
                    data
                )
            returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert(
                        "ERC721: transfer to non ERC721Receiver implementer"
                    );
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}

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

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

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

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

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            index < ERC721.balanceOf(owner),
            "ERC721Enumerable: owner index out of bounds"
        );
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            index < ERC721Enumerable.totalSupply(),
            "ERC721Enumerable: global index out of bounds"
        );
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

        if (batchSize > 1) {
            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
            revert("ERC721Enumerable: consecutive transfers not supported");
        }

        uint256 tokenId = firstTokenId;

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

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

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

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

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

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

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

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

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

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

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

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

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

// File contracts/Soseiki.sol

pragma solidity >=0.7.0 <0.9.0;

contract Soseiki is ERC721Enumerable, Ownable {
    bool internal locked;

    modifier noReentrant() {
        require(!locked, "NO NO!");
        locked = true;
        _;
        locked = false;
    }

    using Strings for uint256;

    string public baseURI;
    string public baseExtension = ".json";
    string public notRevealedUri;
    uint256 public cost = 0 ether;
    uint256 public maxSupply = 1888;
    uint256 public maxMintAmount = 2;
    uint256 public nftPerAddressLimit = 2;
    bool public paused = true;
    bool public revealed = false;
    bool public onlyWhitelisted = true;
    address[] public whitelistedAddresses;
    mapping(address => uint256) public addressMintedBalance;

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _initBaseURI,
        string memory _initNotRevealedUri
    ) ERC721(_name, _symbol) {
        setBaseURI(_initBaseURI);
        setNotRevealedURI(_initNotRevealedUri);
    }

    // internal
    function _baseURI() internal view virtual override returns (string memory) {
        return baseURI;
    }

    // public
    function mint(uint256 _mintAmount) public payable noReentrant {
        require(!paused, "the contract is paused");
        uint256 supply = totalSupply();
        require(_mintAmount > 0, "need to mint at least 1 NFT");
        require(
            _mintAmount <= maxMintAmount,
            "max mint amount per session exceeded"
        );
        require(supply + _mintAmount <= maxSupply, "max NFT limit exceeded");

        if (msg.sender != owner()) {
            if (onlyWhitelisted == true) {
                require(isWhitelisted(msg.sender), "user is not whitelisted");
                uint256 ownerMintedCount = addressMintedBalance[msg.sender];
                require(
                    ownerMintedCount + _mintAmount <= nftPerAddressLimit,
                    "max NFT per address exceeded"
                );
            }
            require(msg.value >= cost * _mintAmount, "insufficient funds");
        }

        for (uint256 i = 1; i <= _mintAmount; i++) {
            addressMintedBalance[msg.sender]++;
            _safeMint(msg.sender, supply + i);
        }
    }

    function isWhitelisted(address _user) public view returns (bool) {
        for (uint256 i = 0; i < whitelistedAddresses.length; i++) {
            if (whitelistedAddresses[i] == _user) {
                return true;
            }
        }
        return false;
    }

    function walletOfOwner(address _owner)
        public
        view
        returns (uint256[] memory)
    {
        uint256 ownerTokenCount = balanceOf(_owner);
        uint256[] memory tokenIds = new uint256[](ownerTokenCount);
        for (uint256 i; i < ownerTokenCount; i++) {
            tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
        }
        return tokenIds;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

        if (revealed == false) {
            return notRevealedUri;
        }

        string memory currentBaseURI = _baseURI();
        return
            bytes(currentBaseURI).length > 0
                ? string(
                    abi.encodePacked(
                        currentBaseURI,
                        tokenId.toString(),
                        baseExtension
                    )
                )
                : "";
    }

    //only owner
    function reveal() public onlyOwner {
        revealed = true;
    }

    function setNftPerAddressLimit(uint256 _limit) public onlyOwner {
        nftPerAddressLimit = _limit;
    }

    function setCost(uint256 _newCost) public onlyOwner {
        cost = _newCost;
    }

    function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
        maxMintAmount = _newmaxMintAmount;
    }

    function setBaseURI(string memory _newBaseURI) public onlyOwner {
        baseURI = _newBaseURI;
    }

    function setBaseExtension(string memory _newBaseExtension)
        public
        onlyOwner
    {
        baseExtension = _newBaseExtension;
    }

    function setNotRevealedURI(string memory _notRevealedURI) public onlyOwner {
        notRevealedUri = _notRevealedURI;
    }

    function pause(bool _state) public onlyOwner {
        paused = _state;
    }

    function setOnlyWhitelisted(bool _state) public onlyOwner {
        onlyWhitelisted = _state;
    }

    function whitelistUsers(address[] calldata _users) public onlyOwner {
        delete whitelistedAddresses;
        whitelistedAddresses = _users;
    }

    function withdraw() public payable onlyOwner {
        (bool success, ) = payable(msg.sender).call{
            value: address(this).balance
        }("");
        require(success);
    }
}

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

// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b)
        internal
        pure
        returns (bool, uint256)
    {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

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

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

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

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

// OpenZeppelin Contracts v4.4.1 (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
 */
contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

// File contracts/SoseikiFarm.sol

pragma solidity ^0.8.9;

// import "./soseikiToken.sol";

interface RewardToken is IERC20 {
    function mint(address to, uint256 amount) external;
}

contract SoseikiFarm is Ownable {
    IERC721 public soseikiNFT;
    RewardToken public soseikiToken;

    uint256 public stakedTotal;
    uint256 public stakingStartTime;
    uint256 constant stakingTime = 43200 seconds;
    uint256 constant token = 10e18;

    struct Staker {
        uint256[] tokenIds;
        mapping(uint256 => uint256) tokenStakingCoolDown;
        uint256 balance;
        uint256 rewardsReleased;
    }

    bool internal locked;

    modifier noReentrant() {
        require(!locked, "NO NO!");
        locked = true;
        _;
        locked = false;
    }

    constructor(IERC721 _soseikiNFT, RewardToken _soseikiToken) {
        soseikiNFT = _soseikiNFT;
        soseikiToken = _soseikiToken;
    }

    mapping(address => Staker) public stakers;
    mapping(uint256 => address) public tokenOwner;
    bool public tokenClaimable;
    bool initialised;

    event Staked(address owner, uint256 amount);
    event Unstaked(address owner, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);
    event ClaimableStatusUpdated(bool status);
    event EmergenctUnstake(address indexed user, uint256 tokenId);

    function initStaking() public onlyOwner {
        require(!initialised, "Already initialised");
        stakingStartTime = block.timestamp;
        initialised = true;
    }

    function setTokenClaimable(bool _enabled) public onlyOwner {
        tokenClaimable = _enabled;
        emit ClaimableStatusUpdated(_enabled);
    }

    function getStakedTokens(address _user)
        public
        view
        returns (uint256[] memory tokenIds)
    {
        return stakers[_user].tokenIds;
    }

    function stake(uint256 tokenId) public {
        _stake(msg.sender, tokenId);
    }

    function unstake(uint256 tokenId) public {
        _unstake(msg.sender, tokenId);
    }

    function _stake(address _user, uint256 _tokenId) internal {
        require(initialised, "Staking System: the stacking has not started");
        require(
            soseikiNFT.ownerOf(_tokenId) == _user,
            "user must be the owner of the token"
        );
        Staker storage staker = stakers[_user];

        staker.tokenIds.push(_tokenId);
        staker.tokenStakingCoolDown[_tokenId] = block.timestamp;
        tokenOwner[_tokenId] = _user;
        soseikiNFT.approve(address(this), _tokenId);
        soseikiNFT.safeTransferFrom(_user, address(this), _tokenId);

        emit Staked(_user, _tokenId);
        stakedTotal++;
    }

    function _unstake(address _user, uint256 _tokenId) internal {
        require(
            tokenOwner[_tokenId] == _user,
            "Nft Staking Syetem: User must be the owner of the staked NFT"
        );

        Staker storage staker = stakers[_user];
        //   uint256 lastIndex = staker.tokenIds.length -1;
        //   uint256 lastIndexKey = staker.tokenIds[lastIndex];

        if (staker.tokenIds.length > 0 && tokenOwner[_tokenId] == _user) {
            uint256 lastIndex = staker.tokenIds.length - 1;
            uint256 lastIndexKey = staker.tokenIds[lastIndex];
            for (uint256 i = 0; i <= lastIndex; i++) {
                if (_tokenId == staker.tokenIds[i]) {
                    staker.tokenIds[i] = lastIndexKey;
                }
            }
            staker.tokenIds.pop();
            staker.tokenStakingCoolDown[_tokenId] = 0;
            delete tokenOwner[_tokenId];
            soseikiNFT.safeTransferFrom(address(this), _user, _tokenId);
            emit Unstaked(_user, _tokenId);
            stakedTotal--;
        }
    }

    function updateReward(address _user) public {
        Staker storage staker = stakers[_user];
        uint256[] storage ids = staker.tokenIds;
        for (uint256 i = 0; i < ids.length; i++) {
            if (
                staker.tokenStakingCoolDown[ids[i]] <
                block.timestamp + stakingTime &&
                staker.tokenStakingCoolDown[ids[i]] > 0
            ) {
                uint256 stakeDays = (
                    (block.timestamp -
                        uint256(staker.tokenStakingCoolDown[ids[i]]))
                ) / stakingTime;
                uint256 partialTime = (
                    (block.timestamp -
                        uint256(staker.tokenStakingCoolDown[ids[i]]))
                ) % stakingTime;

                staker.balance += token * stakeDays;
                staker.tokenStakingCoolDown[ids[i]] =
                    block.timestamp +
                    partialTime;

                // console.log uint(staker.tokenStakingCoolDown[ids[i]]);
                // console.log uint(staker.balance);
            }
        }
    }

    function claimReward(address _user) public noReentrant {
        require(tokenClaimable == true, "Tokens cannot be claimed yet");
        require(stakers[_user].balance > 0, "0 reward yet");

        stakers[_user].rewardsReleased += stakers[_user].balance;

        soseikiToken.mint(_user, stakers[_user].balance);
        stakers[_user].balance = 0;
        emit RewardPaid(_user, stakers[_user].balance);
    }

    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4) {
        return
            bytes4(
                keccak256("onERC721Received(address,address,uint256,bytes)")
            );
    }
}

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

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

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

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

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

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

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue)
        public
        virtual
        returns (bool)
    {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue)
        public
        virtual
        returns (bool)
    {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(
            currentAllowance >= subtractedValue,
            "ERC20: decreased allowance below zero"
        );
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(
            fromBalance >= amount,
            "ERC20: transfer amount exceeds balance"
        );
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(
                currentAllowance >= amount,
                "ERC20: insufficient allowance"
            );
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

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

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.0;

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

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

// File contracts/SoseikiToken.sol

pragma solidity ^0.8.9;

contract SoseikiToken is ERC20, ERC20Burnable, AccessControl, Ownable {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    constructor() ERC20("Soseiki Token", "SDT") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
    }

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_initBaseURI","type":"string"},{"internalType":"string","name":"_initNotRevealedUri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":[{"internalType":"address","name":"","type":"address"}],"name":"addressMintedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"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":"address","name":"_user","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftPerAddressLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notRevealedUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onlyWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseExtension","type":"string"}],"name":"setBaseExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newCost","type":"uint256"}],"name":"setCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setNftPerAddressLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_notRevealedURI","type":"string"}],"name":"setNotRevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"setOnlyWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newmaxMintAmount","type":"uint256"}],"name":"setmaxMintAmount","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"address","name":"_owner","type":"address"}],"name":"walletOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"whitelistUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"whitelistedAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]

60806040526040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250600c9080519060200190620000519291906200034e565b506000600e55610760600f55600260105560026011556001601260006101000a81548160ff0219169083151502179055506000601260016101000a81548160ff0219169083151502179055506001601260026101000a81548160ff021916908315150217905550348015620000c557600080fd5b5060405162005525380380620055258339818101604052810190620000eb91906200059b565b83838160009080519060200190620001059291906200034e565b5080600190805190602001906200011e9291906200034e565b50505062000141620001356200016d60201b60201c565b6200017560201b60201c565b62000152826200023b60201b60201c565b62000163816200026760201b60201c565b5050505062000771565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6200024b6200029360201b60201c565b80600b9080519060200190620002639291906200034e565b5050565b620002776200029360201b60201c565b80600d90805190602001906200028f9291906200034e565b5050565b620002a36200016d60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620002c96200032460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000322576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200031990620006ea565b60405180910390fd5b565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b8280546200035c906200073b565b90600052602060002090601f016020900481019282620003805760008555620003cc565b82601f106200039b57805160ff1916838001178555620003cc565b82800160010185558215620003cc579182015b82811115620003cb578251825591602001919060010190620003ae565b5b509050620003db9190620003df565b5090565b5b80821115620003fa576000816000905550600101620003e0565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000467826200041c565b810181811067ffffffffffffffff821117156200048957620004886200042d565b5b80604052505050565b60006200049e620003fe565b9050620004ac82826200045c565b919050565b600067ffffffffffffffff821115620004cf57620004ce6200042d565b5b620004da826200041c565b9050602081019050919050565b60005b8381101562000507578082015181840152602081019050620004ea565b8381111562000517576000848401525b50505050565b6000620005346200052e84620004b1565b62000492565b90508281526020810184848401111562000553576200055262000417565b5b62000560848285620004e7565b509392505050565b600082601f83011262000580576200057f62000412565b5b8151620005928482602086016200051d565b91505092915050565b60008060008060808587031215620005b857620005b762000408565b5b600085015167ffffffffffffffff811115620005d957620005d86200040d565b5b620005e78782880162000568565b945050602085015167ffffffffffffffff8111156200060b576200060a6200040d565b5b620006198782880162000568565b935050604085015167ffffffffffffffff8111156200063d576200063c6200040d565b5b6200064b8782880162000568565b925050606085015167ffffffffffffffff8111156200066f576200066e6200040d565b5b6200067d8782880162000568565b91505092959194509250565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620006d260208362000689565b9150620006df826200069a565b602082019050919050565b600060208201905081810360008301526200070581620006c3565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200075457607f821691505b602082108114156200076b576200076a6200070c565b5b50919050565b614da480620007816000396000f3fe6080604052600436106102725760003560e01c80636352211e1161014f578063b88d4fde116100c1578063d5abeb011161007a578063d5abeb011461095c578063da3ef23f14610987578063e985e9c5146109b0578063edec5f27146109ed578063f2c4ce1e14610a16578063f2fde38b14610a3f57610272565b8063b88d4fde1461083a578063ba4e5c4914610863578063ba7d2c76146108a0578063c6682862146108cb578063c87b56dd146108f6578063d0eb26b01461093357610272565b80638da5cb5b116101135780638da5cb5b1461075d57806395d89b41146107885780639c70b512146107b3578063a0712d68146107de578063a22cb465146107fa578063a475b5dd1461082357610272565b80636352211e146106785780636c0360eb146106b557806370a08231146106e0578063715018a61461071d5780637f00c7a61461073457610272565b80632f745c59116101e8578063438b6300116101ac578063438b63001461055657806344a0d68a146105935780634f6ccce7146105bc57806351830227146105f957806355f804b3146106245780635c975abb1461064d57610272565b80632f745c59146104805780633af32abf146104bd5780633c952764146104fa5780633ccfd60b1461052357806342842e0e1461052d57610272565b8063095ea7b31161023a578063095ea7b31461037057806313faede61461039957806318160ddd146103c457806318cae269146103ef578063239c70ae1461042c57806323b872dd1461045757610272565b806301ffc9a71461027757806302329a29146102b457806306fdde03146102dd578063081812fc14610308578063081c8c4414610345575b600080fd5b34801561028357600080fd5b5061029e60048036038101906102999190613485565b610a68565b6040516102ab91906134cd565b60405180910390f35b3480156102c057600080fd5b506102db60048036038101906102d69190613514565b610ae2565b005b3480156102e957600080fd5b506102f2610b07565b6040516102ff91906135da565b60405180910390f35b34801561031457600080fd5b5061032f600480360381019061032a9190613632565b610b99565b60405161033c91906136a0565b60405180910390f35b34801561035157600080fd5b5061035a610bdf565b60405161036791906135da565b60405180910390f35b34801561037c57600080fd5b50610397600480360381019061039291906136e7565b610c6d565b005b3480156103a557600080fd5b506103ae610d85565b6040516103bb9190613736565b60405180910390f35b3480156103d057600080fd5b506103d9610d8b565b6040516103e69190613736565b60405180910390f35b3480156103fb57600080fd5b5061041660048036038101906104119190613751565b610d98565b6040516104239190613736565b60405180910390f35b34801561043857600080fd5b50610441610db0565b60405161044e9190613736565b60405180910390f35b34801561046357600080fd5b5061047e6004803603810190610479919061377e565b610db6565b005b34801561048c57600080fd5b506104a760048036038101906104a291906136e7565b610e16565b6040516104b49190613736565b60405180910390f35b3480156104c957600080fd5b506104e460048036038101906104df9190613751565b610ebb565b6040516104f191906134cd565b60405180910390f35b34801561050657600080fd5b50610521600480360381019061051c9190613514565b610f6a565b005b61052b610f8f565b005b34801561053957600080fd5b50610554600480360381019061054f919061377e565b611010565b005b34801561056257600080fd5b5061057d60048036038101906105789190613751565b611030565b60405161058a919061388f565b60405180910390f35b34801561059f57600080fd5b506105ba60048036038101906105b59190613632565b6110de565b005b3480156105c857600080fd5b506105e360048036038101906105de9190613632565b6110f0565b6040516105f09190613736565b60405180910390f35b34801561060557600080fd5b5061060e611161565b60405161061b91906134cd565b60405180910390f35b34801561063057600080fd5b5061064b600480360381019061064691906139e6565b611174565b005b34801561065957600080fd5b50610662611196565b60405161066f91906134cd565b60405180910390f35b34801561068457600080fd5b5061069f600480360381019061069a9190613632565b6111a9565b6040516106ac91906136a0565b60405180910390f35b3480156106c157600080fd5b506106ca611230565b6040516106d791906135da565b60405180910390f35b3480156106ec57600080fd5b5061070760048036038101906107029190613751565b6112be565b6040516107149190613736565b60405180910390f35b34801561072957600080fd5b50610732611376565b005b34801561074057600080fd5b5061075b60048036038101906107569190613632565b61138a565b005b34801561076957600080fd5b5061077261139c565b60405161077f91906136a0565b60405180910390f35b34801561079457600080fd5b5061079d6113c6565b6040516107aa91906135da565b60405180910390f35b3480156107bf57600080fd5b506107c8611458565b6040516107d591906134cd565b60405180910390f35b6107f860048036038101906107f39190613632565b61146b565b005b34801561080657600080fd5b50610821600480360381019061081c9190613a2f565b61183a565b005b34801561082f57600080fd5b50610838611850565b005b34801561084657600080fd5b50610861600480360381019061085c9190613b10565b611875565b005b34801561086f57600080fd5b5061088a60048036038101906108859190613632565b6118d7565b60405161089791906136a0565b60405180910390f35b3480156108ac57600080fd5b506108b5611916565b6040516108c29190613736565b60405180910390f35b3480156108d757600080fd5b506108e061191c565b6040516108ed91906135da565b60405180910390f35b34801561090257600080fd5b5061091d60048036038101906109189190613632565b6119aa565b60405161092a91906135da565b60405180910390f35b34801561093f57600080fd5b5061095a60048036038101906109559190613632565b611b03565b005b34801561096857600080fd5b50610971611b15565b60405161097e9190613736565b60405180910390f35b34801561099357600080fd5b506109ae60048036038101906109a991906139e6565b611b1b565b005b3480156109bc57600080fd5b506109d760048036038101906109d29190613b93565b611b3d565b6040516109e491906134cd565b60405180910390f35b3480156109f957600080fd5b50610a146004803603810190610a0f9190613c33565b611bd1565b005b348015610a2257600080fd5b50610a3d6004803603810190610a3891906139e6565b611bfd565b005b348015610a4b57600080fd5b50610a666004803603810190610a619190613751565b611c1f565b005b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610adb5750610ada82611ca3565b5b9050919050565b610aea611d85565b80601260006101000a81548160ff02191690831515021790555050565b606060008054610b1690613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4290613caf565b8015610b8f5780601f10610b6457610100808354040283529160200191610b8f565b820191906000526020600020905b815481529060010190602001808311610b7257829003601f168201915b5050505050905090565b6000610ba482611e03565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600d8054610bec90613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1890613caf565b8015610c655780601f10610c3a57610100808354040283529160200191610c65565b820191906000526020600020905b815481529060010190602001808311610c4857829003601f168201915b505050505081565b6000610c78826111a9565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610ce9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce090613d53565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610d08611e4e565b73ffffffffffffffffffffffffffffffffffffffff161480610d375750610d3681610d31611e4e565b611b3d565b5b610d76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6d90613de5565b60405180910390fd5b610d808383611e56565b505050565b600e5481565b6000600880549050905090565b60146020528060005260406000206000915090505481565b60105481565b610dc7610dc1611e4e565b82611f0f565b610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90613e77565b60405180910390fd5b610e11838383611fa4565b505050565b6000610e21836112be565b8210610e62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5990613f09565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b600080600090505b601380549050811015610f5f578273ffffffffffffffffffffffffffffffffffffffff1660138281548110610efb57610efa613f29565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610f4c576001915050610f65565b8080610f5790613f87565b915050610ec3565b50600090505b919050565b610f72611d85565b80601260026101000a81548160ff02191690831515021790555050565b610f97611d85565b60003373ffffffffffffffffffffffffffffffffffffffff1647604051610fbd90614001565b60006040518083038185875af1925050503d8060008114610ffa576040519150601f19603f3d011682016040523d82523d6000602084013e610fff565b606091505b505090508061100d57600080fd5b50565b61102b83838360405180602001604052806000815250611875565b505050565b6060600061103d836112be565b905060008167ffffffffffffffff81111561105b5761105a6138bb565b5b6040519080825280602002602001820160405280156110895781602001602082028036833780820191505090505b50905060005b828110156110d3576110a18582610e16565b8282815181106110b4576110b3613f29565b5b60200260200101818152505080806110cb90613f87565b91505061108f565b508092505050919050565b6110e6611d85565b80600e8190555050565b60006110fa610d8b565b821061113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113290614088565b60405180910390fd5b6008828154811061114f5761114e613f29565b5b90600052602060002001549050919050565b601260019054906101000a900460ff1681565b61117c611d85565b80600b90805190602001906111929291906132b5565b5050565b601260009054906101000a900460ff1681565b6000806111b58361229e565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121e906140f4565b60405180910390fd5b80915050919050565b600b805461123d90613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461126990613caf565b80156112b65780601f1061128b576101008083540402835291602001916112b6565b820191906000526020600020905b81548152906001019060200180831161129957829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561132f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132690614186565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61137e611d85565b61138860006122db565b565b611392611d85565b8060108190555050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180546113d590613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461140190613caf565b801561144e5780601f106114235761010080835404028352916020019161144e565b820191906000526020600020905b81548152906001019060200180831161143157829003601f168201915b5050505050905090565b601260029054906101000a900460ff1681565b600a60149054906101000a900460ff16156114bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114b2906141f2565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550601260009054906101000a900460ff1615611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061425e565b60405180910390fd5b6000611530610d8b565b905060008211611575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156c906142ca565b60405180910390fd5b6010548211156115ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b19061435c565b60405180910390fd5b600f5482826115c9919061437c565b111561160a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116019061441e565b60405180910390fd5b61161261139c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461178f5760011515601260029054906101000a900460ff161515141561173e5761166933610ebb565b6116a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169f9061448a565b60405180910390fd5b6000601460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060115483826116fb919061437c565b111561173c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611733906144f6565b60405180910390fd5b505b81600e5461174c9190614516565b34101561178e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611785906145bc565b60405180910390fd5b5b6000600190505b82811161181a57601460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906117ed90613f87565b9190505550611807338284611802919061437c565b6123a1565b808061181290613f87565b915050611796565b50506000600a60146101000a81548160ff02191690831515021790555050565b61184c611845611e4e565b83836123bf565b5050565b611858611d85565b6001601260016101000a81548160ff021916908315150217905550565b611886611880611e4e565b83611f0f565b6118c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bc90613e77565b60405180910390fd5b6118d18484848461252c565b50505050565b601381815481106118e757600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b600c805461192990613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461195590613caf565b80156119a25780601f10611977576101008083540402835291602001916119a2565b820191906000526020600020905b81548152906001019060200180831161198557829003601f168201915b505050505081565b60606119b582612588565b6119f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119eb9061464e565b60405180910390fd5b60001515601260019054906101000a900460ff1615151415611aa257600d8054611a1d90613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054611a4990613caf565b8015611a965780601f10611a6b57610100808354040283529160200191611a96565b820191906000526020600020905b815481529060010190602001808311611a7957829003601f168201915b50505050509050611afe565b6000611aac6125c9565b90506000815111611acc5760405180602001604052806000815250611afa565b80611ad68461265b565b600c604051602001611aea9392919061473e565b6040516020818303038152906040525b9150505b919050565b611b0b611d85565b8060118190555050565b600f5481565b611b23611d85565b80600c9080519060200190611b399291906132b5565b5050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611bd9611d85565b60136000611be7919061333b565b818160139190611bf892919061335c565b505050565b611c05611d85565b80600d9080519060200190611c1b9291906132b5565b5050565b611c27611d85565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8e906147e1565b60405180910390fd5b611ca0816122db565b50565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d6e57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d7e5750611d7d82612733565b5b9050919050565b611d8d611e4e565b73ffffffffffffffffffffffffffffffffffffffff16611dab61139c565b73ffffffffffffffffffffffffffffffffffffffff1614611e01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df89061484d565b60405180910390fd5b565b611e0c81612588565b611e4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e42906140f4565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611ec9836111a9565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611f1b836111a9565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611f5d5750611f5c8185611b3d565b5b80611f9b57508373ffffffffffffffffffffffffffffffffffffffff16611f8384610b99565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611fc4826111a9565b73ffffffffffffffffffffffffffffffffffffffff161461201a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612011906148df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561208a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208190614971565b60405180910390fd5b612097838383600161279d565b8273ffffffffffffffffffffffffffffffffffffffff166120b7826111a9565b73ffffffffffffffffffffffffffffffffffffffff161461210d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612104906148df565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461229983838360016128fd565b505050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6123bb828260405180602001604052806000815250612903565b5050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561242e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612425906149dd565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161251f91906134cd565b60405180910390a3505050565b612537848484611fa4565b6125438484848461295e565b612582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257990614a6f565b60405180910390fd5b50505050565b60008073ffffffffffffffffffffffffffffffffffffffff166125aa8361229e565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6060600b80546125d890613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461260490613caf565b80156126515780601f1061262657610100808354040283529160200191612651565b820191906000526020600020905b81548152906001019060200180831161263457829003601f168201915b5050505050905090565b60606000600161266a84612af5565b01905060008167ffffffffffffffff811115612689576126886138bb565b5b6040519080825280601f01601f1916602001820160405280156126bb5781602001600182028036833780820191505090505b509050600082602001820190505b600115612728578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161271257612711614a8f565b5b049450600085141561272357612728565b6126c9565b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6127a984848484612c48565b60018111156127ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e490614b30565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156128355761283081612d6e565b612874565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612873576128728582612db7565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156128b7576128b281612f24565b6128f6565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146128f5576128f48482612ff5565b5b5b5050505050565b50505050565b61290d8383613074565b61291a600084848461295e565b612959576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295090614a6f565b60405180910390fd5b505050565b600061297f8473ffffffffffffffffffffffffffffffffffffffff16613292565b15612ae8578373ffffffffffffffffffffffffffffffffffffffff1663150b7a026129a8611e4e565b8786866040518563ffffffff1660e01b81526004016129ca9493929190614ba5565b602060405180830381600087803b1580156129e457600080fd5b505af1925050508015612a1557506040513d601f19601f82011682018060405250810190612a129190614c06565b60015b612a98573d8060008114612a45576040519150601f19603f3d011682016040523d82523d6000602084013e612a4a565b606091505b50600081511415612a90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a8790614a6f565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612aed565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612b53577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612b4957612b48614a8f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612b90576d04ee2d6d415b85acef81000000008381612b8657612b85614a8f565b5b0492506020810190505b662386f26fc100008310612bbf57662386f26fc100008381612bb557612bb4614a8f565b5b0492506010810190505b6305f5e1008310612be8576305f5e1008381612bde57612bdd614a8f565b5b0492506008810190505b6127108310612c0d576127108381612c0357612c02614a8f565b5b0492506004810190505b60648310612c305760648381612c2657612c25614a8f565b5b0492506002810190505b600a8310612c3f576001810190505b80915050919050565b6001811115612d6857600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612cdc5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612cd49190614c33565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612d675780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d5f919061437c565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612dc4846112be565b612dce9190614c33565b9050600060076000848152602001908152602001600020549050818114612eb3576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050612f389190614c33565b9050600060096000848152602001908152602001600020549050600060088381548110612f6857612f67613f29565b5b906000526020600020015490508060088381548110612f8a57612f89613f29565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480612fd957612fd8614c67565b5b6001900381819060005260206000200160009055905550505050565b6000613000836112be565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156130e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130db90614ce2565b60405180910390fd5b6130ed81612588565b1561312d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161312490614d4e565b60405180910390fd5b61313b60008383600161279d565b61314481612588565b15613184576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161317b90614d4e565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461328e6000838360016128fd565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b8280546132c190613caf565b90600052602060002090601f0160209004810192826132e3576000855561332a565b82601f106132fc57805160ff191683800117855561332a565b8280016001018555821561332a579182015b8281111561332957825182559160200191906001019061330e565b5b50905061333791906133fc565b5090565b508054600082559060005260206000209081019061335991906133fc565b50565b8280548282559060005260206000209081019282156133eb579160200282015b828111156133ea57823573ffffffffffffffffffffffffffffffffffffffff168260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061337c565b5b5090506133f891906133fc565b5090565b5b808211156134155760008160009055506001016133fd565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6134628161342d565b811461346d57600080fd5b50565b60008135905061347f81613459565b92915050565b60006020828403121561349b5761349a613423565b5b60006134a984828501613470565b91505092915050565b60008115159050919050565b6134c7816134b2565b82525050565b60006020820190506134e260008301846134be565b92915050565b6134f1816134b2565b81146134fc57600080fd5b50565b60008135905061350e816134e8565b92915050565b60006020828403121561352a57613529613423565b5b6000613538848285016134ff565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561357b578082015181840152602081019050613560565b8381111561358a576000848401525b50505050565b6000601f19601f8301169050919050565b60006135ac82613541565b6135b6818561354c565b93506135c681856020860161355d565b6135cf81613590565b840191505092915050565b600060208201905081810360008301526135f481846135a1565b905092915050565b6000819050919050565b61360f816135fc565b811461361a57600080fd5b50565b60008135905061362c81613606565b92915050565b60006020828403121561364857613647613423565b5b60006136568482850161361d565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061368a8261365f565b9050919050565b61369a8161367f565b82525050565b60006020820190506136b56000830184613691565b92915050565b6136c48161367f565b81146136cf57600080fd5b50565b6000813590506136e1816136bb565b92915050565b600080604083850312156136fe576136fd613423565b5b600061370c858286016136d2565b925050602061371d8582860161361d565b9150509250929050565b613730816135fc565b82525050565b600060208201905061374b6000830184613727565b92915050565b60006020828403121561376757613766613423565b5b6000613775848285016136d2565b91505092915050565b60008060006060848603121561379757613796613423565b5b60006137a5868287016136d2565b93505060206137b6868287016136d2565b92505060406137c78682870161361d565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613806816135fc565b82525050565b600061381883836137fd565b60208301905092915050565b6000602082019050919050565b600061383c826137d1565b61384681856137dc565b9350613851836137ed565b8060005b83811015613882578151613869888261380c565b975061387483613824565b925050600181019050613855565b5085935050505092915050565b600060208201905081810360008301526138a98184613831565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6138f382613590565b810181811067ffffffffffffffff82111715613912576139116138bb565b5b80604052505050565b6000613925613419565b905061393182826138ea565b919050565b600067ffffffffffffffff821115613951576139506138bb565b5b61395a82613590565b9050602081019050919050565b82818337600083830152505050565b600061398961398484613936565b61391b565b9050828152602081018484840111156139a5576139a46138b6565b5b6139b0848285613967565b509392505050565b600082601f8301126139cd576139cc6138b1565b5b81356139dd848260208601613976565b91505092915050565b6000602082840312156139fc576139fb613423565b5b600082013567ffffffffffffffff811115613a1a57613a19613428565b5b613a26848285016139b8565b91505092915050565b60008060408385031215613a4657613a45613423565b5b6000613a54858286016136d2565b9250506020613a65858286016134ff565b9150509250929050565b600067ffffffffffffffff821115613a8a57613a896138bb565b5b613a9382613590565b9050602081019050919050565b6000613ab3613aae84613a6f565b61391b565b905082815260208101848484011115613acf57613ace6138b6565b5b613ada848285613967565b509392505050565b600082601f830112613af757613af66138b1565b5b8135613b07848260208601613aa0565b91505092915050565b60008060008060808587031215613b2a57613b29613423565b5b6000613b38878288016136d2565b9450506020613b49878288016136d2565b9350506040613b5a8782880161361d565b925050606085013567ffffffffffffffff811115613b7b57613b7a613428565b5b613b8787828801613ae2565b91505092959194509250565b60008060408385031215613baa57613ba9613423565b5b6000613bb8858286016136d2565b9250506020613bc9858286016136d2565b9150509250929050565b600080fd5b600080fd5b60008083601f840112613bf357613bf26138b1565b5b8235905067ffffffffffffffff811115613c1057613c0f613bd3565b5b602083019150836020820283011115613c2c57613c2b613bd8565b5b9250929050565b60008060208385031215613c4a57613c49613423565b5b600083013567ffffffffffffffff811115613c6857613c67613428565b5b613c7485828601613bdd565b92509250509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613cc757607f821691505b60208210811415613cdb57613cda613c80565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d3d60218361354c565b9150613d4882613ce1565b604082019050919050565b60006020820190508181036000830152613d6c81613d30565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613dcf603d8361354c565b9150613dda82613d73565b604082019050919050565b60006020820190508181036000830152613dfe81613dc2565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613e61602d8361354c565b9150613e6c82613e05565b604082019050919050565b60006020820190508181036000830152613e9081613e54565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000613ef3602b8361354c565b9150613efe82613e97565b604082019050919050565b60006020820190508181036000830152613f2281613ee6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613f92826135fc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613fc557613fc4613f58565b5b600182019050919050565b600081905092915050565b50565b6000613feb600083613fd0565b9150613ff682613fdb565b600082019050919050565b600061400c82613fde565b9150819050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614072602c8361354c565b915061407d82614016565b604082019050919050565b600060208201905081810360008301526140a181614065565b9050919050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b60006140de60188361354c565b91506140e9826140a8565b602082019050919050565b6000602082019050818103600083015261410d816140d1565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061417060298361354c565b915061417b82614114565b604082019050919050565b6000602082019050818103600083015261419f81614163565b9050919050565b7f4e4f204e4f210000000000000000000000000000000000000000000000000000600082015250565b60006141dc60068361354c565b91506141e7826141a6565b602082019050919050565b6000602082019050818103600083015261420b816141cf565b9050919050565b7f74686520636f6e74726163742069732070617573656400000000000000000000600082015250565b600061424860168361354c565b915061425382614212565b602082019050919050565b600060208201905081810360008301526142778161423b565b9050919050565b7f6e65656420746f206d696e74206174206c656173742031204e46540000000000600082015250565b60006142b4601b8361354c565b91506142bf8261427e565b602082019050919050565b600060208201905081810360008301526142e3816142a7565b9050919050565b7f6d6178206d696e7420616d6f756e74207065722073657373696f6e206578636560008201527f6564656400000000000000000000000000000000000000000000000000000000602082015250565b600061434660248361354c565b9150614351826142ea565b604082019050919050565b6000602082019050818103600083015261437581614339565b9050919050565b6000614387826135fc565b9150614392836135fc565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156143c7576143c6613f58565b5b828201905092915050565b7f6d6178204e4654206c696d697420657863656564656400000000000000000000600082015250565b600061440860168361354c565b9150614413826143d2565b602082019050919050565b60006020820190508181036000830152614437816143fb565b9050919050565b7f75736572206973206e6f742077686974656c6973746564000000000000000000600082015250565b600061447460178361354c565b915061447f8261443e565b602082019050919050565b600060208201905081810360008301526144a381614467565b9050919050565b7f6d6178204e465420706572206164647265737320657863656564656400000000600082015250565b60006144e0601c8361354c565b91506144eb826144aa565b602082019050919050565b6000602082019050818103600083015261450f816144d3565b9050919050565b6000614521826135fc565b915061452c836135fc565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561456557614564613f58565b5b828202905092915050565b7f696e73756666696369656e742066756e64730000000000000000000000000000600082015250565b60006145a660128361354c565b91506145b182614570565b602082019050919050565b600060208201905081810360008301526145d581614599565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614638602f8361354c565b9150614643826145dc565b604082019050919050565b600060208201905081810360008301526146678161462b565b9050919050565b600081905092915050565b600061468482613541565b61468e818561466e565b935061469e81856020860161355d565b80840191505092915050565b60008190508160005260206000209050919050565b600081546146cc81613caf565b6146d6818661466e565b945060018216600081146146f1576001811461470257614735565b60ff19831686528186019350614735565b61470b856146aa565b60005b8381101561472d5781548189015260018201915060208101905061470e565b838801955050505b50505092915050565b600061474a8286614679565b91506147568285614679565b915061476282846146bf565b9150819050949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006147cb60268361354c565b91506147d68261476f565b604082019050919050565b600060208201905081810360008301526147fa816147be565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061483760208361354c565b915061484282614801565b602082019050919050565b600060208201905081810360008301526148668161482a565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148c960258361354c565b91506148d48261486d565b604082019050919050565b600060208201905081810360008301526148f8816148bc565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061495b60248361354c565b9150614966826148ff565b604082019050919050565b6000602082019050818103600083015261498a8161494e565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006149c760198361354c565b91506149d282614991565b602082019050919050565b600060208201905081810360008301526149f6816149ba565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614a5960328361354c565b9150614a64826149fd565b604082019050919050565b60006020820190508181036000830152614a8881614a4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000614b1a60358361354c565b9150614b2582614abe565b604082019050919050565b60006020820190508181036000830152614b4981614b0d565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614b7782614b50565b614b818185614b5b565b9350614b9181856020860161355d565b614b9a81613590565b840191505092915050565b6000608082019050614bba6000830187613691565b614bc76020830186613691565b614bd46040830185613727565b8181036060830152614be68184614b6c565b905095945050505050565b600081519050614c0081613459565b92915050565b600060208284031215614c1c57614c1b613423565b5b6000614c2a84828501614bf1565b91505092915050565b6000614c3e826135fc565b9150614c49836135fc565b925082821015614c5c57614c5b613f58565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614ccc60208361354c565b9150614cd782614c96565b602082019050919050565b60006020820190508181036000830152614cfb81614cbf565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614d38601c8361354c565b9150614d4382614d02565b602082019050919050565b60006020820190508181036000830152614d6781614d2b565b905091905056fea2646970667358221220bacafa65a5bc103c03eae59bb79c278cdd6658e5610ee27b74951c8fc4dd360e64736f6c63430008090033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000d536f7365696b6920446961727900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000353444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043697066733a2f2f626166796265696870626f6d667077626672643776697576747a3462786a61623637726935687371697a77636d6f6833706d3761626c6e74616d652f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e697066733a2f2f626166796265696169687576616536376663696f6a6a6735367876727266616e797065686869736c3365726c626f6a766877747a796469637965712f68696464656e2e6a736f6e000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106102725760003560e01c80636352211e1161014f578063b88d4fde116100c1578063d5abeb011161007a578063d5abeb011461095c578063da3ef23f14610987578063e985e9c5146109b0578063edec5f27146109ed578063f2c4ce1e14610a16578063f2fde38b14610a3f57610272565b8063b88d4fde1461083a578063ba4e5c4914610863578063ba7d2c76146108a0578063c6682862146108cb578063c87b56dd146108f6578063d0eb26b01461093357610272565b80638da5cb5b116101135780638da5cb5b1461075d57806395d89b41146107885780639c70b512146107b3578063a0712d68146107de578063a22cb465146107fa578063a475b5dd1461082357610272565b80636352211e146106785780636c0360eb146106b557806370a08231146106e0578063715018a61461071d5780637f00c7a61461073457610272565b80632f745c59116101e8578063438b6300116101ac578063438b63001461055657806344a0d68a146105935780634f6ccce7146105bc57806351830227146105f957806355f804b3146106245780635c975abb1461064d57610272565b80632f745c59146104805780633af32abf146104bd5780633c952764146104fa5780633ccfd60b1461052357806342842e0e1461052d57610272565b8063095ea7b31161023a578063095ea7b31461037057806313faede61461039957806318160ddd146103c457806318cae269146103ef578063239c70ae1461042c57806323b872dd1461045757610272565b806301ffc9a71461027757806302329a29146102b457806306fdde03146102dd578063081812fc14610308578063081c8c4414610345575b600080fd5b34801561028357600080fd5b5061029e60048036038101906102999190613485565b610a68565b6040516102ab91906134cd565b60405180910390f35b3480156102c057600080fd5b506102db60048036038101906102d69190613514565b610ae2565b005b3480156102e957600080fd5b506102f2610b07565b6040516102ff91906135da565b60405180910390f35b34801561031457600080fd5b5061032f600480360381019061032a9190613632565b610b99565b60405161033c91906136a0565b60405180910390f35b34801561035157600080fd5b5061035a610bdf565b60405161036791906135da565b60405180910390f35b34801561037c57600080fd5b50610397600480360381019061039291906136e7565b610c6d565b005b3480156103a557600080fd5b506103ae610d85565b6040516103bb9190613736565b60405180910390f35b3480156103d057600080fd5b506103d9610d8b565b6040516103e69190613736565b60405180910390f35b3480156103fb57600080fd5b5061041660048036038101906104119190613751565b610d98565b6040516104239190613736565b60405180910390f35b34801561043857600080fd5b50610441610db0565b60405161044e9190613736565b60405180910390f35b34801561046357600080fd5b5061047e6004803603810190610479919061377e565b610db6565b005b34801561048c57600080fd5b506104a760048036038101906104a291906136e7565b610e16565b6040516104b49190613736565b60405180910390f35b3480156104c957600080fd5b506104e460048036038101906104df9190613751565b610ebb565b6040516104f191906134cd565b60405180910390f35b34801561050657600080fd5b50610521600480360381019061051c9190613514565b610f6a565b005b61052b610f8f565b005b34801561053957600080fd5b50610554600480360381019061054f919061377e565b611010565b005b34801561056257600080fd5b5061057d60048036038101906105789190613751565b611030565b60405161058a919061388f565b60405180910390f35b34801561059f57600080fd5b506105ba60048036038101906105b59190613632565b6110de565b005b3480156105c857600080fd5b506105e360048036038101906105de9190613632565b6110f0565b6040516105f09190613736565b60405180910390f35b34801561060557600080fd5b5061060e611161565b60405161061b91906134cd565b60405180910390f35b34801561063057600080fd5b5061064b600480360381019061064691906139e6565b611174565b005b34801561065957600080fd5b50610662611196565b60405161066f91906134cd565b60405180910390f35b34801561068457600080fd5b5061069f600480360381019061069a9190613632565b6111a9565b6040516106ac91906136a0565b60405180910390f35b3480156106c157600080fd5b506106ca611230565b6040516106d791906135da565b60405180910390f35b3480156106ec57600080fd5b5061070760048036038101906107029190613751565b6112be565b6040516107149190613736565b60405180910390f35b34801561072957600080fd5b50610732611376565b005b34801561074057600080fd5b5061075b60048036038101906107569190613632565b61138a565b005b34801561076957600080fd5b5061077261139c565b60405161077f91906136a0565b60405180910390f35b34801561079457600080fd5b5061079d6113c6565b6040516107aa91906135da565b60405180910390f35b3480156107bf57600080fd5b506107c8611458565b6040516107d591906134cd565b60405180910390f35b6107f860048036038101906107f39190613632565b61146b565b005b34801561080657600080fd5b50610821600480360381019061081c9190613a2f565b61183a565b005b34801561082f57600080fd5b50610838611850565b005b34801561084657600080fd5b50610861600480360381019061085c9190613b10565b611875565b005b34801561086f57600080fd5b5061088a60048036038101906108859190613632565b6118d7565b60405161089791906136a0565b60405180910390f35b3480156108ac57600080fd5b506108b5611916565b6040516108c29190613736565b60405180910390f35b3480156108d757600080fd5b506108e061191c565b6040516108ed91906135da565b60405180910390f35b34801561090257600080fd5b5061091d60048036038101906109189190613632565b6119aa565b60405161092a91906135da565b60405180910390f35b34801561093f57600080fd5b5061095a60048036038101906109559190613632565b611b03565b005b34801561096857600080fd5b50610971611b15565b60405161097e9190613736565b60405180910390f35b34801561099357600080fd5b506109ae60048036038101906109a991906139e6565b611b1b565b005b3480156109bc57600080fd5b506109d760048036038101906109d29190613b93565b611b3d565b6040516109e491906134cd565b60405180910390f35b3480156109f957600080fd5b50610a146004803603810190610a0f9190613c33565b611bd1565b005b348015610a2257600080fd5b50610a3d6004803603810190610a3891906139e6565b611bfd565b005b348015610a4b57600080fd5b50610a666004803603810190610a619190613751565b611c1f565b005b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610adb5750610ada82611ca3565b5b9050919050565b610aea611d85565b80601260006101000a81548160ff02191690831515021790555050565b606060008054610b1690613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4290613caf565b8015610b8f5780601f10610b6457610100808354040283529160200191610b8f565b820191906000526020600020905b815481529060010190602001808311610b7257829003601f168201915b5050505050905090565b6000610ba482611e03565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600d8054610bec90613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1890613caf565b8015610c655780601f10610c3a57610100808354040283529160200191610c65565b820191906000526020600020905b815481529060010190602001808311610c4857829003601f168201915b505050505081565b6000610c78826111a9565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610ce9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce090613d53565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610d08611e4e565b73ffffffffffffffffffffffffffffffffffffffff161480610d375750610d3681610d31611e4e565b611b3d565b5b610d76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6d90613de5565b60405180910390fd5b610d808383611e56565b505050565b600e5481565b6000600880549050905090565b60146020528060005260406000206000915090505481565b60105481565b610dc7610dc1611e4e565b82611f0f565b610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90613e77565b60405180910390fd5b610e11838383611fa4565b505050565b6000610e21836112be565b8210610e62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5990613f09565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b600080600090505b601380549050811015610f5f578273ffffffffffffffffffffffffffffffffffffffff1660138281548110610efb57610efa613f29565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610f4c576001915050610f65565b8080610f5790613f87565b915050610ec3565b50600090505b919050565b610f72611d85565b80601260026101000a81548160ff02191690831515021790555050565b610f97611d85565b60003373ffffffffffffffffffffffffffffffffffffffff1647604051610fbd90614001565b60006040518083038185875af1925050503d8060008114610ffa576040519150601f19603f3d011682016040523d82523d6000602084013e610fff565b606091505b505090508061100d57600080fd5b50565b61102b83838360405180602001604052806000815250611875565b505050565b6060600061103d836112be565b905060008167ffffffffffffffff81111561105b5761105a6138bb565b5b6040519080825280602002602001820160405280156110895781602001602082028036833780820191505090505b50905060005b828110156110d3576110a18582610e16565b8282815181106110b4576110b3613f29565b5b60200260200101818152505080806110cb90613f87565b91505061108f565b508092505050919050565b6110e6611d85565b80600e8190555050565b60006110fa610d8b565b821061113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113290614088565b60405180910390fd5b6008828154811061114f5761114e613f29565b5b90600052602060002001549050919050565b601260019054906101000a900460ff1681565b61117c611d85565b80600b90805190602001906111929291906132b5565b5050565b601260009054906101000a900460ff1681565b6000806111b58361229e565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121e906140f4565b60405180910390fd5b80915050919050565b600b805461123d90613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461126990613caf565b80156112b65780601f1061128b576101008083540402835291602001916112b6565b820191906000526020600020905b81548152906001019060200180831161129957829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561132f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132690614186565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61137e611d85565b61138860006122db565b565b611392611d85565b8060108190555050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600180546113d590613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461140190613caf565b801561144e5780601f106114235761010080835404028352916020019161144e565b820191906000526020600020905b81548152906001019060200180831161143157829003601f168201915b5050505050905090565b601260029054906101000a900460ff1681565b600a60149054906101000a900460ff16156114bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114b2906141f2565b60405180910390fd5b6001600a60146101000a81548160ff021916908315150217905550601260009054906101000a900460ff1615611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061425e565b60405180910390fd5b6000611530610d8b565b905060008211611575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156c906142ca565b60405180910390fd5b6010548211156115ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b19061435c565b60405180910390fd5b600f5482826115c9919061437c565b111561160a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116019061441e565b60405180910390fd5b61161261139c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461178f5760011515601260029054906101000a900460ff161515141561173e5761166933610ebb565b6116a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169f9061448a565b60405180910390fd5b6000601460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060115483826116fb919061437c565b111561173c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611733906144f6565b60405180910390fd5b505b81600e5461174c9190614516565b34101561178e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611785906145bc565b60405180910390fd5b5b6000600190505b82811161181a57601460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906117ed90613f87565b9190505550611807338284611802919061437c565b6123a1565b808061181290613f87565b915050611796565b50506000600a60146101000a81548160ff02191690831515021790555050565b61184c611845611e4e565b83836123bf565b5050565b611858611d85565b6001601260016101000a81548160ff021916908315150217905550565b611886611880611e4e565b83611f0f565b6118c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bc90613e77565b60405180910390fd5b6118d18484848461252c565b50505050565b601381815481106118e757600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b600c805461192990613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461195590613caf565b80156119a25780601f10611977576101008083540402835291602001916119a2565b820191906000526020600020905b81548152906001019060200180831161198557829003601f168201915b505050505081565b60606119b582612588565b6119f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119eb9061464e565b60405180910390fd5b60001515601260019054906101000a900460ff1615151415611aa257600d8054611a1d90613caf565b80601f0160208091040260200160405190810160405280929190818152602001828054611a4990613caf565b8015611a965780601f10611a6b57610100808354040283529160200191611a96565b820191906000526020600020905b815481529060010190602001808311611a7957829003601f168201915b50505050509050611afe565b6000611aac6125c9565b90506000815111611acc5760405180602001604052806000815250611afa565b80611ad68461265b565b600c604051602001611aea9392919061473e565b6040516020818303038152906040525b9150505b919050565b611b0b611d85565b8060118190555050565b600f5481565b611b23611d85565b80600c9080519060200190611b399291906132b5565b5050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611bd9611d85565b60136000611be7919061333b565b818160139190611bf892919061335c565b505050565b611c05611d85565b80600d9080519060200190611c1b9291906132b5565b5050565b611c27611d85565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8e906147e1565b60405180910390fd5b611ca0816122db565b50565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d6e57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d7e5750611d7d82612733565b5b9050919050565b611d8d611e4e565b73ffffffffffffffffffffffffffffffffffffffff16611dab61139c565b73ffffffffffffffffffffffffffffffffffffffff1614611e01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df89061484d565b60405180910390fd5b565b611e0c81612588565b611e4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e42906140f4565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611ec9836111a9565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611f1b836111a9565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611f5d5750611f5c8185611b3d565b5b80611f9b57508373ffffffffffffffffffffffffffffffffffffffff16611f8384610b99565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611fc4826111a9565b73ffffffffffffffffffffffffffffffffffffffff161461201a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612011906148df565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561208a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208190614971565b60405180910390fd5b612097838383600161279d565b8273ffffffffffffffffffffffffffffffffffffffff166120b7826111a9565b73ffffffffffffffffffffffffffffffffffffffff161461210d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612104906148df565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461229983838360016128fd565b505050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6123bb828260405180602001604052806000815250612903565b5050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561242e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612425906149dd565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161251f91906134cd565b60405180910390a3505050565b612537848484611fa4565b6125438484848461295e565b612582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257990614a6f565b60405180910390fd5b50505050565b60008073ffffffffffffffffffffffffffffffffffffffff166125aa8361229e565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6060600b80546125d890613caf565b80601f016020809104026020016040519081016040528092919081815260200182805461260490613caf565b80156126515780601f1061262657610100808354040283529160200191612651565b820191906000526020600020905b81548152906001019060200180831161263457829003601f168201915b5050505050905090565b60606000600161266a84612af5565b01905060008167ffffffffffffffff811115612689576126886138bb565b5b6040519080825280601f01601f1916602001820160405280156126bb5781602001600182028036833780820191505090505b509050600082602001820190505b600115612728578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161271257612711614a8f565b5b049450600085141561272357612728565b6126c9565b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6127a984848484612c48565b60018111156127ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e490614b30565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156128355761283081612d6e565b612874565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612873576128728582612db7565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156128b7576128b281612f24565b6128f6565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146128f5576128f48482612ff5565b5b5b5050505050565b50505050565b61290d8383613074565b61291a600084848461295e565b612959576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295090614a6f565b60405180910390fd5b505050565b600061297f8473ffffffffffffffffffffffffffffffffffffffff16613292565b15612ae8578373ffffffffffffffffffffffffffffffffffffffff1663150b7a026129a8611e4e565b8786866040518563ffffffff1660e01b81526004016129ca9493929190614ba5565b602060405180830381600087803b1580156129e457600080fd5b505af1925050508015612a1557506040513d601f19601f82011682018060405250810190612a129190614c06565b60015b612a98573d8060008114612a45576040519150601f19603f3d011682016040523d82523d6000602084013e612a4a565b606091505b50600081511415612a90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a8790614a6f565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612aed565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612b53577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612b4957612b48614a8f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612b90576d04ee2d6d415b85acef81000000008381612b8657612b85614a8f565b5b0492506020810190505b662386f26fc100008310612bbf57662386f26fc100008381612bb557612bb4614a8f565b5b0492506010810190505b6305f5e1008310612be8576305f5e1008381612bde57612bdd614a8f565b5b0492506008810190505b6127108310612c0d576127108381612c0357612c02614a8f565b5b0492506004810190505b60648310612c305760648381612c2657612c25614a8f565b5b0492506002810190505b600a8310612c3f576001810190505b80915050919050565b6001811115612d6857600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612cdc5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612cd49190614c33565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612d675780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d5f919061437c565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612dc4846112be565b612dce9190614c33565b9050600060076000848152602001908152602001600020549050818114612eb3576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050612f389190614c33565b9050600060096000848152602001908152602001600020549050600060088381548110612f6857612f67613f29565b5b906000526020600020015490508060088381548110612f8a57612f89613f29565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480612fd957612fd8614c67565b5b6001900381819060005260206000200160009055905550505050565b6000613000836112be565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156130e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130db90614ce2565b60405180910390fd5b6130ed81612588565b1561312d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161312490614d4e565b60405180910390fd5b61313b60008383600161279d565b61314481612588565b15613184576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161317b90614d4e565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461328e6000838360016128fd565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b8280546132c190613caf565b90600052602060002090601f0160209004810192826132e3576000855561332a565b82601f106132fc57805160ff191683800117855561332a565b8280016001018555821561332a579182015b8281111561332957825182559160200191906001019061330e565b5b50905061333791906133fc565b5090565b508054600082559060005260206000209081019061335991906133fc565b50565b8280548282559060005260206000209081019282156133eb579160200282015b828111156133ea57823573ffffffffffffffffffffffffffffffffffffffff168260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061337c565b5b5090506133f891906133fc565b5090565b5b808211156134155760008160009055506001016133fd565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6134628161342d565b811461346d57600080fd5b50565b60008135905061347f81613459565b92915050565b60006020828403121561349b5761349a613423565b5b60006134a984828501613470565b91505092915050565b60008115159050919050565b6134c7816134b2565b82525050565b60006020820190506134e260008301846134be565b92915050565b6134f1816134b2565b81146134fc57600080fd5b50565b60008135905061350e816134e8565b92915050565b60006020828403121561352a57613529613423565b5b6000613538848285016134ff565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561357b578082015181840152602081019050613560565b8381111561358a576000848401525b50505050565b6000601f19601f8301169050919050565b60006135ac82613541565b6135b6818561354c565b93506135c681856020860161355d565b6135cf81613590565b840191505092915050565b600060208201905081810360008301526135f481846135a1565b905092915050565b6000819050919050565b61360f816135fc565b811461361a57600080fd5b50565b60008135905061362c81613606565b92915050565b60006020828403121561364857613647613423565b5b60006136568482850161361d565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061368a8261365f565b9050919050565b61369a8161367f565b82525050565b60006020820190506136b56000830184613691565b92915050565b6136c48161367f565b81146136cf57600080fd5b50565b6000813590506136e1816136bb565b92915050565b600080604083850312156136fe576136fd613423565b5b600061370c858286016136d2565b925050602061371d8582860161361d565b9150509250929050565b613730816135fc565b82525050565b600060208201905061374b6000830184613727565b92915050565b60006020828403121561376757613766613423565b5b6000613775848285016136d2565b91505092915050565b60008060006060848603121561379757613796613423565b5b60006137a5868287016136d2565b93505060206137b6868287016136d2565b92505060406137c78682870161361d565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613806816135fc565b82525050565b600061381883836137fd565b60208301905092915050565b6000602082019050919050565b600061383c826137d1565b61384681856137dc565b9350613851836137ed565b8060005b83811015613882578151613869888261380c565b975061387483613824565b925050600181019050613855565b5085935050505092915050565b600060208201905081810360008301526138a98184613831565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6138f382613590565b810181811067ffffffffffffffff82111715613912576139116138bb565b5b80604052505050565b6000613925613419565b905061393182826138ea565b919050565b600067ffffffffffffffff821115613951576139506138bb565b5b61395a82613590565b9050602081019050919050565b82818337600083830152505050565b600061398961398484613936565b61391b565b9050828152602081018484840111156139a5576139a46138b6565b5b6139b0848285613967565b509392505050565b600082601f8301126139cd576139cc6138b1565b5b81356139dd848260208601613976565b91505092915050565b6000602082840312156139fc576139fb613423565b5b600082013567ffffffffffffffff811115613a1a57613a19613428565b5b613a26848285016139b8565b91505092915050565b60008060408385031215613a4657613a45613423565b5b6000613a54858286016136d2565b9250506020613a65858286016134ff565b9150509250929050565b600067ffffffffffffffff821115613a8a57613a896138bb565b5b613a9382613590565b9050602081019050919050565b6000613ab3613aae84613a6f565b61391b565b905082815260208101848484011115613acf57613ace6138b6565b5b613ada848285613967565b509392505050565b600082601f830112613af757613af66138b1565b5b8135613b07848260208601613aa0565b91505092915050565b60008060008060808587031215613b2a57613b29613423565b5b6000613b38878288016136d2565b9450506020613b49878288016136d2565b9350506040613b5a8782880161361d565b925050606085013567ffffffffffffffff811115613b7b57613b7a613428565b5b613b8787828801613ae2565b91505092959194509250565b60008060408385031215613baa57613ba9613423565b5b6000613bb8858286016136d2565b9250506020613bc9858286016136d2565b9150509250929050565b600080fd5b600080fd5b60008083601f840112613bf357613bf26138b1565b5b8235905067ffffffffffffffff811115613c1057613c0f613bd3565b5b602083019150836020820283011115613c2c57613c2b613bd8565b5b9250929050565b60008060208385031215613c4a57613c49613423565b5b600083013567ffffffffffffffff811115613c6857613c67613428565b5b613c7485828601613bdd565b92509250509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613cc757607f821691505b60208210811415613cdb57613cda613c80565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d3d60218361354c565b9150613d4882613ce1565b604082019050919050565b60006020820190508181036000830152613d6c81613d30565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613dcf603d8361354c565b9150613dda82613d73565b604082019050919050565b60006020820190508181036000830152613dfe81613dc2565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613e61602d8361354c565b9150613e6c82613e05565b604082019050919050565b60006020820190508181036000830152613e9081613e54565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000613ef3602b8361354c565b9150613efe82613e97565b604082019050919050565b60006020820190508181036000830152613f2281613ee6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613f92826135fc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613fc557613fc4613f58565b5b600182019050919050565b600081905092915050565b50565b6000613feb600083613fd0565b9150613ff682613fdb565b600082019050919050565b600061400c82613fde565b9150819050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614072602c8361354c565b915061407d82614016565b604082019050919050565b600060208201905081810360008301526140a181614065565b9050919050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b60006140de60188361354c565b91506140e9826140a8565b602082019050919050565b6000602082019050818103600083015261410d816140d1565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061417060298361354c565b915061417b82614114565b604082019050919050565b6000602082019050818103600083015261419f81614163565b9050919050565b7f4e4f204e4f210000000000000000000000000000000000000000000000000000600082015250565b60006141dc60068361354c565b91506141e7826141a6565b602082019050919050565b6000602082019050818103600083015261420b816141cf565b9050919050565b7f74686520636f6e74726163742069732070617573656400000000000000000000600082015250565b600061424860168361354c565b915061425382614212565b602082019050919050565b600060208201905081810360008301526142778161423b565b9050919050565b7f6e65656420746f206d696e74206174206c656173742031204e46540000000000600082015250565b60006142b4601b8361354c565b91506142bf8261427e565b602082019050919050565b600060208201905081810360008301526142e3816142a7565b9050919050565b7f6d6178206d696e7420616d6f756e74207065722073657373696f6e206578636560008201527f6564656400000000000000000000000000000000000000000000000000000000602082015250565b600061434660248361354c565b9150614351826142ea565b604082019050919050565b6000602082019050818103600083015261437581614339565b9050919050565b6000614387826135fc565b9150614392836135fc565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156143c7576143c6613f58565b5b828201905092915050565b7f6d6178204e4654206c696d697420657863656564656400000000000000000000600082015250565b600061440860168361354c565b9150614413826143d2565b602082019050919050565b60006020820190508181036000830152614437816143fb565b9050919050565b7f75736572206973206e6f742077686974656c6973746564000000000000000000600082015250565b600061447460178361354c565b915061447f8261443e565b602082019050919050565b600060208201905081810360008301526144a381614467565b9050919050565b7f6d6178204e465420706572206164647265737320657863656564656400000000600082015250565b60006144e0601c8361354c565b91506144eb826144aa565b602082019050919050565b6000602082019050818103600083015261450f816144d3565b9050919050565b6000614521826135fc565b915061452c836135fc565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561456557614564613f58565b5b828202905092915050565b7f696e73756666696369656e742066756e64730000000000000000000000000000600082015250565b60006145a660128361354c565b91506145b182614570565b602082019050919050565b600060208201905081810360008301526145d581614599565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614638602f8361354c565b9150614643826145dc565b604082019050919050565b600060208201905081810360008301526146678161462b565b9050919050565b600081905092915050565b600061468482613541565b61468e818561466e565b935061469e81856020860161355d565b80840191505092915050565b60008190508160005260206000209050919050565b600081546146cc81613caf565b6146d6818661466e565b945060018216600081146146f1576001811461470257614735565b60ff19831686528186019350614735565b61470b856146aa565b60005b8381101561472d5781548189015260018201915060208101905061470e565b838801955050505b50505092915050565b600061474a8286614679565b91506147568285614679565b915061476282846146bf565b9150819050949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006147cb60268361354c565b91506147d68261476f565b604082019050919050565b600060208201905081810360008301526147fa816147be565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061483760208361354c565b915061484282614801565b602082019050919050565b600060208201905081810360008301526148668161482a565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148c960258361354c565b91506148d48261486d565b604082019050919050565b600060208201905081810360008301526148f8816148bc565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061495b60248361354c565b9150614966826148ff565b604082019050919050565b6000602082019050818103600083015261498a8161494e565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006149c760198361354c565b91506149d282614991565b602082019050919050565b600060208201905081810360008301526149f6816149ba565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614a5960328361354c565b9150614a64826149fd565b604082019050919050565b60006020820190508181036000830152614a8881614a4c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000614b1a60358361354c565b9150614b2582614abe565b604082019050919050565b60006020820190508181036000830152614b4981614b0d565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614b7782614b50565b614b818185614b5b565b9350614b9181856020860161355d565b614b9a81613590565b840191505092915050565b6000608082019050614bba6000830187613691565b614bc76020830186613691565b614bd46040830185613727565b8181036060830152614be68184614b6c565b905095945050505050565b600081519050614c0081613459565b92915050565b600060208284031215614c1c57614c1b613423565b5b6000614c2a84828501614bf1565b91505092915050565b6000614c3e826135fc565b9150614c49836135fc565b925082821015614c5c57614c5b613f58565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614ccc60208361354c565b9150614cd782614c96565b602082019050919050565b60006020820190508181036000830152614cfb81614cbf565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614d38601c8361354c565b9150614d4382614d02565b602082019050919050565b60006020820190508181036000830152614d6781614d2b565b905091905056fea2646970667358221220bacafa65a5bc103c03eae59bb79c278cdd6658e5610ee27b74951c8fc4dd360e64736f6c63430008090033

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000d536f7365696b6920446961727900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000353444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043697066733a2f2f626166796265696870626f6d667077626672643776697576747a3462786a61623637726935687371697a77636d6f6833706d3761626c6e74616d652f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e697066733a2f2f626166796265696169687576616536376663696f6a6a6735367876727266616e797065686869736c3365726c626f6a766877747a796469637965712f68696464656e2e6a736f6e000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Soseiki Diary
Arg [1] : _symbol (string): SDC
Arg [2] : _initBaseURI (string): ipfs://bafybeihpbomfpwbfrd7viuvtz4bxjab67ri5hsqizwcmoh3pm7ablntame/
Arg [3] : _initNotRevealedUri (string): ipfs://bafybeiaihuvae67fciojjg56xvrrfanypehhisl3erlbojvhwtzydicyeq/hidden.json

-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [5] : 536f7365696b6920446961727900000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 5344430000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [9] : 697066733a2f2f626166796265696870626f6d66707762667264377669757674
Arg [10] : 7a3462786a61623637726935687371697a77636d6f6833706d3761626c6e7461
Arg [11] : 6d652f0000000000000000000000000000000000000000000000000000000000
Arg [12] : 000000000000000000000000000000000000000000000000000000000000004e
Arg [13] : 697066733a2f2f626166796265696169687576616536376663696f6a6a673536
Arg [14] : 7876727266616e797065686869736c3365726c626f6a766877747a7964696379
Arg [15] : 65712f68696464656e2e6a736f6e000000000000000000000000000000000000


Deployed Bytecode Sourcemap

68016:5098:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61749:300;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72561:79;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;44040:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;45649:221;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68341:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;45167:416;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68376:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62552:113;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68685:55;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68450:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;46481:372;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62133:343;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70306:274;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72648:101;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72919:192;;;:::i;:::-;;46924:185;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;70588:390;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;71932:86;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62742:320;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68565:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72156:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68533:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;43700:273;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68269:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;43344:294;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2780:103;;;;;;;;;;;;;:::i;:::-;;72026:122;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2132:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;44209:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68600:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;69182:1116;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;45942:187;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71737:69;;;;;;;;;;;;;:::i;:::-;;47180:359;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68641:37;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68489;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68297;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70986:725;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;71814:110;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;68412:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72268:151;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;46200:214;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72757:154;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72427:126;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3038:238;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;61749:300;61896:4;61953:35;61938:50;;;:11;:50;;;;:103;;;;62005:36;62029:11;62005:23;:36::i;:::-;61938:103;61918:123;;61749:300;;;:::o;72561:79::-;2018:13;:11;:13::i;:::-;72626:6:::1;72617;;:15;;;;;;;;;;;;;;;;;;72561:79:::0;:::o;44040:100::-;44094:13;44127:5;44120:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44040:100;:::o;45649:221::-;45770:7;45795:23;45810:7;45795:14;:23::i;:::-;45838:15;:24;45854:7;45838:24;;;;;;;;;;;;;;;;;;;;;45831:31;;45649:221;;;:::o;68341:28::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;45167:416::-;45248:13;45264:23;45279:7;45264:14;:23::i;:::-;45248:39;;45312:5;45306:11;;:2;:11;;;;45298:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;45406:5;45390:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;45415:37;45432:5;45439:12;:10;:12::i;:::-;45415:16;:37::i;:::-;45390:62;45368:173;;;;;;;;;;;;:::i;:::-;;;;;;;;;45554:21;45563:2;45567:7;45554:8;:21::i;:::-;45237:346;45167:416;;:::o;68376:29::-;;;;:::o;62552:113::-;62613:7;62640:10;:17;;;;62633:24;;62552:113;:::o;68685:55::-;;;;;;;;;;;;;;;;;:::o;68450:32::-;;;;:::o;46481:372::-;46690:41;46709:12;:10;:12::i;:::-;46723:7;46690:18;:41::i;:::-;46668:136;;;;;;;;;;;;:::i;:::-;;;;;;;;;46817:28;46827:4;46833:2;46837:7;46817:9;:28::i;:::-;46481:372;;;:::o;62133:343::-;62275:7;62330:23;62347:5;62330:16;:23::i;:::-;62322:5;:31;62300:124;;;;;;;;;;;;:::i;:::-;;;;;;;;;62442:12;:19;62455:5;62442:19;;;;;;;;;;;;;;;:26;62462:5;62442:26;;;;;;;;;;;;62435:33;;62133:343;;;;:::o;70306:274::-;70365:4;70387:9;70399:1;70387:13;;70382:168;70406:20;:27;;;;70402:1;:31;70382:168;;;70486:5;70459:32;;:20;70480:1;70459:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:32;;;70455:84;;;70519:4;70512:11;;;;;70455:84;70435:3;;;;;:::i;:::-;;;;70382:168;;;;70567:5;70560:12;;70306:274;;;;:::o;72648:101::-;2018:13;:11;:13::i;:::-;72735:6:::1;72717:15;;:24;;;;;;;;;;;;;;;;;;72648:101:::0;:::o;72919:192::-;2018:13;:11;:13::i;:::-;72976:12:::1;73002:10;72994:24;;73040:21;72994:82;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72975:101;;;73095:7;73087:16;;;::::0;::::1;;72964:147;72919:192::o:0;46924:185::-;47062:39;47079:4;47085:2;47089:7;47062:39;;;;;;;;;;;;:16;:39::i;:::-;46924:185;;;:::o;70588:390::-;70675:16;70709:23;70735:17;70745:6;70735:9;:17::i;:::-;70709:43;;70763:25;70805:15;70791:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70763:58;;70837:9;70832:113;70852:15;70848:1;:19;70832:113;;;70903:30;70923:6;70931:1;70903:19;:30::i;:::-;70889:8;70898:1;70889:11;;;;;;;;:::i;:::-;;;;;;;:44;;;;;70869:3;;;;;:::i;:::-;;;;70832:113;;;;70962:8;70955:15;;;;70588:390;;;:::o;71932:86::-;2018:13;:11;:13::i;:::-;72002:8:::1;71995:4;:15;;;;71932:86:::0;:::o;62742:320::-;62862:7;62917:30;:28;:30::i;:::-;62909:5;:38;62887:132;;;;;;;;;;;;:::i;:::-;;;;;;;;;63037:10;63048:5;63037:17;;;;;;;;:::i;:::-;;;;;;;;;;63030:24;;62742:320;;;:::o;68565:28::-;;;;;;;;;;;;;:::o;72156:104::-;2018:13;:11;:13::i;:::-;72241:11:::1;72231:7;:21;;;;;;;;;;;;:::i;:::-;;72156:104:::0;:::o;68533:25::-;;;;;;;;;;;;;:::o;43700:273::-;43817:7;43842:13;43858:17;43867:7;43858:8;:17::i;:::-;43842:33;;43911:1;43894:19;;:5;:19;;;;43886:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;43960:5;43953:12;;;43700:273;;;:::o;68269:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;43344:294::-;43461:7;43525:1;43508:19;;:5;:19;;;;43486:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;43614:9;:16;43624:5;43614:16;;;;;;;;;;;;;;;;43607:23;;43344:294;;;:::o;2780:103::-;2018:13;:11;:13::i;:::-;2845:30:::1;2872:1;2845:18;:30::i;:::-;2780:103::o:0;72026:122::-;2018:13;:11;:13::i;:::-;72123:17:::1;72107:13;:33;;;;72026:122:::0;:::o;2132:87::-;2178:7;2205:6;;;;;;;;;;;2198:13;;2132:87;:::o;44209:104::-;44265:13;44298:7;44291:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44209:104;:::o;68600:34::-;;;;;;;;;;;;;:::o;69182:1116::-;68141:6;;;;;;;;;;;68140:7;68132:26;;;;;;;;;;;;:::i;:::-;;;;;;;;;68178:4;68169:6;;:13;;;;;;;;;;;;;;;;;;69264:6:::1;;;;;;;;;;;69263:7;69255:42;;;;;;;;;;;;:::i;:::-;;;;;;;;;69308:14;69325:13;:11;:13::i;:::-;69308:30;;69371:1;69357:11;:15;69349:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;69452:13;;69437:11;:28;;69415:114;;;;;;;;;;;;:::i;:::-;;;;;;;;;69572:9;;69557:11;69548:6;:20;;;;:::i;:::-;:33;;69540:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;69639:7;:5;:7::i;:::-;69625:21;;:10;:21;;;69621:506;;69686:4;69667:23;;:15;;;;;;;;;;;:23;;;69663:376;;;69719:25;69733:10;69719:13;:25::i;:::-;69711:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;69791:24;69818:20;:32;69839:10;69818:32;;;;;;;;;;;;;;;;69791:59;;69933:18;;69918:11;69899:16;:30;;;;:::i;:::-;:52;;69869:154;;;;;;;;;;;;:::i;:::-;;;;;;;;;69692:347;69663:376;70081:11;70074:4;;:18;;;;:::i;:::-;70061:9;:31;;70053:62;;;;;;;;;;;;:::i;:::-;;;;;;;;;69621:506;70144:9;70156:1;70144:13;;70139:152;70164:11;70159:1;:16;70139:152;;70197:20;:32;70218:10;70197:32;;;;;;;;;;;;;;;;:34;;;;;;;;;:::i;:::-;;;;;;70246:33;70256:10;70277:1;70268:6;:10;;;;:::i;:::-;70246:9;:33::i;:::-;70177:3;;;;;:::i;:::-;;;;70139:152;;;;69244:1054;68214:5:::0;68205:6;;:14;;;;;;;;;;;;;;;;;;69182:1116;:::o;45942:187::-;46069:52;46088:12;:10;:12::i;:::-;46102:8;46112;46069:18;:52::i;:::-;45942:187;;:::o;71737:69::-;2018:13;:11;:13::i;:::-;71794:4:::1;71783:8;;:15;;;;;;;;;;;;;;;;;;71737:69::o:0;47180:359::-;47368:41;47387:12;:10;:12::i;:::-;47401:7;47368:18;:41::i;:::-;47346:136;;;;;;;;;;;;:::i;:::-;;;;;;;;;47493:38;47507:4;47513:2;47517:7;47526:4;47493:13;:38::i;:::-;47180:359;;;;:::o;68641:37::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;68489:::-;;;;:::o;68297:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;70986:725::-;71104:13;71157:16;71165:7;71157;:16::i;:::-;71135:113;;;;;;;;;;;;:::i;:::-;;;;;;;;;71277:5;71265:17;;:8;;;;;;;;;;;:17;;;71261:71;;;71306:14;71299:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71261:71;71344:28;71375:10;:8;:10::i;:::-;71344:41;;71447:1;71422:14;71416:28;:32;:287;;;;;;;;;;;;;;;;;71540:14;71581:18;:7;:16;:18::i;:::-;71626:13;71497:165;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;71416:287;71396:307;;;70986:725;;;;:::o;71814:110::-;2018:13;:11;:13::i;:::-;71910:6:::1;71889:18;:27;;;;71814:110:::0;:::o;68412:31::-;;;;:::o;72268:151::-;2018:13;:11;:13::i;:::-;72394:17:::1;72378:13;:33;;;;;;;;;;;;:::i;:::-;;72268:151:::0;:::o;46200:214::-;46342:4;46371:18;:25;46390:5;46371:25;;;;;;;;;;;;;;;:35;46397:8;46371:35;;;;;;;;;;;;;;;;;;;;;;;;;46364:42;;46200:214;;;;:::o;72757:154::-;2018:13;:11;:13::i;:::-;72843:20:::1;;72836:27;;;;:::i;:::-;72897:6;;72874:20;:29;;;;;;;:::i;:::-;;72757:154:::0;;:::o;72427:126::-;2018:13;:11;:13::i;:::-;72530:15:::1;72513:14;:32;;;;;;;;;;;;:::i;:::-;;72427:126:::0;:::o;3038:238::-;2018:13;:11;:13::i;:::-;3161:1:::1;3141:22;;:8;:22;;;;3119:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;3240:28;3259:8;3240:18;:28::i;:::-;3038:238:::0;:::o;42925:355::-;43072:4;43129:25;43114:40;;;:11;:40;;;;:105;;;;43186:33;43171:48;;;:11;:48;;;;43114:105;:158;;;;43236:36;43260:11;43236:23;:36::i;:::-;43114:158;43094:178;;42925:355;;;:::o;2297:132::-;2372:12;:10;:12::i;:::-;2361:23;;:7;:5;:7::i;:::-;:23;;;2353:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2297:132::o;55852:135::-;55934:16;55942:7;55934;:16::i;:::-;55926:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;55852:135;:::o;656:98::-;709:7;736:10;729:17;;656:98;:::o;55131:174::-;55233:2;55206:15;:24;55222:7;55206:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;55289:7;55285:2;55251:46;;55260:23;55275:7;55260:14;:23::i;:::-;55251:46;;;;;;;;;;;;55131:174;;:::o;49609:331::-;49738:4;49760:13;49776:23;49791:7;49776:14;:23::i;:::-;49760:39;;49829:5;49818:16;;:7;:16;;;:65;;;;49851:32;49868:5;49875:7;49851:16;:32::i;:::-;49818:65;:113;;;;49924:7;49900:31;;:20;49912:7;49900:11;:20::i;:::-;:31;;;49818:113;49810:122;;;49609:331;;;;:::o;53675:1337::-;53848:4;53821:31;;:23;53836:7;53821:14;:23::i;:::-;:31;;;53799:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;53950:1;53936:16;;:2;:16;;;;53928:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;54006:42;54027:4;54033:2;54037:7;54046:1;54006:20;:42::i;:::-;54192:4;54165:31;;:23;54180:7;54165:14;:23::i;:::-;:31;;;54143:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;54333:15;:24;54349:7;54333:24;;;;;;;;;;;;54326:31;;;;;;;;;;;54828:1;54809:9;:15;54819:4;54809:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;54861:1;54844:9;:13;54854:2;54844:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;54903:2;54884:7;:16;54892:7;54884:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;54942:7;54938:2;54923:27;;54932:4;54923:27;;;;;;;;;;;;54963:41;54983:4;54989:2;54993:7;55002:1;54963:19;:41::i;:::-;53675:1337;;;:::o;48884:117::-;48950:7;48977;:16;48985:7;48977:16;;;;;;;;;;;;;;;;;;;;;48970:23;;48884:117;;;:::o;3436:191::-;3510:16;3529:6;;;;;;;;;;;3510:25;;3555:8;3546:6;;:17;;;;;;;;;;;;;;;;;;3610:8;3579:40;;3600:8;3579:40;;;;;;;;;;;;3499:128;3436:191;:::o;50282:110::-;50358:26;50368:2;50372:7;50358:26;;;;;;;;;;;;:9;:26::i;:::-;50282:110;;:::o;55448:315::-;55603:8;55594:17;;:5;:17;;;;55586:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;55690:8;55652:18;:25;55671:5;55652:25;;;;;;;;;;;;;;;:35;55678:8;55652:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;55736:8;55714:41;;55729:5;55714:41;;;55746:8;55714:41;;;;;;:::i;:::-;;;;;;;;55448:315;;;:::o;48420:350::-;48576:28;48586:4;48592:2;48596:7;48576:9;:28::i;:::-;48637:47;48660:4;48666:2;48670:7;48679:4;48637:22;:47::i;:::-;48615:147;;;;;;;;;;;;:::i;:::-;;;;;;;;;48420:350;;;;:::o;49314:128::-;49379:4;49432:1;49403:31;;:17;49412:7;49403:8;:17::i;:::-;:31;;;;49396:38;;49314:128;;;:::o;69051:108::-;69111:13;69144:7;69137:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69051:108;:::o;20159:716::-;20215:13;20266:14;20303:1;20283:17;20294:5;20283:10;:17::i;:::-;:21;20266:38;;20319:20;20353:6;20342:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20319:41;;20375:11;20504:6;20500:2;20496:15;20488:6;20484:28;20477:35;;20541:288;20548:4;20541:288;;;20573:5;;;;;;;;20715:8;20710:2;20703:5;20699:14;20694:30;20689:3;20681:44;20771:2;20762:11;;;;;;:::i;:::-;;;;;20805:1;20796:5;:10;20792:21;;;20808:5;;20792:21;20541:288;;;20850:6;20843:13;;;;;20159:716;;;:::o;23873:207::-;24003:4;24047:25;24032:40;;;:11;:40;;;;24025:47;;23873:207;;;:::o;63136:915::-;63313:61;63340:4;63346:2;63350:12;63364:9;63313:26;:61::i;:::-;63403:1;63391:9;:13;63387:222;;;63534:63;;;;;;;;;;:::i;:::-;;;;;;;;63387:222;63621:15;63639:12;63621:30;;63684:1;63668:18;;:4;:18;;;63664:187;;;63703:40;63735:7;63703:31;:40::i;:::-;63664:187;;;63773:2;63765:10;;:4;:10;;;63761:90;;63792:47;63825:4;63831:7;63792:32;:47::i;:::-;63761:90;63664:187;63879:1;63865:16;;:2;:16;;;63861:183;;;63898:45;63935:7;63898:36;:45::i;:::-;63861:183;;;63971:4;63965:10;;:2;:10;;;63961:83;;63992:40;64020:2;64024:7;63992:27;:40::i;:::-;63961:83;63861:183;63302:749;63136:915;;;;:::o;59449:158::-;;;;;:::o;50619:319::-;50748:18;50754:2;50758:7;50748:5;:18::i;:::-;50799:53;50830:1;50834:2;50838:7;50847:4;50799:22;:53::i;:::-;50777:153;;;;;;;;;;;;:::i;:::-;;;;;;;;;50619:319;;;:::o;56551:1034::-;56705:4;56726:15;:2;:13;;;:15::i;:::-;56722:856;;;56795:2;56779:36;;;56838:12;:10;:12::i;:::-;56873:4;56900:7;56930:4;56779:174;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;56758:765;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57153:1;57136:6;:13;:18;57132:376;;;57179:108;;;;;;;;;;:::i;:::-;;;;;;;;57132:376;57458:6;57452:13;57443:6;57439:2;57435:15;57428:38;56758:765;57027:41;;;57017:51;;;:6;:51;;;;57010:58;;;;;56722:856;57562:4;57555:11;;56551:1034;;;;;;;:::o;16891:922::-;16944:7;16964:14;16981:1;16964:18;;17031:6;17022:5;:15;17018:102;;17067:6;17058:15;;;;;;:::i;:::-;;;;;17102:2;17092:12;;;;17018:102;17147:6;17138:5;:15;17134:102;;17183:6;17174:15;;;;;;:::i;:::-;;;;;17218:2;17208:12;;;;17134:102;17263:6;17254:5;:15;17250:102;;17299:6;17290:15;;;;;;:::i;:::-;;;;;17334:2;17324:12;;;;17250:102;17379:5;17370;:14;17366:99;;17414:5;17405:14;;;;;;:::i;:::-;;;;;17448:1;17438:11;;;;17366:99;17492:5;17483;:14;17479:99;;17527:5;17518:14;;;;;;:::i;:::-;;;;;17561:1;17551:11;;;;17479:99;17605:5;17596;:14;17592:99;;17640:5;17631:14;;;;;;:::i;:::-;;;;;17674:1;17664:11;;;;17592:99;17718:5;17709;:14;17705:66;;17754:1;17744:11;;;;17705:66;17799:6;17792:13;;;16891:922;;;:::o;58317:410::-;58507:1;58495:9;:13;58491:229;;;58545:1;58529:18;;:4;:18;;;58525:87;;58587:9;58568;:15;58578:4;58568:15;;;;;;;;;;;;;;;;:28;;;;;;;:::i;:::-;;;;;;;;58525:87;58644:1;58630:16;;:2;:16;;;58626:83;;58684:9;58667;:13;58677:2;58667:13;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;58626:83;58491:229;58317:410;;;;:::o;64774:164::-;64878:10;:17;;;;64851:15;:24;64867:7;64851:24;;;;;;;;;;;:44;;;;64906:10;64922:7;64906:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64774:164;:::o;65565:1002::-;65845:22;65895:1;65870:22;65887:4;65870:16;:22::i;:::-;:26;;;;:::i;:::-;65845:51;;65907:18;65928:17;:26;65946:7;65928:26;;;;;;;;;;;;65907:47;;66075:14;66061:10;:28;66057:328;;66106:19;66128:12;:18;66141:4;66128:18;;;;;;;;;;;;;;;:34;66147:14;66128:34;;;;;;;;;;;;66106:56;;66212:11;66179:12;:18;66192:4;66179:18;;;;;;;;;;;;;;;:30;66198:10;66179:30;;;;;;;;;;;:44;;;;66329:10;66296:17;:30;66314:11;66296:30;;;;;;;;;;;:43;;;;66091:294;66057:328;66481:17;:26;66499:7;66481:26;;;;;;;;;;;66474:33;;;66525:12;:18;66538:4;66525:18;;;;;;;;;;;;;;;:34;66544:14;66525:34;;;;;;;;;;;66518:41;;;65660:907;;65565:1002;;:::o;66862:1079::-;67115:22;67160:1;67140:10;:17;;;;:21;;;;:::i;:::-;67115:46;;67172:18;67193:15;:24;67209:7;67193:24;;;;;;;;;;;;67172:45;;67544:19;67566:10;67577:14;67566:26;;;;;;;;:::i;:::-;;;;;;;;;;67544:48;;67630:11;67605:10;67616;67605:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;67741:10;67710:15;:28;67726:11;67710:28;;;;;;;;;;;:41;;;;67882:15;:24;67898:7;67882:24;;;;;;;;;;;67875:31;;;67917:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66933:1008;;;66862:1079;:::o;64352:221::-;64437:14;64454:20;64471:2;64454:16;:20::i;:::-;64437:37;;64512:7;64485:12;:16;64498:2;64485:16;;;;;;;;;;;;;;;:24;64502:6;64485:24;;;;;;;;;;;:34;;;;64559:6;64530:17;:26;64548:7;64530:26;;;;;;;;;;;:35;;;;64426:147;64352:221;;:::o;51274:942::-;51368:1;51354:16;;:2;:16;;;;51346:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;51427:16;51435:7;51427;:16::i;:::-;51426:17;51418:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;51489:48;51518:1;51522:2;51526:7;51535:1;51489:20;:48::i;:::-;51636:16;51644:7;51636;:16::i;:::-;51635:17;51627:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;52051:1;52034:9;:13;52044:2;52034:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;52095:2;52076:7;:16;52084:7;52076:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;52140:7;52136:2;52115:33;;52132:1;52115:33;;;;;;;;;;;;52161:47;52189:1;52193:2;52197:7;52206:1;52161:19;:47::i;:::-;51274:942;;:::o;31644:326::-;31704:4;31961:1;31939:7;:19;;;:23;31932:30;;31644:326;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:116::-;1588:21;1603:5;1588:21;:::i;:::-;1581:5;1578:32;1568:60;;1624:1;1621;1614:12;1568:60;1518:116;:::o;1640:133::-;1683:5;1721:6;1708:20;1699:29;;1737:30;1761:5;1737:30;:::i;:::-;1640:133;;;;:::o;1779:323::-;1835:6;1884:2;1872:9;1863:7;1859:23;1855:32;1852:119;;;1890:79;;:::i;:::-;1852:119;2010:1;2035:50;2077:7;2068:6;2057:9;2053:22;2035:50;:::i;:::-;2025:60;;1981:114;1779:323;;;;:::o;2108:99::-;2160:6;2194:5;2188:12;2178:22;;2108:99;;;:::o;2213:169::-;2297:11;2331:6;2326:3;2319:19;2371:4;2366:3;2362:14;2347:29;;2213:169;;;;:::o;2388:307::-;2456:1;2466:113;2480:6;2477:1;2474:13;2466:113;;;2565:1;2560:3;2556:11;2550:18;2546:1;2541:3;2537:11;2530:39;2502:2;2499:1;2495:10;2490:15;;2466:113;;;2597:6;2594:1;2591:13;2588:101;;;2677:1;2668:6;2663:3;2659:16;2652:27;2588:101;2437:258;2388:307;;;:::o;2701:102::-;2742:6;2793:2;2789:7;2784:2;2777:5;2773:14;2769:28;2759:38;;2701:102;;;:::o;2809:364::-;2897:3;2925:39;2958:5;2925:39;:::i;:::-;2980:71;3044:6;3039:3;2980:71;:::i;:::-;2973:78;;3060:52;3105:6;3100:3;3093:4;3086:5;3082:16;3060:52;:::i;:::-;3137:29;3159:6;3137:29;:::i;:::-;3132:3;3128:39;3121:46;;2901:272;2809:364;;;;:::o;3179:313::-;3292:4;3330:2;3319:9;3315:18;3307:26;;3379:9;3373:4;3369:20;3365:1;3354:9;3350:17;3343:47;3407:78;3480:4;3471:6;3407:78;:::i;:::-;3399:86;;3179:313;;;;:::o;3498:77::-;3535:7;3564:5;3553:16;;3498:77;;;:::o;3581:122::-;3654:24;3672:5;3654:24;:::i;:::-;3647:5;3644:35;3634:63;;3693:1;3690;3683:12;3634:63;3581:122;:::o;3709:139::-;3755:5;3793:6;3780:20;3771:29;;3809:33;3836:5;3809:33;:::i;:::-;3709:139;;;;:::o;3854:329::-;3913:6;3962:2;3950:9;3941:7;3937:23;3933:32;3930:119;;;3968:79;;:::i;:::-;3930:119;4088:1;4113:53;4158:7;4149:6;4138:9;4134:22;4113:53;:::i;:::-;4103:63;;4059:117;3854:329;;;;:::o;4189:126::-;4226:7;4266:42;4259:5;4255:54;4244:65;;4189:126;;;:::o;4321:96::-;4358:7;4387:24;4405:5;4387:24;:::i;:::-;4376:35;;4321:96;;;:::o;4423:118::-;4510:24;4528:5;4510:24;:::i;:::-;4505:3;4498:37;4423:118;;:::o;4547:222::-;4640:4;4678:2;4667:9;4663:18;4655:26;;4691:71;4759:1;4748:9;4744:17;4735:6;4691:71;:::i;:::-;4547:222;;;;:::o;4775:122::-;4848:24;4866:5;4848:24;:::i;:::-;4841:5;4838:35;4828:63;;4887:1;4884;4877:12;4828:63;4775:122;:::o;4903:139::-;4949:5;4987:6;4974:20;4965:29;;5003:33;5030:5;5003:33;:::i;:::-;4903:139;;;;:::o;5048:474::-;5116:6;5124;5173:2;5161:9;5152:7;5148:23;5144:32;5141:119;;;5179:79;;:::i;:::-;5141:119;5299:1;5324:53;5369:7;5360:6;5349:9;5345:22;5324:53;:::i;:::-;5314:63;;5270:117;5426:2;5452:53;5497:7;5488:6;5477:9;5473:22;5452:53;:::i;:::-;5442:63;;5397:118;5048:474;;;;;:::o;5528:118::-;5615:24;5633:5;5615:24;:::i;:::-;5610:3;5603:37;5528:118;;:::o;5652:222::-;5745:4;5783:2;5772:9;5768:18;5760:26;;5796:71;5864:1;5853:9;5849:17;5840:6;5796:71;:::i;:::-;5652:222;;;;:::o;5880:329::-;5939:6;5988:2;5976:9;5967:7;5963:23;5959:32;5956:119;;;5994:79;;:::i;:::-;5956:119;6114:1;6139:53;6184:7;6175:6;6164:9;6160:22;6139:53;:::i;:::-;6129:63;;6085:117;5880:329;;;;:::o;6215:619::-;6292:6;6300;6308;6357:2;6345:9;6336:7;6332:23;6328:32;6325:119;;;6363:79;;:::i;:::-;6325:119;6483:1;6508:53;6553:7;6544:6;6533:9;6529:22;6508:53;:::i;:::-;6498:63;;6454:117;6610:2;6636:53;6681:7;6672:6;6661:9;6657:22;6636:53;:::i;:::-;6626:63;;6581:118;6738:2;6764:53;6809:7;6800:6;6789:9;6785:22;6764:53;:::i;:::-;6754:63;;6709:118;6215:619;;;;;:::o;6840:114::-;6907:6;6941:5;6935:12;6925:22;;6840:114;;;:::o;6960:184::-;7059:11;7093:6;7088:3;7081:19;7133:4;7128:3;7124:14;7109:29;;6960:184;;;;:::o;7150:132::-;7217:4;7240:3;7232:11;;7270:4;7265:3;7261:14;7253:22;;7150:132;;;:::o;7288:108::-;7365:24;7383:5;7365:24;:::i;:::-;7360:3;7353:37;7288:108;;:::o;7402:179::-;7471:10;7492:46;7534:3;7526:6;7492:46;:::i;:::-;7570:4;7565:3;7561:14;7547:28;;7402:179;;;;:::o;7587:113::-;7657:4;7689;7684:3;7680:14;7672:22;;7587:113;;;:::o;7736:732::-;7855:3;7884:54;7932:5;7884:54;:::i;:::-;7954:86;8033:6;8028:3;7954:86;:::i;:::-;7947:93;;8064:56;8114:5;8064:56;:::i;:::-;8143:7;8174:1;8159:284;8184:6;8181:1;8178:13;8159:284;;;8260:6;8254:13;8287:63;8346:3;8331:13;8287:63;:::i;:::-;8280:70;;8373:60;8426:6;8373:60;:::i;:::-;8363:70;;8219:224;8206:1;8203;8199:9;8194:14;;8159:284;;;8163:14;8459:3;8452:10;;7860:608;;;7736:732;;;;:::o;8474:373::-;8617:4;8655:2;8644:9;8640:18;8632:26;;8704:9;8698:4;8694:20;8690:1;8679:9;8675:17;8668:47;8732:108;8835:4;8826:6;8732:108;:::i;:::-;8724:116;;8474:373;;;;:::o;8853:117::-;8962:1;8959;8952:12;8976:117;9085:1;9082;9075:12;9099:180;9147:77;9144:1;9137:88;9244:4;9241:1;9234:15;9268:4;9265:1;9258:15;9285:281;9368:27;9390:4;9368:27;:::i;:::-;9360:6;9356:40;9498:6;9486:10;9483:22;9462:18;9450:10;9447:34;9444:62;9441:88;;;9509:18;;:::i;:::-;9441:88;9549:10;9545:2;9538:22;9328:238;9285:281;;:::o;9572:129::-;9606:6;9633:20;;:::i;:::-;9623:30;;9662:33;9690:4;9682:6;9662:33;:::i;:::-;9572:129;;;:::o;9707:308::-;9769:4;9859:18;9851:6;9848:30;9845:56;;;9881:18;;:::i;:::-;9845:56;9919:29;9941:6;9919:29;:::i;:::-;9911:37;;10003:4;9997;9993:15;9985:23;;9707:308;;;:::o;10021:154::-;10105:6;10100:3;10095;10082:30;10167:1;10158:6;10153:3;10149:16;10142:27;10021:154;;;:::o;10181:412::-;10259:5;10284:66;10300:49;10342:6;10300:49;:::i;:::-;10284:66;:::i;:::-;10275:75;;10373:6;10366:5;10359:21;10411:4;10404:5;10400:16;10449:3;10440:6;10435:3;10431:16;10428:25;10425:112;;;10456:79;;:::i;:::-;10425:112;10546:41;10580:6;10575:3;10570;10546:41;:::i;:::-;10265:328;10181:412;;;;;:::o;10613:340::-;10669:5;10718:3;10711:4;10703:6;10699:17;10695:27;10685:122;;10726:79;;:::i;:::-;10685:122;10843:6;10830:20;10868:79;10943:3;10935:6;10928:4;10920:6;10916:17;10868:79;:::i;:::-;10859:88;;10675:278;10613:340;;;;:::o;10959:509::-;11028:6;11077:2;11065:9;11056:7;11052:23;11048:32;11045:119;;;11083:79;;:::i;:::-;11045:119;11231:1;11220:9;11216:17;11203:31;11261:18;11253:6;11250:30;11247:117;;;11283:79;;:::i;:::-;11247:117;11388:63;11443:7;11434:6;11423:9;11419:22;11388:63;:::i;:::-;11378:73;;11174:287;10959:509;;;;:::o;11474:468::-;11539:6;11547;11596:2;11584:9;11575:7;11571:23;11567:32;11564:119;;;11602:79;;:::i;:::-;11564:119;11722:1;11747:53;11792:7;11783:6;11772:9;11768:22;11747:53;:::i;:::-;11737:63;;11693:117;11849:2;11875:50;11917:7;11908:6;11897:9;11893:22;11875:50;:::i;:::-;11865:60;;11820:115;11474:468;;;;;:::o;11948:307::-;12009:4;12099:18;12091:6;12088:30;12085:56;;;12121:18;;:::i;:::-;12085:56;12159:29;12181:6;12159:29;:::i;:::-;12151:37;;12243:4;12237;12233:15;12225:23;;11948:307;;;:::o;12261:410::-;12338:5;12363:65;12379:48;12420:6;12379:48;:::i;:::-;12363:65;:::i;:::-;12354:74;;12451:6;12444:5;12437:21;12489:4;12482:5;12478:16;12527:3;12518:6;12513:3;12509:16;12506:25;12503:112;;;12534:79;;:::i;:::-;12503:112;12624:41;12658:6;12653:3;12648;12624:41;:::i;:::-;12344:327;12261:410;;;;;:::o;12690:338::-;12745:5;12794:3;12787:4;12779:6;12775:17;12771:27;12761:122;;12802:79;;:::i;:::-;12761:122;12919:6;12906:20;12944:78;13018:3;13010:6;13003:4;12995:6;12991:17;12944:78;:::i;:::-;12935:87;;12751:277;12690:338;;;;:::o;13034:943::-;13129:6;13137;13145;13153;13202:3;13190:9;13181:7;13177:23;13173:33;13170:120;;;13209:79;;:::i;:::-;13170:120;13329:1;13354:53;13399:7;13390:6;13379:9;13375:22;13354:53;:::i;:::-;13344:63;;13300:117;13456:2;13482:53;13527:7;13518:6;13507:9;13503:22;13482:53;:::i;:::-;13472:63;;13427:118;13584:2;13610:53;13655:7;13646:6;13635:9;13631:22;13610:53;:::i;:::-;13600:63;;13555:118;13740:2;13729:9;13725:18;13712:32;13771:18;13763:6;13760:30;13757:117;;;13793:79;;:::i;:::-;13757:117;13898:62;13952:7;13943:6;13932:9;13928:22;13898:62;:::i;:::-;13888:72;;13683:287;13034:943;;;;;;;:::o;13983:474::-;14051:6;14059;14108:2;14096:9;14087:7;14083:23;14079:32;14076:119;;;14114:79;;:::i;:::-;14076:119;14234:1;14259:53;14304:7;14295:6;14284:9;14280:22;14259:53;:::i;:::-;14249:63;;14205:117;14361:2;14387:53;14432:7;14423:6;14412:9;14408:22;14387:53;:::i;:::-;14377:63;;14332:118;13983:474;;;;;:::o;14463:117::-;14572:1;14569;14562:12;14586:117;14695:1;14692;14685:12;14726:568;14799:8;14809:6;14859:3;14852:4;14844:6;14840:17;14836:27;14826:122;;14867:79;;:::i;:::-;14826:122;14980:6;14967:20;14957:30;;15010:18;15002:6;14999:30;14996:117;;;15032:79;;:::i;:::-;14996:117;15146:4;15138:6;15134:17;15122:29;;15200:3;15192:4;15184:6;15180:17;15170:8;15166:32;15163:41;15160:128;;;15207:79;;:::i;:::-;15160:128;14726:568;;;;;:::o;15300:559::-;15386:6;15394;15443:2;15431:9;15422:7;15418:23;15414:32;15411:119;;;15449:79;;:::i;:::-;15411:119;15597:1;15586:9;15582:17;15569:31;15627:18;15619:6;15616:30;15613:117;;;15649:79;;:::i;:::-;15613:117;15762:80;15834:7;15825:6;15814:9;15810:22;15762:80;:::i;:::-;15744:98;;;;15540:312;15300:559;;;;;:::o;15865:180::-;15913:77;15910:1;15903:88;16010:4;16007:1;16000:15;16034:4;16031:1;16024:15;16051:320;16095:6;16132:1;16126:4;16122:12;16112:22;;16179:1;16173:4;16169:12;16200:18;16190:81;;16256:4;16248:6;16244:17;16234:27;;16190:81;16318:2;16310:6;16307:14;16287:18;16284:38;16281:84;;;16337:18;;:::i;:::-;16281:84;16102:269;16051:320;;;:::o;16377:220::-;16517:34;16513:1;16505:6;16501:14;16494:58;16586:3;16581:2;16573:6;16569:15;16562:28;16377:220;:::o;16603:366::-;16745:3;16766:67;16830:2;16825:3;16766:67;:::i;:::-;16759:74;;16842:93;16931:3;16842:93;:::i;:::-;16960:2;16955:3;16951:12;16944:19;;16603:366;;;:::o;16975:419::-;17141:4;17179:2;17168:9;17164:18;17156:26;;17228:9;17222:4;17218:20;17214:1;17203:9;17199:17;17192:47;17256:131;17382:4;17256:131;:::i;:::-;17248:139;;16975:419;;;:::o;17400:248::-;17540:34;17536:1;17528:6;17524:14;17517:58;17609:31;17604:2;17596:6;17592:15;17585:56;17400:248;:::o;17654:366::-;17796:3;17817:67;17881:2;17876:3;17817:67;:::i;:::-;17810:74;;17893:93;17982:3;17893:93;:::i;:::-;18011:2;18006:3;18002:12;17995:19;;17654:366;;;:::o;18026:419::-;18192:4;18230:2;18219:9;18215:18;18207:26;;18279:9;18273:4;18269:20;18265:1;18254:9;18250:17;18243:47;18307:131;18433:4;18307:131;:::i;:::-;18299:139;;18026:419;;;:::o;18451:232::-;18591:34;18587:1;18579:6;18575:14;18568:58;18660:15;18655:2;18647:6;18643:15;18636:40;18451:232;:::o;18689:366::-;18831:3;18852:67;18916:2;18911:3;18852:67;:::i;:::-;18845:74;;18928:93;19017:3;18928:93;:::i;:::-;19046:2;19041:3;19037:12;19030:19;;18689:366;;;:::o;19061:419::-;19227:4;19265:2;19254:9;19250:18;19242:26;;19314:9;19308:4;19304:20;19300:1;19289:9;19285:17;19278:47;19342:131;19468:4;19342:131;:::i;:::-;19334:139;;19061:419;;;:::o;19486:230::-;19626:34;19622:1;19614:6;19610:14;19603:58;19695:13;19690:2;19682:6;19678:15;19671:38;19486:230;:::o;19722:366::-;19864:3;19885:67;19949:2;19944:3;19885:67;:::i;:::-;19878:74;;19961:93;20050:3;19961:93;:::i;:::-;20079:2;20074:3;20070:12;20063:19;;19722:366;;;:::o;20094:419::-;20260:4;20298:2;20287:9;20283:18;20275:26;;20347:9;20341:4;20337:20;20333:1;20322:9;20318:17;20311:47;20375:131;20501:4;20375:131;:::i;:::-;20367:139;;20094:419;;;:::o;20519:180::-;20567:77;20564:1;20557:88;20664:4;20661:1;20654:15;20688:4;20685:1;20678:15;20705:180;20753:77;20750:1;20743:88;20850:4;20847:1;20840:15;20874:4;20871:1;20864:15;20891:233;20930:3;20953:24;20971:5;20953:24;:::i;:::-;20944:33;;20999:66;20992:5;20989:77;20986:103;;;21069:18;;:::i;:::-;20986:103;21116:1;21109:5;21105:13;21098:20;;20891:233;;;:::o;21130:147::-;21231:11;21268:3;21253:18;;21130:147;;;;:::o;21283:114::-;;:::o;21403:398::-;21562:3;21583:83;21664:1;21659:3;21583:83;:::i;:::-;21576:90;;21675:93;21764:3;21675:93;:::i;:::-;21793:1;21788:3;21784:11;21777:18;;21403:398;;;:::o;21807:379::-;21991:3;22013:147;22156:3;22013:147;:::i;:::-;22006:154;;22177:3;22170:10;;21807:379;;;:::o;22192:231::-;22332:34;22328:1;22320:6;22316:14;22309:58;22401:14;22396:2;22388:6;22384:15;22377:39;22192:231;:::o;22429:366::-;22571:3;22592:67;22656:2;22651:3;22592:67;:::i;:::-;22585:74;;22668:93;22757:3;22668:93;:::i;:::-;22786:2;22781:3;22777:12;22770:19;;22429:366;;;:::o;22801:419::-;22967:4;23005:2;22994:9;22990:18;22982:26;;23054:9;23048:4;23044:20;23040:1;23029:9;23025:17;23018:47;23082:131;23208:4;23082:131;:::i;:::-;23074:139;;22801:419;;;:::o;23226:174::-;23366:26;23362:1;23354:6;23350:14;23343:50;23226:174;:::o;23406:366::-;23548:3;23569:67;23633:2;23628:3;23569:67;:::i;:::-;23562:74;;23645:93;23734:3;23645:93;:::i;:::-;23763:2;23758:3;23754:12;23747:19;;23406:366;;;:::o;23778:419::-;23944:4;23982:2;23971:9;23967:18;23959:26;;24031:9;24025:4;24021:20;24017:1;24006:9;24002:17;23995:47;24059:131;24185:4;24059:131;:::i;:::-;24051:139;;23778:419;;;:::o;24203:228::-;24343:34;24339:1;24331:6;24327:14;24320:58;24412:11;24407:2;24399:6;24395:15;24388:36;24203:228;:::o;24437:366::-;24579:3;24600:67;24664:2;24659:3;24600:67;:::i;:::-;24593:74;;24676:93;24765:3;24676:93;:::i;:::-;24794:2;24789:3;24785:12;24778:19;;24437:366;;;:::o;24809:419::-;24975:4;25013:2;25002:9;24998:18;24990:26;;25062:9;25056:4;25052:20;25048:1;25037:9;25033:17;25026:47;25090:131;25216:4;25090:131;:::i;:::-;25082:139;;24809:419;;;:::o;25234:156::-;25374:8;25370:1;25362:6;25358:14;25351:32;25234:156;:::o;25396:365::-;25538:3;25559:66;25623:1;25618:3;25559:66;:::i;:::-;25552:73;;25634:93;25723:3;25634:93;:::i;:::-;25752:2;25747:3;25743:12;25736:19;;25396:365;;;:::o;25767:419::-;25933:4;25971:2;25960:9;25956:18;25948:26;;26020:9;26014:4;26010:20;26006:1;25995:9;25991:17;25984:47;26048:131;26174:4;26048:131;:::i;:::-;26040:139;;25767:419;;;:::o;26192:172::-;26332:24;26328:1;26320:6;26316:14;26309:48;26192:172;:::o;26370:366::-;26512:3;26533:67;26597:2;26592:3;26533:67;:::i;:::-;26526:74;;26609:93;26698:3;26609:93;:::i;:::-;26727:2;26722:3;26718:12;26711:19;;26370:366;;;:::o;26742:419::-;26908:4;26946:2;26935:9;26931:18;26923:26;;26995:9;26989:4;26985:20;26981:1;26970:9;26966:17;26959:47;27023:131;27149:4;27023:131;:::i;:::-;27015:139;;26742:419;;;:::o;27167:177::-;27307:29;27303:1;27295:6;27291:14;27284:53;27167:177;:::o;27350:366::-;27492:3;27513:67;27577:2;27572:3;27513:67;:::i;:::-;27506:74;;27589:93;27678:3;27589:93;:::i;:::-;27707:2;27702:3;27698:12;27691:19;;27350:366;;;:::o;27722:419::-;27888:4;27926:2;27915:9;27911:18;27903:26;;27975:9;27969:4;27965:20;27961:1;27950:9;27946:17;27939:47;28003:131;28129:4;28003:131;:::i;:::-;27995:139;;27722:419;;;:::o;28147:223::-;28287:34;28283:1;28275:6;28271:14;28264:58;28356:6;28351:2;28343:6;28339:15;28332:31;28147:223;:::o;28376:366::-;28518:3;28539:67;28603:2;28598:3;28539:67;:::i;:::-;28532:74;;28615:93;28704:3;28615:93;:::i;:::-;28733:2;28728:3;28724:12;28717:19;;28376:366;;;:::o;28748:419::-;28914:4;28952:2;28941:9;28937:18;28929:26;;29001:9;28995:4;28991:20;28987:1;28976:9;28972:17;28965:47;29029:131;29155:4;29029:131;:::i;:::-;29021:139;;28748:419;;;:::o;29173:305::-;29213:3;29232:20;29250:1;29232:20;:::i;:::-;29227:25;;29266:20;29284:1;29266:20;:::i;:::-;29261:25;;29420:1;29352:66;29348:74;29345:1;29342:81;29339:107;;;29426:18;;:::i;:::-;29339:107;29470:1;29467;29463:9;29456:16;;29173:305;;;;:::o;29484:172::-;29624:24;29620:1;29612:6;29608:14;29601:48;29484:172;:::o;29662:366::-;29804:3;29825:67;29889:2;29884:3;29825:67;:::i;:::-;29818:74;;29901:93;29990:3;29901:93;:::i;:::-;30019:2;30014:3;30010:12;30003:19;;29662:366;;;:::o;30034:419::-;30200:4;30238:2;30227:9;30223:18;30215:26;;30287:9;30281:4;30277:20;30273:1;30262:9;30258:17;30251:47;30315:131;30441:4;30315:131;:::i;:::-;30307:139;;30034:419;;;:::o;30459:173::-;30599:25;30595:1;30587:6;30583:14;30576:49;30459:173;:::o;30638:366::-;30780:3;30801:67;30865:2;30860:3;30801:67;:::i;:::-;30794:74;;30877:93;30966:3;30877:93;:::i;:::-;30995:2;30990:3;30986:12;30979:19;;30638:366;;;:::o;31010:419::-;31176:4;31214:2;31203:9;31199:18;31191:26;;31263:9;31257:4;31253:20;31249:1;31238:9;31234:17;31227:47;31291:131;31417:4;31291:131;:::i;:::-;31283:139;;31010:419;;;:::o;31435:178::-;31575:30;31571:1;31563:6;31559:14;31552:54;31435:178;:::o;31619:366::-;31761:3;31782:67;31846:2;31841:3;31782:67;:::i;:::-;31775:74;;31858:93;31947:3;31858:93;:::i;:::-;31976:2;31971:3;31967:12;31960:19;;31619:366;;;:::o;31991:419::-;32157:4;32195:2;32184:9;32180:18;32172:26;;32244:9;32238:4;32234:20;32230:1;32219:9;32215:17;32208:47;32272:131;32398:4;32272:131;:::i;:::-;32264:139;;31991:419;;;:::o;32416:348::-;32456:7;32479:20;32497:1;32479:20;:::i;:::-;32474:25;;32513:20;32531:1;32513:20;:::i;:::-;32508:25;;32701:1;32633:66;32629:74;32626:1;32623:81;32618:1;32611:9;32604:17;32600:105;32597:131;;;32708:18;;:::i;:::-;32597:131;32756:1;32753;32749:9;32738:20;;32416:348;;;;:::o;32770:168::-;32910:20;32906:1;32898:6;32894:14;32887:44;32770:168;:::o;32944:366::-;33086:3;33107:67;33171:2;33166:3;33107:67;:::i;:::-;33100:74;;33183:93;33272:3;33183:93;:::i;:::-;33301:2;33296:3;33292:12;33285:19;;32944:366;;;:::o;33316:419::-;33482:4;33520:2;33509:9;33505:18;33497:26;;33569:9;33563:4;33559:20;33555:1;33544:9;33540:17;33533:47;33597:131;33723:4;33597:131;:::i;:::-;33589:139;;33316:419;;;:::o;33741:234::-;33881:34;33877:1;33869:6;33865:14;33858:58;33950:17;33945:2;33937:6;33933:15;33926:42;33741:234;:::o;33981:366::-;34123:3;34144:67;34208:2;34203:3;34144:67;:::i;:::-;34137:74;;34220:93;34309:3;34220:93;:::i;:::-;34338:2;34333:3;34329:12;34322:19;;33981:366;;;:::o;34353:419::-;34519:4;34557:2;34546:9;34542:18;34534:26;;34606:9;34600:4;34596:20;34592:1;34581:9;34577:17;34570:47;34634:131;34760:4;34634:131;:::i;:::-;34626:139;;34353:419;;;:::o;34778:148::-;34880:11;34917:3;34902:18;;34778:148;;;;:::o;34932:377::-;35038:3;35066:39;35099:5;35066:39;:::i;:::-;35121:89;35203:6;35198:3;35121:89;:::i;:::-;35114:96;;35219:52;35264:6;35259:3;35252:4;35245:5;35241:16;35219:52;:::i;:::-;35296:6;35291:3;35287:16;35280:23;;35042:267;34932:377;;;;:::o;35315:141::-;35364:4;35387:3;35379:11;;35410:3;35407:1;35400:14;35444:4;35441:1;35431:18;35423:26;;35315:141;;;:::o;35486:845::-;35589:3;35626:5;35620:12;35655:36;35681:9;35655:36;:::i;:::-;35707:89;35789:6;35784:3;35707:89;:::i;:::-;35700:96;;35827:1;35816:9;35812:17;35843:1;35838:137;;;;35989:1;35984:341;;;;35805:520;;35838:137;35922:4;35918:9;35907;35903:25;35898:3;35891:38;35958:6;35953:3;35949:16;35942:23;;35838:137;;35984:341;36051:38;36083:5;36051:38;:::i;:::-;36111:1;36125:154;36139:6;36136:1;36133:13;36125:154;;;36213:7;36207:14;36203:1;36198:3;36194:11;36187:35;36263:1;36254:7;36250:15;36239:26;;36161:4;36158:1;36154:12;36149:17;;36125:154;;;36308:6;36303:3;36299:16;36292:23;;35991:334;;35805:520;;35593:738;;35486:845;;;;:::o;36337:589::-;36562:3;36584:95;36675:3;36666:6;36584:95;:::i;:::-;36577:102;;36696:95;36787:3;36778:6;36696:95;:::i;:::-;36689:102;;36808:92;36896:3;36887:6;36808:92;:::i;:::-;36801:99;;36917:3;36910:10;;36337:589;;;;;;:::o;36932:225::-;37072:34;37068:1;37060:6;37056:14;37049:58;37141:8;37136:2;37128:6;37124:15;37117:33;36932:225;:::o;37163:366::-;37305:3;37326:67;37390:2;37385:3;37326:67;:::i;:::-;37319:74;;37402:93;37491:3;37402:93;:::i;:::-;37520:2;37515:3;37511:12;37504:19;;37163:366;;;:::o;37535:419::-;37701:4;37739:2;37728:9;37724:18;37716:26;;37788:9;37782:4;37778:20;37774:1;37763:9;37759:17;37752:47;37816:131;37942:4;37816:131;:::i;:::-;37808:139;;37535:419;;;:::o;37960:182::-;38100:34;38096:1;38088:6;38084:14;38077:58;37960:182;:::o;38148:366::-;38290:3;38311:67;38375:2;38370:3;38311:67;:::i;:::-;38304:74;;38387:93;38476:3;38387:93;:::i;:::-;38505:2;38500:3;38496:12;38489:19;;38148:366;;;:::o;38520:419::-;38686:4;38724:2;38713:9;38709:18;38701:26;;38773:9;38767:4;38763:20;38759:1;38748:9;38744:17;38737:47;38801:131;38927:4;38801:131;:::i;:::-;38793:139;;38520:419;;;:::o;38945:224::-;39085:34;39081:1;39073:6;39069:14;39062:58;39154:7;39149:2;39141:6;39137:15;39130:32;38945:224;:::o;39175:366::-;39317:3;39338:67;39402:2;39397:3;39338:67;:::i;:::-;39331:74;;39414:93;39503:3;39414:93;:::i;:::-;39532:2;39527:3;39523:12;39516:19;;39175:366;;;:::o;39547:419::-;39713:4;39751:2;39740:9;39736:18;39728:26;;39800:9;39794:4;39790:20;39786:1;39775:9;39771:17;39764:47;39828:131;39954:4;39828:131;:::i;:::-;39820:139;;39547:419;;;:::o;39972:223::-;40112:34;40108:1;40100:6;40096:14;40089:58;40181:6;40176:2;40168:6;40164:15;40157:31;39972:223;:::o;40201:366::-;40343:3;40364:67;40428:2;40423:3;40364:67;:::i;:::-;40357:74;;40440:93;40529:3;40440:93;:::i;:::-;40558:2;40553:3;40549:12;40542:19;;40201:366;;;:::o;40573:419::-;40739:4;40777:2;40766:9;40762:18;40754:26;;40826:9;40820:4;40816:20;40812:1;40801:9;40797:17;40790:47;40854:131;40980:4;40854:131;:::i;:::-;40846:139;;40573:419;;;:::o;40998:175::-;41138:27;41134:1;41126:6;41122:14;41115:51;40998:175;:::o;41179:366::-;41321:3;41342:67;41406:2;41401:3;41342:67;:::i;:::-;41335:74;;41418:93;41507:3;41418:93;:::i;:::-;41536:2;41531:3;41527:12;41520:19;;41179:366;;;:::o;41551:419::-;41717:4;41755:2;41744:9;41740:18;41732:26;;41804:9;41798:4;41794:20;41790:1;41779:9;41775:17;41768:47;41832:131;41958:4;41832:131;:::i;:::-;41824:139;;41551:419;;;:::o;41976:237::-;42116:34;42112:1;42104:6;42100:14;42093:58;42185:20;42180:2;42172:6;42168:15;42161:45;41976:237;:::o;42219:366::-;42361:3;42382:67;42446:2;42441:3;42382:67;:::i;:::-;42375:74;;42458:93;42547:3;42458:93;:::i;:::-;42576:2;42571:3;42567:12;42560:19;;42219:366;;;:::o;42591:419::-;42757:4;42795:2;42784:9;42780:18;42772:26;;42844:9;42838:4;42834:20;42830:1;42819:9;42815:17;42808:47;42872:131;42998:4;42872:131;:::i;:::-;42864:139;;42591:419;;;:::o;43016:180::-;43064:77;43061:1;43054:88;43161:4;43158:1;43151:15;43185:4;43182:1;43175:15;43202:240;43342:34;43338:1;43330:6;43326:14;43319:58;43411:23;43406:2;43398:6;43394:15;43387:48;43202:240;:::o;43448:366::-;43590:3;43611:67;43675:2;43670:3;43611:67;:::i;:::-;43604:74;;43687:93;43776:3;43687:93;:::i;:::-;43805:2;43800:3;43796:12;43789:19;;43448:366;;;:::o;43820:419::-;43986:4;44024:2;44013:9;44009:18;44001:26;;44073:9;44067:4;44063:20;44059:1;44048:9;44044:17;44037:47;44101:131;44227:4;44101:131;:::i;:::-;44093:139;;43820:419;;;:::o;44245:98::-;44296:6;44330:5;44324:12;44314:22;;44245:98;;;:::o;44349:168::-;44432:11;44466:6;44461:3;44454:19;44506:4;44501:3;44497:14;44482:29;;44349:168;;;;:::o;44523:360::-;44609:3;44637:38;44669:5;44637:38;:::i;:::-;44691:70;44754:6;44749:3;44691:70;:::i;:::-;44684:77;;44770:52;44815:6;44810:3;44803:4;44796:5;44792:16;44770:52;:::i;:::-;44847:29;44869:6;44847:29;:::i;:::-;44842:3;44838:39;44831:46;;44613:270;44523:360;;;;:::o;44889:640::-;45084:4;45122:3;45111:9;45107:19;45099:27;;45136:71;45204:1;45193:9;45189:17;45180:6;45136:71;:::i;:::-;45217:72;45285:2;45274:9;45270:18;45261:6;45217:72;:::i;:::-;45299;45367:2;45356:9;45352:18;45343:6;45299:72;:::i;:::-;45418:9;45412:4;45408:20;45403:2;45392:9;45388:18;45381:48;45446:76;45517:4;45508:6;45446:76;:::i;:::-;45438:84;;44889:640;;;;;;;:::o;45535:141::-;45591:5;45622:6;45616:13;45607:22;;45638:32;45664:5;45638:32;:::i;:::-;45535:141;;;;:::o;45682:349::-;45751:6;45800:2;45788:9;45779:7;45775:23;45771:32;45768:119;;;45806:79;;:::i;:::-;45768:119;45926:1;45951:63;46006:7;45997:6;45986:9;45982:22;45951:63;:::i;:::-;45941:73;;45897:127;45682:349;;;;:::o;46037:191::-;46077:4;46097:20;46115:1;46097:20;:::i;:::-;46092:25;;46131:20;46149:1;46131:20;:::i;:::-;46126:25;;46170:1;46167;46164:8;46161:34;;;46175:18;;:::i;:::-;46161:34;46220:1;46217;46213:9;46205:17;;46037:191;;;;:::o;46234:180::-;46282:77;46279:1;46272:88;46379:4;46376:1;46369:15;46403:4;46400:1;46393:15;46420:182;46560:34;46556:1;46548:6;46544:14;46537:58;46420:182;:::o;46608:366::-;46750:3;46771:67;46835:2;46830:3;46771:67;:::i;:::-;46764:74;;46847:93;46936:3;46847:93;:::i;:::-;46965:2;46960:3;46956:12;46949:19;;46608:366;;;:::o;46980:419::-;47146:4;47184:2;47173:9;47169:18;47161:26;;47233:9;47227:4;47223:20;47219:1;47208:9;47204:17;47197:47;47261:131;47387:4;47261:131;:::i;:::-;47253:139;;46980:419;;;:::o;47405:178::-;47545:30;47541:1;47533:6;47529:14;47522:54;47405:178;:::o;47589:366::-;47731:3;47752:67;47816:2;47811:3;47752:67;:::i;:::-;47745:74;;47828:93;47917:3;47828:93;:::i;:::-;47946:2;47941:3;47937:12;47930:19;;47589:366;;;:::o;47961:419::-;48127:4;48165:2;48154:9;48150:18;48142:26;;48214:9;48208:4;48204:20;48200:1;48189:9;48185:17;48178:47;48242:131;48368:4;48242:131;:::i;:::-;48234:139;;47961:419;;;:::o

Swarm Source

ipfs://bacafa65a5bc103c03eae59bb79c278cdd6658e5610ee27b74951c8fc4dd360e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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