ETH Price: $3,352.06 (+0.52%)

Meta-Life Residence (MLR)
 

Overview

TokenID

126

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

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:
MetaLifeResidence

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.20;

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

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

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

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

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


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

pragma solidity ^0.8.20;


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

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

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

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.20;

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

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    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
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

// File: contracts/ERC721.sol


pragma solidity ^0.8.4;

/// @notice Simple ERC721 implementation with storage hitchhiking.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol)
///
/// @dev Note:
/// The ERC721 standard allows for self-approvals.
/// For performance, this implementation WILL NOT revert for such actions.
/// Please add any checks with overrides if desired.
abstract contract ERC721 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An account can hold up to 4294967295 tokens.
    uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Only the token owner or an approved account can manage the token.
    error NotOwnerNorApproved();

    /// @dev The token does not exist.
    error TokenDoesNotExist();

    /// @dev The token already exists.
    error TokenAlreadyExists();

    /// @dev Cannot query the balance for the zero address.
    error BalanceQueryForZeroAddress();

    /// @dev Cannot mint or transfer to the zero address.
    error TransferToZeroAddress();

    /// @dev The token must be owned by `from`.
    error TransferFromIncorrectOwner();

    /// @dev The recipient's balance has overflowed.
    error AccountBalanceOverflow();

    /// @dev Cannot safely transfer to a contract that does not implement
    /// the ERC721Receiver interface.
    error TransferToNonERC721ReceiverImplementer();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when token `id` is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

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

    /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens.
    event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
    0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`.
    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
    0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership data slot of `id` is given by:
    /// ```
    ///     mstore(0x00, id)
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
    /// ```
    /// Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `extraData`
    ///
    /// The approved address slot is given by: `add(1, ownershipSlot)`.
    ///
    /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip
    ///
    /// The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x1c)
    /// ```
    /// Bits Layout:
    /// - [0..31]   `balance`
    /// - [32..225] `aux`
    ///
    /// The `operator` approval slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
    ///     mstore(0x00, owner)
    ///     let operatorApprovalSlot := keccak256(0x0c, 0x30)
    /// ```
    uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192;

    /// @dev Pre-shifted and pre-masked constant.
    uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC721 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the token collection name.
    function name() public view virtual returns (string memory);

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

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.
    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC721                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function ownerOf(uint256 id) public view virtual returns (address result) {
        result = _ownerOf(id);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(result) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the number of tokens owned by `owner`.
    ///
    /// Requirements:
    /// - `owner` must not be the zero address.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
        // Revert if the `owner` is the zero address.
            if iszero(owner) {
                mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`.
                revert(0x1c, 0x04)
            }
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE)
        }
    }

    /// @dev Returns the account approved to managed token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function getApproved(uint256 id) public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            if iszero(shr(96, shl(96, sload(ownershipSlot)))) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            result := sload(add(1, ownershipSlot))
        }
    }

    /// @dev Sets `account` as the approved account to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - The caller must be the owner of the token,
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Approval} event.
    function approve(address account, uint256 id) public payable virtual {
        _approve(msg.sender, account, id);
    }

    /// @dev Returns whether `operator` is approved to manage the tokens of `owner`.
    function isApprovedForAll(address owner, address operator)
    public
    view
    virtual
    returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x30))
        }
    }

    /// @dev Sets whether `operator` is approved to manage the tokens of the caller.
    ///
    /// Emits a {ApprovalForAll} event.
    function setApprovalForAll(address operator, bool isApproved) public virtual {
        /// @solidity memory-safe-assembly
        assembly {
        // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
        // Update the `isApproved` for (`msg.sender`, `operator`).
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x30), isApproved)
        // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(
            0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator))
            )
        }
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 id) public payable virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
        // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
        // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller()))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
        // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
        // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
        // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
            // Revert if the caller is not the owner, nor approved.
                if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
            // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
        // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
        // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
        // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
        // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - 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 id, bytes calldata data)
    public
    payable
    virtual
    {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Returns true if this contract implements the interface defined by `interfaceId`.
    /// See: https://eips.ethereum.org/EIPS/eip-165
    /// This function call must use less than 30000 gas.
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let s := shr(224, interfaceId)
        // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.
            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL QUERY FUNCTIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if token `id` exists.
    function _exists(uint256 id) internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Returns the owner of token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _ownerOf(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            INTERNAL DATA HITCHHIKING FUNCTIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the auxiliary data for `owner`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _getAux(address owner) internal view virtual returns (uint224 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := shr(32, sload(keccak256(0x0c, 0x1c)))
        }
    }

    /// @dev Set the auxiliary data for `owner` to `value`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _setAux(address owner, uint224 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            let balanceSlot := keccak256(0x0c, 0x1c)
            let packed := sload(balanceSlot)
            sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed)))))
        }
    }

    /// @dev Returns the extra data for token `id`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _getExtraData(uint256 id) internal view virtual returns (uint96 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Sets the extra data for token `id` to `value`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _setExtraData(uint256 id, uint96 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let packed := sload(ownershipSlot)
            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 id) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
        // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
        // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
        // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
        // Revert if the token already exists.
            if shl(96, ownershipPacked) {
                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.
                revert(0x1c, 0x04)
            }
        // Update with the owner.
            sstore(ownershipSlot, or(ownershipPacked, to))
        // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
        // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

    /// @dev Equivalent to `_safeMint(to, id, "")`.
    function _safeMint(address to, uint256 id) internal virtual {
        _safeMint(to, id, "");
    }

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
        _mint(to, id);
        if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_burn(address(0), id)`.
    function _burn(uint256 id) internal virtual {
        _burn(address(0), id);
    }

    /// @dev Destroys token `id`, using `by`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _burn(address by, uint256 id) internal virtual {
        address owner = ownerOf(id);
        _beforeTokenTransfer(owner, address(0), id);
        /// @solidity memory-safe-assembly
        assembly {
        // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
        // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
        // Reload the owner in case it is changed in `_beforeTokenTransfer`.
            owner := shr(96, shl(96, ownershipPacked))
        // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        // Load and check the token approval.
            {
                mstore(0x00, owner)
                let approvedAddress := sload(add(1, ownershipSlot))
            // If `by` is not the zero address, do the authorization check.
            // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
            // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
        // Clear the owner.
            sstore(ownershipSlot, xor(ownershipPacked, owner))
        // Decrement the balance of `owner`.
            {
                let balanceSlot := keccak256(0x0c, 0x1c)
                sstore(balanceSlot, sub(sload(balanceSlot), 1))
            }
        // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id)
        }
        _afterTokenTransfer(owner, address(0), id);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL APPROVAL FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `account` is the owner of token `id`, or is approved to managed it.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function _isApprovedOrOwner(address account, uint256 id)
    internal
    view
    virtual
    returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
        // Clear the upper 96 bits.
            account := shr(96, shl(96, account))
        // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := shr(96, shl(96, sload(ownershipSlot)))
        // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        // Check if `account` is the `owner`.
            if iszero(eq(account, owner)) {
                mstore(0x00, owner)
            // Check if `account` is approved to
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    result := eq(account, sload(add(1, ownershipSlot)))
                }
            }
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _getApproved(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Equivalent to `_approve(address(0), account, id)`.
    function _approve(address account, uint256 id) internal virtual {
        _approve(address(0), account, id);
    }

    /// @dev Sets `account` as the approved account to manage token `id`, using `by`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - If `by` is not the zero address, `by` must be the owner
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Transfer} event.
    function _approve(address by, address account, uint256 id) internal virtual {
        assembly {
        // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            account := and(bitmaskAddress, account)
            by := and(bitmaskAddress, by)
        // Load the owner of the token.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := and(bitmaskAddress, sload(ownershipSlot))
        // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        // If `by` is not the zero address, do the authorization check.
        // Revert if `by` is not the owner, nor approved.
            if iszero(or(iszero(by), eq(by, owner))) {
                mstore(0x00, owner)
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                    revert(0x1c, 0x04)
                }
            }
        // Sets `account` as the approved account to manage `id`.
            sstore(add(1, ownershipSlot), account)
        // Emit the {Approval} event.
            log4(0x00, 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id)
        }
    }

    /// @dev Approve or remove the `operator` as an operator for `by`,
    /// without authorization checks.
    ///
    /// Emits a {ApprovalForAll} event.
    function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
        // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            operator := shr(96, shl(96, operator))
        // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
        // Update the `isApproved` for (`by`, `operator`).
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
            mstore(0x00, by)
            sstore(keccak256(0x0c, 0x30), isApproved)
        // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_transfer(address(0), from, to, id)`.
    function _transfer(address from, address to, uint256 id) internal virtual {
        _transfer(address(0), from, to, id);
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _transfer(address by, address from, address to, uint256 id) internal virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
        // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            by := and(bitmaskAddress, by)
        // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
        // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
        // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
        // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
            // If `by` is not the zero address, do the authorization check.
            // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
            // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
        // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
        // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
        // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
        // Emit the {Transfer} event.
            log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `_safeTransfer(from, to, id, "")`.
    function _safeTransfer(address from, address to, uint256 id) internal virtual {
        _safeTransfer(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - 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 id, bytes memory data)
    internal
    virtual
    {
        _transfer(address(0), from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`.
    function _safeTransfer(address by, address from, address to, uint256 id) internal virtual {
        _safeTransfer(by, from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    /// - 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 by, address from, address to, uint256 id, bytes memory data)
    internal
    virtual
    {
        _transfer(by, from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    HOOKS FOR OVERRIDING                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any token transfers, including minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /// @dev Hook that is called after any token transfers, including minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if `a` has bytecode of non-zero length.
    function _hasCode(address a) private view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := extcodesize(a) // Can handle dirty upper bits.
        }
    }

    /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.
    /// Reverts if the target does not support the function correctly.
    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)
    private
    {
        /// @solidity memory-safe-assembly
        assembly {
        // Prepare the calldata.
            let m := mload(0x40)
            let onERC721ReceivedSelector := 0x150b7a02
            mstore(m, onERC721ReceivedSelector)
            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.
            mstore(add(m, 0x40), shr(96, shl(96, from)))
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), 0x80)
            let n := mload(data)
            mstore(add(m, 0xa0), n)
            if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }
        // Revert if the call reverts.
            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {
                if returndatasize() {
                // Bubble up the revert if the call reverts.
                    returndatacopy(0x00, 0x00, returndatasize())
                    revert(0x00, returndatasize())
                }
                mstore(m, 0)
            }
        // Load the returndata and compare it.
            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

// File: contracts/LibPRNG.sol


pragma solidity ^0.8.4;

/// @notice Library for generating psuedorandom numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibPRNG.sol)
library LibPRNG {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A psuedorandom number state in memory.
    struct PRNG {
        uint256 state;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         OPERATIONS                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Seeds the `prng` with `state`.
    function seed(PRNG memory prng, uint256 state) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(prng, state)
        }
    }

    /// @dev Returns the next psuedorandom uint256.
    /// All bits of the returned uint256 pass the NIST Statistical Test Suite.
    function next(PRNG memory prng) internal pure returns (uint256 result) {
        // We simply use `keccak256` for a great balance between
        // runtime gas costs, bytecode size, and statistical properties.
        //
        // A high-quality LCG with a 32-byte state
        // is only about 30% more gas efficient during runtime,
        // but requires a 32-byte multiplier, which can cause bytecode bloat
        // when this function is inlined.
        //
        // Using this method is about 2x more efficient than
        // `nextRandomness = uint256(keccak256(abi.encode(randomness)))`.
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(prng, 0x20)
            mstore(prng, result)
        }
    }

    /// @dev Returns a psuedorandom uint256, uniformly distributed
    /// between 0 (inclusive) and `upper` (exclusive).
    /// If your modulus is big, this method is recommended
    /// for uniform sampling to avoid modulo bias.
    /// For uniform sampling across all uint256 values,
    /// or for small enough moduli such that the bias is neligible,
    /// use {next} instead.
    function uniform(PRNG memory prng, uint256 upper) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := keccak256(prng, 0x20)
                mstore(prng, result)
                if iszero(lt(result, mod(sub(0, upper), upper))) { break }
            }
            result := mod(result, upper)
        }
    }

    /// @dev Shuffles the array in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, uint256[] memory a) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(a)
            let w := not(0)
            let mask := shr(128, w)
            if n {
                for { a := add(a, 0x20) } 1 {} {
                // We can just directly use `keccak256`, cuz
                // the other approaches don't save much.
                    let r := keccak256(prng, 0x20)
                    mstore(prng, r)

                // Note that there will be a very tiny modulo bias
                // if the length of the array is not a power of 2.
                // For all practical purposes, it is negligible
                // and will not be a fairness or security concern.
                    {
                        let j := add(a, shl(5, mod(shr(128, r), n)))
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let i := add(a, shl(5, n))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                    }

                    {
                        let j := add(a, shl(5, mod(and(r, mask), n)))
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let i := add(a, shl(5, n))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                    }
                }
            }
        }
    }

    /// @dev Shuffles the bytes in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, bytes memory a) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(a)
            let w := not(0)
            let mask := shr(128, w)
            if n {
                let b := add(a, 0x01)
                for { a := add(a, 0x20) } 1 {} {
                // We can just directly use `keccak256`, cuz
                // the other approaches don't save much.
                    let r := keccak256(prng, 0x20)
                    mstore(prng, r)

                // Note that there will be a very tiny modulo bias
                // if the length of the array is not a power of 2.
                // For all practical purposes, it is negligible
                // and will not be a fairness or security concern.
                    {
                        let o := mod(shr(128, r), n)
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let t := mload(add(b, n))
                        mstore8(add(a, n), mload(add(b, o)))
                        mstore8(add(a, o), t)
                    }

                    {
                        let o := mod(and(r, mask), n)
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let t := mload(add(b, n))
                        mstore8(add(a, n), mload(add(b, o)))
                        mstore8(add(a, o), t)
                    }
                }
            }
        }
    }
}

// File: contracts/LibString.sol


pragma solidity ^0.8.4;

/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
library LibString {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The `length` of the output is too small to contain all the hex digits.
    error HexLengthInsufficient();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when the `search` is not found in the string.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     DECIMAL OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
        // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
        // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
        // We will need 1 word for the trailing zeros padding, 1 word for the length,
        // and 3 words for a maximum of 78 digits.
            str := add(mload(0x40), 0x80)
        // Update the free memory pointer to allocate.
            mstore(0x40, add(str, 0x20))
        // Zeroize the slot after the string.
            mstore(str, 0)

        // Cache the end of the memory to calculate the length later.
            let end := str

            let w := not(0) // Tsk.
        // We write the string from rightmost digit to leftmost digit.
        // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `sub(str, 1)`.
            // Write the character to the pointer.
            // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
            // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                if iszero(temp) { break }
            }

            let length := sub(end, str)
        // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
        // Store the length.
            mstore(str, length)
        }
    }

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(int256 value) internal pure returns (string memory str) {
        if (value >= 0) {
            return toString(uint256(value));
        }
    unchecked {
        str = toString(uint256(-value));
    }
        /// @solidity memory-safe-assembly
        assembly {
        // We still have some spare memory space on the left,
        // as we have allocated 3 words (96 bytes) for up to 78 digits.
            let length := mload(str) // Load the string length.
            mstore(str, 0x2d) // Store the '-' character.
            str := sub(str, 1) // Move back the string pointer by a byte.
            mstore(str, add(length, 1)) // Update the string length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   HEXADECIMAL OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2 + 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value, length);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexStringNoPrefix(uint256 value, uint256 length)
    internal
    pure
    returns (string memory str)
    {
        /// @solidity memory-safe-assembly
        assembly {
        // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
        // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
        // We add 0x20 to the total and round down to a multiple of 0x20.
        // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
            str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))
        // Allocate the memory.
            mstore(0x40, add(str, 0x20))
        // Zeroize the slot after the string.
            mstore(str, 0)

        // Cache the end to calculate the length later.
            let end := str
        // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let start := sub(str, add(length, length))
            let w := not(1) // Tsk.
            let temp := value
        // We write the string from rightmost digit to leftmost digit.
        // The following is essentially a do-while loop that also handles the zero case.
            for {} 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(xor(str, start)) { break }
            }

            if temp {
            // Store the function selector of `HexLengthInsufficient()`.
                mstore(0x00, 0x2194895a)
            // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

        // Compute the string's length.
            let strLength := sub(end, str)
        // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2 + 2` bytes.
    function toHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2` bytes.
    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
        // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
        // 0x02 bytes for the prefix, and 0x40 bytes for the digits.
        // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
            str := add(mload(0x40), 0x80)
        // Allocate the memory.
            mstore(0x40, add(str, 0x20))
        // Zeroize the slot after the string.
            mstore(str, 0)

        // Cache the end to calculate the length later.
            let end := str
        // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let w := not(1) // Tsk.
        // We write the string from rightmost digit to leftmost digit.
        // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(temp) { break }
            }

        // Compute the string's length.
            let strLength := sub(end, str)
        // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
    /// and the alphabets are capitalized conditionally according to
    /// https://eips.ethereum.org/EIPS/eip-55
    function toHexStringChecksummed(address value) internal pure returns (string memory str) {
        str = toHexString(value);
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
            let o := add(str, 0x22)
            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
            let t := shl(240, 136) // `0b10001000 << 240`
            for { let i := 0 } 1 {} {
                mstore(add(i, i), mul(t, byte(i, hashed)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
            o := add(o, 0x20)
            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function toHexString(address value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

        // Allocate the memory.
        // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
        // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
        // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

        // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

        // We write the string from rightmost digit to leftmost digit.
        // The following is essentially a do-while loop that also handles the zero case.
            for { let i := 0 } 1 {} {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexString(bytes memory raw) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(raw);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(raw)
            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
            mstore(str, add(length, length)) // Store the length of the output.

        // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let o := add(str, 0x20)
            let end := add(raw, length)

            for {} iszero(eq(raw, end)) {} {
                raw := add(raw, 1)
                mstore8(add(o, 1), mload(and(mload(raw), 15)))
                mstore8(o, mload(and(shr(4, mload(raw)), 15)))
                o := add(o, 2)
            }
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RUNE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of UTF characters in the string.
    function runeCount(string memory s) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(s) {
                mstore(0x00, div(not(0), 255))
                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
                let o := add(s, 0x20)
                let end := add(o, mload(s))
                for { result := 1 } 1 { result := add(result, 1) } {
                    o := add(o, byte(0, mload(shr(250, mload(o)))))
                    if iszero(lt(o, end)) { break }
                }
            }
        }
    }

    /// @dev Returns if this string is a 7-bit ASCII string.
    /// (i.e. all characters codes are in [0..127])
    function is7BitASCII(string memory s) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(7, div(not(0), 255))
            result := 1
            let n := mload(s)
            if n {
                let o := add(s, 0x20)
                let end := add(o, n)
                let last := mload(end)
                mstore(end, 0)
                for {} 1 {} {
                    if and(mask, mload(o)) {
                        result := 0
                        break
                    }
                    o := add(o, 0x20)
                    if iszero(lt(o, end)) { break }
                }
                mstore(end, last)
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   BYTE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance and bytecode compactness, all indices of the following operations
    // are byte (ASCII) offsets, not UTF character offsets.

    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
    function replace(string memory subject, string memory search, string memory replacement)
    internal
    pure
    returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)
            let replacementLength := mload(replacement)

            subject := add(subject, 0x20)
            search := add(search, 0x20)
            replacement := add(replacement, 0x20)
            result := add(mload(0x40), 0x20)

            let subjectEnd := add(subject, subjectLength)
            if iszero(gt(searchLength, subjectLength)) {
                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                // Whether the first `searchLength % 32` bytes of
                // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                mstore(result, t)
                                result := add(result, 1)
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                    // Copy the `replacement` one word at a time.
                        for { let o := 0 } 1 {} {
                            mstore(add(result, o), mload(add(replacement, o)))
                            o := add(o, 0x20)
                            if iszero(lt(o, replacementLength)) { break }
                        }
                        result := add(result, replacementLength)
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    mstore(result, t)
                    result := add(result, 1)
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
            }

            let resultRemainder := result
            result := add(mload(0x40), 0x20)
            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
        // Copy the rest of the string one word at a time.
            for {} lt(subject, subjectEnd) {} {
                mstore(resultRemainder, mload(subject))
                resultRemainder := add(resultRemainder, 0x20)
                subject := add(subject, 0x20)
            }
            result := sub(result, 0x20)
            let last := add(add(result, 0x20), k) // Zeroize the slot after the string.
            mstore(last, 0)
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
            mstore(result, k) // Store the length.
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search, uint256 from)
    internal
    pure
    returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let subjectLength := mload(subject) } 1 {} {
                if iszero(mload(search)) {
                    if iszero(gt(from, subjectLength)) {
                        result := from
                        break
                    }
                    result := subjectLength
                    break
                }
                let searchLength := mload(search)
                let subjectStart := add(subject, 0x20)

                result := not(0) // Initialize to `NOT_FOUND`.

                subject := add(subjectStart, from)
                let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)

                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(add(search, 0x20))

                if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }

                if iszero(lt(searchLength, 0x20)) {
                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                        if iszero(shr(m, xor(mload(subject), s))) {
                            if eq(keccak256(subject, searchLength), h) {
                                result := sub(subject, subjectStart)
                                break
                            }
                        }
                        subject := add(subject, 1)
                        if iszero(lt(subject, end)) { break }
                    }
                    break
                }
                for {} 1 {} {
                    if iszero(shr(m, xor(mload(subject), s))) {
                        result := sub(subject, subjectStart)
                        break
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search)
    internal
    pure
    returns (uint256 result)
    {
        result = indexOf(subject, search, 0);
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search, uint256 from)
    internal
    pure
    returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := not(0) // Initialize to `NOT_FOUND`.
                let searchLength := mload(search)
                if gt(searchLength, mload(subject)) { break }
                let w := result

                let fromMax := sub(mload(subject), searchLength)
                if iszero(gt(fromMax, from)) { from := fromMax }

                let end := add(add(subject, 0x20), w)
                subject := add(add(subject, 0x20), from)
                if iszero(gt(subject, end)) { break }
            // As this function is not too often used,
            // we shall simply use keccak256 for smaller bytecode size.
                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                    if eq(keccak256(subject, searchLength), h) {
                        result := sub(subject, add(end, 1))
                        break
                    }
                    subject := add(subject, w) // `sub(subject, 1)`.
                    if iszero(gt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search)
    internal
    pure
    returns (uint256 result)
    {
        result = lastIndexOf(subject, search, uint256(int256(-1)));
    }

    /// @dev Returns whether `subject` starts with `search`.
    function startsWith(string memory subject, string memory search)
    internal
    pure
    returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
        // Just using keccak256 directly is actually cheaper.
        // forgefmt: disable-next-item
            result := and(
            iszero(gt(searchLength, mload(subject))),
            eq(
            keccak256(add(subject, 0x20), searchLength),
            keccak256(add(search, 0x20), searchLength)
            )
            )
        }
    }

    /// @dev Returns whether `subject` ends with `search`.
    function endsWith(string memory subject, string memory search)
    internal
    pure
    returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            let subjectLength := mload(subject)
        // Whether `search` is not longer than `subject`.
            let withinRange := iszero(gt(searchLength, subjectLength))
        // Just using keccak256 directly is actually cheaper.
        // forgefmt: disable-next-item
            result := and(
            withinRange,
            eq(
            keccak256(
            // `subject + 0x20 + max(subjectLength - searchLength, 0)`.
            add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
            searchLength
            ),
            keccak256(add(search, 0x20), searchLength)
            )
            )
        }
    }

    /// @dev Returns `subject` repeated `times`.
    function repeat(string memory subject, uint256 times)
    internal
    pure
    returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(or(iszero(times), iszero(subjectLength))) {
                subject := add(subject, 0x20)
                result := mload(0x40)
                let output := add(result, 0x20)
                for {} 1 {} {
                // Copy the `subject` one word at a time.
                    for { let o := 0 } 1 {} {
                        mstore(add(output, o), mload(add(subject, o)))
                        o := add(o, 0x20)
                        if iszero(lt(o, subjectLength)) { break }
                    }
                    output := add(output, subjectLength)
                    times := sub(times, 1)
                    if iszero(times) { break }
                }
                mstore(output, 0) // Zeroize the slot after the string.
                let resultLength := sub(output, add(result, 0x20))
                mstore(result, resultLength) // Store the length.
            // Allocate the memory.
                mstore(0x40, add(result, add(resultLength, 0x20)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function slice(string memory subject, uint256 start, uint256 end)
    internal
    pure
    returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(gt(subjectLength, end)) { end := subjectLength }
            if iszero(gt(subjectLength, start)) { start := subjectLength }
            if lt(start, end) {
                result := mload(0x40)
                let resultLength := sub(end, start)
                mstore(result, resultLength)
                subject := add(subject, start)
                let w := not(0x1f)
            // Copy the `subject` one word at a time, backwards.
                for { let o := and(add(resultLength, 0x1f), w) } 1 {} {
                    mstore(add(result, o), mload(add(subject, o)))
                    o := add(o, w) // `sub(o, 0x20)`.
                    if iszero(o) { break }
                }
            // Zeroize the slot after the string.
                mstore(add(add(result, 0x20), resultLength), 0)
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
                mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
    /// `start` is a byte offset.
    function slice(string memory subject, uint256 start)
    internal
    pure
    returns (string memory result)
    {
        result = slice(subject, start, uint256(int256(-1)));
    }

    /// @dev Returns all the indices of `search` in `subject`.
    /// The indices are byte offsets.
    function indicesOf(string memory subject, string memory search)
    internal
    pure
    returns (uint256[] memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)

            if iszero(gt(searchLength, subjectLength)) {
                subject := add(subject, 0x20)
                search := add(search, 0x20)
                result := add(mload(0x40), 0x20)

                let subjectStart := subject
                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                // Whether the first `searchLength % 32` bytes of
                // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                    // Append to `result`.
                        mstore(result, sub(subject, subjectStart))
                        result := add(result, 0x20)
                    // Advance `subject` by `searchLength`.
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
                let resultEnd := result
            // Assign `result` to the free memory pointer.
                result := mload(0x40)
            // Store the length of `result`.
                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
            // Allocate memory for result.
            // We allocate one more word, so this array can be recycled for {split}.
                mstore(0x40, add(resultEnd, 0x20))
            }
        }
    }

    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
    function split(string memory subject, string memory delimiter)
    internal
    pure
    returns (string[] memory result)
    {
        uint256[] memory indices = indicesOf(subject, delimiter);
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            let indexPtr := add(indices, 0x20)
            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
            mstore(add(indicesEnd, w), mload(subject))
            mstore(indices, add(mload(indices), 1))
            let prevIndex := 0
            for {} 1 {} {
                let index := mload(indexPtr)
                mstore(indexPtr, 0x60)
                if iszero(eq(index, prevIndex)) {
                    let element := mload(0x40)
                    let elementLength := sub(index, prevIndex)
                    mstore(element, elementLength)
                // Copy the `subject` one word at a time, backwards.
                    for { let o := and(add(elementLength, 0x1f), w) } 1 {} {
                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
                        o := add(o, w) // `sub(o, 0x20)`.
                        if iszero(o) { break }
                    }
                // Zeroize the slot after the string.
                    mstore(add(add(element, 0x20), elementLength), 0)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                    mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))
                // Store the `element` into the array.
                    mstore(indexPtr, element)
                }
                prevIndex := add(index, mload(delimiter))
                indexPtr := add(indexPtr, 0x20)
                if iszero(lt(indexPtr, indicesEnd)) { break }
            }
            result := indices
            if iszero(mload(delimiter)) {
                result := add(indices, 0x20)
                mstore(result, sub(mload(indices), 2))
            }
        }
    }

    /// @dev Returns a concatenated string of `a` and `b`.
    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.
    function concat(string memory a, string memory b)
    internal
    pure
    returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            result := mload(0x40)
            let aLength := mload(a)
        // Copy `a` one word at a time, backwards.
            for { let o := and(add(mload(a), 0x20), w) } 1 {} {
                mstore(add(result, o), mload(add(a, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let bLength := mload(b)
            let output := add(result, mload(a))
        // Copy `b` one word at a time, backwards.
            for { let o := and(add(bLength, 0x20), w) } 1 {} {
                mstore(add(output, o), mload(add(b, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let totalLength := add(aLength, bLength)
            let last := add(add(result, 0x20), totalLength)
        // Zeroize the slot after the string.
            mstore(last, 0)
        // Stores the length.
            mstore(result, totalLength)
        // Allocate memory for the length and the bytes,
        // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 0x1f), w))
        }
    }

    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function toCase(string memory subject, bool toUpper)
    internal
    pure
    returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(subject)
            if length {
                result := add(mload(0x40), 0x20)
                subject := add(subject, 1)
                let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)
                let w := not(0)
                for { let o := length } 1 {} {
                    o := add(o, w)
                    let b := and(0xff, mload(add(subject, o)))
                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
                    if iszero(o) { break }
                }
                result := mload(0x40)
                mstore(result, length) // Store the length.
                let last := add(add(result, 0x20), length)
                mstore(last, 0) // Zeroize the slot after the string.
                mstore(0x40, add(last, 0x20)) // Allocate the memory.
            }
        }
    }

    /// @dev Returns a lowercased copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function lower(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, false);
    }

    /// @dev Returns an UPPERCASED copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function upper(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, true);
    }

    /// @dev Escapes the string to be used within HTML tags.
    function escapeHTML(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {
                let end := add(s, mload(s))
                result := add(mload(0x40), 0x20)
            // Store the bytes of the packed offsets and strides into the scratch space.
            // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
                mstore(0x1f, 0x900094)
                mstore(0x08, 0xc0000000a6ab)
            // Store "&quot;&amp;&#39;&lt;&gt;" into the scratch space.
                mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
            } iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
            // Not in `["\"","'","&","<",">"]`.
                if iszero(and(shl(c, 1), 0x500000c400000000)) {
                    mstore8(result, c)
                    result := add(result, 1)
                    continue
                }
                let t := shr(248, mload(c))
                mstore(result, mload(and(t, 0x1f)))
                result := add(result, shr(5, t))
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    function escapeJSON(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {
                let end := add(s, mload(s))
                result := add(mload(0x40), 0x20)
            // Store "\\u0000" in scratch space.
            // Store "0123456789abcdef" in scratch space.
            // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
            // into the scratch space.
                mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
            // Bitmask for detecting `["\"","\\"]`.
                let e := or(shl(0x22, 1), shl(0x5c, 1))
            } iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                if iszero(lt(c, 0x20)) {
                    if iszero(and(shl(c, 1), e)) {
                    // Not in `["\"","\\"]`.
                        mstore8(result, c)
                        result := add(result, 1)
                        continue
                    }
                    mstore8(result, 0x5c) // "\\".
                    mstore8(add(result, 1), c)
                    result := add(result, 2)
                    continue
                }
                if iszero(and(shl(c, 1), 0x3700)) {
                // Not in `["\b","\t","\n","\f","\d"]`.
                    mstore8(0x1d, mload(shr(4, c))) // Hex value.
                    mstore8(0x1e, mload(and(c, 15))) // Hex value.
                    mstore(result, mload(0x19)) // "\\u00XX".
                    result := add(result, 6)
                    continue
                }
                mstore8(result, 0x5c) // "\\".
                mstore8(add(result, 1), mload(add(c, 8)))
                result := add(result, 2)
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Returns whether `a` equals `b`.
    function eq(string memory a, string memory b) internal pure returns (bool result) {
        assembly {
            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
        }
    }

    /// @dev Packs a single string with its length into a single word.
    /// Returns `bytes32(0)` if the length is zero or greater than 31.
    function packOne(string memory a) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
        // We don't need to zero right pad the string,
        // since this is our own custom non-standard packing scheme.
            result :=
            mul(
            // Load the length and the bytes.
            mload(add(a, 0x1f)),
            // `length != 0 && length < 32`. Abuses underflow.
            // Assumes that the length is valid and within the block gas limit.
            lt(sub(mload(a), 1), 0x1f)
            )
        }
    }

    /// @dev Unpacks a string packed using {packOne}.
    /// Returns the empty string if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packOne}, the output behaviour is undefined.
    function unpackOne(bytes32 packed) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
        // Grab the free memory pointer.
            result := mload(0x40)
        // Allocate 2 words (1 for the length, 1 for the bytes).
            mstore(0x40, add(result, 0x40))
        // Zeroize the length slot.
            mstore(result, 0)
        // Store the length and bytes.
            mstore(add(result, 0x1f), packed)
        // Right pad with zeroes.
            mstore(add(add(result, 0x20), mload(result)), 0)
        }
    }

    /// @dev Packs two strings with their lengths into a single word.
    /// Returns `bytes32(0)` if combined length is zero or greater than 30.
    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let aLength := mload(a)
        // We don't need to zero right pad the strings,
        // since this is our own custom non-standard packing scheme.
            result :=
            mul(
            // Load the length and the bytes of `a` and `b`.
            or(
            shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
            mload(sub(add(b, 0x1e), aLength))
            ),
            // `totalLength != 0 && totalLength < 31`. Abuses underflow.
            // Assumes that the lengths are valid and within the block gas limit.
            lt(sub(add(aLength, mload(b)), 1), 0x1e)
            )
        }
    }

    /// @dev Unpacks strings packed using {packTwo}.
    /// Returns the empty strings if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packTwo}, the output behaviour is undefined.
    function unpackTwo(bytes32 packed)
    internal
    pure
    returns (string memory resultA, string memory resultB)
    {
        /// @solidity memory-safe-assembly
        assembly {
        // Grab the free memory pointer.
            resultA := mload(0x40)
            resultB := add(resultA, 0x40)
        // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
            mstore(0x40, add(resultB, 0x40))
        // Zeroize the length slots.
            mstore(resultA, 0)
            mstore(resultB, 0)
        // Store the lengths and bytes.
            mstore(add(resultA, 0x1f), packed)
            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
        // Right pad with zeroes.
            mstore(add(add(resultA, 0x20), mload(resultA)), 0)
            mstore(add(add(resultB, 0x20), mload(resultB)), 0)
        }
    }

    /// @dev Directly returns `a` without copying.
    function directReturn(string memory a) internal pure {
        assembly {
        // Assumes that the string does not start from the scratch space.
            let retStart := sub(a, 0x20)
            let retSize := add(mload(a), 0x40)
        // Right pad with zeroes. Just in case the string is produced
        // by a method that doesn't zero right pad.
            mstore(add(retStart, retSize), 0)
        // Store the return offset.
            mstore(retStart, 0x20)
        // End the transaction, returning the string.
            return(retStart, retSize)
        }
    }
}

// File: contracts/ERC721r.sol


pragma solidity ^0.8.17;

//import "@openzeppelin/contracts/token/ERC721/ERC721.sol";



//import {ERC721} from "solady/src/tokens/ERC721.sol";
//import {LibPRNG} from "solady/src/utils/LibPRNG.sol";
//import {LibString} from "solady/src/utils/LibString.sol";


abstract contract ERC721r is ERC721 {
    using LibPRNG for LibPRNG.PRNG;
    using LibString for uint256;

    error ContractsCannotMint();
    error MustMintAtLeastOneToken();
    error NotEnoughAvailableTokens();

    string private _name;
    string private _symbol;

    mapping(uint256 => uint256) private _availableTokens;
    uint256 public remainingSupply;

    uint256 public immutable maxSupply;

    constructor(string memory name_, string memory symbol_, uint256 maxSupply_) {
        _name = name_;
        _symbol = symbol_;
        maxSupply = maxSupply_;
        remainingSupply = maxSupply_;
    }

    function totalSupply() public view virtual returns (uint256) {
        return maxSupply - remainingSupply;
    }

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function numberMinted(address minter) public view virtual returns (uint32) {
        return uint32(ERC721._getAux(minter) >> 192);
    }

    function _mintRandom(address to, uint256 _numToMint) internal virtual {
        if (msg.sender != tx.origin) revert ContractsCannotMint();
        if (_numToMint == 0) revert MustMintAtLeastOneToken();
        if (remainingSupply < _numToMint) revert NotEnoughAvailableTokens();

        LibPRNG.PRNG memory prng = LibPRNG.PRNG(uint256(keccak256(abi.encodePacked(
            block.timestamp, block.prevrandao
        ))));

        uint256 updatedRemainingSupply = remainingSupply;

        for (uint256 i; i < _numToMint; ) {
            uint256 randomIndex = prng.uniform(updatedRemainingSupply);

            uint256 tokenId = getAvailableTokenAtIndex(randomIndex, updatedRemainingSupply);

            _mint(to, tokenId);

            --updatedRemainingSupply;

        unchecked {++i;}
        }

        _incrementAmountMinted(to, uint32(_numToMint));
        remainingSupply = updatedRemainingSupply;
    }

    // Must be called in descending order of index
    function _mintAtIndex(address to, uint256 index) internal virtual {
        if (msg.sender != tx.origin) revert ContractsCannotMint();
        if (remainingSupply == 0) revert NotEnoughAvailableTokens();

        uint256 tokenId = getAvailableTokenAtIndex(index, remainingSupply);

        --remainingSupply;
        _incrementAmountMinted(to, 1);

        _mint(to, tokenId);
    }

    // Implements https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. Code taken from CryptoPhunksV2
    function getAvailableTokenAtIndex(uint256 indexToUse, uint256 updatedNumAvailableTokens)
    private
    returns (uint256 result)
    {
        uint256 valAtIndex = _availableTokens[indexToUse];
        uint256 lastIndex = updatedNumAvailableTokens - 1;
        uint256 lastValInArray = _availableTokens[lastIndex];

        result = valAtIndex == 0 ? indexToUse : valAtIndex;

        if (indexToUse != lastIndex) {
            _availableTokens[indexToUse] = lastValInArray == 0 ? lastIndex : lastValInArray;
        }

        if (lastValInArray != 0) {
            delete _availableTokens[lastIndex];
        }
    }

    function _setExtraAddressData(address minter, uint192 extraData) internal virtual {
        uint32 numMinted = numberMinted(minter);

        ERC721._setAux(
            minter,
            uint224((uint256(numMinted) << 192)) | uint224(extraData)
        );
    }

    function _getAddressExtraData(address minter) internal view virtual returns (uint192) {
        return uint192(_getAux(minter));
    }

    function _incrementAmountMinted(address minter, uint32 newMints) private {
        uint32 numMinted = numberMinted(minter);
        uint32 newMintNumMinted = numMinted + uint32(newMints);
        uint224 auxData = ERC721._getAux(minter);

        ERC721._setAux(
            minter,
            uint224(uint256(newMintNumMinted) << 192) | uint224(uint192(auxData))
        );
    }
}

// File: contracts/MetaLifeResidence.sol


pragma solidity 0.8.23;




contract MetaLifeResidence is ReentrancyGuard, Ownable, ERC721r {

  using Strings for uint256;
  string public baseURI;

  address public originOwner = 0x4aBd9bd6f92654b45C42A9e0f9a3D23C7c14406e;
  address payable public collector;

  struct Eligibility {
    uint8 total;
    uint8 claimed;
  }

  mapping(address => Eligibility) public allowlist;
  event Minted(address indexed from, uint256 timestamp);

  constructor() ERC721r('Meta-Life Residence', 'MLR', 7_00) Ownable(originOwner){}

  function withdrawAll() public payable onlyOwner {
    collector.transfer(address(this).balance);
  }

  function setCollector(address payable _newCollector) public onlyOwner {
    collector = _newCollector;
  }

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

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

  function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    require(_exists(tokenId), 'unknow token');
    string memory uri = _baseURI();
    return bytes(uri).length > 0 ? string(abi.encodePacked(uri, tokenId.toString())) : "";
  }

  function tokenExist(uint256 tokenId) public view returns(bool) {
    return _exists(tokenId);
  }

  function remaining(address wallet) public view virtual returns (uint8) {
    return allowlist[wallet].total - allowlist[wallet].claimed;
  }

  function addAllowlist(address[] calldata _toAddAddresses, uint8[] calldata _quantities) external onlyOwner {
    require(_toAddAddresses.length == _quantities.length, 'Nb address and nb quantities must be equal');
    for (uint i = 0; i < _toAddAddresses.length; i++) {
      allowlist[_toAddAddresses[i]].total += _quantities[i];
    }
  }

  function removeAllowlist(address[] calldata _addresses, uint8[] calldata _quantities) external onlyOwner {
    require(_addresses.length == _quantities.length, 'Nb address and nb quantities must be equal');
    for (uint i = 0; i < _addresses.length; i++) {
      if (remaining(_addresses[i]) - _quantities[i] >= 0) {
        allowlist[_addresses[i]].total -= _quantities[i];
      }
    }
  }

  function mintRandom(uint8 _quantities) external {
    require(remaining(msg.sender) > 0, "Not eligible");
    require(remaining(msg.sender) >= _quantities, "Not enough claimable tokens");
    require(maxSupply >= totalSupply() + _quantities, "Supply limit exceed");
    allowlist[msg.sender].claimed += _quantities;
    _mintRandom(msg.sender, _quantities);
    emit Minted(msg.sender, block.timestamp);
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"ContractsCannotMint","type":"error"},{"inputs":[],"name":"MustMintAtLeastOneToken","type":"error"},{"inputs":[],"name":"NotEnoughAvailableTokens","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Minted","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"_setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_toAddAddresses","type":"address[]"},{"internalType":"uint8[]","name":"_quantities","type":"uint8[]"}],"name":"addAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowlist","outputs":[{"internalType":"uint8","name":"total","type":"uint8"},{"internalType":"uint8","name":"claimed","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collector","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"result","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":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quantities","type":"uint8"}],"name":"mintRandom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"originOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"remaining","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remainingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint8[]","name":"_quantities","type":"uint8[]"}],"name":"removeAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newCollector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenExist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"payable","type":"function"}]

60a0604052734abd9bd6f92654b45c42a9e0f9a3d23c7c14406e60075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801562000064575f80fd5b506040518060400160405280601381526020017f4d6574612d4c696665205265736964656e6365000000000000000000000000008152506040518060400160405280600381526020017f4d4c5200000000000000000000000000000000000000000000000000000000008152506102bc60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660015f819055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000170575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001679190620002c4565b60405180910390fd5b6200018181620001be60201b60201c565b50826002908162000193919062000543565b508160039081620001a5919062000543565b5080608081815250508060058190555050505062000627565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002ac8262000281565b9050919050565b620002be81620002a0565b82525050565b5f602082019050620002d95f830184620002b3565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200035b57607f821691505b60208210810362000371576200037062000316565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620003d57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000398565b620003e1868362000398565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200042b620004256200041f84620003f9565b62000402565b620003f9565b9050919050565b5f819050919050565b62000446836200040b565b6200045e620004558262000432565b848454620003a4565b825550505050565b5f90565b6200047462000466565b620004818184846200043b565b505050565b5b81811015620004a8576200049c5f826200046a565b60018101905062000487565b5050565b601f821115620004f757620004c18162000377565b620004cc8462000389565b81016020851015620004dc578190505b620004f4620004eb8562000389565b83018262000486565b50505b505050565b5f82821c905092915050565b5f620005195f1984600802620004fc565b1980831691505092915050565b5f62000533838362000508565b9150826002028217905092915050565b6200054e82620002df565b67ffffffffffffffff8111156200056a5762000569620002e9565b5b62000576825462000343565b62000583828285620004ac565b5f60209050601f831160018114620005b9575f8415620005a4578287015190505b620005b0858262000526565b8655506200061f565b601f198416620005c98662000377565b5f5b82811015620005f257848901518255600182019150602085019450602081019050620005cb565b868310156200061257848901516200060e601f89168262000508565b8355505b6001600288020188555050505b505050505050565b608051612f256200064e5f395f818161088001528181610ac501526113d00152612f255ff3fe6080604052600436106101e2575f3560e01c8063853828b611610101578063c87b56dd11610094578063dc33e68111610063578063dc33e68114610699578063e985e9c5146106d5578063f2fde38b14610711578063fb5b82d014610739576101e2565b8063c87b56dd146105cd578063cc0c523614610609578063d5abeb0114610645578063da0239a61461066f576101e2565b8063a22cb465116100d0578063a22cb46514610510578063a7cd52cb14610538578063b399b0bc14610575578063b88d4fde146105b1576101e2565b8063853828b6146104885780638da5cb5b14610492578063913e77ad146104bc57806395d89b41146104e6576101e2565b806331b5b907116101795780636352211e116101485780636352211e146103d05780636c0360eb1461040c57806370a0823114610436578063715018a614610472576101e2565b806331b5b9071461033c5780633fb580f71461036457806342842e0e1461038c578063594bf62b146103a8576101e2565b806318160ddd116101b557806318160ddd146102a457806323b872dd146102ce578063282e7811146102ea5780632db5b8e714610314576101e2565b806301ffc9a7146101e657806306fdde0314610222578063081812fc1461024c578063095ea7b314610288575b5f80fd5b3480156101f1575f80fd5b5061020c60048036038101906102079190611f3d565b610761565b6040516102199190611f82565b60405180910390f35b34801561022d575f80fd5b50610236610785565b6040516102439190612025565b60405180910390f35b348015610257575f80fd5b50610272600480360381019061026d9190612078565b610815565b60405161027f91906120e2565b60405180910390f35b6102a2600480360381019061029d9190612125565b61086b565b005b3480156102af575f80fd5b506102b861087a565b6040516102c59190612172565b60405180910390f35b6102e860048036038101906102e3919061218b565b6108ae565b005b3480156102f5575f80fd5b506102fe6109ea565b60405161030b91906120e2565b60405180910390f35b34801561031f575f80fd5b5061033a60048036038101906103359190612211565b610a0f565b005b348015610347575f80fd5b50610362600480360381019061035d9190612368565b610bf6565b005b34801561036f575f80fd5b5061038a60048036038101906103859190612461565b610c11565b005b6103a660048036038101906103a1919061218b565b610d42565b005b3480156103b3575f80fd5b506103ce60048036038101906103c99190612461565b610d7b565b005b3480156103db575f80fd5b506103f660048036038101906103f19190612078565b610f18565b60405161040391906120e2565b60405180910390f35b348015610417575f80fd5b50610420610f3b565b60405161042d9190612025565b60405180910390f35b348015610441575f80fd5b5061045c600480360381019061045791906124df565b610fc7565b6040516104699190612172565b60405180910390f35b34801561047d575f80fd5b50610486611014565b005b610490611027565b005b34801561049d575f80fd5b506104a6611096565b6040516104b391906120e2565b60405180910390f35b3480156104c7575f80fd5b506104d06110be565b6040516104dd919061252a565b60405180910390f35b3480156104f1575f80fd5b506104fa6110e3565b6040516105079190612025565b60405180910390f35b34801561051b575f80fd5b506105366004803603810190610531919061256d565b611173565b005b348015610543575f80fd5b5061055e600480360381019061055991906124df565b6111c6565b60405161056c9291906125ba565b60405180910390f35b348015610580575f80fd5b5061059b600480360381019061059691906124df565b6111fe565b6040516105a891906125e1565b60405180910390f35b6105cb60048036038101906105c6919061264f565b6112a9565b005b3480156105d8575f80fd5b506105f360048036038101906105ee9190612078565b611319565b6040516106009190612025565b60405180910390f35b348015610614575f80fd5b5061062f600480360381019061062a9190612078565b6113bd565b60405161063c9190611f82565b60405180910390f35b348015610650575f80fd5b506106596113ce565b6040516106669190612172565b60405180910390f35b34801561067a575f80fd5b506106836113f2565b6040516106909190612172565b60405180910390f35b3480156106a4575f80fd5b506106bf60048036038101906106ba91906124df565b6113f8565b6040516106cc91906126f1565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f6919061270a565b61142b565b6040516107089190611f82565b60405180910390f35b34801561071c575f80fd5b50610737600480360381019061073291906124df565b61144d565b005b348015610744575f80fd5b5061075f600480360381019061075a9190612772565b6114d1565b005b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b606060028054610794906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546107c0906127ca565b801561080b5780601f106107e25761010080835404028352916020019161080b565b820191905f5260205f20905b8154815290600101906020018083116107ee57829003601f168201915b5050505050905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b60601c61085e5763ceea21b65f526004601cfd5b8060010154915050919050565b61087633838361151c565b5050565b5f6005547f00000000000000000000000000000000000000000000000000000000000000006108a99190612827565b905090565b6108b98383836115cc565b5f1960601c83811693508281169250815f52337f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054808316868114810261092657806109195763ceea21b65f526004601cfd5b63a11481005f526004601cfd5b856109385763ea553b345f526004601cfd5b865f52826001015480331488331417610963576030600c205461096257634b6e7f185f526004601cfd5b5b8015610970575f84600101555b5085871882188355601c600c206001815403815550855f52601c600c20600181540163ffffffff81166109aa576301336cea5f526004601cfd5b80825550508486887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4505050506109e58383836115d1565b505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610a19336111fe565b60ff1611610a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a53906128a4565b60405180910390fd5b8060ff16610a69336111fe565b60ff161015610aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa49061290c565b60405180910390fd5b8060ff16610ab961087a565b610ac3919061292a565b7f00000000000000000000000000000000000000000000000000000000000000001015610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906129a7565b60405180910390fd5b8060095f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160018282829054906101000a900460ff16610b8091906129c5565b92506101000a81548160ff021916908360ff160217905550610ba5338260ff166115d6565b3373ffffffffffffffffffffffffffffffffffffffff167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe42604051610beb9190612172565b60405180910390a250565b610bfe61175a565b8060069081610c0d9190612b96565b5050565b610c1961175a565b818190508484905014610c61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c5890612cd5565b60405180910390fd5b5f5b84849050811015610d3b57828282818110610c8157610c80612cf3565b5b9050602002016020810190610c969190612211565b60095f878785818110610cac57610cab612cf3565b5b9050602002016020810190610cc191906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610d1691906129c5565b92506101000a81548160ff021916908360ff1602179055508080600101915050610c63565b5050505050565b610d4d8383836108ae565b610d56826117e1565b15610d7657610d7583838360405180602001604052805f8152506117eb565b5b505050565b610d8361175a565b818190508484905014610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc290612cd5565b60405180910390fd5b5f5b84849050811015610f11575f838383818110610dec57610deb612cf3565b5b9050602002016020810190610e019190612211565b610e31878785818110610e1757610e16612cf3565b5b9050602002016020810190610e2c91906124df565b6111fe565b610e3b9190612d20565b60ff1610610f0457828282818110610e5657610e55612cf3565b5b9050602002016020810190610e6b9190612211565b60095f878785818110610e8157610e80612cf3565b5b9050602002016020810190610e9691906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610eeb9190612d20565b92506101000a81548160ff021916908360ff1602179055505b8080600101915050610dcd565b5050505050565b5f610f2282611878565b905080610f365763ceea21b65f526004601cfd5b919050565b60068054610f48906127ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610f74906127ca565b8015610fbf5780601f10610f9657610100808354040283529160200191610fbf565b820191905f5260205f20905b815481529060010190602001808311610fa257829003601f168201915b505050505081565b5f81610fda57638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b61101c61175a565b6110255f6118b6565b565b61102f61175a565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015611093573d5f803e3d5ffd5b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546110f2906127ca565b80601f016020809104026020016040519081016040528092919081815260200182805461111e906127ca565b80156111695780601f1061114057610100808354040283529160200191611169565b820191905f5260205f20905b81548152906001019060200180831161114c57829003601f168201915b5050505050905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b6009602052805f5260405f205f91509050805f015f9054906101000a900460ff1690805f0160019054906101000a900460ff16905082565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160019054906101000a900460ff1660095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f9054906101000a900460ff166112a29190612d20565b9050919050565b6112b48585856108ae565b6112bd846117e1565b156113125761131185858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050506117eb565b5b5050505050565b606061132482611979565b611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135a90612d9e565b60405180910390fd5b5f61136c6119b4565b90505f81511161138a5760405180602001604052805f8152506113b5565b8061139484611a44565b6040516020016113a5929190612df6565b6040516020818303038152906040525b915050919050565b5f6113c782611979565b9050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055481565b5f60c061140483611b0e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16901c9050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b61145561175a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114bc91906120e2565b60405180910390fd5b6114ce816118b6565b50565b6114d961175a565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f208201820180548216806115725763ceea21b65f526004601cfd5b80861486151761159757805f526030600c205461159657634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4505050505050565b505050565b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461163b576040517fd9d552c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103611674576040517f4600cfe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055410156116b0576040517f7775abdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051806020016040528042446040516020016116cf929190612e39565b604051602081830303815290604052805190602001205f1c81525090505f60055490505f5b83811015611742575f6117108385611b4690919063ffffffff16565b90505f61171d8285611b6f565b90506117298782611c0c565b8361173390612e64565b935082600101925050506116f4565b5061174d8484611ce0565b8060058190555050505050565b611762611d3e565b73ffffffffffffffffffffffffffffffffffffffff16611780611096565b73ffffffffffffffffffffffffffffffffffffffff16146117df576117a3611d3e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016117d691906120e2565b60405180910390fd5b565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611832578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611857573d15611853573d5f803e3d5ffd5b5f83525b8160e01b83511461186f5763d1a57ed65f526004601cfd5b50505050505050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b9050919050565b6060600680546119c3906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546119ef906127ca565b8015611a3a5780601f10611a1157610100808354040283529160200191611a3a565b820191905f5260205f20905b815481529060010190602001808311611a1d57829003601f168201915b5050505050905090565b60605f6001611a5284611d45565b0190505f8167ffffffffffffffff811115611a7057611a6f612244565b5b6040519080825280601f01601f191660200182016040528015611aa25781602001600182028036833780820191505090505b5090505f82602001820190505b600115611b03578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611af857611af7612e8b565b5b0494505f8503611aaf575b819350505050919050565b5f7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c205460201c9050919050565b5f5b600115611b645760208320905080835281825f03068110611b48575b818106905092915050565b5f8060045f8581526020019081526020015f205490505f600184611b939190612827565b90505f60045f8381526020019081526020015f205490505f8314611bb75782611bb9565b855b9350818614611be7575f8114611bcf5780611bd1565b815b60045f8881526020019081526020015f20819055505b5f8114611c035760045f8381526020019081526020015f205f90555b50505092915050565b611c175f83836115cc565b8160601b60601c915081611c325763ea553b345f526004601cfd5b805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b15611c795763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff8116611ca3576301336cea5f526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45050611cdc5f83836115d1565b5050565b5f611cea836113f8565b90505f8282611cf99190612eb8565b90505f611d0585611b0e565b9050611d37858277ffffffffffffffffffffffffffffffffffffffffffffffff1660c08563ffffffff16901b17611e96565b5050505050565b5f33905090565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611da1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611d9757611d96612e8b565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611dde576d04ee2d6d415b85acef81000000008381611dd457611dd3612e8b565b5b0492506020810190505b662386f26fc100008310611e0d57662386f26fc100008381611e0357611e02612e8b565b5b0492506010810190505b6305f5e1008310611e36576305f5e1008381611e2c57611e2b612e8b565b5b0492506008810190505b6127108310611e5b576127108381611e5157611e50612e8b565b5b0492506004810190505b60648310611e7e5760648381611e7457611e73612e8b565b5b0492506002810190505b600a8310611e8d576001810190505b80915050919050565b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c2080548060201c831860201b8118825550505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611f1c81611ee8565b8114611f26575f80fd5b50565b5f81359050611f3781611f13565b92915050565b5f60208284031215611f5257611f51611ee0565b5b5f611f5f84828501611f29565b91505092915050565b5f8115159050919050565b611f7c81611f68565b82525050565b5f602082019050611f955f830184611f73565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611fd2578082015181840152602081019050611fb7565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611ff782611f9b565b6120018185611fa5565b9350612011818560208601611fb5565b61201a81611fdd565b840191505092915050565b5f6020820190508181035f83015261203d8184611fed565b905092915050565b5f819050919050565b61205781612045565b8114612061575f80fd5b50565b5f813590506120728161204e565b92915050565b5f6020828403121561208d5761208c611ee0565b5b5f61209a84828501612064565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6120cc826120a3565b9050919050565b6120dc816120c2565b82525050565b5f6020820190506120f55f8301846120d3565b92915050565b612104816120c2565b811461210e575f80fd5b50565b5f8135905061211f816120fb565b92915050565b5f806040838503121561213b5761213a611ee0565b5b5f61214885828601612111565b925050602061215985828601612064565b9150509250929050565b61216c81612045565b82525050565b5f6020820190506121855f830184612163565b92915050565b5f805f606084860312156121a2576121a1611ee0565b5b5f6121af86828701612111565b93505060206121c086828701612111565b92505060406121d186828701612064565b9150509250925092565b5f60ff82169050919050565b6121f0816121db565b81146121fa575f80fd5b50565b5f8135905061220b816121e7565b92915050565b5f6020828403121561222657612225611ee0565b5b5f612233848285016121fd565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61227a82611fdd565b810181811067ffffffffffffffff8211171561229957612298612244565b5b80604052505050565b5f6122ab611ed7565b90506122b78282612271565b919050565b5f67ffffffffffffffff8211156122d6576122d5612244565b5b6122df82611fdd565b9050602081019050919050565b828183375f83830152505050565b5f61230c612307846122bc565b6122a2565b90508281526020810184848401111561232857612327612240565b5b6123338482856122ec565b509392505050565b5f82601f83011261234f5761234e61223c565b5b813561235f8482602086016122fa565b91505092915050565b5f6020828403121561237d5761237c611ee0565b5b5f82013567ffffffffffffffff81111561239a57612399611ee4565b5b6123a68482850161233b565b91505092915050565b5f80fd5b5f80fd5b5f8083601f8401126123cc576123cb61223c565b5b8235905067ffffffffffffffff8111156123e9576123e86123af565b5b602083019150836020820283011115612405576124046123b3565b5b9250929050565b5f8083601f8401126124215761242061223c565b5b8235905067ffffffffffffffff81111561243e5761243d6123af565b5b60208301915083602082028301111561245a576124596123b3565b5b9250929050565b5f805f806040858703121561247957612478611ee0565b5b5f85013567ffffffffffffffff81111561249657612495611ee4565b5b6124a2878288016123b7565b9450945050602085013567ffffffffffffffff8111156124c5576124c4611ee4565b5b6124d18782880161240c565b925092505092959194509250565b5f602082840312156124f4576124f3611ee0565b5b5f61250184828501612111565b91505092915050565b5f612514826120a3565b9050919050565b6125248161250a565b82525050565b5f60208201905061253d5f83018461251b565b92915050565b61254c81611f68565b8114612556575f80fd5b50565b5f8135905061256781612543565b92915050565b5f806040838503121561258357612582611ee0565b5b5f61259085828601612111565b92505060206125a185828601612559565b9150509250929050565b6125b4816121db565b82525050565b5f6040820190506125cd5f8301856125ab565b6125da60208301846125ab565b9392505050565b5f6020820190506125f45f8301846125ab565b92915050565b5f8083601f84011261260f5761260e61223c565b5b8235905067ffffffffffffffff81111561262c5761262b6123af565b5b602083019150836001820283011115612648576126476123b3565b5b9250929050565b5f805f805f6080868803121561266857612667611ee0565b5b5f61267588828901612111565b955050602061268688828901612111565b945050604061269788828901612064565b935050606086013567ffffffffffffffff8111156126b8576126b7611ee4565b5b6126c4888289016125fa565b92509250509295509295909350565b5f63ffffffff82169050919050565b6126eb816126d3565b82525050565b5f6020820190506127045f8301846126e2565b92915050565b5f80604083850312156127205761271f611ee0565b5b5f61272d85828601612111565b925050602061273e85828601612111565b9150509250929050565b6127518161250a565b811461275b575f80fd5b50565b5f8135905061276c81612748565b92915050565b5f6020828403121561278757612786611ee0565b5b5f6127948482850161275e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806127e157607f821691505b6020821081036127f4576127f361279d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61283182612045565b915061283c83612045565b9250828203905081811115612854576128536127fa565b5b92915050565b7f4e6f7420656c696769626c6500000000000000000000000000000000000000005f82015250565b5f61288e600c83611fa5565b91506128998261285a565b602082019050919050565b5f6020820190508181035f8301526128bb81612882565b9050919050565b7f4e6f7420656e6f75676820636c61696d61626c6520746f6b656e7300000000005f82015250565b5f6128f6601b83611fa5565b9150612901826128c2565b602082019050919050565b5f6020820190508181035f830152612923816128ea565b9050919050565b5f61293482612045565b915061293f83612045565b9250828201905080821115612957576129566127fa565b5b92915050565b7f537570706c79206c696d697420657863656564000000000000000000000000005f82015250565b5f612991601383611fa5565b915061299c8261295d565b602082019050919050565b5f6020820190508181035f8301526129be81612985565b9050919050565b5f6129cf826121db565b91506129da836121db565b9250828201905060ff8111156129f3576129f26127fa565b5b92915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302612a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612a1a565b612a5f8683612a1a565b95508019841693508086168417925050509392505050565b5f819050919050565b5f612a9a612a95612a9084612045565b612a77565b612045565b9050919050565b5f819050919050565b612ab383612a80565b612ac7612abf82612aa1565b848454612a26565b825550505050565b5f90565b612adb612acf565b612ae6818484612aaa565b505050565b5b81811015612b0957612afe5f82612ad3565b600181019050612aec565b5050565b601f821115612b4e57612b1f816129f9565b612b2884612a0b565b81016020851015612b37578190505b612b4b612b4385612a0b565b830182612aeb565b50505b505050565b5f82821c905092915050565b5f612b6e5f1984600802612b53565b1980831691505092915050565b5f612b868383612b5f565b9150826002028217905092915050565b612b9f82611f9b565b67ffffffffffffffff811115612bb857612bb7612244565b5b612bc282546127ca565b612bcd828285612b0d565b5f60209050601f831160018114612bfe575f8415612bec578287015190505b612bf68582612b7b565b865550612c5d565b601f198416612c0c866129f9565b5f5b82811015612c3357848901518255600182019150602085019450602081019050612c0e565b86831015612c505784890151612c4c601f891682612b5f565b8355505b6001600288020188555050505b505050505050565b7f4e62206164647265737320616e64206e62207175616e746974696573206d75735f8201527f7420626520657175616c00000000000000000000000000000000000000000000602082015250565b5f612cbf602a83611fa5565b9150612cca82612c65565b604082019050919050565b5f6020820190508181035f830152612cec81612cb3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d2a826121db565b9150612d35836121db565b9250828203905060ff811115612d4e57612d4d6127fa565b5b92915050565b7f756e6b6e6f7720746f6b656e00000000000000000000000000000000000000005f82015250565b5f612d88600c83611fa5565b9150612d9382612d54565b602082019050919050565b5f6020820190508181035f830152612db581612d7c565b9050919050565b5f81905092915050565b5f612dd082611f9b565b612dda8185612dbc565b9350612dea818560208601611fb5565b80840191505092915050565b5f612e018285612dc6565b9150612e0d8284612dc6565b91508190509392505050565b5f819050919050565b612e33612e2e82612045565b612e19565b82525050565b5f612e448285612e22565b602082019150612e548284612e22565b6020820191508190509392505050565b5f612e6e82612045565b91505f8203612e8057612e7f6127fa565b5b600182039050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612ec2826126d3565b9150612ecd836126d3565b9250828201905063ffffffff811115612ee957612ee86127fa565b5b9291505056fea2646970667358221220b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd08386126364736f6c63430008170033

Deployed Bytecode

0x6080604052600436106101e2575f3560e01c8063853828b611610101578063c87b56dd11610094578063dc33e68111610063578063dc33e68114610699578063e985e9c5146106d5578063f2fde38b14610711578063fb5b82d014610739576101e2565b8063c87b56dd146105cd578063cc0c523614610609578063d5abeb0114610645578063da0239a61461066f576101e2565b8063a22cb465116100d0578063a22cb46514610510578063a7cd52cb14610538578063b399b0bc14610575578063b88d4fde146105b1576101e2565b8063853828b6146104885780638da5cb5b14610492578063913e77ad146104bc57806395d89b41146104e6576101e2565b806331b5b907116101795780636352211e116101485780636352211e146103d05780636c0360eb1461040c57806370a0823114610436578063715018a614610472576101e2565b806331b5b9071461033c5780633fb580f71461036457806342842e0e1461038c578063594bf62b146103a8576101e2565b806318160ddd116101b557806318160ddd146102a457806323b872dd146102ce578063282e7811146102ea5780632db5b8e714610314576101e2565b806301ffc9a7146101e657806306fdde0314610222578063081812fc1461024c578063095ea7b314610288575b5f80fd5b3480156101f1575f80fd5b5061020c60048036038101906102079190611f3d565b610761565b6040516102199190611f82565b60405180910390f35b34801561022d575f80fd5b50610236610785565b6040516102439190612025565b60405180910390f35b348015610257575f80fd5b50610272600480360381019061026d9190612078565b610815565b60405161027f91906120e2565b60405180910390f35b6102a2600480360381019061029d9190612125565b61086b565b005b3480156102af575f80fd5b506102b861087a565b6040516102c59190612172565b60405180910390f35b6102e860048036038101906102e3919061218b565b6108ae565b005b3480156102f5575f80fd5b506102fe6109ea565b60405161030b91906120e2565b60405180910390f35b34801561031f575f80fd5b5061033a60048036038101906103359190612211565b610a0f565b005b348015610347575f80fd5b50610362600480360381019061035d9190612368565b610bf6565b005b34801561036f575f80fd5b5061038a60048036038101906103859190612461565b610c11565b005b6103a660048036038101906103a1919061218b565b610d42565b005b3480156103b3575f80fd5b506103ce60048036038101906103c99190612461565b610d7b565b005b3480156103db575f80fd5b506103f660048036038101906103f19190612078565b610f18565b60405161040391906120e2565b60405180910390f35b348015610417575f80fd5b50610420610f3b565b60405161042d9190612025565b60405180910390f35b348015610441575f80fd5b5061045c600480360381019061045791906124df565b610fc7565b6040516104699190612172565b60405180910390f35b34801561047d575f80fd5b50610486611014565b005b610490611027565b005b34801561049d575f80fd5b506104a6611096565b6040516104b391906120e2565b60405180910390f35b3480156104c7575f80fd5b506104d06110be565b6040516104dd919061252a565b60405180910390f35b3480156104f1575f80fd5b506104fa6110e3565b6040516105079190612025565b60405180910390f35b34801561051b575f80fd5b506105366004803603810190610531919061256d565b611173565b005b348015610543575f80fd5b5061055e600480360381019061055991906124df565b6111c6565b60405161056c9291906125ba565b60405180910390f35b348015610580575f80fd5b5061059b600480360381019061059691906124df565b6111fe565b6040516105a891906125e1565b60405180910390f35b6105cb60048036038101906105c6919061264f565b6112a9565b005b3480156105d8575f80fd5b506105f360048036038101906105ee9190612078565b611319565b6040516106009190612025565b60405180910390f35b348015610614575f80fd5b5061062f600480360381019061062a9190612078565b6113bd565b60405161063c9190611f82565b60405180910390f35b348015610650575f80fd5b506106596113ce565b6040516106669190612172565b60405180910390f35b34801561067a575f80fd5b506106836113f2565b6040516106909190612172565b60405180910390f35b3480156106a4575f80fd5b506106bf60048036038101906106ba91906124df565b6113f8565b6040516106cc91906126f1565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f6919061270a565b61142b565b6040516107089190611f82565b60405180910390f35b34801561071c575f80fd5b50610737600480360381019061073291906124df565b61144d565b005b348015610744575f80fd5b5061075f600480360381019061075a9190612772565b6114d1565b005b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b606060028054610794906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546107c0906127ca565b801561080b5780601f106107e25761010080835404028352916020019161080b565b820191905f5260205f20905b8154815290600101906020018083116107ee57829003601f168201915b5050505050905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b60601c61085e5763ceea21b65f526004601cfd5b8060010154915050919050565b61087633838361151c565b5050565b5f6005547f00000000000000000000000000000000000000000000000000000000000002bc6108a99190612827565b905090565b6108b98383836115cc565b5f1960601c83811693508281169250815f52337f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054808316868114810261092657806109195763ceea21b65f526004601cfd5b63a11481005f526004601cfd5b856109385763ea553b345f526004601cfd5b865f52826001015480331488331417610963576030600c205461096257634b6e7f185f526004601cfd5b5b8015610970575f84600101555b5085871882188355601c600c206001815403815550855f52601c600c20600181540163ffffffff81166109aa576301336cea5f526004601cfd5b80825550508486887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4505050506109e58383836115d1565b505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610a19336111fe565b60ff1611610a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a53906128a4565b60405180910390fd5b8060ff16610a69336111fe565b60ff161015610aad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa49061290c565b60405180910390fd5b8060ff16610ab961087a565b610ac3919061292a565b7f00000000000000000000000000000000000000000000000000000000000002bc1015610b25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1c906129a7565b60405180910390fd5b8060095f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160018282829054906101000a900460ff16610b8091906129c5565b92506101000a81548160ff021916908360ff160217905550610ba5338260ff166115d6565b3373ffffffffffffffffffffffffffffffffffffffff167f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe42604051610beb9190612172565b60405180910390a250565b610bfe61175a565b8060069081610c0d9190612b96565b5050565b610c1961175a565b818190508484905014610c61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c5890612cd5565b60405180910390fd5b5f5b84849050811015610d3b57828282818110610c8157610c80612cf3565b5b9050602002016020810190610c969190612211565b60095f878785818110610cac57610cab612cf3565b5b9050602002016020810190610cc191906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610d1691906129c5565b92506101000a81548160ff021916908360ff1602179055508080600101915050610c63565b5050505050565b610d4d8383836108ae565b610d56826117e1565b15610d7657610d7583838360405180602001604052805f8152506117eb565b5b505050565b610d8361175a565b818190508484905014610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc290612cd5565b60405180910390fd5b5f5b84849050811015610f11575f838383818110610dec57610deb612cf3565b5b9050602002016020810190610e019190612211565b610e31878785818110610e1757610e16612cf3565b5b9050602002016020810190610e2c91906124df565b6111fe565b610e3b9190612d20565b60ff1610610f0457828282818110610e5657610e55612cf3565b5b9050602002016020810190610e6b9190612211565b60095f878785818110610e8157610e80612cf3565b5b9050602002016020810190610e9691906124df565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282829054906101000a900460ff16610eeb9190612d20565b92506101000a81548160ff021916908360ff1602179055505b8080600101915050610dcd565b5050505050565b5f610f2282611878565b905080610f365763ceea21b65f526004601cfd5b919050565b60068054610f48906127ca565b80601f0160208091040260200160405190810160405280929190818152602001828054610f74906127ca565b8015610fbf5780601f10610f9657610100808354040283529160200191610fbf565b820191905f5260205f20905b815481529060010190602001808311610fa257829003601f168201915b505050505081565b5f81610fda57638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b61101c61175a565b6110255f6118b6565b565b61102f61175a565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015611093573d5f803e3d5ffd5b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546110f2906127ca565b80601f016020809104026020016040519081016040528092919081815260200182805461111e906127ca565b80156111695780601f1061114057610100808354040283529160200191611169565b820191905f5260205f20905b81548152906001019060200180831161114c57829003601f168201915b5050505050905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b6009602052805f5260405f205f91509050805f015f9054906101000a900460ff1690805f0160019054906101000a900460ff16905082565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160019054906101000a900460ff1660095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f9054906101000a900460ff166112a29190612d20565b9050919050565b6112b48585856108ae565b6112bd846117e1565b156113125761131185858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050506117eb565b5b5050505050565b606061132482611979565b611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135a90612d9e565b60405180910390fd5b5f61136c6119b4565b90505f81511161138a5760405180602001604052805f8152506113b5565b8061139484611a44565b6040516020016113a5929190612df6565b6040516020818303038152906040525b915050919050565b5f6113c782611979565b9050919050565b7f00000000000000000000000000000000000000000000000000000000000002bc81565b60055481565b5f60c061140483611b0e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16901c9050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b61145561175a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016114bc91906120e2565b60405180910390fd5b6114ce816118b6565b50565b6114d961175a565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f208201820180548216806115725763ceea21b65f526004601cfd5b80861486151761159757805f526030600c205461159657634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4505050505050565b505050565b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461163b576040517fd9d552c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103611674576040517f4600cfe900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055410156116b0576040517f7775abdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051806020016040528042446040516020016116cf929190612e39565b604051602081830303815290604052805190602001205f1c81525090505f60055490505f5b83811015611742575f6117108385611b4690919063ffffffff16565b90505f61171d8285611b6f565b90506117298782611c0c565b8361173390612e64565b935082600101925050506116f4565b5061174d8484611ce0565b8060058190555050505050565b611762611d3e565b73ffffffffffffffffffffffffffffffffffffffff16611780611096565b73ffffffffffffffffffffffffffffffffffffffff16146117df576117a3611d3e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016117d691906120e2565b60405180910390fd5b565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611832578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611857573d15611853573d5f803e3d5ffd5b5f83525b8160e01b83511461186f5763d1a57ed65f526004601cfd5b50505050505050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b9050919050565b6060600680546119c3906127ca565b80601f01602080910402602001604051908101604052809291908181526020018280546119ef906127ca565b8015611a3a5780601f10611a1157610100808354040283529160200191611a3a565b820191905f5260205f20905b815481529060010190602001808311611a1d57829003601f168201915b5050505050905090565b60605f6001611a5284611d45565b0190505f8167ffffffffffffffff811115611a7057611a6f612244565b5b6040519080825280601f01601f191660200182016040528015611aa25781602001600182028036833780820191505090505b5090505f82602001820190505b600115611b03578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611af857611af7612e8b565b5b0494505f8503611aaf575b819350505050919050565b5f7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c205460201c9050919050565b5f5b600115611b645760208320905080835281825f03068110611b48575b818106905092915050565b5f8060045f8581526020019081526020015f205490505f600184611b939190612827565b90505f60045f8381526020019081526020015f205490505f8314611bb75782611bb9565b855b9350818614611be7575f8114611bcf5780611bd1565b815b60045f8881526020019081526020015f20819055505b5f8114611c035760045f8381526020019081526020015f205f90555b50505092915050565b611c175f83836115cc565b8160601b60601c915081611c325763ea553b345f526004601cfd5b805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b15611c795763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff8116611ca3576301336cea5f526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45050611cdc5f83836115d1565b5050565b5f611cea836113f8565b90505f8282611cf99190612eb8565b90505f611d0585611b0e565b9050611d37858277ffffffffffffffffffffffffffffffffffffffffffffffff1660c08563ffffffff16901b17611e96565b5050505050565b5f33905090565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611da1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611d9757611d96612e8b565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611dde576d04ee2d6d415b85acef81000000008381611dd457611dd3612e8b565b5b0492506020810190505b662386f26fc100008310611e0d57662386f26fc100008381611e0357611e02612e8b565b5b0492506010810190505b6305f5e1008310611e36576305f5e1008381611e2c57611e2b612e8b565b5b0492506008810190505b6127108310611e5b576127108381611e5157611e50612e8b565b5b0492506004810190505b60648310611e7e5760648381611e7457611e73612e8b565b5b0492506002810190505b600a8310611e8d576001810190505b80915050919050565b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f52601c600c2080548060201c831860201b8118825550505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611f1c81611ee8565b8114611f26575f80fd5b50565b5f81359050611f3781611f13565b92915050565b5f60208284031215611f5257611f51611ee0565b5b5f611f5f84828501611f29565b91505092915050565b5f8115159050919050565b611f7c81611f68565b82525050565b5f602082019050611f955f830184611f73565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611fd2578082015181840152602081019050611fb7565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611ff782611f9b565b6120018185611fa5565b9350612011818560208601611fb5565b61201a81611fdd565b840191505092915050565b5f6020820190508181035f83015261203d8184611fed565b905092915050565b5f819050919050565b61205781612045565b8114612061575f80fd5b50565b5f813590506120728161204e565b92915050565b5f6020828403121561208d5761208c611ee0565b5b5f61209a84828501612064565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6120cc826120a3565b9050919050565b6120dc816120c2565b82525050565b5f6020820190506120f55f8301846120d3565b92915050565b612104816120c2565b811461210e575f80fd5b50565b5f8135905061211f816120fb565b92915050565b5f806040838503121561213b5761213a611ee0565b5b5f61214885828601612111565b925050602061215985828601612064565b9150509250929050565b61216c81612045565b82525050565b5f6020820190506121855f830184612163565b92915050565b5f805f606084860312156121a2576121a1611ee0565b5b5f6121af86828701612111565b93505060206121c086828701612111565b92505060406121d186828701612064565b9150509250925092565b5f60ff82169050919050565b6121f0816121db565b81146121fa575f80fd5b50565b5f8135905061220b816121e7565b92915050565b5f6020828403121561222657612225611ee0565b5b5f612233848285016121fd565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61227a82611fdd565b810181811067ffffffffffffffff8211171561229957612298612244565b5b80604052505050565b5f6122ab611ed7565b90506122b78282612271565b919050565b5f67ffffffffffffffff8211156122d6576122d5612244565b5b6122df82611fdd565b9050602081019050919050565b828183375f83830152505050565b5f61230c612307846122bc565b6122a2565b90508281526020810184848401111561232857612327612240565b5b6123338482856122ec565b509392505050565b5f82601f83011261234f5761234e61223c565b5b813561235f8482602086016122fa565b91505092915050565b5f6020828403121561237d5761237c611ee0565b5b5f82013567ffffffffffffffff81111561239a57612399611ee4565b5b6123a68482850161233b565b91505092915050565b5f80fd5b5f80fd5b5f8083601f8401126123cc576123cb61223c565b5b8235905067ffffffffffffffff8111156123e9576123e86123af565b5b602083019150836020820283011115612405576124046123b3565b5b9250929050565b5f8083601f8401126124215761242061223c565b5b8235905067ffffffffffffffff81111561243e5761243d6123af565b5b60208301915083602082028301111561245a576124596123b3565b5b9250929050565b5f805f806040858703121561247957612478611ee0565b5b5f85013567ffffffffffffffff81111561249657612495611ee4565b5b6124a2878288016123b7565b9450945050602085013567ffffffffffffffff8111156124c5576124c4611ee4565b5b6124d18782880161240c565b925092505092959194509250565b5f602082840312156124f4576124f3611ee0565b5b5f61250184828501612111565b91505092915050565b5f612514826120a3565b9050919050565b6125248161250a565b82525050565b5f60208201905061253d5f83018461251b565b92915050565b61254c81611f68565b8114612556575f80fd5b50565b5f8135905061256781612543565b92915050565b5f806040838503121561258357612582611ee0565b5b5f61259085828601612111565b92505060206125a185828601612559565b9150509250929050565b6125b4816121db565b82525050565b5f6040820190506125cd5f8301856125ab565b6125da60208301846125ab565b9392505050565b5f6020820190506125f45f8301846125ab565b92915050565b5f8083601f84011261260f5761260e61223c565b5b8235905067ffffffffffffffff81111561262c5761262b6123af565b5b602083019150836001820283011115612648576126476123b3565b5b9250929050565b5f805f805f6080868803121561266857612667611ee0565b5b5f61267588828901612111565b955050602061268688828901612111565b945050604061269788828901612064565b935050606086013567ffffffffffffffff8111156126b8576126b7611ee4565b5b6126c4888289016125fa565b92509250509295509295909350565b5f63ffffffff82169050919050565b6126eb816126d3565b82525050565b5f6020820190506127045f8301846126e2565b92915050565b5f80604083850312156127205761271f611ee0565b5b5f61272d85828601612111565b925050602061273e85828601612111565b9150509250929050565b6127518161250a565b811461275b575f80fd5b50565b5f8135905061276c81612748565b92915050565b5f6020828403121561278757612786611ee0565b5b5f6127948482850161275e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806127e157607f821691505b6020821081036127f4576127f361279d565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61283182612045565b915061283c83612045565b9250828203905081811115612854576128536127fa565b5b92915050565b7f4e6f7420656c696769626c6500000000000000000000000000000000000000005f82015250565b5f61288e600c83611fa5565b91506128998261285a565b602082019050919050565b5f6020820190508181035f8301526128bb81612882565b9050919050565b7f4e6f7420656e6f75676820636c61696d61626c6520746f6b656e7300000000005f82015250565b5f6128f6601b83611fa5565b9150612901826128c2565b602082019050919050565b5f6020820190508181035f830152612923816128ea565b9050919050565b5f61293482612045565b915061293f83612045565b9250828201905080821115612957576129566127fa565b5b92915050565b7f537570706c79206c696d697420657863656564000000000000000000000000005f82015250565b5f612991601383611fa5565b915061299c8261295d565b602082019050919050565b5f6020820190508181035f8301526129be81612985565b9050919050565b5f6129cf826121db565b91506129da836121db565b9250828201905060ff8111156129f3576129f26127fa565b5b92915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302612a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612a1a565b612a5f8683612a1a565b95508019841693508086168417925050509392505050565b5f819050919050565b5f612a9a612a95612a9084612045565b612a77565b612045565b9050919050565b5f819050919050565b612ab383612a80565b612ac7612abf82612aa1565b848454612a26565b825550505050565b5f90565b612adb612acf565b612ae6818484612aaa565b505050565b5b81811015612b0957612afe5f82612ad3565b600181019050612aec565b5050565b601f821115612b4e57612b1f816129f9565b612b2884612a0b565b81016020851015612b37578190505b612b4b612b4385612a0b565b830182612aeb565b50505b505050565b5f82821c905092915050565b5f612b6e5f1984600802612b53565b1980831691505092915050565b5f612b868383612b5f565b9150826002028217905092915050565b612b9f82611f9b565b67ffffffffffffffff811115612bb857612bb7612244565b5b612bc282546127ca565b612bcd828285612b0d565b5f60209050601f831160018114612bfe575f8415612bec578287015190505b612bf68582612b7b565b865550612c5d565b601f198416612c0c866129f9565b5f5b82811015612c3357848901518255600182019150602085019450602081019050612c0e565b86831015612c505784890151612c4c601f891682612b5f565b8355505b6001600288020188555050505b505050505050565b7f4e62206164647265737320616e64206e62207175616e746974696573206d75735f8201527f7420626520657175616c00000000000000000000000000000000000000000000602082015250565b5f612cbf602a83611fa5565b9150612cca82612c65565b604082019050919050565b5f6020820190508181035f830152612cec81612cb3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d2a826121db565b9150612d35836121db565b9250828203905060ff811115612d4e57612d4d6127fa565b5b92915050565b7f756e6b6e6f7720746f6b656e00000000000000000000000000000000000000005f82015250565b5f612d88600c83611fa5565b9150612d9382612d54565b602082019050919050565b5f6020820190508181035f830152612db581612d7c565b9050919050565b5f81905092915050565b5f612dd082611f9b565b612dda8185612dbc565b9350612dea818560208601611fb5565b80840191505092915050565b5f612e018285612dc6565b9150612e0d8284612dc6565b91508190509392505050565b5f819050919050565b612e33612e2e82612045565b612e19565b82525050565b5f612e448285612e22565b602082019150612e548284612e22565b6020820191508190509392505050565b5f612e6e82612045565b91505f8203612e8057612e7f6127fa565b5b600182039050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612ec2826126d3565b9150612ecd836126d3565b9250828201905063ffffffff811115612ee957612ee86127fa565b5b9291505056fea2646970667358221220b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd08386126364736f6c63430008170033

Deployed Bytecode Sourcemap

123294:2642:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42035:383;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119876:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35086:553;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35942:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119754:114;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37770:3015;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123423:71;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125519:414;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124028:99;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124762:345;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;40859:201;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125113:400;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;33914:341;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123395:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34405:541;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;23418:103;;;;;;;;;;;;;:::i;:::-;;123806:102;;;:::i;:::-;;22743:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123499:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119984:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36690:713;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123607:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;124614:142;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41577:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124232:271;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124509:99;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119495:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119456:30;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120096:138;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36157:389;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;23676:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123914:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42035:383;42111:11;42221;42216:3;42212:21;42388:10;42385:1;42382:17;42368:10;42365:1;42362:17;42349:10;42346:1;42343:17;42340:40;42337:63;42327:73;;42188:223;42035:383;;;:::o;119876:100::-;119930:13;119963:5;119956:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119876:100;:::o;35086:553::-;35148:14;35256:2;35250:4;35243:16;35286:24;35280:4;35273:38;35378:4;35372;35362:21;35358:2;35354:30;35350:2;35346:39;35431:13;35425:20;35421:2;35417:29;35413:2;35409:38;35399:170;;35481:10;35475:4;35468:24;35549:4;35543;35536:18;35399:170;35606:13;35603:1;35599:21;35593:28;35583:38;;35228:404;35086:553;;;:::o;35942:121::-;36022:33;36031:10;36043:7;36052:2;36022:8;:33::i;:::-;35942:121;;:::o;119754:114::-;119806:7;119845:15;;119833:9;:27;;;;:::i;:::-;119826:34;;119754:114;:::o;37770:3015::-;37864:34;37885:4;37891:2;37895;37864:20;:34::i;:::-;38048:1;38044:6;38040:2;38036:15;38093:4;38077:14;38073:25;38065:33;;38138:2;38122:14;38118:23;38112:29;;38205:2;38199:4;38192:16;38264:8;38238:24;38235:38;38229:4;38222:52;38341:4;38335;38325:21;38321:2;38317:30;38313:2;38309:39;38391:13;38385:20;38452:15;38436:14;38432:36;38579:4;38572:5;38569:15;38562:5;38558:27;38548:335;;38616:5;38606:149;;38659:10;38653:4;38646:24;38731:4;38725;38718:18;38606:149;38786:10;38780:4;38773:24;38863:4;38857;38850:18;38548:335;38955:2;38945:138;;38991:10;38985:4;38978:24;39063:4;39057;39050:18;38945:138;39185:4;39179;39172:18;39244:13;39241:1;39237:21;39231:28;39392:15;39382:8;39379:29;39372:4;39362:8;39359:18;39356:53;39346:293;;39466:4;39460;39450:21;39444:28;39434:186;;39514:10;39508:4;39501:24;39592:4;39586;39579:18;39434:186;39346:293;39712:15;39709:55;;;39760:1;39744:13;39741:1;39737:21;39730:32;39709:55;39153:626;39885:2;39879:4;39875:13;39858:15;39854:35;39839:13;39832:58;40007:4;40001;39991:21;40082:1;40064:15;40058:22;40054:30;40037:15;40030:55;39949:151;40189:2;40183:4;40176:16;40247:4;40241;40231:21;40323:1;40307:13;40301:20;40297:28;40378:20;40357:19;40353:46;40343:195;;40437:10;40431:4;40424:24;40514:4;40508;40501:18;40343:195;40578:19;40563:13;40556:42;40157:456;;40720:2;40716;40710:4;40683:25;40677:4;40671;40666:57;37962:2772;;;;40744:33;40764:4;40770:2;40774;40744:19;:33::i;:::-;37770:3015;;;:::o;123423:71::-;;;;;;;;;;;;;:::o;125519:414::-;125606:1;125582:21;125592:10;125582:9;:21::i;:::-;:25;;;125574:50;;;;;;;;;;;;:::i;:::-;;;;;;;;;125664:11;125639:36;;:21;125649:10;125639:9;:21::i;:::-;:36;;;;125631:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;125751:11;125735:27;;:13;:11;:13::i;:::-;:27;;;;:::i;:::-;125722:9;:40;;125714:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;125826:11;125793:9;:21;125803:10;125793:21;;;;;;;;;;;;;;;:29;;;:44;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125844:36;125856:10;125868:11;125844:36;;:11;:36::i;:::-;125899:10;125892:35;;;125911:15;125892:35;;;;;;:::i;:::-;;;;;;;;125519:414;:::o;124028:99::-;22629:13;:11;:13::i;:::-;124110:11:::1;124100:7;:21;;;;;;:::i;:::-;;124028:99:::0;:::o;124762:345::-;22629:13;:11;:13::i;:::-;124910:11:::1;;:18;;124884:15;;:22;;:44;124876:99;;;;;;;;;;;;:::i;:::-;;;;;;;;;124987:6;124982:120;125003:15;;:22;;124999:1;:26;124982:120;;;125080:11;;125092:1;125080:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125041:9;:29;125051:15;;125067:1;125051:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125041:29;;;;;;;;;;;;;;;:35;;;:53;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125027:3;;;;;;;124982:120;;;;124762:345:::0;;;;:::o;40859:201::-;40957:26;40970:4;40976:2;40980;40957:12;:26::i;:::-;40998:12;41007:2;40998:8;:12::i;:::-;40994:58;;;41012:40;41035:4;41041:2;41045;41012:40;;;;;;;;;;;;:22;:40::i;:::-;40994:58;40859:201;;;:::o;125113:400::-;22629:13;:11;:13::i;:::-;125254:11:::1;;:18;;125233:10;;:17;;:39;125225:94;;;;;;;;;;;;:::i;:::-;;;;;;;;;125331:6;125326:182;125347:10;;:17;;125343:1;:21;125326:182;;;125429:1;125411:11;;125423:1;125411:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125384:24;125394:10;;125405:1;125394:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125384:9;:24::i;:::-;:41;;;;:::i;:::-;:46;;;125380:121;;125477:11;;125489:1;125477:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125443:9;:24;125453:10;;125464:1;125453:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;125443:24;;;;;;;;;;;;;;;:30;;;:48;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;125380:121;125366:3;;;;;;;125326:182;;;;125113:400:::0;;;;:::o;33914:341::-;33972:14;34008:12;34017:2;34008:8;:12::i;:::-;33999:21;;34109:6;34099:138;;34149:10;34143:4;34136:24;34217:4;34211;34204:18;34099:138;33914:341;;;:::o;123395:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;34405:541::-;34468:14;34628:5;34618:146;;34667:10;34661:4;34654:24;34744:4;34738;34731:18;34618:146;34791:24;34785:4;34778:38;34843:5;34837:4;34830:19;34907:20;34899:4;34893;34883:21;34877:28;34873:55;34863:65;;34405:541;;;:::o;23418:103::-;22629:13;:11;:13::i;:::-;23483:30:::1;23510:1;23483:18;:30::i;:::-;23418:103::o:0;123806:102::-;22629:13;:11;:13::i;:::-;123861:9:::1;;;;;;;;;;;:18;;:41;123880:21;123861:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;123806:102::o:0;22743:87::-;22789:7;22816:6;;;;;;;;;;;22809:13;;22743:87;:::o;123499:32::-;;;;;;;;;;;;;:::o;119984:104::-;120040:13;120073:7;120066:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119984:104;:::o;36690:713::-;36905:10;36898:18;36891:26;36877:40;;37012:8;37006:4;36999:22;37048:31;37042:4;37035:45;37107:8;37101:4;37094:22;37160:10;37153:4;37147;37137:21;37130:41;37243:10;37237:4;37230:24;37360:8;37356:2;37352:17;37348:2;37344:26;37334:8;37299:33;37293:4;37287;37268:117;36690:713;;:::o;123607:48::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;124614:142::-;124678:5;124725:9;:17;124735:6;124725:17;;;;;;;;;;;;;;;:25;;;;;;;;;;;;124699:9;:17;124709:6;124699:17;;;;;;;;;;;;;;;:23;;;;;;;;;;;;:51;;;;:::i;:::-;124692:58;;124614:142;;;:::o;41577:244::-;41716:26;41729:4;41735:2;41739;41716:12;:26::i;:::-;41757:12;41766:2;41757:8;:12::i;:::-;41753:60;;;41771:42;41794:4;41800:2;41804;41808:4;;41771:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:22;:42::i;:::-;41753:60;41577:244;;;;;:::o;124232:271::-;124305:13;124335:16;124343:7;124335;:16::i;:::-;124327:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;124375:17;124395:10;:8;:10::i;:::-;124375:30;;124439:1;124425:3;124419:17;:21;:78;;;;;;;;;;;;;;;;;124467:3;124472:18;:7;:16;:18::i;:::-;124450:41;;;;;;;;;:::i;:::-;;;;;;;;;;;;;124419:78;124412:85;;;124232:271;;;:::o;124509:99::-;124566:4;124586:16;124594:7;124586;:16::i;:::-;124579:23;;124509:99;;;:::o;119495:34::-;;;:::o;119456:30::-;;;;:::o;120096:138::-;120163:6;120222:3;120196:22;120211:6;120196:14;:22::i;:::-;:29;;;;120182:44;;120096:138;;;:::o;36157:389::-;36265:11;36375:8;36369:4;36362:22;36411:31;36405:4;36398:45;36470:5;36464:4;36457:19;36522:4;36516;36506:21;36500:28;36490:38;;36157:389;;;;:::o;23676:220::-;22629:13;:11;:13::i;:::-;23781:1:::1;23761:22;;:8;:22;;::::0;23757:93:::1;;23835:1;23807:31;;;;;;;;;;;:::i;:::-;;;;;;;;23757:93;23860:28;23879:8;23860:18;:28::i;:::-;23676:220:::0;:::o;123914:108::-;22629:13;:11;:13::i;:::-;124003::::1;123991:9;;:25;;;;;;;;;;;;;;;;;;123914:108:::0;:::o;54585:1438::-;54767:1;54763:6;54759:2;54755:15;54815:7;54799:14;54795:28;54784:39;;54863:2;54847:14;54843:23;54837:29;;54934:2;54928:4;54921:16;54993:2;54967:24;54964:32;54958:4;54951:46;55064:4;55058;55048:21;55044:2;55040:30;55036:2;55032:39;55124:13;55118:20;55102:14;55098:41;55211:5;55201:137;;55250:10;55244:4;55237:24;55318:4;55312;55305:18;55201:137;55516:5;55512:2;55509:13;55504:2;55497:10;55494:29;55484:286;;55557:5;55551:4;55544:19;55613:4;55607;55597:21;55591:28;55581:174;;55657:10;55651:4;55644:24;55731:4;55725;55718:18;55581:174;55484:286;55881:7;55865:13;55862:1;55858:21;55851:38;56002:2;55993:7;55986:5;55959:25;55953:4;55947;55942:63;54681:1335;;;54585:1438;;;:::o;63335:87::-;;;;:::o;63522:86::-;;;;:::o;120242:939::-;120341:9;120327:23;;:10;:23;;;120323:57;;120359:21;;;;;;;;;;;;;;120323:57;120409:1;120395:10;:15;120391:53;;120419:25;;;;;;;;;;;;;;120391:53;120477:10;120459:15;;:28;120455:67;;;120496:26;;;;;;;;;;;;;;120455:67;120535:24;120562:109;;;;;;;;120624:15;120641:16;120593:75;;;;;;;;;:::i;:::-;;;;;;;;;;;;;120583:86;;;;;;120575:95;;120562:109;;;120535:136;;120684:30;120717:15;;120684:48;;120750:9;120745:319;120765:10;120761:1;:14;120745:319;;;120794:19;120816:36;120829:22;120816:4;:12;;:36;;;;:::i;:::-;120794:58;;120869:15;120887:61;120912:11;120925:22;120887:24;:61::i;:::-;120869:79;;120965:18;120971:2;120975:7;120965:5;:18::i;:::-;121000:24;;;;:::i;:::-;;;121048:3;;;;;120779:285;;120745:319;;;;121076:46;121099:2;121110:10;121076:22;:46::i;:::-;121151:22;121133:15;:40;;;;120312:869;;120242:939;;:::o;22908:166::-;22979:12;:10;:12::i;:::-;22968:23;;:7;:5;:7::i;:::-;:23;;;22964:103;;23042:12;:10;:12::i;:::-;23015:40;;;;;;;;;;;:::i;:::-;;;;;;;;22964:103;22908:166::o;63965:217::-;64016:11;64130:1;64118:14;64108:24;;63965:217;;;:::o;64345:1416::-;64580:4;64574:11;64631:10;64665:24;64662:1;64655:35;64725:8;64718:4;64715:1;64711:12;64704:30;64834:4;64830:2;64826:13;64822:2;64818:22;64811:4;64808:1;64804:12;64797:44;64876:2;64869:4;64866:1;64862:12;64855:24;64914:4;64907;64904:1;64900:12;64893:26;64948:4;64942:11;64988:1;64981:4;64978:1;64974:12;64967:23;65007:1;65004:71;;;65070:1;65063:4;65060:1;65056:12;65053:1;65046:4;65040;65036:15;65033:1;65026:5;65015:57;65011:62;65004:71;65189:4;65186:1;65179:4;65176:1;65172:12;65165:4;65162:1;65158:12;65155:1;65151:2;65144:5;65139:55;65129:351;;65218:16;65215:220;;;65347:16;65341:4;65335;65320:44;65399:16;65393:4;65386:30;65215:220;65463:1;65460;65453:12;65129:351;65574:24;65569:3;65565:34;65561:1;65555:8;65552:48;65542:201;;65634:10;65628:4;65621:24;65723:4;65717;65710:18;65542:201;64516:1238;;;64345:1416;;;;:::o;43213:330::-;43274:14;43382:2;43376:4;43369:16;43412:24;43406:4;43399:38;43515:4;43509;43499:21;43495:2;43491:30;43487:2;43483:39;43477:46;43473:2;43469:55;43465:2;43461:64;43451:74;;43213:330;;;:::o;24056:191::-;24130:16;24149:6;;;;;;;;;;;24130:25;;24175:8;24166:6;;:17;;;;;;;;;;;;;;;;;;24230:8;24199:40;;24220:8;24199:40;;;;;;;;;;;;24119:128;24056:191;:::o;42757:317::-;42817:11;42922:2;42916:4;42909:16;42952:24;42946:4;42939:38;43047:4;43041;43031:21;43027:2;43023:30;43019:2;43015:39;43009:46;43005:2;43001:55;42991:65;;42757:317;;;:::o;124133:93::-;124184:13;124213:7;124206:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124133:93;:::o;17524:718::-;17580:13;17631:14;17668:1;17648:17;17659:5;17648:10;:17::i;:::-;:21;17631:38;;17684:20;17718:6;17707:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17684:41;;17740:11;17869:6;17865:2;17861:15;17853:6;17849:28;17842:35;;17906:290;17913:4;17906:290;;;17938:5;;;;;;;;18080:10;18075:2;18068:5;18064:14;18059:32;18054:3;18046:46;18138:2;18129:11;;;;;;:::i;:::-;;;;;18172:1;18163:5;:10;17906:290;18159:21;17906:290;18217:6;18210:13;;;;;17524:718;;;:::o;44079:308::-;44142:14;44250:24;44244:4;44237:38;44302:5;44296:4;44289:19;44362:4;44356;44346:21;44340:28;44336:2;44332:37;44322:47;;44079:308;;;:::o;68216:419::-;68289:14;68384:191;68391:1;68384:191;;;68441:4;68435;68425:21;68415:31;;68477:6;68471:4;68464:20;68542:5;68534;68531:1;68527:13;68523:25;68515:6;68512:37;68384:191;68502:58;68384:191;68611:5;68603:6;68599:18;68589:28;;68216:419;;;;:::o;121751:636::-;121867:14;121899:18;121920:16;:28;121937:10;121920:28;;;;;;;;;;;;121899:49;;121959:17;122007:1;121979:25;:29;;;;:::i;:::-;121959:49;;122019:22;122044:16;:27;122061:9;122044:27;;;;;;;;;;;;122019:52;;122107:1;122093:10;:15;:41;;122124:10;122093:41;;;122111:10;122093:41;122084:50;;122165:9;122151:10;:23;122147:135;;122240:1;122222:14;:19;:48;;122256:14;122222:48;;;122244:9;122222:48;122191:16;:28;122208:10;122191:28;;;;;;;;;;;:79;;;;122147:135;122316:1;122298:14;:19;122294:86;;122341:16;:27;122358:9;122341:27;;;;;;;;;;;122334:34;;;122294:86;121888:499;;;121751:636;;;;:::o;46738:1686::-;46805:40;46834:1;46838:2;46842;46805:20;:40::i;:::-;46983:2;46979;46975:11;46971:2;46967:20;46961:26;;47059:2;47049:138;;47095:10;47089:4;47082:24;47167:4;47161;47154:18;47049:138;47251:2;47245:4;47238:16;47281:24;47275:4;47268:38;47373:4;47367;47357:21;47353:2;47349:30;47345:2;47341:39;47423:13;47417:20;47510:15;47506:2;47502:24;47499:149;;;47559:10;47553:4;47546:24;47628:4;47622;47615:18;47499:149;47739:2;47722:15;47719:23;47704:13;47697:46;47837:2;47831:4;47824:16;47893:4;47887;47877:21;47965:1;47951:11;47945:18;47941:26;48018:20;47999:17;47995:44;47985:193;;48077:10;48071:4;48064:24;48154:4;48148;48141:18;47985:193;48216:17;48203:11;48196:38;47805:444;;48353:2;48349;48346:1;48319:25;48313:4;48307;48302:54;46909:1458;;48377:39;48405:1;48409:2;48413;48377:19;:39::i;:::-;46738:1686;;:::o;122818:390::-;122902:16;122921:20;122934:6;122921:12;:20::i;:::-;122902:39;;122952:23;122997:8;122978:9;:28;;;;:::i;:::-;122952:54;;123017:15;123035:22;123050:6;123035:14;:22::i;:::-;123017:40;;123070:130;123099:6;123180:7;123164:25;;123157:3;123136:16;123128:25;;:32;;123120:69;123070:14;:130::i;:::-;122891:317;;;122818:390;;:::o;20754:98::-;20807:7;20834:10;20827:17;;20754:98;:::o;12590:948::-;12643:7;12663:14;12680:1;12663:18;;12730:8;12721:5;:17;12717:106;;12768:8;12759:17;;;;;;:::i;:::-;;;;;12805:2;12795:12;;;;12717:106;12850:8;12841:5;:17;12837:106;;12888:8;12879:17;;;;;;:::i;:::-;;;;;12925:2;12915:12;;;;12837:106;12970:8;12961:5;:17;12957:106;;13008:8;12999:17;;;;;;:::i;:::-;;;;;13045:2;13035:12;;;;12957:106;13090:7;13081:5;:16;13077:103;;13127:7;13118:16;;;;;;:::i;:::-;;;;;13163:1;13153:11;;;;13077:103;13207:7;13198:5;:16;13194:103;;13244:7;13235:16;;;;;;:::i;:::-;;;;;13280:1;13270:11;;;;13194:103;13324:7;13315:5;:16;13311:103;;13361:7;13352:16;;;;;;:::i;:::-;;;;;13397:1;13387:11;;;;13311:103;13441:7;13432:5;:16;13428:68;;13479:1;13469:11;;;;13428:68;13524:6;13517:13;;;12590:948;;;:::o;44643:416::-;44799:24;44793:4;44786:38;44851:5;44845:4;44838:19;44906:4;44900;44890:21;44945:11;44939:18;45030:6;45026:2;45022:15;45015:5;45011:27;45007:2;45003:36;44995:6;44991:49;44978:11;44971:70;44771:281;;44643:416;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:86::-;5902:7;5942:4;5935:5;5931:16;5920:27;;5867:86;;;:::o;5959:118::-;6030:22;6046:5;6030:22;:::i;:::-;6023:5;6020:33;6010:61;;6067:1;6064;6057:12;6010:61;5959:118;:::o;6083:135::-;6127:5;6165:6;6152:20;6143:29;;6181:31;6206:5;6181:31;:::i;:::-;6083:135;;;;:::o;6224:325::-;6281:6;6330:2;6318:9;6309:7;6305:23;6301:32;6298:119;;;6336:79;;:::i;:::-;6298:119;6456:1;6481:51;6524:7;6515:6;6504:9;6500:22;6481:51;:::i;:::-;6471:61;;6427:115;6224:325;;;;:::o;6555:117::-;6664:1;6661;6654:12;6678:117;6787:1;6784;6777:12;6801:180;6849:77;6846:1;6839:88;6946:4;6943:1;6936:15;6970:4;6967:1;6960:15;6987:281;7070:27;7092:4;7070:27;:::i;:::-;7062:6;7058:40;7200:6;7188:10;7185:22;7164:18;7152:10;7149:34;7146:62;7143:88;;;7211:18;;:::i;:::-;7143:88;7251:10;7247:2;7240:22;7030:238;6987:281;;:::o;7274:129::-;7308:6;7335:20;;:::i;:::-;7325:30;;7364:33;7392:4;7384:6;7364:33;:::i;:::-;7274:129;;;:::o;7409:308::-;7471:4;7561:18;7553:6;7550:30;7547:56;;;7583:18;;:::i;:::-;7547:56;7621:29;7643:6;7621:29;:::i;:::-;7613:37;;7705:4;7699;7695:15;7687:23;;7409:308;;;:::o;7723:146::-;7820:6;7815:3;7810;7797:30;7861:1;7852:6;7847:3;7843:16;7836:27;7723:146;;;:::o;7875:425::-;7953:5;7978:66;7994:49;8036:6;7994:49;:::i;:::-;7978:66;:::i;:::-;7969:75;;8067:6;8060:5;8053:21;8105:4;8098:5;8094:16;8143:3;8134:6;8129:3;8125:16;8122:25;8119:112;;;8150:79;;:::i;:::-;8119:112;8240:54;8287:6;8282:3;8277;8240:54;:::i;:::-;7959:341;7875:425;;;;;:::o;8320:340::-;8376:5;8425:3;8418:4;8410:6;8406:17;8402:27;8392:122;;8433:79;;:::i;:::-;8392:122;8550:6;8537:20;8575:79;8650:3;8642:6;8635:4;8627:6;8623:17;8575:79;:::i;:::-;8566:88;;8382:278;8320:340;;;;:::o;8666:509::-;8735:6;8784:2;8772:9;8763:7;8759:23;8755:32;8752:119;;;8790:79;;:::i;:::-;8752:119;8938:1;8927:9;8923:17;8910:31;8968:18;8960:6;8957:30;8954:117;;;8990:79;;:::i;:::-;8954:117;9095:63;9150:7;9141:6;9130:9;9126:22;9095:63;:::i;:::-;9085:73;;8881:287;8666:509;;;;:::o;9181:117::-;9290:1;9287;9280:12;9304:117;9413:1;9410;9403:12;9444:568;9517:8;9527:6;9577:3;9570:4;9562:6;9558:17;9554:27;9544:122;;9585:79;;:::i;:::-;9544:122;9698:6;9685:20;9675:30;;9728:18;9720:6;9717:30;9714:117;;;9750:79;;:::i;:::-;9714:117;9864:4;9856:6;9852:17;9840:29;;9918:3;9910:4;9902:6;9898:17;9888:8;9884:32;9881:41;9878:128;;;9925:79;;:::i;:::-;9878:128;9444:568;;;;;:::o;10033:566::-;10104:8;10114:6;10164:3;10157:4;10149:6;10145:17;10141:27;10131:122;;10172:79;;:::i;:::-;10131:122;10285:6;10272:20;10262:30;;10315:18;10307:6;10304:30;10301:117;;;10337:79;;:::i;:::-;10301:117;10451:4;10443:6;10439:17;10427:29;;10505:3;10497:4;10489:6;10485:17;10475:8;10471:32;10468:41;10465:128;;;10512:79;;:::i;:::-;10465:128;10033:566;;;;;:::o;10605:930::-;10725:6;10733;10741;10749;10798:2;10786:9;10777:7;10773:23;10769:32;10766:119;;;10804:79;;:::i;:::-;10766:119;10952:1;10941:9;10937:17;10924:31;10982:18;10974:6;10971:30;10968:117;;;11004:79;;:::i;:::-;10968:117;11117:80;11189:7;11180:6;11169:9;11165:22;11117:80;:::i;:::-;11099:98;;;;10895:312;11274:2;11263:9;11259:18;11246:32;11305:18;11297:6;11294:30;11291:117;;;11327:79;;:::i;:::-;11291:117;11440:78;11510:7;11501:6;11490:9;11486:22;11440:78;:::i;:::-;11422:96;;;;11217:311;10605:930;;;;;;;:::o;11541:329::-;11600:6;11649:2;11637:9;11628:7;11624:23;11620:32;11617:119;;;11655:79;;:::i;:::-;11617:119;11775:1;11800:53;11845:7;11836:6;11825:9;11821:22;11800:53;:::i;:::-;11790:63;;11746:117;11541:329;;;;:::o;11876:104::-;11921:7;11950:24;11968:5;11950:24;:::i;:::-;11939:35;;11876:104;;;:::o;11986:142::-;12089:32;12115:5;12089:32;:::i;:::-;12084:3;12077:45;11986:142;;:::o;12134:254::-;12243:4;12281:2;12270:9;12266:18;12258:26;;12294:87;12378:1;12367:9;12363:17;12354:6;12294:87;:::i;:::-;12134:254;;;;:::o;12394:116::-;12464:21;12479:5;12464:21;:::i;:::-;12457:5;12454:32;12444:60;;12500:1;12497;12490:12;12444:60;12394:116;:::o;12516:133::-;12559:5;12597:6;12584:20;12575:29;;12613:30;12637:5;12613:30;:::i;:::-;12516:133;;;;:::o;12655:468::-;12720:6;12728;12777:2;12765:9;12756:7;12752:23;12748:32;12745:119;;;12783:79;;:::i;:::-;12745:119;12903:1;12928:53;12973:7;12964:6;12953:9;12949:22;12928:53;:::i;:::-;12918:63;;12874:117;13030:2;13056:50;13098:7;13089:6;13078:9;13074:22;13056:50;:::i;:::-;13046:60;;13001:115;12655:468;;;;;:::o;13129:112::-;13212:22;13228:5;13212:22;:::i;:::-;13207:3;13200:35;13129:112;;:::o;13247:316::-;13360:4;13398:2;13387:9;13383:18;13375:26;;13411:67;13475:1;13464:9;13460:17;13451:6;13411:67;:::i;:::-;13488:68;13552:2;13541:9;13537:18;13528:6;13488:68;:::i;:::-;13247:316;;;;;:::o;13569:214::-;13658:4;13696:2;13685:9;13681:18;13673:26;;13709:67;13773:1;13762:9;13758:17;13749:6;13709:67;:::i;:::-;13569:214;;;;:::o;13802:552::-;13859:8;13869:6;13919:3;13912:4;13904:6;13900:17;13896:27;13886:122;;13927:79;;:::i;:::-;13886:122;14040:6;14027:20;14017:30;;14070:18;14062:6;14059:30;14056:117;;;14092:79;;:::i;:::-;14056:117;14206:4;14198:6;14194:17;14182:29;;14260:3;14252:4;14244:6;14240:17;14230:8;14226:32;14223:41;14220:128;;;14267:79;;:::i;:::-;14220:128;13802:552;;;;;:::o;14360:963::-;14457:6;14465;14473;14481;14489;14538:3;14526:9;14517:7;14513:23;14509:33;14506:120;;;14545:79;;:::i;:::-;14506:120;14665:1;14690:53;14735:7;14726:6;14715:9;14711:22;14690:53;:::i;:::-;14680:63;;14636:117;14792:2;14818:53;14863:7;14854:6;14843:9;14839:22;14818:53;:::i;:::-;14808:63;;14763:118;14920:2;14946:53;14991:7;14982:6;14971:9;14967:22;14946:53;:::i;:::-;14936:63;;14891:118;15076:2;15065:9;15061:18;15048:32;15107:18;15099:6;15096:30;15093:117;;;15129:79;;:::i;:::-;15093:117;15242:64;15298:7;15289:6;15278:9;15274:22;15242:64;:::i;:::-;15224:82;;;;15019:297;14360:963;;;;;;;;:::o;15329:93::-;15365:7;15405:10;15398:5;15394:22;15383:33;;15329:93;;;:::o;15428:115::-;15513:23;15530:5;15513:23;:::i;:::-;15508:3;15501:36;15428:115;;:::o;15549:218::-;15640:4;15678:2;15667:9;15663:18;15655:26;;15691:69;15757:1;15746:9;15742:17;15733:6;15691:69;:::i;:::-;15549:218;;;;:::o;15773:474::-;15841:6;15849;15898:2;15886:9;15877:7;15873:23;15869:32;15866:119;;;15904:79;;:::i;:::-;15866:119;16024:1;16049:53;16094:7;16085:6;16074:9;16070:22;16049:53;:::i;:::-;16039:63;;15995:117;16151:2;16177:53;16222:7;16213:6;16202:9;16198:22;16177:53;:::i;:::-;16167:63;;16122:118;15773:474;;;;;:::o;16253:138::-;16334:32;16360:5;16334:32;:::i;:::-;16327:5;16324:43;16314:71;;16381:1;16378;16371:12;16314:71;16253:138;:::o;16397:155::-;16451:5;16489:6;16476:20;16467:29;;16505:41;16540:5;16505:41;:::i;:::-;16397:155;;;;:::o;16558:345::-;16625:6;16674:2;16662:9;16653:7;16649:23;16645:32;16642:119;;;16680:79;;:::i;:::-;16642:119;16800:1;16825:61;16878:7;16869:6;16858:9;16854:22;16825:61;:::i;:::-;16815:71;;16771:125;16558:345;;;;:::o;16909:180::-;16957:77;16954:1;16947:88;17054:4;17051:1;17044:15;17078:4;17075:1;17068:15;17095:320;17139:6;17176:1;17170:4;17166:12;17156:22;;17223:1;17217:4;17213:12;17244:18;17234:81;;17300:4;17292:6;17288:17;17278:27;;17234:81;17362:2;17354:6;17351:14;17331:18;17328:38;17325:84;;17381:18;;:::i;:::-;17325:84;17146:269;17095:320;;;:::o;17421:180::-;17469:77;17466:1;17459:88;17566:4;17563:1;17556:15;17590:4;17587:1;17580:15;17607:194;17647:4;17667:20;17685:1;17667:20;:::i;:::-;17662:25;;17701:20;17719:1;17701:20;:::i;:::-;17696:25;;17745:1;17742;17738:9;17730:17;;17769:1;17763:4;17760:11;17757:37;;;17774:18;;:::i;:::-;17757:37;17607:194;;;;:::o;17807:162::-;17947:14;17943:1;17935:6;17931:14;17924:38;17807:162;:::o;17975:366::-;18117:3;18138:67;18202:2;18197:3;18138:67;:::i;:::-;18131:74;;18214:93;18303:3;18214:93;:::i;:::-;18332:2;18327:3;18323:12;18316:19;;17975:366;;;:::o;18347:419::-;18513:4;18551:2;18540:9;18536:18;18528:26;;18600:9;18594:4;18590:20;18586:1;18575:9;18571:17;18564:47;18628:131;18754:4;18628:131;:::i;:::-;18620:139;;18347:419;;;:::o;18772:177::-;18912:29;18908:1;18900:6;18896:14;18889:53;18772:177;:::o;18955:366::-;19097:3;19118:67;19182:2;19177:3;19118:67;:::i;:::-;19111:74;;19194:93;19283:3;19194:93;:::i;:::-;19312:2;19307:3;19303:12;19296:19;;18955:366;;;:::o;19327:419::-;19493:4;19531:2;19520:9;19516:18;19508:26;;19580:9;19574:4;19570:20;19566:1;19555:9;19551:17;19544:47;19608:131;19734:4;19608:131;:::i;:::-;19600:139;;19327:419;;;:::o;19752:191::-;19792:3;19811:20;19829:1;19811:20;:::i;:::-;19806:25;;19845:20;19863:1;19845:20;:::i;:::-;19840:25;;19888:1;19885;19881:9;19874:16;;19909:3;19906:1;19903:10;19900:36;;;19916:18;;:::i;:::-;19900:36;19752:191;;;;:::o;19949:169::-;20089:21;20085:1;20077:6;20073:14;20066:45;19949:169;:::o;20124:366::-;20266:3;20287:67;20351:2;20346:3;20287:67;:::i;:::-;20280:74;;20363:93;20452:3;20363:93;:::i;:::-;20481:2;20476:3;20472:12;20465:19;;20124:366;;;:::o;20496:419::-;20662:4;20700:2;20689:9;20685:18;20677:26;;20749:9;20743:4;20739:20;20735:1;20724:9;20720:17;20713:47;20777:131;20903:4;20777:131;:::i;:::-;20769:139;;20496:419;;;:::o;20921:188::-;20959:3;20978:18;20994:1;20978:18;:::i;:::-;20973:23;;21010:18;21026:1;21010:18;:::i;:::-;21005:23;;21051:1;21048;21044:9;21037:16;;21074:4;21069:3;21066:13;21063:39;;;21082:18;;:::i;:::-;21063:39;20921:188;;;;:::o;21115:141::-;21164:4;21187:3;21179:11;;21210:3;21207:1;21200:14;21244:4;21241:1;21231:18;21223:26;;21115:141;;;:::o;21262:93::-;21299:6;21346:2;21341;21334:5;21330:14;21326:23;21316:33;;21262:93;;;:::o;21361:107::-;21405:8;21455:5;21449:4;21445:16;21424:37;;21361:107;;;;:::o;21474:393::-;21543:6;21593:1;21581:10;21577:18;21616:97;21646:66;21635:9;21616:97;:::i;:::-;21734:39;21764:8;21753:9;21734:39;:::i;:::-;21722:51;;21806:4;21802:9;21795:5;21791:21;21782:30;;21855:4;21845:8;21841:19;21834:5;21831:30;21821:40;;21550:317;;21474:393;;;;;:::o;21873:60::-;21901:3;21922:5;21915:12;;21873:60;;;:::o;21939:142::-;21989:9;22022:53;22040:34;22049:24;22067:5;22049:24;:::i;:::-;22040:34;:::i;:::-;22022:53;:::i;:::-;22009:66;;21939:142;;;:::o;22087:75::-;22130:3;22151:5;22144:12;;22087:75;;;:::o;22168:269::-;22278:39;22309:7;22278:39;:::i;:::-;22339:91;22388:41;22412:16;22388:41;:::i;:::-;22380:6;22373:4;22367:11;22339:91;:::i;:::-;22333:4;22326:105;22244:193;22168:269;;;:::o;22443:73::-;22488:3;22443:73;:::o;22522:189::-;22599:32;;:::i;:::-;22640:65;22698:6;22690;22684:4;22640:65;:::i;:::-;22575:136;22522:189;;:::o;22717:186::-;22777:120;22794:3;22787:5;22784:14;22777:120;;;22848:39;22885:1;22878:5;22848:39;:::i;:::-;22821:1;22814:5;22810:13;22801:22;;22777:120;;;22717:186;;:::o;22909:543::-;23010:2;23005:3;23002:11;22999:446;;;23044:38;23076:5;23044:38;:::i;:::-;23128:29;23146:10;23128:29;:::i;:::-;23118:8;23114:44;23311:2;23299:10;23296:18;23293:49;;;23332:8;23317:23;;23293:49;23355:80;23411:22;23429:3;23411:22;:::i;:::-;23401:8;23397:37;23384:11;23355:80;:::i;:::-;23014:431;;22999:446;22909:543;;;:::o;23458:117::-;23512:8;23562:5;23556:4;23552:16;23531:37;;23458:117;;;;:::o;23581:169::-;23625:6;23658:51;23706:1;23702:6;23694:5;23691:1;23687:13;23658:51;:::i;:::-;23654:56;23739:4;23733;23729:15;23719:25;;23632:118;23581:169;;;;:::o;23755:295::-;23831:4;23977:29;24002:3;23996:4;23977:29;:::i;:::-;23969:37;;24039:3;24036:1;24032:11;24026:4;24023:21;24015:29;;23755:295;;;;:::o;24055:1395::-;24172:37;24205:3;24172:37;:::i;:::-;24274:18;24266:6;24263:30;24260:56;;;24296:18;;:::i;:::-;24260:56;24340:38;24372:4;24366:11;24340:38;:::i;:::-;24425:67;24485:6;24477;24471:4;24425:67;:::i;:::-;24519:1;24543:4;24530:17;;24575:2;24567:6;24564:14;24592:1;24587:618;;;;25249:1;25266:6;25263:77;;;25315:9;25310:3;25306:19;25300:26;25291:35;;25263:77;25366:67;25426:6;25419:5;25366:67;:::i;:::-;25360:4;25353:81;25222:222;24557:887;;24587:618;24639:4;24635:9;24627:6;24623:22;24673:37;24705:4;24673:37;:::i;:::-;24732:1;24746:208;24760:7;24757:1;24754:14;24746:208;;;24839:9;24834:3;24830:19;24824:26;24816:6;24809:42;24890:1;24882:6;24878:14;24868:24;;24937:2;24926:9;24922:18;24909:31;;24783:4;24780:1;24776:12;24771:17;;24746:208;;;24982:6;24973:7;24970:19;24967:179;;;25040:9;25035:3;25031:19;25025:26;25083:48;25125:4;25117:6;25113:17;25102:9;25083:48;:::i;:::-;25075:6;25068:64;24990:156;24967:179;25192:1;25188;25180:6;25176:14;25172:22;25166:4;25159:36;24594:611;;;24557:887;;24147:1303;;;24055:1395;;:::o;25456:229::-;25596:34;25592:1;25584:6;25580:14;25573:58;25665:12;25660:2;25652:6;25648:15;25641:37;25456:229;:::o;25691:366::-;25833:3;25854:67;25918:2;25913:3;25854:67;:::i;:::-;25847:74;;25930:93;26019:3;25930:93;:::i;:::-;26048:2;26043:3;26039:12;26032:19;;25691:366;;;:::o;26063:419::-;26229:4;26267:2;26256:9;26252:18;26244:26;;26316:9;26310:4;26306:20;26302:1;26291:9;26287:17;26280:47;26344:131;26470:4;26344:131;:::i;:::-;26336:139;;26063:419;;;:::o;26488:180::-;26536:77;26533:1;26526:88;26633:4;26630:1;26623:15;26657:4;26654:1;26647:15;26674:191;26712:4;26732:18;26748:1;26732:18;:::i;:::-;26727:23;;26764:18;26780:1;26764:18;:::i;:::-;26759:23;;26806:1;26803;26799:9;26791:17;;26830:4;26824;26821:14;26818:40;;;26838:18;;:::i;:::-;26818:40;26674:191;;;;:::o;26871:162::-;27011:14;27007:1;26999:6;26995:14;26988:38;26871:162;:::o;27039:366::-;27181:3;27202:67;27266:2;27261:3;27202:67;:::i;:::-;27195:74;;27278:93;27367:3;27278:93;:::i;:::-;27396:2;27391:3;27387:12;27380:19;;27039:366;;;:::o;27411:419::-;27577:4;27615:2;27604:9;27600:18;27592:26;;27664:9;27658:4;27654:20;27650:1;27639:9;27635:17;27628:47;27692:131;27818:4;27692:131;:::i;:::-;27684:139;;27411:419;;;:::o;27836:148::-;27938:11;27975:3;27960:18;;27836:148;;;;:::o;27990:390::-;28096:3;28124:39;28157:5;28124:39;:::i;:::-;28179:89;28261:6;28256:3;28179:89;:::i;:::-;28172:96;;28277:65;28335:6;28330:3;28323:4;28316:5;28312:16;28277:65;:::i;:::-;28367:6;28362:3;28358:16;28351:23;;28100:280;27990:390;;;;:::o;28386:435::-;28566:3;28588:95;28679:3;28670:6;28588:95;:::i;:::-;28581:102;;28700:95;28791:3;28782:6;28700:95;:::i;:::-;28693:102;;28812:3;28805:10;;28386:435;;;;;:::o;28827:79::-;28866:7;28895:5;28884:16;;28827:79;;;:::o;28912:157::-;29017:45;29037:24;29055:5;29037:24;:::i;:::-;29017:45;:::i;:::-;29012:3;29005:58;28912:157;;:::o;29075:397::-;29215:3;29230:75;29301:3;29292:6;29230:75;:::i;:::-;29330:2;29325:3;29321:12;29314:19;;29343:75;29414:3;29405:6;29343:75;:::i;:::-;29443:2;29438:3;29434:12;29427:19;;29463:3;29456:10;;29075:397;;;;;:::o;29478:171::-;29517:3;29540:24;29558:5;29540:24;:::i;:::-;29531:33;;29586:4;29579:5;29576:15;29573:41;;29594:18;;:::i;:::-;29573:41;29641:1;29634:5;29630:13;29623:20;;29478:171;;;:::o;29655:180::-;29703:77;29700:1;29693:88;29800:4;29797:1;29790:15;29824:4;29821:1;29814:15;29841:197;29880:3;29899:19;29916:1;29899:19;:::i;:::-;29894:24;;29932:19;29949:1;29932:19;:::i;:::-;29927:24;;29974:1;29971;29967:9;29960:16;;29997:10;29992:3;29989:19;29986:45;;;30011:18;;:::i;:::-;29986:45;29841:197;;;;:::o

Swarm Source

ipfs://b759f54012460361b42f3a4227bec927bf17ab62cd396622764adcd083861263
Loading...
Loading
Loading...
Loading
[ 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.