Token Phenix New Year 2024

Overview CRC721

Total Supply:
926 PNYE2024

Holders:
918 addresses
Balance
1 PNYE2024
0xc51128485f62ca6d485214fbfdab6c39bae7f0c5
Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
PhenixNewYear

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at cronoscan.com on 2023-12-29
*/

// File: contracts/includes/WithLimitedSupply.sol


pragma solidity ^0.8.4;

/// @author Modified version of original code by 1001.digital
/// @title A token tracker that limits the token supply and increments token IDs on each new mint.
abstract contract WithLimitedSupply {
    // Keeps track of how many we have minted
    uint256 private _tokenCount;

    /// @dev The maximum count of tokens this token tracker will issue.
    uint256 private immutable _maxAvailableSupply;

    /// Instanciate the contract
    /// @param maxSupply_ how many tokens this collection should hold
    constructor(uint256 maxSupply_, uint256 reserved_) {
        _maxAvailableSupply = maxSupply_ - reserved_;
    }

    function maxAvailableSupply() public view returns (uint256) {
        return _maxAvailableSupply;
    }

    /// @dev Get the current token count
    /// @return the created token count
    /// TODO: if this is not required externally, does making it `public view` use unneccary gas?
    function tokenCount() public view returns (uint256) {
        return _tokenCount;
    }

    /// @dev Check whether tokens are still available
    /// @return the available token count
    function availableTokenCount() public view returns (uint256) {
        return maxAvailableSupply() - tokenCount();
    }

    /// @dev Increment the token count and fetch the latest count
    /// @return the next token id
    function nextToken() internal virtual ensureAvailability returns (uint256) {
        return _tokenCount++;
    }

    /// @dev Check whether another token is still available
    modifier ensureAvailability() {
        require(availableTokenCount() > 0, "No more tokens available");
        _;
    }

    /// @param amount Check whether number of tokens are still available
    /// @dev Check whether tokens are still available
    modifier ensureAvailabilityFor(uint256 amount) {
        require(
            availableTokenCount() >= amount,
            "Requested number of tokens not available"
        );
        _;
    }
}

// File: contracts/includes/RandomlyAssigned.sol


pragma solidity ^0.8.4;


/// @author Modified version of original code by 1001.digital
/// @title Randomly assign tokenIDs from a given set of tokens.
abstract contract RandomlyAssigned is WithLimitedSupply {
    // Used for random index assignment
    mapping(uint256 => uint256) private tokenMatrix;

    // The initial token ID
    uint256 private immutable startFrom;

    /// Instanciate the contract
    /// @param maxSupply_ how many tokens this collection should hold
    /// @param numReserved_ the number of tokens reserved whose IDs dont come from the randomizer
    constructor(
        uint256 maxSupply_,
        uint256 numReserved_
    ) WithLimitedSupply(maxSupply_, numReserved_) {
        startFrom = numReserved_ + 1;
    }

    /// Get the next token ID
    /// @dev Randomly gets a new token ID and keeps track of the ones that are still available.
    /// @return the next token ID
    function nextToken() internal override returns (uint256) {
        uint256 maxIndex = maxAvailableSupply() - tokenCount();
        uint256 random = uint256(
            keccak256(
                abi.encodePacked(
                    msg.sender,
                    block.coinbase,
                    block.prevrandao,
                    block.gaslimit,
                    block.timestamp
                )
            )
        ) % maxIndex;

        uint256 value = 0;
        if (tokenMatrix[random] == 0) {
            // If this matrix position is empty, set the value to the generated random number.
            value = random;
        } else {
            // Otherwise, use the previously stored number from the matrix.
            value = tokenMatrix[random];
        }

        // If the last available tokenID is still unused...
        if (tokenMatrix[maxIndex - 1] == 0) {
            // ...store that ID in the current matrix position.
            tokenMatrix[random] = maxIndex - 1;
        } else {
            // ...otherwise copy over the stored number to the current matrix position.
            tokenMatrix[random] = tokenMatrix[maxIndex - 1];
        }

        // Increment counts (ie. qty minted)
        super.nextToken();

        return value + startFrom;
    }
}

// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

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


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

pragma solidity ^0.8.20;

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

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

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

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

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


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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.20;



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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.20;

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

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


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

pragma solidity ^0.8.20;

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

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


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

pragma solidity ^0.8.20;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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


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

pragma solidity ^0.8.20;


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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.20;


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

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

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

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


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

pragma solidity ^0.8.20;


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

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

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

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


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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/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/token/ERC721/ERC721.sol


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

pragma solidity ^0.8.20;








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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    mapping(uint256 tokenId => address) private _tokenApprovals;

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

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

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

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

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

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

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

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

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

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

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

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

        return _getApproved(tokenId);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

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

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

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

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

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

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

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

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

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

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

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

        _tokenApprovals[tokenId] = to;
    }

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

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

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

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


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

pragma solidity ^0.8.20;




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

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

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

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

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

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

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

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

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

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

        return previousOwner;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/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: contracts/BitBirdClubNFT.sol

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;






contract PhenixNewYear is ERC721Enumerable, RandomlyAssigned, Ownable {
    uint256 constant MAX_MINT = 2000;
    uint256 constant MAX_MINT_PER_TRANSACTION = 50;

    mapping(address => bool) public whitelist;
    mapping(address => uint256) public totalUserMints;

    uint256 public normalMintCost;
    uint256 public whitelistMintCost;

    uint256 public whitelistMintStartTimestamp;
    uint256 public mintStartTimestamp;

    uint256 public payableERC20TokenMintCost;
    address public payableERC20Token;

    // Drop Operator Fee Setup
    address private constant OPERATOR_ADDRESS =
        0x16d934B9646d9DA51Db92627BF0070Be0Ab72389;
    uint256 private constant OPERATOR_FEE = 0;
    uint256 private constant OPERATOR_FEE_DENOMINATOR = 1000;

    string baseURI;
    string revealURI;
    bool public mintEnabled = true;
    bool public whitelistOnly;
    bool public canMintWithERC20;
    bool public isRevealed;
    uint256 public maxMintPerAddress;

    modifier onlyMintEnabled() {
        require(
            mintEnabled ||
                (block.timestamp >= mintStartTimestamp) ||
                (whitelist[msg.sender] == true &&
                    block.timestamp >= whitelistMintStartTimestamp),
            "Mint Disabled"
        );
        _;
    }

    modifier onlyWhitelisted() {
        if (whitelistOnly) {
            require(isWhitelisted(msg.sender), "Not Whitelisted");
        }
        _;
    }

    modifier ERC20MintingAllowed() {
        require(canMintWithERC20 == true, "ERC20 Token Minting is disabled");
        _;
    }

    constructor(
        string memory _nftBaseURI,
        string memory _nftRevealURI,
        uint256 _initialTeamReserve,
        uint256 _mintStartTimestamp,
        uint256 _whitelistMintStartTimestamp,
        uint256 _maxMintPerAddress
    ) ERC721("Phenix New Year 2024", "PNYE2024") RandomlyAssigned(MAX_MINT, 0) Ownable(msg.sender) {
        baseURI = _nftBaseURI;
        revealURI = _nftRevealURI;
        maxMintPerAddress = _maxMintPerAddress;

        payableERC20Token = address(0);

        normalMintCost = 100 ether;
        whitelistMintCost = 100 ether;
        payableERC20TokenMintCost = 1 ether;

        whitelistMintStartTimestamp = _whitelistMintStartTimestamp;
        mintStartTimestamp = _mintStartTimestamp;

        // Mint initial team reserve
        if (_initialTeamReserve > 0) {
            for (uint256 i = 0; i < _initialTeamReserve; i++) {
                uint256 index = nextToken();
                _safeMint(msg.sender, index);
            }
        }

        isRevealed = true;
    }

    function canUserStartMinting(address _address) public view returns (bool) {
        return
            mintEnabled ||
            (block.timestamp >= mintStartTimestamp) ||
            (whitelist[_address] == true &&
                block.timestamp >= whitelistMintStartTimestamp);
    }

    function setRevealed() external onlyOwner {
        isRevealed = true;
    }

    function setMaxMintPerAddress(
        uint256 _maxMintPerAddress
    ) external onlyOwner {
        maxMintPerAddress = _maxMintPerAddress;
    }

    function updateBaseURI(string memory _newURI) external onlyOwner {
        baseURI = _newURI;
    }

    function updateRevealURI(string memory _newURI) external onlyOwner {
        revealURI = _newURI;
    }

    function setMintEnabled(bool _mintEnabled) external onlyOwner {
        mintEnabled = _mintEnabled;
    }

    function setWhitelistOnly(bool _whitelistOnly) external onlyOwner {
        whitelistOnly = _whitelistOnly;
    }

    function setCanMintWithERC20(bool _canMintWithERC20) external onlyOwner {
        canMintWithERC20 = _canMintWithERC20;
    }

    function setPayableERC20Token(
        address _payableERC20Token
    ) external onlyOwner {
        payableERC20Token = _payableERC20Token;
    }

    function setMintCosts(
        uint256 _normalMintCost,
        uint256 _whitelistMintCost,
        uint256 _payableERC20TokenMintCost
    ) external onlyOwner {
        normalMintCost = _normalMintCost;
        whitelistMintCost = _whitelistMintCost;
        payableERC20TokenMintCost = _payableERC20TokenMintCost;
    }

    function setMintStartTimestamps(
        uint256 _mintStartTimestamp,
        uint256 _whitelistMintStartTimestamp
    ) external onlyOwner {
        mintStartTimestamp = _mintStartTimestamp;
        whitelistMintStartTimestamp = _whitelistMintStartTimestamp;
    }

    function mint(
        uint256 _amount
    ) external payable onlyMintEnabled onlyWhitelisted {
        _mintNFT(_amount);
    }

    function mintWithERC20Token(
        uint256 _amount
    ) external onlyMintEnabled onlyWhitelisted ERC20MintingAllowed {
        require(_amount <= MAX_MINT_PER_TRANSACTION, "Invalid mint amount");
        require(_amount > 0, "Invalid mint amount");
        require(
            totalSupply() + _amount <= MAX_MINT,
            "Exceeding Max Mint Count"
        );
        require(
            maxMintPerAddress == 0 ||
                totalUserMints[msg.sender] + _amount <= maxMintPerAddress ||
                msg.sender == owner(),
            "Exceeding Max Mint Per Address"
        );

        uint256 requiredAmount = payableERC20TokenMintCost * _amount;

        // send tokens to owner
        IERC20(payableERC20Token).transferFrom(
            msg.sender,
            address(this),
            requiredAmount
        );

        for (uint256 i = 0; i < _amount; i++) {
            uint256 index = totalSupply() + 1;
            _safeMint(msg.sender, index);
        }

        totalUserMints[msg.sender] += _amount;
    }

    function _mintNFT(uint256 _amount) internal {
        require(_amount <= MAX_MINT_PER_TRANSACTION, "Invalid mint amount");
        require(_amount > 0, "Invalid mint amount");
        require(
            totalSupply() + _amount <= MAX_MINT,
            "Exceeding Max Mint Count"
        );
        require(
            maxMintPerAddress == 0 ||
                totalUserMints[msg.sender] + _amount <= maxMintPerAddress ||
                msg.sender == owner(),
            "Exceeding Max Mint Per Address"
        );

        uint256 requiredAmount = mintCost(msg.sender) * _amount;
        uint256 operatorFee = OPERATOR_FEE > 0
            ? (requiredAmount * OPERATOR_FEE) / OPERATOR_FEE_DENOMINATOR
            : 0;

        // Ensure the caller has sent enough ETH to cover the cost of minting
        require(
            msg.value == requiredAmount || msg.sender == owner(),
            "Insufficient Payment"
        );

        // Send operator fee to designated address
        if (operatorFee > 0) {
            (bool sent, ) = OPERATOR_ADDRESS.call{value: operatorFee}("");
            require(sent, "Failed to send operator fee");
        }

        for (uint256 i = 0; i < _amount; i++) {
            uint256 index = nextToken();
            _safeMint(msg.sender, index);
        }

        totalUserMints[msg.sender] += _amount;
    }

    function mintForUsers(address[] calldata _addresses, uint256 _amount) external onlyOwner {
        require(_amount <= MAX_MINT_PER_TRANSACTION, "Invalid mint amount");
        require(_amount > 0, "Invalid mint amount");
        require(
            totalSupply() + (_amount * _addresses.length) <= MAX_MINT,
            "Exceeding Max Mint Count"
        );

        for(uint256 i = 0; i < _addresses.length; i++) {
            for(uint256 j = 0; j < _amount; j++) {
                uint256 index = nextToken();
                _safeMint(_addresses[i], index);
            }
        }
    }

    function addWhitelist(address[] calldata _addresses) external onlyOwner {
        for (uint256 index = 0; index < _addresses.length; index++) {
            whitelist[_addresses[index]] = true;
        }
    }

    function removeWhitelist(address[] calldata _addresses) external onlyOwner {
        for (uint256 index = 0; index < _addresses.length; index++) {
            whitelist[_addresses[index]] = false;
        }
    }

    function mintCost(address _minter) public view returns (uint256) {
        uint256 _mintCost = normalMintCost;

        if (whitelist[_minter] == true) {
            _mintCost = whitelistMintCost;
        }

        if (_minter == owner()) {
            _mintCost = 0;
        }

        return _mintCost;
    }

    function maxMintPerTransaction() public pure returns (uint256) {
        return MAX_MINT_PER_TRANSACTION;
    }

    function canMint(address _minter) external view returns (uint256) {

        if(_minter == owner()) {
            return MAX_MINT_PER_TRANSACTION;
        }

        if (mintEnabled == false) {
            return 0;
        }

        if (whitelistOnly == true && isWhitelisted(_minter) == false) {
            return 0;
        }

        if (totalSupply() >= MAX_MINT) {
            return 0;
        }

        return MAX_MINT_PER_TRANSACTION;
    }

    function adminWithdrawETH() external onlyOwner {
        require(address(this).balance > 0, "No ETH to withdraw.");

        (bool success, ) = address(msg.sender).call{
            value: address(this).balance
        }("");

        require(success, "Failed to withdraw ETH.");
    }

    function adminWithdrawToken(address _tokenAddress) external onlyOwner {
        require(
            IERC20(_tokenAddress).balanceOf(address(this)) > 0,
            "No tokens to recover."
        );
        IERC20(_tokenAddress).transfer(
            msg.sender,
            IERC20(_tokenAddress).balanceOf(address(this))
        );
    }

    function maxSupply() external pure returns (uint256) {
        return MAX_MINT;
    }

    function isWhitelisted(address _address) public view returns (bool) {
        return whitelist[_address];
    }

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

    function getBaseURI() external view returns (string memory) {
        return _baseURI();
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view override(ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function tokenURI(
        uint256 tokenID
    ) public view virtual override returns (string memory) {
        if (isRevealed != true) {
            return string(abi.encodePacked(revealURI));
        }

        return string(abi.encodePacked(super.tokenURI(tokenID)));
    }

    function ownedNFTIdList(
        address _ownerAddress
    ) public view returns (uint256[] memory) {
        uint256 balance = balanceOf(_ownerAddress);

        uint256[] memory allIndexes = new uint256[](balance);
        for (uint256 i = 0; i < balance; i++) {
            uint256 tokenIndex = tokenOfOwnerByIndex(_ownerAddress, i);
            allIndexes[i] = tokenIndex;
        }

        return allIndexes;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_nftBaseURI","type":"string"},{"internalType":"string","name":"_nftRevealURI","type":"string"},{"internalType":"uint256","name":"_initialTeamReserve","type":"uint256"},{"internalType":"uint256","name":"_mintStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"_whitelistMintStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxMintPerAddress","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"addWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminWithdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"adminWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"availableTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"canMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canMintWithERC20","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"canUserStartMinting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAvailableSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintPerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintPerTransaction","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"mintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintForUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintWithERC20Token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"normalMintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ownerAddress","type":"address"}],"name":"ownedNFTIdList","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payableERC20Token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payableERC20TokenMintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"removeWhitelist","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":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_canMintWithERC20","type":"bool"}],"name":"setCanMintWithERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMintPerAddress","type":"uint256"}],"name":"setMaxMintPerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_normalMintCost","type":"uint256"},{"internalType":"uint256","name":"_whitelistMintCost","type":"uint256"},{"internalType":"uint256","name":"_payableERC20TokenMintCost","type":"uint256"}],"name":"setMintCosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_mintEnabled","type":"bool"}],"name":"setMintEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"_whitelistMintStartTimestamp","type":"uint256"}],"name":"setMintStartTimestamps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payableERC20Token","type":"address"}],"name":"setPayableERC20Token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_whitelistOnly","type":"bool"}],"name":"setWhitelistOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalUserMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newURI","type":"string"}],"name":"updateBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newURI","type":"string"}],"name":"updateRevealURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistMintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistMintStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistOnly","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60c06040526017805460ff191660011790553480156200001e57600080fd5b506040516200421938038062004219833981016040819052620000419162000cf5565b336107d0600081816040518060400160405280601481526020017f5068656e6978204e65772059656172203230323400000000000000000000000081525060405180604001604052806008815260200167141396514c8c0c8d60c21b8152508160009081620000b1919062000e14565b506001620000c0828262000e14565b5050508082620000d1919062000ef6565b60805250620000e4905081600162000f0c565b60a05250506001600160a01b0381166200011957604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200012481620001d9565b50601562000133878262000e14565b50601662000142868262000e14565b506018819055601480546001600160a01b031916905568056bc75e2d63100000600f819055601055670de0b6b3a7640000601355601182905560128390558315620001b95760005b84811015620001b75760006200019f6200022b565b9050620001ad33826200037c565b506001016200018a565b505b50506017805463ff00000019166301000000179055506200101692505050565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008062000238600a5490565b60805162000247919062000ef6565b6040516001600160601b031933606090811b8216602084015241901b166034820152446048820152456068820152426088820152909150600090829060a8016040516020818303038152906040528051906020012060001c620002ab919062000f22565b6000818152600b6020526040812054919250908103620002cd575080620002de565b506000818152600b60205260409020545b600b6000620002ef60018662000ef6565b81526020019081526020016000205460000362000328576200031360018462000ef6565b6000838152600b60205260409020556200035a565b600b60006200033960018662000ef6565b81526020808201929092526040908101600090812054858252600b90935220555b62000364620003a2565b5060a05162000374908262000f0c565b935050505090565b6200039e8282604051806020016040528060008152506200041960201b60201c565b5050565b600080620003af62000439565b11620003fe5760405162461bcd60e51b815260206004820152601860248201527f4e6f206d6f726520746f6b656e7320617661696c61626c650000000000000000604482015260640162000110565b600a8054906000620004108362000f45565b91905055905090565b62000425838362000459565b620004346000848484620004c3565b505050565b600062000445600a5490565b60805162000454919062000ef6565b905090565b6001600160a01b0382166200048557604051633250574960e11b81526000600482015260240162000110565b600062000494838383620005fa565b90506001600160a01b0381161562000434576040516339e3563760e11b81526000600482015260240162000110565b6001600160a01b0383163b15620005f457604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906200050890339088908790879060040162000f61565b6020604051808303816000875af192505050801562000546575060408051601f3d908101601f19168201909252620005439181019062000fb7565b60015b620005b4573d80801562000577576040519150601f19603f3d011682016040523d82523d6000602084013e6200057c565b606091505b508051600003620005ac57604051633250574960e11b81526001600160a01b038516600482015260240162000110565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14620005f257604051633250574960e11b81526001600160a01b038516600482015260240162000110565b505b50505050565b6000806200060a858585620006de565b90506001600160a01b0381166200066a576200066484600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b62000690565b846001600160a01b0316816001600160a01b0316146200069057620006908185620007dd565b6001600160a01b038516620006b057620006aa8462000871565b620006d6565b846001600160a01b0316816001600160a01b031614620006d657620006d685856200092b565b949350505050565b6000828152600260205260408120546001600160a01b03908116908316156200070e576200070e8184866200097f565b6001600160a01b038116156200074e576200072d6000858180620009e9565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b038516156200077e576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6000620007ea8362000b17565b6000838152600760205260409020549091508082146200083e576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090620008859060019062000ef6565b60008381526009602052604081205460088054939450909284908110620008b057620008b062000fea565b906000526020600020015490508060088381548110620008d457620008d462000fea565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806200090f576200090f62001000565b6001900381819060005260206000200160009055905550505050565b600060016200093a8462000b17565b62000946919062000ef6565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6200098c83838362000b61565b62000434576001600160a01b038316620009bd57604051637e27328960e01b81526004810182905260240162000110565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440162000110565b8080620009fe57506001600160a01b03821615155b1562000ae757600062000a118462000be7565b90506001600160a01b0383161580159062000a3e5750826001600160a01b0316816001600160a01b031614155b801562000a7157506001600160a01b0380821660009081526005602090815260408083209387168352929052205460ff16155b1562000a9c5760405163a9fbf51f60e01b81526001600160a01b038416600482015260240162000110565b811562000ae55783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b03821662000b45576040516322718ad960e21b81526000600482015260240162000110565b506001600160a01b031660009081526003602052604090205490565b60006001600160a01b03831615801590620006d65750826001600160a01b0316846001600160a01b0316148062000bbd57506001600160a01b0380851660009081526005602090815260408083209387168352929052205460ff165b80620006d65750506000908152600460205260409020546001600160a01b03908116911614919050565b6000818152600260205260408120546001600160a01b03168062000c2257604051637e27328960e01b81526004810184905260240162000110565b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000c5b57818101518382015260200162000c41565b50506000910152565b600082601f83011262000c7657600080fd5b81516001600160401b038082111562000c935762000c9362000c28565b604051601f8301601f19908116603f0116810190828211818310171562000cbe5762000cbe62000c28565b8160405283815286602085880101111562000cd857600080fd5b62000ceb84602083016020890162000c3e565b9695505050505050565b60008060008060008060c0878903121562000d0f57600080fd5b86516001600160401b038082111562000d2757600080fd5b62000d358a838b0162000c64565b9750602089015191508082111562000d4c57600080fd5b5062000d5b89828a0162000c64565b95505060408701519350606087015192506080870151915060a087015190509295509295509295565b600181811c9082168062000d9957607f821691505b60208210810362000dba57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000434576000816000526020600020601f850160051c8101602086101562000deb5750805b601f850160051c820191505b8181101562000e0c5782815560010162000df7565b505050505050565b81516001600160401b0381111562000e305762000e3062000c28565b62000e488162000e41845462000d84565b8462000dc0565b602080601f83116001811462000e80576000841562000e675750858301515b600019600386901b1c1916600185901b17855562000e0c565b600085815260208120601f198616915b8281101562000eb15788860151825594840194600190910190840162000e90565b508582101562000ed05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c225762000c2262000ee0565b8082018082111562000c225762000c2262000ee0565b60008262000f4057634e487b7160e01b600052601260045260246000fd5b500690565b60006001820162000f5a5762000f5a62000ee0565b5060010190565b600060018060a01b03808716835280861660208401525083604083015260806060830152825180608084015262000fa08160a085016020870162000c3e565b601f01601f19169190910160a00195945050505050565b60006020828403121562000fca57600080fd5b81516001600160e01b03198116811462000fe357600080fd5b9392505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a0516131cf6200104a6000396000611d460152600081816104bd015281816113480152611c0801526131cf6000f3fe6080604052600436106103975760003560e01c8063715018a6116101dc578063b88d4fde11610102578063e985e9c5116100a0578063f2fde38b1161006f578063f2fde38b14610a6d578063f46a04eb14610a8d578063fa0cf53814610aad578063fee9d13b14610acd57600080fd5b8063e985e9c5146109f8578063ea05a8c614610a18578063ed84fc9114610a38578063edac985b14610a4d57600080fd5b8063d1239730116100dc578063d123973014610994578063d48997df146109ae578063d5abeb01146109ce578063e14ca353146109e357600080fd5b8063b88d4fde14610934578063c2ba474414610954578063c87b56dd1461097457600080fd5b80639b19251a1161017a578063a0e389de11610149578063a0e389de146108c8578063a22cb465146108de578063b0d356e5146108fe578063b12dab6e1461091e57600080fd5b80639b19251a146108505780639b667f80146108805780639f181b5e146108a0578063a0712d68146108b557600080fd5b8063931688cb116101b6578063931688cb146107db57806395d89b41146107fb57806399f7e45f146108105780639a8c00351461083057600080fd5b8063715018a61461077b578063839ad1d3146107905780638da5cb5b146107bd57600080fd5b80633096b9e8116102c15780634b4687b51161025f5780636352211e1161022e5780636352211e146107105780636a7957321461073057806370a0823114610746578063714c53981461076657600080fd5b80634b4687b51461069a5780634f6ccce7146106b957806354214f69146106d9578063572849c4146106fa57600080fd5b80633b71275d1161029b5780633b71275d1461062f5780633bd649681461064f578063413fa8e31461066457806342842e0e1461067a57600080fd5b80633096b9e8146105b657806333a5f120146105d65780633af32abf146105f657600080fd5b806315f91c18116103395780632324521611610308578063232452161461053657806323b872dd146105565780632acc659e146105765780632f745c591461059657600080fd5b806315f91c18146104ae57806318160ddd146104e15780631e0d6eea146104f65780631e14d44b1461051657600080fd5b806306fdde031161037557806306fdde0314610405578063081812fc14610427578063095ea7b31461045f57806310d8bc091461048157600080fd5b806301f569971461039c57806301ffc9a7146103bf57806302ddfd21146103ef575b600080fd5b3480156103a857600080fd5b5060325b6040519081526020015b60405180910390f35b3480156103cb57600080fd5b506103df6103da366004612950565b610aed565b60405190151581526020016103b6565b3480156103fb57600080fd5b506103ac60115481565b34801561041157600080fd5b5061041a610afe565b6040516103b691906129bd565b34801561043357600080fd5b506104476104423660046129d0565b610b90565b6040516001600160a01b0390911681526020016103b6565b34801561046b57600080fd5b5061047f61047a366004612a05565b610bb9565b005b34801561048d57600080fd5b506103ac61049c366004612a2f565b600e6020526000908152604090205481565b3480156104ba57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103ac565b3480156104ed57600080fd5b506008546103ac565b34801561050257600080fd5b5061047f610511366004612a4a565b610bc8565b34801561052257600080fd5b5061047f6105313660046129d0565b610bde565b34801561054257600080fd5b5061047f610551366004612ac2565b610beb565b34801561056257600080fd5b5061047f610571366004612b04565b610c60565b34801561058257600080fd5b506103ac610591366004612a2f565b610cf0565b3480156105a257600080fd5b506103ac6105b1366004612a05565b610d4d565b3480156105c257600080fd5b5061047f6105d1366004612b4e565b610db2565b3480156105e257600080fd5b506103df6105f1366004612a2f565b610dd6565b34801561060257600080fd5b506103df610611366004612a2f565b6001600160a01b03166000908152600d602052604090205460ff1690565b34801561063b57600080fd5b506017546103df9062010000900460ff1681565b34801561065b57600080fd5b5061047f610e26565b34801561067057600080fd5b506103ac60135481565b34801561068657600080fd5b5061047f610695366004612b04565b610e43565b3480156106a657600080fd5b506017546103df90610100900460ff1681565b3480156106c557600080fd5b506103ac6106d43660046129d0565b610e5e565b3480156106e557600080fd5b506017546103df906301000000900460ff1681565b34801561070657600080fd5b506103ac60185481565b34801561071c57600080fd5b5061044761072b3660046129d0565b610eb7565b34801561073c57600080fd5b506103ac600f5481565b34801561075257600080fd5b506103ac610761366004612a2f565b610ec2565b34801561077257600080fd5b5061041a610f0a565b34801561078757600080fd5b5061047f610f19565b34801561079c57600080fd5b506107b06107ab366004612a2f565b610f2d565b6040516103b69190612b6b565b3480156107c957600080fd5b50600c546001600160a01b0316610447565b3480156107e757600080fd5b5061047f6107f6366004612c3b565b610fcb565b34801561080757600080fd5b5061041a610fdf565b34801561081c57600080fd5b5061047f61082b366004612a2f565b610fee565b34801561083c57600080fd5b5061047f61084b366004612c3b565b611018565b34801561085c57600080fd5b506103df61086b366004612a2f565b600d6020526000908152604090205460ff1681565b34801561088c57600080fd5b5061047f61089b366004612c84565b61102c565b3480156108ac57600080fd5b50600a546103ac565b61047f6108c33660046129d0565b611111565b3480156108d457600080fd5b506103ac60125481565b3480156108ea57600080fd5b5061047f6108f9366004612cd0565b6111f9565b34801561090a57600080fd5b50601454610447906001600160a01b031681565b34801561092a57600080fd5b506103ac60105481565b34801561094057600080fd5b5061047f61094f366004612d07565b611204565b34801561096057600080fd5b506103ac61096f366004612a2f565b61121b565b34801561098057600080fd5b5061041a61098f3660046129d0565b6112ca565b3480156109a057600080fd5b506017546103df9060ff1681565b3480156109ba57600080fd5b5061047f6109c9366004612d83565b611324565b3480156109da57600080fd5b506107d06103ac565b3480156109ef57600080fd5b506103ac611337565b348015610a0457600080fd5b506103df610a13366004612da5565b61136c565b348015610a2457600080fd5b5061047f610a33366004612b4e565b61139a565b348015610a4457600080fd5b5061047f6113bc565b348015610a5957600080fd5b5061047f610a68366004612ac2565b6114a2565b348015610a7957600080fd5b5061047f610a88366004612a2f565b611512565b348015610a9957600080fd5b5061047f610aa8366004612b4e565b61154d565b348015610ab957600080fd5b5061047f610ac83660046129d0565b611568565b348015610ad957600080fd5b5061047f610ae8366004612a2f565b61188f565b6000610af882611a28565b92915050565b606060008054610b0d90612dd8565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3990612dd8565b8015610b865780601f10610b5b57610100808354040283529160200191610b86565b820191906000526020600020905b815481529060010190602001808311610b6957829003601f168201915b5050505050905090565b6000610b9b82611a4d565b506000828152600460205260409020546001600160a01b0316610af8565b610bc4828233611a86565b5050565b610bd0611a93565b600f92909255601055601355565b610be6611a93565b601855565b610bf3611a93565b60005b81811015610c5b576000600d6000858585818110610c1657610c16612e12565b9050602002016020810190610c2b9190612a2f565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610bf6565b505050565b6001600160a01b038216610c8f57604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610c9c838333611ac0565b9050836001600160a01b0316816001600160a01b031614610cea576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610c86565b50505050565b600f546001600160a01b0382166000908152600d602052604081205490919060ff161515600103610d2057506010545b600c546001600160a01b03166001600160a01b0316836001600160a01b031603610af85750600092915050565b6000610d5883610ec2565b8210610d895760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610c86565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b610dba611a93565b60178054911515620100000262ff000019909216919091179055565b60175460009060ff1680610dec57506012544210155b80610af857506001600160a01b0382166000908152600d602052604090205460ff1615156001148015610af8575060115442101592915050565b610e2e611a93565b6017805463ff00000019166301000000179055565b610c5b83838360405180602001604052806000815250611204565b6000610e6960085490565b8210610e925760405163295f44f760e21b81526000600482015260248101839052604401610c86565b60088281548110610ea557610ea5612e12565b90600052602060002001549050919050565b6000610af882611a4d565b60006001600160a01b038216610eee576040516322718ad960e21b815260006004820152602401610c86565b506001600160a01b031660009081526003602052604090205490565b6060610f14611b95565b905090565b610f21611a93565b610f2b6000611ba4565b565b60606000610f3a83610ec2565b905060008167ffffffffffffffff811115610f5757610f57612baf565b604051908082528060200260200182016040528015610f80578160200160208202803683370190505b50905060005b82811015610fc3576000610f9a8683610d4d565b905080838381518110610faf57610faf612e12565b602090810291909101015250600101610f86565b509392505050565b610fd3611a93565b6015610bc48282612e78565b606060018054610b0d90612dd8565b610ff6611a93565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b611020611a93565b6016610bc48282612e78565b611034611a93565b60328111156110555760405162461bcd60e51b8152600401610c8690612f38565b600081116110755760405162461bcd60e51b8152600401610c8690612f38565b6107d06110828383612f7b565b60085461108f9190612f92565b11156110ad5760405162461bcd60e51b8152600401610c8690612fa5565b60005b82811015610cea5760005b828110156111085760006110cd611bf6565b90506110ff8686858181106110e4576110e4612e12565b90506020020160208101906110f99190612a2f565b82611d73565b506001016110bb565b506001016110b0565b60175460ff168061112457506012544210155b806111505750336000908152600d602052604090205460ff161515600114801561115057506011544210155b61118c5760405162461bcd60e51b815260206004820152600d60248201526c135a5b9d08111a5cd8589b1959609a1b6044820152606401610c86565b601754610100900460ff16156111ed57336000908152600d602052604090205460ff166111ed5760405162461bcd60e51b815260206004820152600f60248201526e139bdd0815da1a5d195b1a5cdd1959608a1b6044820152606401610c86565b6111f681611d8d565b50565b610bc433838361200c565b61120f848484610c60565b610cea848484846120ab565b600061122f600c546001600160a01b031690565b6001600160a01b0316826001600160a01b03160361124f57506032919050565b60175460ff16151560000361126657506000919050565b60175460ff610100909104161515600114801561129c57506001600160a01b0382166000908152600d602052604090205460ff16155b156112a957506000919050565b6107d06112b560085490565b106112c257506000919050565b506032919050565b6017546060906301000000900460ff16151560011461130b5760166040516020016112f59190612fdc565b6040516020818303038152906040529050919050565b611314826121d4565b6040516020016112f59190613052565b61132c611a93565b601291909155601155565b6000611342600a5490565b610f14907f000000000000000000000000000000000000000000000000000000000000000061306e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6113a2611a93565b601780549115156101000261ff0019909216919091179055565b6113c4611a93565b6000471161140a5760405162461bcd60e51b815260206004820152601360248201527227379022aa24103a37903bb4ba34323930bb9760691b6044820152606401610c86565b604051600090339047908381818185875af1925050503d806000811461144c576040519150601f19603f3d011682016040523d82523d6000602084013e611451565b606091505b50509050806111f65760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f207769746864726177204554482e0000000000000000006044820152606401610c86565b6114aa611a93565b60005b81811015610c5b576001600d60008585858181106114cd576114cd612e12565b90506020020160208101906114e29190612a2f565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016114ad565b61151a611a93565b6001600160a01b03811661154457604051631e4fbdf760e01b815260006004820152602401610c86565b6111f681611ba4565b611555611a93565b6017805460ff1916911515919091179055565b60175460ff168061157b57506012544210155b806115a75750336000908152600d602052604090205460ff16151560011480156115a757506011544210155b6115e35760405162461bcd60e51b815260206004820152600d60248201526c135a5b9d08111a5cd8589b1959609a1b6044820152606401610c86565b601754610100900460ff161561164457336000908152600d602052604090205460ff166116445760405162461bcd60e51b815260206004820152600f60248201526e139bdd0815da1a5d195b1a5cdd1959608a1b6044820152606401610c86565b60175462010000900460ff1615156001146116a15760405162461bcd60e51b815260206004820152601f60248201527f455243323020546f6b656e204d696e74696e672069732064697361626c6564006044820152606401610c86565b60328111156116c25760405162461bcd60e51b8152600401610c8690612f38565b600081116116e25760405162461bcd60e51b8152600401610c8690612f38565b6107d0816116ef60085490565b6116f99190612f92565b11156117175760405162461bcd60e51b8152600401610c8690612fa5565b60185415806117425750601854336000908152600e602052604090205461173f908390612f92565b11155b806117575750600c546001600160a01b031633145b6117a35760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e67204d6178204d696e7420506572204164647265737300006044820152606401610c86565b6000816013546117b39190612f7b565b6014546040516323b872dd60e01b8152336004820152306024820152604481018390529192506001600160a01b0316906323b872dd906064016020604051808303816000875af115801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f9190613081565b5060005b8281101561186657600061184660085490565b611851906001612f92565b905061185d3382611d73565b50600101611833565b50336000908152600e602052604081208054849290611886908490612f92565b90915550505050565b611897611a93565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156118de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611902919061309e565b116119475760405162461bcd60e51b81526020600482015260156024820152742737903a37b5b2b739903a37903932b1b7bb32b91760591b6044820152606401610c86565b6040516370a0823160e01b81523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015611995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b9919061309e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190613081565b60006001600160e01b0319821663780e9d6360e01b1480610af85750610af88261223c565b6000818152600260205260408120546001600160a01b031680610af857604051637e27328960e01b815260048101849052602401610c86565b610c5b838383600161228c565b600c546001600160a01b03163314610f2b5760405163118cdaa760e01b8152336004820152602401610c86565b600080611ace858585612392565b90506001600160a01b038116611b2b57611b2684600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611b4e565b846001600160a01b0316816001600160a01b031614611b4e57611b4e818561248b565b6001600160a01b038516611b6a57611b658461251c565b611b8d565b846001600160a01b0316816001600160a01b031614611b8d57611b8d85856125cb565b949350505050565b606060158054610b0d90612dd8565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080611c02600a5490565b611c2c907f000000000000000000000000000000000000000000000000000000000000000061306e565b6040516bffffffffffffffffffffffff1933606090811b8216602084015241901b166034820152446048820152456068820152426088820152909150600090829060a8016040516020818303038152906040528051906020012060001c611c9391906130cd565b6000818152600b6020526040812054919250908103611cb3575080611cc4565b506000818152600b60205260409020545b600b6000611cd360018661306e565b815260200190815260200160002054600003611d0857611cf460018461306e565b6000838152600b6020526040902055611d38565b600b6000611d1760018661306e565b81526020808201929092526040908101600090812054858252600b90935220555b611d4061261b565b50611d6b7f000000000000000000000000000000000000000000000000000000000000000082612f92565b935050505090565b610bc482826040518060200160405280600081525061268c565b6032811115611dae5760405162461bcd60e51b8152600401610c8690612f38565b60008111611dce5760405162461bcd60e51b8152600401610c8690612f38565b6107d081611ddb60085490565b611de59190612f92565b1115611e035760405162461bcd60e51b8152600401610c8690612fa5565b6018541580611e2e5750601854336000908152600e6020526040902054611e2b908390612f92565b11155b80611e435750600c546001600160a01b031633145b611e8f5760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e67204d6178204d696e7420506572204164647265737300006044820152606401610c86565b600081611e9b33610cf0565b611ea59190612f7b565b9050600081341480611ec15750600c546001600160a01b031633145b611f045760405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d0814185e5b595b9d60621b6044820152606401610c86565b8015611fb8576040516000907316d934b9646d9da51db92627bf0070be0ab723899083908381818185875af1925050503d8060008114611f60576040519150601f19603f3d011682016040523d82523d6000602084013e611f65565b606091505b5050905080611fb65760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2073656e64206f70657261746f722066656500000000006044820152606401610c86565b505b60005b83811015611fe2576000611fcd611bf6565b9050611fd93382611d73565b50600101611fbb565b50336000908152600e602052604081208054859290612002908490612f92565b9091555050505050565b6001600160a01b03821661203e57604051630b61174360e31b81526001600160a01b0383166004820152602401610c86565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610cea57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906120ed9033908890879087906004016130e1565b6020604051808303816000875af1925050508015612128575060408051601f3d908101601f191682019092526121259181019061311e565b60015b612191573d808015612156576040519150601f19603f3d011682016040523d82523d6000602084013e61215b565b606091505b50805160000361218957604051633250574960e11b81526001600160a01b0385166004820152602401610c86565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146121cd57604051633250574960e11b81526001600160a01b0385166004820152602401610c86565b5050505050565b60606121df82611a4d565b5060006121ea611b95565b9050600081511161220a5760405180602001604052806000815250612235565b80612214846126a3565b60405160200161222592919061313b565b6040516020818303038152906040525b9392505050565b60006001600160e01b031982166380ac58cd60e01b148061226d57506001600160e01b03198216635b5e139f60e01b145b80610af857506301ffc9a760e01b6001600160e01b0319831614610af8565b80806122a057506001600160a01b03821615155b156123625760006122b084611a4d565b90506001600160a01b038316158015906122dc5750826001600160a01b0316816001600160a01b031614155b80156122ef57506122ed818461136c565b155b156123185760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610c86565b81156123605783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152600260205260408120546001600160a01b03908116908316156123bf576123bf818486612736565b6001600160a01b038116156123fd576123dc60008560008061228c565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561242c576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600061249683610ec2565b6000838152600760205260409020549091508082146124e9576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061252e9060019061306e565b6000838152600960205260408120546008805493945090928490811061255657612556612e12565b90600052602060002001549050806008838154811061257757612577612e12565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806125af576125af61316a565b6001900381819060005260206000200160009055905550505050565b600060016125d884610ec2565b6125e2919061306e565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b600080612626611337565b116126735760405162461bcd60e51b815260206004820152601860248201527f4e6f206d6f726520746f6b656e7320617661696c61626c6500000000000000006044820152606401610c86565b600a805490600061268383613180565b91905055905090565b612696838361279a565b610c5b60008484846120ab565b606060006126b0836127ff565b600101905060008167ffffffffffffffff8111156126d0576126d0612baf565b6040519080825280601f01601f1916602001820160405280156126fa576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461270457509392505050565b6127418383836128d7565b610c5b576001600160a01b03831661276f57604051637e27328960e01b815260048101829052602401610c86565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610c86565b6001600160a01b0382166127c457604051633250574960e11b815260006004820152602401610c86565b60006127d283836000611ac0565b90506001600160a01b03811615610c5b576040516339e3563760e11b815260006004820152602401610c86565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061283e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061286a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061288857662386f26fc10000830492506010015b6305f5e10083106128a0576305f5e100830492506008015b61271083106128b457612710830492506004015b606483106128c6576064830492506002015b600a8310610af85760010192915050565b60006001600160a01b03831615801590611b8d5750826001600160a01b0316846001600160a01b031614806129115750612911848461136c565b80611b8d5750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b0319811681146111f657600080fd5b60006020828403121561296257600080fd5b81356122358161293a565b60005b83811015612988578181015183820152602001612970565b50506000910152565b600081518084526129a981602086016020860161296d565b601f01601f19169290920160200192915050565b6020815260006122356020830184612991565b6000602082840312156129e257600080fd5b5035919050565b80356001600160a01b0381168114612a0057600080fd5b919050565b60008060408385031215612a1857600080fd5b612a21836129e9565b946020939093013593505050565b600060208284031215612a4157600080fd5b612235826129e9565b600080600060608486031215612a5f57600080fd5b505081359360208301359350604090920135919050565b60008083601f840112612a8857600080fd5b50813567ffffffffffffffff811115612aa057600080fd5b6020830191508360208260051b8501011115612abb57600080fd5b9250929050565b60008060208385031215612ad557600080fd5b823567ffffffffffffffff811115612aec57600080fd5b612af885828601612a76565b90969095509350505050565b600080600060608486031215612b1957600080fd5b612b22846129e9565b9250612b30602085016129e9565b9150604084013590509250925092565b80151581146111f657600080fd5b600060208284031215612b6057600080fd5b813561223581612b40565b6020808252825182820181905260009190848201906040850190845b81811015612ba357835183529284019291840191600101612b87565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115612be057612be0612baf565b604051601f8501601f19908116603f01168101908282118183101715612c0857612c08612baf565b81604052809350858152868686011115612c2157600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612c4d57600080fd5b813567ffffffffffffffff811115612c6457600080fd5b8201601f81018413612c7557600080fd5b611b8d84823560208401612bc5565b600080600060408486031215612c9957600080fd5b833567ffffffffffffffff811115612cb057600080fd5b612cbc86828701612a76565b909790965060209590950135949350505050565b60008060408385031215612ce357600080fd5b612cec836129e9565b91506020830135612cfc81612b40565b809150509250929050565b60008060008060808587031215612d1d57600080fd5b612d26856129e9565b9350612d34602086016129e9565b925060408501359150606085013567ffffffffffffffff811115612d5757600080fd5b8501601f81018713612d6857600080fd5b612d7787823560208401612bc5565b91505092959194509250565b60008060408385031215612d9657600080fd5b50508035926020909101359150565b60008060408385031215612db857600080fd5b612dc1836129e9565b9150612dcf602084016129e9565b90509250929050565b600181811c90821680612dec57607f821691505b602082108103612e0c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f821115610c5b576000816000526020600020601f850160051c81016020861015612e515750805b601f850160051c820191505b81811015612e7057828155600101612e5d565b505050505050565b815167ffffffffffffffff811115612e9257612e92612baf565b612ea681612ea08454612dd8565b84612e28565b602080601f831160018114612edb5760008415612ec35750858301515b600019600386901b1c1916600185901b178555612e70565b600085815260208120601f198616915b82811015612f0a57888601518255948401946001909101908401612eeb565b5085821015612f285787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825260139082015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610af857610af8612f65565b80820180821115610af857610af8612f65565b60208082526018908201527f457863656564696e67204d6178204d696e7420436f756e740000000000000000604082015260600190565b6000808354612fea81612dd8565b60018281168015613002576001811461301757613046565b60ff1984168752821515830287019450613046565b8760005260208060002060005b8581101561303d5781548a820152908401908201613024565b50505082870194505b50929695505050505050565b6000825161306481846020870161296d565b9190910192915050565b81810381811115610af857610af8612f65565b60006020828403121561309357600080fd5b815161223581612b40565b6000602082840312156130b057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826130dc576130dc6130b7565b500690565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061311490830184612991565b9695505050505050565b60006020828403121561313057600080fd5b81516122358161293a565b6000835161314d81846020880161296d565b83519083019061316181836020880161296d565b01949350505050565b634e487b7160e01b600052603160045260246000fd5b60006001820161319257613192612f65565b506001019056fea264697066735822122037faf7921b529fd918f850c3fc31cd135213810b9aae7a7d55f7600c2633b59264736f6c6343000816003300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000043697066733a2f2f62616679626569643665356d6762686570747175756770337865616d79697866696e72616163336f77357873757873717a7137627366746c7077342f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043697066733a2f2f62616679626569643665356d6762686570747175756770337865616d79697866696e72616163336f77357873757873717a7137627366746c7077342f0000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106103975760003560e01c8063715018a6116101dc578063b88d4fde11610102578063e985e9c5116100a0578063f2fde38b1161006f578063f2fde38b14610a6d578063f46a04eb14610a8d578063fa0cf53814610aad578063fee9d13b14610acd57600080fd5b8063e985e9c5146109f8578063ea05a8c614610a18578063ed84fc9114610a38578063edac985b14610a4d57600080fd5b8063d1239730116100dc578063d123973014610994578063d48997df146109ae578063d5abeb01146109ce578063e14ca353146109e357600080fd5b8063b88d4fde14610934578063c2ba474414610954578063c87b56dd1461097457600080fd5b80639b19251a1161017a578063a0e389de11610149578063a0e389de146108c8578063a22cb465146108de578063b0d356e5146108fe578063b12dab6e1461091e57600080fd5b80639b19251a146108505780639b667f80146108805780639f181b5e146108a0578063a0712d68146108b557600080fd5b8063931688cb116101b6578063931688cb146107db57806395d89b41146107fb57806399f7e45f146108105780639a8c00351461083057600080fd5b8063715018a61461077b578063839ad1d3146107905780638da5cb5b146107bd57600080fd5b80633096b9e8116102c15780634b4687b51161025f5780636352211e1161022e5780636352211e146107105780636a7957321461073057806370a0823114610746578063714c53981461076657600080fd5b80634b4687b51461069a5780634f6ccce7146106b957806354214f69146106d9578063572849c4146106fa57600080fd5b80633b71275d1161029b5780633b71275d1461062f5780633bd649681461064f578063413fa8e31461066457806342842e0e1461067a57600080fd5b80633096b9e8146105b657806333a5f120146105d65780633af32abf146105f657600080fd5b806315f91c18116103395780632324521611610308578063232452161461053657806323b872dd146105565780632acc659e146105765780632f745c591461059657600080fd5b806315f91c18146104ae57806318160ddd146104e15780631e0d6eea146104f65780631e14d44b1461051657600080fd5b806306fdde031161037557806306fdde0314610405578063081812fc14610427578063095ea7b31461045f57806310d8bc091461048157600080fd5b806301f569971461039c57806301ffc9a7146103bf57806302ddfd21146103ef575b600080fd5b3480156103a857600080fd5b5060325b6040519081526020015b60405180910390f35b3480156103cb57600080fd5b506103df6103da366004612950565b610aed565b60405190151581526020016103b6565b3480156103fb57600080fd5b506103ac60115481565b34801561041157600080fd5b5061041a610afe565b6040516103b691906129bd565b34801561043357600080fd5b506104476104423660046129d0565b610b90565b6040516001600160a01b0390911681526020016103b6565b34801561046b57600080fd5b5061047f61047a366004612a05565b610bb9565b005b34801561048d57600080fd5b506103ac61049c366004612a2f565b600e6020526000908152604090205481565b3480156104ba57600080fd5b507f00000000000000000000000000000000000000000000000000000000000007d06103ac565b3480156104ed57600080fd5b506008546103ac565b34801561050257600080fd5b5061047f610511366004612a4a565b610bc8565b34801561052257600080fd5b5061047f6105313660046129d0565b610bde565b34801561054257600080fd5b5061047f610551366004612ac2565b610beb565b34801561056257600080fd5b5061047f610571366004612b04565b610c60565b34801561058257600080fd5b506103ac610591366004612a2f565b610cf0565b3480156105a257600080fd5b506103ac6105b1366004612a05565b610d4d565b3480156105c257600080fd5b5061047f6105d1366004612b4e565b610db2565b3480156105e257600080fd5b506103df6105f1366004612a2f565b610dd6565b34801561060257600080fd5b506103df610611366004612a2f565b6001600160a01b03166000908152600d602052604090205460ff1690565b34801561063b57600080fd5b506017546103df9062010000900460ff1681565b34801561065b57600080fd5b5061047f610e26565b34801561067057600080fd5b506103ac60135481565b34801561068657600080fd5b5061047f610695366004612b04565b610e43565b3480156106a657600080fd5b506017546103df90610100900460ff1681565b3480156106c557600080fd5b506103ac6106d43660046129d0565b610e5e565b3480156106e557600080fd5b506017546103df906301000000900460ff1681565b34801561070657600080fd5b506103ac60185481565b34801561071c57600080fd5b5061044761072b3660046129d0565b610eb7565b34801561073c57600080fd5b506103ac600f5481565b34801561075257600080fd5b506103ac610761366004612a2f565b610ec2565b34801561077257600080fd5b5061041a610f0a565b34801561078757600080fd5b5061047f610f19565b34801561079c57600080fd5b506107b06107ab366004612a2f565b610f2d565b6040516103b69190612b6b565b3480156107c957600080fd5b50600c546001600160a01b0316610447565b3480156107e757600080fd5b5061047f6107f6366004612c3b565b610fcb565b34801561080757600080fd5b5061041a610fdf565b34801561081c57600080fd5b5061047f61082b366004612a2f565b610fee565b34801561083c57600080fd5b5061047f61084b366004612c3b565b611018565b34801561085c57600080fd5b506103df61086b366004612a2f565b600d6020526000908152604090205460ff1681565b34801561088c57600080fd5b5061047f61089b366004612c84565b61102c565b3480156108ac57600080fd5b50600a546103ac565b61047f6108c33660046129d0565b611111565b3480156108d457600080fd5b506103ac60125481565b3480156108ea57600080fd5b5061047f6108f9366004612cd0565b6111f9565b34801561090a57600080fd5b50601454610447906001600160a01b031681565b34801561092a57600080fd5b506103ac60105481565b34801561094057600080fd5b5061047f61094f366004612d07565b611204565b34801561096057600080fd5b506103ac61096f366004612a2f565b61121b565b34801561098057600080fd5b5061041a61098f3660046129d0565b6112ca565b3480156109a057600080fd5b506017546103df9060ff1681565b3480156109ba57600080fd5b5061047f6109c9366004612d83565b611324565b3480156109da57600080fd5b506107d06103ac565b3480156109ef57600080fd5b506103ac611337565b348015610a0457600080fd5b506103df610a13366004612da5565b61136c565b348015610a2457600080fd5b5061047f610a33366004612b4e565b61139a565b348015610a4457600080fd5b5061047f6113bc565b348015610a5957600080fd5b5061047f610a68366004612ac2565b6114a2565b348015610a7957600080fd5b5061047f610a88366004612a2f565b611512565b348015610a9957600080fd5b5061047f610aa8366004612b4e565b61154d565b348015610ab957600080fd5b5061047f610ac83660046129d0565b611568565b348015610ad957600080fd5b5061047f610ae8366004612a2f565b61188f565b6000610af882611a28565b92915050565b606060008054610b0d90612dd8565b80601f0160208091040260200160405190810160405280929190818152602001828054610b3990612dd8565b8015610b865780601f10610b5b57610100808354040283529160200191610b86565b820191906000526020600020905b815481529060010190602001808311610b6957829003601f168201915b5050505050905090565b6000610b9b82611a4d565b506000828152600460205260409020546001600160a01b0316610af8565b610bc4828233611a86565b5050565b610bd0611a93565b600f92909255601055601355565b610be6611a93565b601855565b610bf3611a93565b60005b81811015610c5b576000600d6000858585818110610c1657610c16612e12565b9050602002016020810190610c2b9190612a2f565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101610bf6565b505050565b6001600160a01b038216610c8f57604051633250574960e11b8152600060048201526024015b60405180910390fd5b6000610c9c838333611ac0565b9050836001600160a01b0316816001600160a01b031614610cea576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610c86565b50505050565b600f546001600160a01b0382166000908152600d602052604081205490919060ff161515600103610d2057506010545b600c546001600160a01b03166001600160a01b0316836001600160a01b031603610af85750600092915050565b6000610d5883610ec2565b8210610d895760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610c86565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b610dba611a93565b60178054911515620100000262ff000019909216919091179055565b60175460009060ff1680610dec57506012544210155b80610af857506001600160a01b0382166000908152600d602052604090205460ff1615156001148015610af8575060115442101592915050565b610e2e611a93565b6017805463ff00000019166301000000179055565b610c5b83838360405180602001604052806000815250611204565b6000610e6960085490565b8210610e925760405163295f44f760e21b81526000600482015260248101839052604401610c86565b60088281548110610ea557610ea5612e12565b90600052602060002001549050919050565b6000610af882611a4d565b60006001600160a01b038216610eee576040516322718ad960e21b815260006004820152602401610c86565b506001600160a01b031660009081526003602052604090205490565b6060610f14611b95565b905090565b610f21611a93565b610f2b6000611ba4565b565b60606000610f3a83610ec2565b905060008167ffffffffffffffff811115610f5757610f57612baf565b604051908082528060200260200182016040528015610f80578160200160208202803683370190505b50905060005b82811015610fc3576000610f9a8683610d4d565b905080838381518110610faf57610faf612e12565b602090810291909101015250600101610f86565b509392505050565b610fd3611a93565b6015610bc48282612e78565b606060018054610b0d90612dd8565b610ff6611a93565b601480546001600160a01b0319166001600160a01b0392909216919091179055565b611020611a93565b6016610bc48282612e78565b611034611a93565b60328111156110555760405162461bcd60e51b8152600401610c8690612f38565b600081116110755760405162461bcd60e51b8152600401610c8690612f38565b6107d06110828383612f7b565b60085461108f9190612f92565b11156110ad5760405162461bcd60e51b8152600401610c8690612fa5565b60005b82811015610cea5760005b828110156111085760006110cd611bf6565b90506110ff8686858181106110e4576110e4612e12565b90506020020160208101906110f99190612a2f565b82611d73565b506001016110bb565b506001016110b0565b60175460ff168061112457506012544210155b806111505750336000908152600d602052604090205460ff161515600114801561115057506011544210155b61118c5760405162461bcd60e51b815260206004820152600d60248201526c135a5b9d08111a5cd8589b1959609a1b6044820152606401610c86565b601754610100900460ff16156111ed57336000908152600d602052604090205460ff166111ed5760405162461bcd60e51b815260206004820152600f60248201526e139bdd0815da1a5d195b1a5cdd1959608a1b6044820152606401610c86565b6111f681611d8d565b50565b610bc433838361200c565b61120f848484610c60565b610cea848484846120ab565b600061122f600c546001600160a01b031690565b6001600160a01b0316826001600160a01b03160361124f57506032919050565b60175460ff16151560000361126657506000919050565b60175460ff610100909104161515600114801561129c57506001600160a01b0382166000908152600d602052604090205460ff16155b156112a957506000919050565b6107d06112b560085490565b106112c257506000919050565b506032919050565b6017546060906301000000900460ff16151560011461130b5760166040516020016112f59190612fdc565b6040516020818303038152906040529050919050565b611314826121d4565b6040516020016112f59190613052565b61132c611a93565b601291909155601155565b6000611342600a5490565b610f14907f00000000000000000000000000000000000000000000000000000000000007d061306e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6113a2611a93565b601780549115156101000261ff0019909216919091179055565b6113c4611a93565b6000471161140a5760405162461bcd60e51b815260206004820152601360248201527227379022aa24103a37903bb4ba34323930bb9760691b6044820152606401610c86565b604051600090339047908381818185875af1925050503d806000811461144c576040519150601f19603f3d011682016040523d82523d6000602084013e611451565b606091505b50509050806111f65760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f207769746864726177204554482e0000000000000000006044820152606401610c86565b6114aa611a93565b60005b81811015610c5b576001600d60008585858181106114cd576114cd612e12565b90506020020160208101906114e29190612a2f565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016114ad565b61151a611a93565b6001600160a01b03811661154457604051631e4fbdf760e01b815260006004820152602401610c86565b6111f681611ba4565b611555611a93565b6017805460ff1916911515919091179055565b60175460ff168061157b57506012544210155b806115a75750336000908152600d602052604090205460ff16151560011480156115a757506011544210155b6115e35760405162461bcd60e51b815260206004820152600d60248201526c135a5b9d08111a5cd8589b1959609a1b6044820152606401610c86565b601754610100900460ff161561164457336000908152600d602052604090205460ff166116445760405162461bcd60e51b815260206004820152600f60248201526e139bdd0815da1a5d195b1a5cdd1959608a1b6044820152606401610c86565b60175462010000900460ff1615156001146116a15760405162461bcd60e51b815260206004820152601f60248201527f455243323020546f6b656e204d696e74696e672069732064697361626c6564006044820152606401610c86565b60328111156116c25760405162461bcd60e51b8152600401610c8690612f38565b600081116116e25760405162461bcd60e51b8152600401610c8690612f38565b6107d0816116ef60085490565b6116f99190612f92565b11156117175760405162461bcd60e51b8152600401610c8690612fa5565b60185415806117425750601854336000908152600e602052604090205461173f908390612f92565b11155b806117575750600c546001600160a01b031633145b6117a35760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e67204d6178204d696e7420506572204164647265737300006044820152606401610c86565b6000816013546117b39190612f7b565b6014546040516323b872dd60e01b8152336004820152306024820152604481018390529192506001600160a01b0316906323b872dd906064016020604051808303816000875af115801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f9190613081565b5060005b8281101561186657600061184660085490565b611851906001612f92565b905061185d3382611d73565b50600101611833565b50336000908152600e602052604081208054849290611886908490612f92565b90915550505050565b611897611a93565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156118de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611902919061309e565b116119475760405162461bcd60e51b81526020600482015260156024820152742737903a37b5b2b739903a37903932b1b7bb32b91760591b6044820152606401610c86565b6040516370a0823160e01b81523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015611995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b9919061309e565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190613081565b60006001600160e01b0319821663780e9d6360e01b1480610af85750610af88261223c565b6000818152600260205260408120546001600160a01b031680610af857604051637e27328960e01b815260048101849052602401610c86565b610c5b838383600161228c565b600c546001600160a01b03163314610f2b5760405163118cdaa760e01b8152336004820152602401610c86565b600080611ace858585612392565b90506001600160a01b038116611b2b57611b2684600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611b4e565b846001600160a01b0316816001600160a01b031614611b4e57611b4e818561248b565b6001600160a01b038516611b6a57611b658461251c565b611b8d565b846001600160a01b0316816001600160a01b031614611b8d57611b8d85856125cb565b949350505050565b606060158054610b0d90612dd8565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600080611c02600a5490565b611c2c907f00000000000000000000000000000000000000000000000000000000000007d061306e565b6040516bffffffffffffffffffffffff1933606090811b8216602084015241901b166034820152446048820152456068820152426088820152909150600090829060a8016040516020818303038152906040528051906020012060001c611c9391906130cd565b6000818152600b6020526040812054919250908103611cb3575080611cc4565b506000818152600b60205260409020545b600b6000611cd360018661306e565b815260200190815260200160002054600003611d0857611cf460018461306e565b6000838152600b6020526040902055611d38565b600b6000611d1760018661306e565b81526020808201929092526040908101600090812054858252600b90935220555b611d4061261b565b50611d6b7f000000000000000000000000000000000000000000000000000000000000000182612f92565b935050505090565b610bc482826040518060200160405280600081525061268c565b6032811115611dae5760405162461bcd60e51b8152600401610c8690612f38565b60008111611dce5760405162461bcd60e51b8152600401610c8690612f38565b6107d081611ddb60085490565b611de59190612f92565b1115611e035760405162461bcd60e51b8152600401610c8690612fa5565b6018541580611e2e5750601854336000908152600e6020526040902054611e2b908390612f92565b11155b80611e435750600c546001600160a01b031633145b611e8f5760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e67204d6178204d696e7420506572204164647265737300006044820152606401610c86565b600081611e9b33610cf0565b611ea59190612f7b565b9050600081341480611ec15750600c546001600160a01b031633145b611f045760405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d0814185e5b595b9d60621b6044820152606401610c86565b8015611fb8576040516000907316d934b9646d9da51db92627bf0070be0ab723899083908381818185875af1925050503d8060008114611f60576040519150601f19603f3d011682016040523d82523d6000602084013e611f65565b606091505b5050905080611fb65760405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2073656e64206f70657261746f722066656500000000006044820152606401610c86565b505b60005b83811015611fe2576000611fcd611bf6565b9050611fd93382611d73565b50600101611fbb565b50336000908152600e602052604081208054859290612002908490612f92565b9091555050505050565b6001600160a01b03821661203e57604051630b61174360e31b81526001600160a01b0383166004820152602401610c86565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610cea57604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906120ed9033908890879087906004016130e1565b6020604051808303816000875af1925050508015612128575060408051601f3d908101601f191682019092526121259181019061311e565b60015b612191573d808015612156576040519150601f19603f3d011682016040523d82523d6000602084013e61215b565b606091505b50805160000361218957604051633250574960e11b81526001600160a01b0385166004820152602401610c86565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146121cd57604051633250574960e11b81526001600160a01b0385166004820152602401610c86565b5050505050565b60606121df82611a4d565b5060006121ea611b95565b9050600081511161220a5760405180602001604052806000815250612235565b80612214846126a3565b60405160200161222592919061313b565b6040516020818303038152906040525b9392505050565b60006001600160e01b031982166380ac58cd60e01b148061226d57506001600160e01b03198216635b5e139f60e01b145b80610af857506301ffc9a760e01b6001600160e01b0319831614610af8565b80806122a057506001600160a01b03821615155b156123625760006122b084611a4d565b90506001600160a01b038316158015906122dc5750826001600160a01b0316816001600160a01b031614155b80156122ef57506122ed818461136c565b155b156123185760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610c86565b81156123605783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152600260205260408120546001600160a01b03908116908316156123bf576123bf818486612736565b6001600160a01b038116156123fd576123dc60008560008061228c565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b0385161561242c576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600061249683610ec2565b6000838152600760205260409020549091508082146124e9576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061252e9060019061306e565b6000838152600960205260408120546008805493945090928490811061255657612556612e12565b90600052602060002001549050806008838154811061257757612577612e12565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806125af576125af61316a565b6001900381819060005260206000200160009055905550505050565b600060016125d884610ec2565b6125e2919061306e565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b600080612626611337565b116126735760405162461bcd60e51b815260206004820152601860248201527f4e6f206d6f726520746f6b656e7320617661696c61626c6500000000000000006044820152606401610c86565b600a805490600061268383613180565b91905055905090565b612696838361279a565b610c5b60008484846120ab565b606060006126b0836127ff565b600101905060008167ffffffffffffffff8111156126d0576126d0612baf565b6040519080825280601f01601f1916602001820160405280156126fa576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461270457509392505050565b6127418383836128d7565b610c5b576001600160a01b03831661276f57604051637e27328960e01b815260048101829052602401610c86565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610c86565b6001600160a01b0382166127c457604051633250574960e11b815260006004820152602401610c86565b60006127d283836000611ac0565b90506001600160a01b03811615610c5b576040516339e3563760e11b815260006004820152602401610c86565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061283e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061286a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061288857662386f26fc10000830492506010015b6305f5e10083106128a0576305f5e100830492506008015b61271083106128b457612710830492506004015b606483106128c6576064830492506002015b600a8310610af85760010192915050565b60006001600160a01b03831615801590611b8d5750826001600160a01b0316846001600160a01b031614806129115750612911848461136c565b80611b8d5750506000908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b0319811681146111f657600080fd5b60006020828403121561296257600080fd5b81356122358161293a565b60005b83811015612988578181015183820152602001612970565b50506000910152565b600081518084526129a981602086016020860161296d565b601f01601f19169290920160200192915050565b6020815260006122356020830184612991565b6000602082840312156129e257600080fd5b5035919050565b80356001600160a01b0381168114612a0057600080fd5b919050565b60008060408385031215612a1857600080fd5b612a21836129e9565b946020939093013593505050565b600060208284031215612a4157600080fd5b612235826129e9565b600080600060608486031215612a5f57600080fd5b505081359360208301359350604090920135919050565b60008083601f840112612a8857600080fd5b50813567ffffffffffffffff811115612aa057600080fd5b6020830191508360208260051b8501011115612abb57600080fd5b9250929050565b60008060208385031215612ad557600080fd5b823567ffffffffffffffff811115612aec57600080fd5b612af885828601612a76565b90969095509350505050565b600080600060608486031215612b1957600080fd5b612b22846129e9565b9250612b30602085016129e9565b9150604084013590509250925092565b80151581146111f657600080fd5b600060208284031215612b6057600080fd5b813561223581612b40565b6020808252825182820181905260009190848201906040850190845b81811015612ba357835183529284019291840191600101612b87565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115612be057612be0612baf565b604051601f8501601f19908116603f01168101908282118183101715612c0857612c08612baf565b81604052809350858152868686011115612c2157600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612c4d57600080fd5b813567ffffffffffffffff811115612c6457600080fd5b8201601f81018413612c7557600080fd5b611b8d84823560208401612bc5565b600080600060408486031215612c9957600080fd5b833567ffffffffffffffff811115612cb057600080fd5b612cbc86828701612a76565b909790965060209590950135949350505050565b60008060408385031215612ce357600080fd5b612cec836129e9565b91506020830135612cfc81612b40565b809150509250929050565b60008060008060808587031215612d1d57600080fd5b612d26856129e9565b9350612d34602086016129e9565b925060408501359150606085013567ffffffffffffffff811115612d5757600080fd5b8501601f81018713612d6857600080fd5b612d7787823560208401612bc5565b91505092959194509250565b60008060408385031215612d9657600080fd5b50508035926020909101359150565b60008060408385031215612db857600080fd5b612dc1836129e9565b9150612dcf602084016129e9565b90509250929050565b600181811c90821680612dec57607f821691505b602082108103612e0c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f821115610c5b576000816000526020600020601f850160051c81016020861015612e515750805b601f850160051c820191505b81811015612e7057828155600101612e5d565b505050505050565b815167ffffffffffffffff811115612e9257612e92612baf565b612ea681612ea08454612dd8565b84612e28565b602080601f831160018114612edb5760008415612ec35750858301515b600019600386901b1c1916600185901b178555612e70565b600085815260208120601f198616915b82811015612f0a57888601518255948401946001909101908401612eeb565b5085821015612f285787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825260139082015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610af857610af8612f65565b80820180821115610af857610af8612f65565b60208082526018908201527f457863656564696e67204d6178204d696e7420436f756e740000000000000000604082015260600190565b6000808354612fea81612dd8565b60018281168015613002576001811461301757613046565b60ff1984168752821515830287019450613046565b8760005260208060002060005b8581101561303d5781548a820152908401908201613024565b50505082870194505b50929695505050505050565b6000825161306481846020870161296d565b9190910192915050565b81810381811115610af857610af8612f65565b60006020828403121561309357600080fd5b815161223581612b40565b6000602082840312156130b057600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826130dc576130dc6130b7565b500690565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061311490830184612991565b9695505050505050565b60006020828403121561313057600080fd5b81516122358161293a565b6000835161314d81846020880161296d565b83519083019061316181836020880161296d565b01949350505050565b634e487b7160e01b600052603160045260246000fd5b60006001820161319257613192612f65565b506001019056fea264697066735822122037faf7921b529fd918f850c3fc31cd135213810b9aae7a7d55f7600c2633b59264736f6c63430008160033

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

00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000043697066733a2f2f62616679626569643665356d6762686570747175756770337865616d79697866696e72616163336f77357873757873717a7137627366746c7077342f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043697066733a2f2f62616679626569643665356d6762686570747175756770337865616d79697866696e72616163336f77357873757873717a7137627366746c7077342f0000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _nftBaseURI (string): ipfs://bafybeid6e5mgbheptquugp3xeamyixfinraac3ow5xsuxsqzq7bsftlpw4/
Arg [1] : _nftRevealURI (string): ipfs://bafybeid6e5mgbheptquugp3xeamyixfinraac3ow5xsuxsqzq7bsftlpw4/
Arg [2] : _initialTeamReserve (uint256): 5
Arg [3] : _mintStartTimestamp (uint256): 0
Arg [4] : _whitelistMintStartTimestamp (uint256): 0
Arg [5] : _maxMintPerAddress (uint256): 2000

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [7] : 697066733a2f2f62616679626569643665356d67626865707471757567703378
Arg [8] : 65616d79697866696e72616163336f77357873757873717a7137627366746c70
Arg [9] : 77342f0000000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [11] : 697066733a2f2f62616679626569643665356d67626865707471757567703378
Arg [12] : 65616d79697866696e72616163336f77357873757873717a7137627366746c70
Arg [13] : 77342f0000000000000000000000000000000000000000000000000000000000


Deployed ByteCode Sourcemap

73419:11199:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82019:113;;;;;;;;;;-1:-1:-1;73579:2:0;82019:113;;;160:25:1;;;148:2;133:18;82019:113:0;;;;;;;;83704:179;;;;;;;;;;-1:-1:-1;83704:179:0;;;;;:::i;:::-;;:::i;:::-;;;747:14:1;;740:22;722:41;;710:2;695:18;83704:179:0;582:187:1;73773:42:0;;;;;;;;;;;;;;;;47029:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;48201:158::-;;;;;;;;;;-1:-1:-1;48201:158:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1879:32:1;;;1861:51;;1849:2;1834:18;48201:158:0;1715:203:1;48020:115:0;;;;;;;;;;-1:-1:-1;48020:115:0;;;;;:::i;:::-;;:::i;:::-;;73638:49;;;;;;;;;;-1:-1:-1;73638:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;725:105;;;;;;;;;;-1:-1:-1;803:19:0;725:105;;64785:104;;;;;;;;;;-1:-1:-1;64864:10:0;:17;64785:104;;77403:329;;;;;;;;;;-1:-1:-1;77403:329:0;;;;;:::i;:::-;;:::i;76492:150::-;;;;;;;;;;-1:-1:-1;76492:150:0;;;;;:::i;:::-;;:::i;81464:216::-;;;;;;;;;;-1:-1:-1;81464:216:0;;;;;:::i;:::-;;:::i;48870:588::-;;;;;;;;;;-1:-1:-1;48870:588:0;;;;;:::i;:::-;;:::i;81688:323::-;;;;;;;;;;-1:-1:-1;81688:323:0;;;;;:::i;:::-;;:::i;64449:260::-;;;;;;;;;;-1:-1:-1;64449:260:0;;;;;:::i;:::-;;:::i;77110:127::-;;;;;;;;;;-1:-1:-1;77110:127:0;;;;;:::i;:::-;;:::i;76105:293::-;;;;;;;;;;-1:-1:-1;76105:293:0;;;;;:::i;:::-;;:::i;83371:113::-;;;;;;;;;;-1:-1:-1;83371:113:0;;;;;:::i;:::-;-1:-1:-1;;;;;83457:19:0;83433:4;83457:19;;;:9;:19;;;;;;;;;83371:113;74312:28;;;;;;;;;;-1:-1:-1;74312:28:0;;;;;;;;;;;76406:78;;;;;;;;;;;;;:::i;73864:40::-;;;;;;;;;;;;;;;;49529:134;;;;;;;;;;-1:-1:-1;49529:134:0;;;;;:::i;:::-;;:::i;74280:25::-;;;;;;;;;;-1:-1:-1;74280:25:0;;;;;;;;;;;64966:231;;;;;;;;;;-1:-1:-1;64966:231:0;;;;;:::i;:::-;;:::i;74347:22::-;;;;;;;;;;-1:-1:-1;74347:22:0;;;;;;;;;;;74376:32;;;;;;;;;;;;;;;;46842:120;;;;;;;;;;-1:-1:-1;46842:120:0;;;;;:::i;:::-;;:::i;73696:29::-;;;;;;;;;;;;;;;;46567:213;;;;;;;;;;-1:-1:-1;46567:213:0;;;;;:::i;:::-;;:::i;83600:96::-;;;;;;;;;;;;;:::i;72473:103::-;;;;;;;;;;;;;:::i;84183:432::-;;;;;;;;;;-1:-1:-1;84183:432:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;71798:87::-;;;;;;;;;;-1:-1:-1;71871:6:0;;-1:-1:-1;;;;;71871:6:0;71798:87;;76650:101;;;;;;;;;;-1:-1:-1;76650:101:0;;;;;:::i;:::-;;:::i;47189:95::-;;;;;;;;;;;;;:::i;77245:150::-;;;;;;;;;;-1:-1:-1;77245:150:0;;;;;:::i;:::-;;:::i;76759:105::-;;;;;;;;;;-1:-1:-1;76759:105:0;;;;;:::i;:::-;;:::i;73590:41::-;;;;;;;;;;-1:-1:-1;73590:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;80631:605;;;;;;;;;;-1:-1:-1;80631:605:0;;;;;:::i;:::-;;:::i;1020:89::-;;;;;;;;;;-1:-1:-1;1090:11:0;;1020:89;;78019:132;;;;;;:::i;:::-;;:::i;73822:33::-;;;;;;;;;;;;;;;;48431:146;;;;;;;;;;-1:-1:-1;48431:146:0;;;;;:::i;:::-;;:::i;73911:32::-;;;;;;;;;;-1:-1:-1;73911:32:0;;;;-1:-1:-1;;;;;73911:32:0;;;73732;;;;;;;;;;;;;;;;49734:211;;;;;;;;;;-1:-1:-1;49734:211:0;;;;;:::i;:::-;;:::i;82140:471::-;;;;;;;;;;-1:-1:-1;82140:471:0;;;;;:::i;:::-;;:::i;83891:284::-;;;;;;;;;;-1:-1:-1;83891:284:0;;;;;:::i;:::-;;:::i;74243:30::-;;;;;;;;;;-1:-1:-1;74243:30:0;;;;;;;;77740:271;;;;;;;;;;-1:-1:-1;77740:271:0;;;;;:::i;:::-;;:::i;83276:87::-;;;;;;;;;;-1:-1:-1;73524:4:0;83276:87;;1215:122;;;;;;;;;;;;;:::i;48648:155::-;;;;;;;;;;-1:-1:-1;48648:155:0;;;;;:::i;:::-;;:::i;76987:115::-;;;;;;;;;;-1:-1:-1;76987:115:0;;;;;:::i;:::-;;:::i;82619:293::-;;;;;;;;;;;;;:::i;81244:212::-;;;;;;;;;;-1:-1:-1;81244:212:0;;;;;:::i;:::-;;:::i;72731:220::-;;;;;;;;;;-1:-1:-1;72731:220:0;;;;;:::i;:::-;;:::i;76872:107::-;;;;;;;;;;-1:-1:-1;76872:107:0;;;;;:::i;:::-;;:::i;78159:1068::-;;;;;;;;;;-1:-1:-1;78159:1068:0;;;;;:::i;:::-;;:::i;82920:348::-;;;;;;;;;;-1:-1:-1;82920:348:0;;;;;:::i;:::-;;:::i;83704:179::-;83815:4;83839:36;83863:11;83839:23;:36::i;:::-;83832:43;83704:179;-1:-1:-1;;83704:179:0:o;47029:91::-;47074:13;47107:5;47100:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47029:91;:::o;48201:158::-;48268:7;48288:22;48302:7;48288:13;:22::i;:::-;-1:-1:-1;50777:7:0;50804:24;;;:15;:24;;;;;;-1:-1:-1;;;;;50804:24:0;48330:21;50707:129;48020:115;48092:35;48101:2;48105:7;44711:10;48092:8;:35::i;:::-;48020:115;;:::o;77403:329::-;71684:13;:11;:13::i;:::-;77578:14:::1;:32:::0;;;;77621:17:::1;:38:::0;77670:25:::1;:54:::0;77403:329::o;76492:150::-;71684:13;:11;:13::i;:::-;76596:17:::1;:38:::0;76492:150::o;81464:216::-;71684:13;:11;:13::i;:::-;81555::::1;81550:123;81574:25:::0;;::::1;81550:123;;;81656:5;81625:9;:28;81635:10;;81646:5;81635:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;81625:28:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;81625:28:0;:36;;-1:-1:-1;;81625:36:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;81601:7:0::1;81550:123;;;;81464:216:::0;;:::o;48870:588::-;-1:-1:-1;;;;;48965:16:0;;48961:89;;49005:33;;-1:-1:-1;;;49005:33:0;;49035:1;49005:33;;;1861:51:1;1834:18;;49005:33:0;;;;;;;;48961:89;49271:21;49295:34;49303:2;49307:7;44711:10;49295:7;:34::i;:::-;49271:58;;49361:4;-1:-1:-1;;;;;49344:21:0;:13;-1:-1:-1;;;;;49344:21:0;;49340:111;;49389:50;;-1:-1:-1;;;49389:50:0;;-1:-1:-1;;;;;9045:15:1;;;49389:50:0;;;9027:34:1;9077:18;;;9070:34;;;9140:15;;9120:18;;;9113:43;8962:18;;49389:50:0;8787:375:1;49340:111:0;48950:508;48870:588;;;:::o;81688:323::-;81784:14;;-1:-1:-1;;;;;81815:18:0;;81744:7;81815:18;;;:9;:18;;;;;;81744:7;;81784:14;81815:18;;:26;;:18;:26;81811:88;;-1:-1:-1;81870:17:0;;81811:88;71871:6;;-1:-1:-1;;;;;71871:6:0;-1:-1:-1;;;;;81915:18:0;:7;-1:-1:-1;;;;;81915:18:0;;81911:64;;-1:-1:-1;81962:1:0;81994:9;81688:323;-1:-1:-1;;81688:323:0:o;64449:260::-;64537:7;64570:16;64580:5;64570:9;:16::i;:::-;64561:5;:25;64557:101;;64610:36;;-1:-1:-1;;;64610:36:0;;-1:-1:-1;;;;;9359:32:1;;64610:36:0;;;9341:51:1;9408:18;;;9401:34;;;9314:18;;64610:36:0;9167:274:1;64557:101:0;-1:-1:-1;;;;;;64675:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;64449:260::o;77110:127::-;71684:13;:11;:13::i;:::-;77193:16:::1;:36:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;77193:36:0;;::::1;::::0;;;::::1;::::0;;77110:127::o;76105:293::-;76210:11;;76173:4;;76210:11;;;:67;;;76258:18;;76239:15;:37;;76210:67;:180;;;-1:-1:-1;;;;;;76295:19:0;;;;;;:9;:19;;;;;;;;:27;;:19;:27;:94;;;;;76362:27;;76343:15;:46;;76190:200;76105:293;-1:-1:-1;;76105:293:0:o;76406:78::-;71684:13;:11;:13::i;:::-;76459:10:::1;:17:::0;;-1:-1:-1;;76459:17:0::1;::::0;::::1;::::0;;76406:78::o;49529:134::-;49616:39;49633:4;49639:2;49643:7;49616:39;;;;;;;;;;;;:16;:39::i;64966:231::-;65032:7;65065:13;64864:10;:17;;64785:104;65065:13;65056:5;:22;65052:103;;65102:41;;-1:-1:-1;;;65102:41:0;;65133:1;65102:41;;;9341:51:1;9408:18;;;9401:34;;;9314:18;;65102:41:0;9167:274:1;65052:103:0;65172:10;65183:5;65172:17;;;;;;;;:::i;:::-;;;;;;;;;65165:24;;64966:231;;;:::o;46842:120::-;46905:7;46932:22;46946:7;46932:13;:22::i;46567:213::-;46630:7;-1:-1:-1;;;;;46654:19:0;;46650:89;;46697:30;;-1:-1:-1;;;46697:30:0;;46724:1;46697:30;;;1861:51:1;1834:18;;46697:30:0;1715:203:1;46650:89:0;-1:-1:-1;;;;;;46756:16:0;;;;;:9;:16;;;;;;;46567:213::o;83600:96::-;83645:13;83678:10;:8;:10::i;:::-;83671:17;;83600:96;:::o;72473:103::-;71684:13;:11;:13::i;:::-;72538:30:::1;72565:1;72538:18;:30::i;:::-;72473:103::o:0;84183:432::-;84267:16;84296:15;84314:24;84324:13;84314:9;:24::i;:::-;84296:42;;84351:27;84395:7;84381:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84381:22:0;;84351:52;;84419:9;84414:164;84438:7;84434:1;:11;84414:164;;;84467:18;84488:37;84508:13;84523:1;84488:19;:37::i;:::-;84467:58;;84556:10;84540;84551:1;84540:13;;;;;;;;:::i;:::-;;;;;;;;;;:26;-1:-1:-1;84447:3:0;;84414:164;;;-1:-1:-1;84597:10:0;84183:432;-1:-1:-1;;;84183:432:0:o;76650:101::-;71684:13;:11;:13::i;:::-;76726:7:::1;:17;76736:7:::0;76726;:17:::1;:::i;47189:95::-:0;47236:13;47269:7;47262:14;;;;;:::i;77245:150::-;71684:13;:11;:13::i;:::-;77349:17:::1;:38:::0;;-1:-1:-1;;;;;;77349:38:0::1;-1:-1:-1::0;;;;;77349:38:0;;;::::1;::::0;;;::::1;::::0;;77245:150::o;76759:105::-;71684:13;:11;:13::i;:::-;76837:9:::1;:19;76849:7:::0;76837:9;:19:::1;:::i;80631:605::-:0;71684:13;:11;:13::i;:::-;73579:2:::1;80739:7;:35;;80731:67;;;;-1:-1:-1::0;;;80731:67:0::1;;;;;;;:::i;:::-;80827:1;80817:7;:11;80809:43;;;;-1:-1:-1::0;;;80809:43:0::1;;;;;;;:::i;:::-;73524:4;80902:27;80912:10:::0;80902:7;:27:::1;:::i;:::-;64864:10:::0;:17;80885:45:::1;;;;:::i;:::-;:57;;80863:131;;;;-1:-1:-1::0;;;80863:131:0::1;;;;;;;:::i;:::-;81011:9;81007:222;81026:21:::0;;::::1;81007:222;;;81073:9;81069:149;81092:7;81088:1;:11;81069:149;;;81125:13;81141:11;:9;:11::i;:::-;81125:27;;81171:31;81181:10;;81192:1;81181:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;81196:5;81171:9;:31::i;:::-;-1:-1:-1::0;81101:3:0::1;;81069:149;;;-1:-1:-1::0;81049:3:0::1;;81007:222;;78019:132:::0;74477:11;;;;;:71;;;74529:18;;74510:15;:37;;74477:71;:194;;;-1:-1:-1;74580:10:0;74570:21;;;;:9;:21;;;;;;;;:29;;:21;:29;:100;;;;;74643:27;;74624:15;:46;;74570:100;74455:257;;;;-1:-1:-1;;;74455:257:0;;12979:2:1;74455:257:0;;;12961:21:1;13018:2;12998:18;;;12991:30;-1:-1:-1;;;13037:18:1;;;13030:43;13090:18;;74455:257:0;12777:337:1;74455:257:0;74782:13:::1;::::0;::::1;::::0;::::1;;;74778:99;;;74834:10;83433:4:::0;83457:19;;;:9;:19;;;;;;;;74812:53:::1;;;::::0;-1:-1:-1;;;74812:53:0;;13321:2:1;74812:53:0::1;::::0;::::1;13303:21:1::0;13360:2;13340:18;;;13333:30;-1:-1:-1;;;13379:18:1;;;13372:45;13434:18;;74812:53:0::1;13119:339:1::0;74812:53:0::1;78126:17:::2;78135:7;78126:8;:17::i;:::-;78019:132:::0;:::o;48431:146::-;48517:52;44711:10;48550:8;48560;48517:18;:52::i;49734:211::-;49848:31;49861:4;49867:2;49871:7;49848:12;:31::i;:::-;49890:47;49913:4;49919:2;49923:7;49932:4;49890:22;:47::i;82140:471::-;82197:7;82233;71871:6;;-1:-1:-1;;;;;71871:6:0;;71798:87;82233:7;-1:-1:-1;;;;;82222:18:0;:7;-1:-1:-1;;;;;82222:18:0;;82219:81;;-1:-1:-1;73579:2:0;;82140:471;-1:-1:-1;82140:471:0:o;82219:81::-;82316:11;;;;:20;;:11;:20;82312:61;;-1:-1:-1;82360:1:0;;82140:471;-1:-1:-1;82140:471:0:o;82312:61::-;82389:13;;;;;;;;:21;;:13;:21;:56;;;;-1:-1:-1;;;;;;83457:19:0;;83433:4;83457:19;;;:9;:19;;;;;;;;82414:31;82389:56;82385:97;;;-1:-1:-1;82469:1:0;;82140:471;-1:-1:-1;82140:471:0:o;82385:97::-;73524:4;82498:13;64864:10;:17;;64785:104;82498:13;:25;82494:66;;-1:-1:-1;82547:1:0;;82140:471;-1:-1:-1;82140:471:0:o;82494:66::-;-1:-1:-1;73579:2:0;;82140:471;-1:-1:-1;82140:471:0:o;83891:284::-;84010:10;;83980:13;;84010:10;;;;;:18;;84024:4;84010:18;84006:93;;84076:9;84059:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;84045:42;;83891:284;;;:::o;84006:93::-;84142:23;84157:7;84142:14;:23::i;:::-;84125:41;;;;;;;;:::i;77740:271::-;71684:13;:11;:13::i;:::-;77894:18:::1;:40:::0;;;;77945:27:::1;:58:::0;77740:271::o;1215:122::-;1267:7;1317:12;1090:11;;;1020:89;1317:12;1294:35;;803:19;1294:35;:::i;48648:155::-;-1:-1:-1;;;;;48760:25:0;;;48736:4;48760:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;48648:155::o;76987:115::-;71684:13;:11;:13::i;:::-;77064::::1;:30:::0;;;::::1;;;;-1:-1:-1::0;;77064:30:0;;::::1;::::0;;;::::1;::::0;;76987:115::o;82619:293::-;71684:13;:11;:13::i;:::-;82709:1:::1;82685:21;:25;82677:57;;;::::0;-1:-1:-1;;;82677:57:0;;14940:2:1;82677:57:0::1;::::0;::::1;14922:21:1::0;14979:2;14959:18;;;14952:30;-1:-1:-1;;;14998:18:1;;;14991:49;15057:18;;82677:57:0::1;14738:343:1::0;82677:57:0::1;82766:82;::::0;82748:12:::1;::::0;82774:10:::1;::::0;82812:21:::1;::::0;82748:12;82766:82;82748:12;82766:82;82812:21;82774:10;82766:82:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82747:101;;;82869:7;82861:43;;;::::0;-1:-1:-1;;;82861:43:0;;15498:2:1;82861:43:0::1;::::0;::::1;15480:21:1::0;15537:2;15517:18;;;15510:30;15576:25;15556:18;;;15549:53;15619:18;;82861:43:0::1;15296:347:1::0;81244:212:0;71684:13;:11;:13::i;:::-;81332::::1;81327:122;81351:25:::0;;::::1;81327:122;;;81433:4;81402:9;:28;81412:10;;81423:5;81412:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;81402:28:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;81402:28:0;:35;;-1:-1:-1;;81402:35:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;81378:7:0::1;81327:122;;72731:220:::0;71684:13;:11;:13::i;:::-;-1:-1:-1;;;;;72816:22:0;::::1;72812:93;;72862:31;::::0;-1:-1:-1;;;72862:31:0;;72890:1:::1;72862:31;::::0;::::1;1861:51:1::0;1834:18;;72862:31:0::1;1715:203:1::0;72812:93:0::1;72915:28;72934:8;72915:18;:28::i;76872:107::-:0;71684:13;:11;:13::i;:::-;76945:11:::1;:26:::0;;-1:-1:-1;;76945:26:0::1;::::0;::::1;;::::0;;;::::1;::::0;;76872:107::o;78159:1068::-;74477:11;;;;;:71;;;74529:18;;74510:15;:37;;74477:71;:194;;;-1:-1:-1;74580:10:0;74570:21;;;;:9;:21;;;;;;;;:29;;:21;:29;:100;;;;;74643:27;;74624:15;:46;;74570:100;74455:257;;;;-1:-1:-1;;;74455:257:0;;12979:2:1;74455:257:0;;;12961:21:1;13018:2;12998:18;;;12991:30;-1:-1:-1;;;13037:18:1;;;13030:43;13090:18;;74455:257:0;12777:337:1;74455:257:0;74782:13:::1;::::0;::::1;::::0;::::1;;;74778:99;;;74834:10;83433:4:::0;83457:19;;;:9;:19;;;;;;;;74812:53:::1;;;::::0;-1:-1:-1;;;74812:53:0;;13321:2:1;74812:53:0::1;::::0;::::1;13303:21:1::0;13360:2;13340:18;;;13333:30;-1:-1:-1;;;13379:18:1;;;13372:45;13434:18;;74812:53:0::1;13119:339:1::0;74812:53:0::1;74954:16:::2;::::0;;;::::2;;;:24;;74974:4;74954:24;74946:68;;;::::0;-1:-1:-1;;;74946:68:0;;15850:2:1;74946:68:0::2;::::0;::::2;15832:21:1::0;15889:2;15869:18;;;15862:30;15928:33;15908:18;;;15901:61;15979:18;;74946:68:0::2;15648:355:1::0;74946:68:0::2;73579:2:::3;78300:7;:35;;78292:67;;;;-1:-1:-1::0;;;78292:67:0::3;;;;;;;:::i;:::-;78388:1;78378:7;:11;78370:43;;;;-1:-1:-1::0;;;78370:43:0::3;;;;;;;:::i;:::-;73524:4;78462:7;78446:13;64864:10:::0;:17;;64785:104;78446:13:::3;:23;;;;:::i;:::-;:35;;78424:109;;;;-1:-1:-1::0;;;78424:109:0::3;;;;;;;:::i;:::-;78566:17;::::0;:22;;:100:::3;;-1:-1:-1::0;78649:17:0::3;::::0;78624:10:::3;78609:26;::::0;;;:14:::3;:26;::::0;;;;;:36:::3;::::0;78638:7;;78609:36:::3;:::i;:::-;:57;;78566:100;:142;;;-1:-1:-1::0;71871:6:0;;-1:-1:-1;;;;;71871:6:0;78687:10:::3;:21;78566:142;78544:222;;;::::0;-1:-1:-1;;;78544:222:0;;16210:2:1;78544:222:0::3;::::0;::::3;16192:21:1::0;16249:2;16229:18;;;16222:30;16288:32;16268:18;;;16261:60;16338:18;;78544:222:0::3;16008:354:1::0;78544:222:0::3;78779:22;78832:7;78804:25;;:35;;;;:::i;:::-;78892:17;::::0;78885:131:::3;::::0;-1:-1:-1;;;78885:131:0;;78938:10:::3;78885:131;::::0;::::3;16607:34:1::0;78971:4:0::3;16657:18:1::0;;;16650:43;16709:18;;;16702:34;;;78779:60:0;;-1:-1:-1;;;;;;78892:17:0::3;::::0;78885:38:::3;::::0;16542:18:1;;78885:131:0::3;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;79034:9;79029:141;79053:7;79049:1;:11;79029:141;;;79082:13;79098;64864:10:::0;:17;;64785:104;79098:13:::3;:17;::::0;79114:1:::3;79098:17;:::i;:::-;79082:33;;79130:28;79140:10;79152:5;79130:9;:28::i;:::-;-1:-1:-1::0;79062:3:0::3;;79029:141;;;-1:-1:-1::0;79197:10:0::3;79182:26;::::0;;;:14:::3;:26;::::0;;;;:37;;79212:7;;79182:26;:37:::3;::::0;79212:7;;79182:37:::3;:::i;:::-;::::0;;;-1:-1:-1;;;;78159:1068:0:o;82920:348::-;71684:13;:11;:13::i;:::-;83023:46:::1;::::0;-1:-1:-1;;;83023:46:0;;83063:4:::1;83023:46;::::0;::::1;1861:51:1::0;83072:1:0::1;::::0;-1:-1:-1;;;;;83023:31:0;::::1;::::0;::::1;::::0;1834:18:1;;83023:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;83001:121;;;::::0;-1:-1:-1;;;83001:121:0;;17388:2:1;83001:121:0::1;::::0;::::1;17370:21:1::0;17427:2;17407:18;;;17400:30;-1:-1:-1;;;17446:18:1;;;17439:51;17507:18;;83001:121:0::1;17186:345:1::0;83001:121:0::1;83203:46;::::0;-1:-1:-1;;;83203:46:0;;83243:4:::1;83203:46;::::0;::::1;1861:51:1::0;-1:-1:-1;;;;;83133:30:0;::::1;::::0;::::1;::::0;83178:10:::1;::::0;83133:30;;83203:31:::1;::::0;1834:18:1;;83203:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83133:127;::::0;-1:-1:-1;;;;;;83133:127:0::1;::::0;;;;;;-1:-1:-1;;;;;9359:32:1;;;83133:127:0::1;::::0;::::1;9341:51:1::0;9408:18;;;9401:34;9314:18;;83133:127:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;64141:224::-:0;64243:4;-1:-1:-1;;;;;;64267:50:0;;-1:-1:-1;;;64267:50:0;;:90;;;64321:36;64345:11;64321:23;:36::i;61176:247::-;61239:7;50562:16;;;:7;:16;;;;;;-1:-1:-1;;;;;50562:16:0;;61303:90;;61350:31;;-1:-1:-1;;;61350:31:0;;;;;160:25:1;;;133:18;;61350:31:0;14:177:1;59408:122:0;59489:33;59498:2;59502:7;59511:4;59517;59489:8;:33::i;71963:166::-;71871:6;;-1:-1:-1;;;;;71871:6:0;44711:10;72023:23;72019:103;;72070:40;;-1:-1:-1;;;72070:40:0;;44711:10;72070:40;;;1861:51:1;1834:18;;72070:40:0;1715:203:1;65258:640:0;65353:7;65373:21;65397:32;65411:2;65415:7;65424:4;65397:13;:32::i;:::-;65373:56;-1:-1:-1;;;;;;65446:27:0;;65442:214;;65490:40;65522:7;66722:10;:17;;66695:24;;;;:15;:24;;;;;:44;;;66750:24;;;;;;;;;;;;66618:164;65490:40;65442:214;;;65569:2;-1:-1:-1;;;;;65552:19:0;:13;-1:-1:-1;;;;;65552:19:0;;65548:108;;65588:56;65621:13;65636:7;65588:32;:56::i;:::-;-1:-1:-1;;;;;65670:16:0;;65666:192;;65703:45;65740:7;65703:36;:45::i;:::-;65666:192;;;65787:2;-1:-1:-1;;;;;65770:19:0;:13;-1:-1:-1;;;;;65770:19:0;;65766:92;;65806:40;65834:2;65838:7;65806:27;:40::i;:::-;65877:13;65258:640;-1:-1:-1;;;;65258:640:0:o;83492:100::-;83544:13;83577:7;83570:14;;;;;:::i;73111:191::-;73204:6;;;-1:-1:-1;;;;;73221:17:0;;;-1:-1:-1;;;;;;73221:17:0;;;;;;;73254:40;;73204:6;;;73221:17;73204:6;;73254:40;;73185:16;;73254:40;73174:128;73111:191;:::o;3085:1325::-;3133:7;3153:16;3195:12;1090:11;;;1020:89;3195:12;3172:35;;803:19;3172:35;:::i;:::-;3285:219;;-1:-1:-1;;3324:10:0;17863:2:1;17859:15;;;17855:24;;3285:219:0;;;17843:37:1;3357:14:0;17914:15:1;;17910:24;17896:12;;;17889:46;3394:16:0;17951:12:1;;;17944:28;3433:14:0;17988:12:1;;;17981:28;3470:15:0;18025:13:1;;;18018:29;3153:54:0;;-1:-1:-1;3218:14:0;;3153:54;;18063:13:1;;3285:219:0;;;;;;;;;;;;3257:262;;;;;;3235:295;;:306;;;;:::i;:::-;3554:13;3586:19;;;:11;:19;;;;;;3218:323;;-1:-1:-1;3554:13:0;3586:24;;3582:304;;-1:-1:-1;3731:6:0;3582:304;;;-1:-1:-1;3855:19:0;;;;:11;:19;;;;;;3582:304;3963:11;:25;3975:12;3986:1;3975:8;:12;:::i;:::-;3963:25;;;;;;;;;;;;3992:1;3963:30;3959:331;;4097:12;4108:1;4097:8;:12;:::i;:::-;4075:19;;;;:11;:19;;;;;:34;3959:331;;;4253:11;:25;4265:12;4276:1;4265:8;:12;:::i;:::-;4253:25;;;;;;;;;;;;;;-1:-1:-1;4253:25:0;;;;4231:19;;;:11;:19;;;;:47;3959:331;4348:17;:15;:17::i;:::-;-1:-1:-1;4385:17:0;4393:9;4385:5;:17;:::i;:::-;4378:24;;;;;3085:1325;:::o;55527:102::-;55595:26;55605:2;55609:7;55595:26;;;;;;;;;;;;:9;:26::i;79235:1388::-;73579:2;79298:7;:35;;79290:67;;;;-1:-1:-1;;;79290:67:0;;;;;;;:::i;:::-;79386:1;79376:7;:11;79368:43;;;;-1:-1:-1;;;79368:43:0;;;;;;;:::i;:::-;73524:4;79460:7;79444:13;64864:10;:17;;64785:104;79444:13;:23;;;;:::i;:::-;:35;;79422:109;;;;-1:-1:-1;;;79422:109:0;;;;;;;:::i;:::-;79564:17;;:22;;:100;;-1:-1:-1;79647:17:0;;79622:10;79607:26;;;;:14;:26;;;;;;:36;;79636:7;;79607:36;:::i;:::-;:57;;79564:100;:142;;;-1:-1:-1;71871:6:0;;-1:-1:-1;;;;;71871:6:0;79685:10;:21;79564:142;79542:222;;;;-1:-1:-1;;;79542:222:0;;16210:2:1;79542:222:0;;;16192:21:1;16249:2;16229:18;;;16222:30;16288:32;16268:18;;;16261:60;16338:18;;79542:222:0;16008:354:1;79542:222:0;79777:22;79825:7;79802:20;79811:10;79802:8;:20::i;:::-;:30;;;;:::i;:::-;79777:55;-1:-1:-1;79843:19:0;80099:14;80086:9;:27;:52;;;-1:-1:-1;71871:6:0;;-1:-1:-1;;;;;71871:6:0;80117:10;:21;80086:52;80064:122;;;;-1:-1:-1;;;80064:122:0;;18663:2:1;80064:122:0;;;18645:21:1;18702:2;18682:18;;;18675:30;-1:-1:-1;;;18721:18:1;;;18714:50;18781:18;;80064:122:0;18461:344:1;80064:122:0;80255:15;;80251:168;;80303:45;;80288:9;;74037:42;;80332:11;;80288:9;80303:45;80288:9;80303:45;80332:11;74037:42;80303:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80287:61;;;80371:4;80363:44;;;;-1:-1:-1;;;80363:44:0;;19012:2:1;80363:44:0;;;18994:21:1;19051:2;19031:18;;;19024:30;19090:29;19070:18;;;19063:57;19137:18;;80363:44:0;18810:351:1;80363:44:0;80272:147;80251:168;80436:9;80431:135;80455:7;80451:1;:11;80431:135;;;80484:13;80500:11;:9;:11::i;:::-;80484:27;;80526:28;80536:10;80548:5;80526:9;:28::i;:::-;-1:-1:-1;80464:3:0;;80431:135;;;-1:-1:-1;80593:10:0;80578:26;;;;:14;:26;;;;;:37;;80608:7;;80578:26;:37;;80608:7;;80578:37;:::i;:::-;;;;-1:-1:-1;;;;;79235:1388:0:o;60615:318::-;-1:-1:-1;;;;;60723:22:0;;60719:93;;60769:31;;-1:-1:-1;;;60769:31:0;;-1:-1:-1;;;;;1879:32:1;;60769:31:0;;;1861:51:1;1834:18;;60769:31:0;1715:203:1;60719:93:0;-1:-1:-1;;;;;60822:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;60822:46:0;;;;;;;;;;60884:41;;722::1;;;60884::0;;695:18:1;60884:41:0;;;;;;;60615:318;;;:::o;61973:799::-;-1:-1:-1;;;;;62090:14:0;;;:18;62086:679;;62129:71;;-1:-1:-1;;;62129:71:0;;-1:-1:-1;;;;;62129:36:0;;;;;:71;;44711:10;;62180:4;;62186:7;;62195:4;;62129:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62129:71:0;;;;;;;;-1:-1:-1;;62129:71:0;;;;;;;;;;;;:::i;:::-;;;62125:629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62443:6;:13;62460:1;62443:18;62439:300;;62493:25;;-1:-1:-1;;;62493:25:0;;-1:-1:-1;;;;;1879:32:1;;62493:25:0;;;1861:51:1;1834:18;;62493:25:0;1715:203:1;62439:300:0;62689:6;62683:13;62674:6;62670:2;62666:15;62659:38;62125:629;-1:-1:-1;;;;;;62248:51:0;;-1:-1:-1;;;62248:51:0;62244:132;;62331:25;;-1:-1:-1;;;62331:25:0;;-1:-1:-1;;;;;1879:32:1;;62331:25:0;;;1861:51:1;1834:18;;62331:25:0;1715:203:1;62244:132:0;62201:190;61973:799;;;;:::o;47355:260::-;47419:13;47445:22;47459:7;47445:13;:22::i;:::-;;47480:21;47504:10;:8;:10::i;:::-;47480:34;;47556:1;47538:7;47532:21;:25;:75;;;;;;;;;;;;;;;;;47574:7;47583:18;:7;:16;:18::i;:::-;47560:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;47532:75;47525:82;47355:260;-1:-1:-1;;;47355:260:0:o;46198:305::-;46300:4;-1:-1:-1;;;;;;46337:40:0;;-1:-1:-1;;;46337:40:0;;:105;;-1:-1:-1;;;;;;;46394:48:0;;-1:-1:-1;;;46394:48:0;46337:105;:158;;;-1:-1:-1;;;;;;;;;;34054:40:0;;;46459:36;33954:148;59718:678;59880:9;:31;;;-1:-1:-1;;;;;;59893:18:0;;;;59880:31;59876:471;;;59928:13;59944:22;59958:7;59944:13;:22::i;:::-;59928:38;-1:-1:-1;;;;;;60097:18:0;;;;;;:35;;;60128:4;-1:-1:-1;;;;;60119:13:0;:5;-1:-1:-1;;;;;60119:13:0;;;60097:35;:69;;;;;60137:29;60154:5;60161:4;60137:16;:29::i;:::-;60136:30;60097:69;60093:144;;;60194:27;;-1:-1:-1;;;60194:27:0;;-1:-1:-1;;;;;1879:32:1;;60194:27:0;;;1861:51:1;1834:18;;60194:27:0;1715:203:1;60093:144:0;60257:9;60253:83;;;60312:7;60308:2;-1:-1:-1;;;;;60292:28:0;60301:5;-1:-1:-1;;;;;60292:28:0;;;;;;;;;;;60253:83;59913:434;59876:471;-1:-1:-1;;60359:24:0;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;60359:29:0;-1:-1:-1;;;;;60359:29:0;;;;;;;;;;59718:678::o;53669:824::-;53755:7;50562:16;;;:7;:16;;;;;;-1:-1:-1;;;;;50562:16:0;;;;53870:18;;;53866:88;;53905:37;53922:4;53928;53934:7;53905:16;:37::i;:::-;-1:-1:-1;;;;;54001:18:0;;;53997:263;;54119:48;54136:1;54140:7;54157:1;54161:5;54119:8;:48::i;:::-;-1:-1:-1;;;;;54213:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;54213:20:0;;;53997:263;-1:-1:-1;;;;;54276:16:0;;;54272:111;;-1:-1:-1;;;;;54338:13:0;;;;;;:9;:13;;;;;:18;;54355:1;54338:18;;;54272:111;54395:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;54395:21:0;-1:-1:-1;;;;;54395:21:0;;;;;;;;;54434:27;;54395:16;;54434:27;;;;;;;54481:4;53669:824;-1:-1:-1;;;;53669:824:0:o;67409:977::-;67675:22;67700:15;67710:4;67700:9;:15::i;:::-;67726:18;67747:26;;;:17;:26;;;;;;67675:40;;-1:-1:-1;67880:28:0;;;67876:328;;-1:-1:-1;;;;;67947:18:0;;67925:19;67947:18;;;:12;:18;;;;;;;;:34;;;;;;;;;67998:30;;;;;;:44;;;68115:30;;:17;:30;;;;;:43;;;67876:328;-1:-1:-1;68300:26:0;;;;:17;:26;;;;;;;;68293:33;;;-1:-1:-1;;;;;68344:18:0;;;;;:12;:18;;;;;:34;;;;;;;68337:41;67409:977::o;68681:1079::-;68959:10;:17;68934:22;;68959:21;;68979:1;;68959:21;:::i;:::-;68991:18;69012:24;;;:15;:24;;;;;;69385:10;:26;;68934:46;;-1:-1:-1;69012:24:0;;68934:46;;69385:26;;;;;;:::i;:::-;;;;;;;;;69363:48;;69449:11;69424:10;69435;69424:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;69529:28;;;:15;:28;;;;;;;:41;;;69701:24;;;;;69694:31;69736:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;68752:1008;;;68681:1079;:::o;66199:218::-;66284:14;66317:1;66301:13;66311:2;66301:9;:13::i;:::-;:17;;;;:::i;:::-;-1:-1:-1;;;;;66329:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;66374:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;66199:218:0:o;1447:114::-;1513:7;1703:1;1679:21;:19;:21::i;:::-;:25;1671:62;;;;-1:-1:-1;;;1671:62:0;;20749:2:1;1671:62:0;;;20731:21:1;20788:2;20768:18;;;20761:30;20827:26;20807:18;;;20800:54;20871:18;;1671:62:0;20547:348:1;1671:62:0;1540:11:::1;:13:::0;;;:11:::1;:13;::::0;::::1;:::i;:::-;;;;;1533:20;;1447:114:::0;:::o;55856:185::-;55951:18;55957:2;55961:7;55951:5;:18::i;:::-;55980:53;56011:1;56015:2;56019:7;56028:4;55980:22;:53::i;28642:718::-;28698:13;28749:14;28766:17;28777:5;28766:10;:17::i;:::-;28786:1;28766:21;28749:38;;28802:20;28836:6;28825:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28825:18:0;-1:-1:-1;28802:41:0;-1:-1:-1;28967:28:0;;;28983:2;28967:28;29024:290;-1:-1:-1;;29056:5:0;-1:-1:-1;;;29193:2:0;29182:14;;29177:32;29056:5;29164:46;29256:2;29247:11;;;-1:-1:-1;29277:21:0;29024:290;29277:21;-1:-1:-1;29335:6:0;28642:718;-1:-1:-1;;;28642:718:0:o;51876:376::-;51989:38;52003:5;52010:7;52019;51989:13;:38::i;:::-;51984:261;;-1:-1:-1;;;;;52048:19:0;;52044:190;;52095:31;;-1:-1:-1;;;52095:31:0;;;;;160:25:1;;;133:18;;52095:31:0;14:177:1;52044:190:0;52174:44;;-1:-1:-1;;;52174:44:0;;-1:-1:-1;;;;;9359:32:1;;52174:44:0;;;9341:51:1;9408:18;;;9401:34;;;9314:18;;52174:44:0;9167:274:1;54829:335:0;-1:-1:-1;;;;;54897:16:0;;54893:89;;54937:33;;-1:-1:-1;;;54937:33:0;;54967:1;54937:33;;;1861:51:1;1834:18;;54937:33:0;1715:203:1;54893:89:0;54992:21;55016:32;55024:2;55028:7;55045:1;55016:7;:32::i;:::-;54992:56;-1:-1:-1;;;;;;55063:27:0;;;55059:98;;55114:31;;-1:-1:-1;;;55114:31:0;;55142:1;55114:31;;;1861:51:1;1834:18;;55114:31:0;1715:203:1;25046:948:0;25099:7;;-1:-1:-1;;;25177:17:0;;25173:106;;-1:-1:-1;;;25215:17:0;;;-1:-1:-1;25261:2:0;25251:12;25173:106;25306:8;25297:5;:17;25293:106;;25344:8;25335:17;;;-1:-1:-1;25381:2:0;25371:12;25293:106;25426:8;25417:5;:17;25413:106;;25464:8;25455:17;;;-1:-1:-1;25501:2:0;25491:12;25413:106;25546:7;25537:5;:16;25533:103;;25583:7;25574:16;;;-1:-1:-1;25619:1:0;25609:11;25533:103;25663:7;25654:5;:16;25650:103;;25700:7;25691:16;;;-1:-1:-1;25736:1:0;25726:11;25650:103;25780:7;25771:5;:16;25767:103;;25817:7;25808:16;;;-1:-1:-1;25853:1:0;25843:11;25767:103;25897:7;25888:5;:16;25884:68;;25935:1;25925:11;25980:6;25046:948;-1:-1:-1;;25046:948:0:o;51156:276::-;51259:4;-1:-1:-1;;;;;51296:21:0;;;;;;:128;;;51344:7;-1:-1:-1;;;;;51335:16:0;:5;-1:-1:-1;;;;;51335:16:0;;:52;;;;51355:32;51372:5;51379:7;51355:16;:32::i;:::-;51335:88;;;-1:-1:-1;;50777:7:0;50804:24;;;:15;:24;;;;;;-1:-1:-1;;;;;50804:24:0;;;51391:32;;;;51276:148;-1:-1:-1;51156:276:0:o;196:131:1:-;-1:-1:-1;;;;;;270:32:1;;260:43;;250:71;;317:1;314;307:12;332:245;390:6;443:2;431:9;422:7;418:23;414:32;411:52;;;459:1;456;449:12;411:52;498:9;485:23;517:30;541:5;517:30;:::i;774:250::-;859:1;869:113;883:6;880:1;877:13;869:113;;;959:11;;;953:18;940:11;;;933:39;905:2;898:10;869:113;;;-1:-1:-1;;1016:1:1;998:16;;991:27;774:250::o;1029:271::-;1071:3;1109:5;1103:12;1136:6;1131:3;1124:19;1152:76;1221:6;1214:4;1209:3;1205:14;1198:4;1191:5;1187:16;1152:76;:::i;:::-;1282:2;1261:15;-1:-1:-1;;1257:29:1;1248:39;;;;1289:4;1244:50;;1029:271;-1:-1:-1;;1029:271:1:o;1305:220::-;1454:2;1443:9;1436:21;1417:4;1474:45;1515:2;1504:9;1500:18;1492:6;1474:45;:::i;1530:180::-;1589:6;1642:2;1630:9;1621:7;1617:23;1613:32;1610:52;;;1658:1;1655;1648:12;1610:52;-1:-1:-1;1681:23:1;;1530:180;-1:-1:-1;1530:180:1:o;1923:173::-;1991:20;;-1:-1:-1;;;;;2040:31:1;;2030:42;;2020:70;;2086:1;2083;2076:12;2020:70;1923:173;;;:::o;2101:254::-;2169:6;2177;2230:2;2218:9;2209:7;2205:23;2201:32;2198:52;;;2246:1;2243;2236:12;2198:52;2269:29;2288:9;2269:29;:::i;:::-;2259:39;2345:2;2330:18;;;;2317:32;;-1:-1:-1;;;2101:254:1:o;2360:186::-;2419:6;2472:2;2460:9;2451:7;2447:23;2443:32;2440:52;;;2488:1;2485;2478:12;2440:52;2511:29;2530:9;2511:29;:::i;2551:316::-;2628:6;2636;2644;2697:2;2685:9;2676:7;2672:23;2668:32;2665:52;;;2713:1;2710;2703:12;2665:52;-1:-1:-1;;2736:23:1;;;2806:2;2791:18;;2778:32;;-1:-1:-1;2857:2:1;2842:18;;;2829:32;;2551:316;-1:-1:-1;2551:316:1:o;2872:367::-;2935:8;2945:6;2999:3;2992:4;2984:6;2980:17;2976:27;2966:55;;3017:1;3014;3007:12;2966:55;-1:-1:-1;3040:20:1;;3083:18;3072:30;;3069:50;;;3115:1;3112;3105:12;3069:50;3152:4;3144:6;3140:17;3128:29;;3212:3;3205:4;3195:6;3192:1;3188:14;3180:6;3176:27;3172:38;3169:47;3166:67;;;3229:1;3226;3219:12;3166:67;2872:367;;;;;:::o;3244:437::-;3330:6;3338;3391:2;3379:9;3370:7;3366:23;3362:32;3359:52;;;3407:1;3404;3397:12;3359:52;3447:9;3434:23;3480:18;3472:6;3469:30;3466:50;;;3512:1;3509;3502:12;3466:50;3551:70;3613:7;3604:6;3593:9;3589:22;3551:70;:::i;:::-;3640:8;;3525:96;;-1:-1:-1;3244:437:1;-1:-1:-1;;;;3244:437:1:o;3686:328::-;3763:6;3771;3779;3832:2;3820:9;3811:7;3807:23;3803:32;3800:52;;;3848:1;3845;3838:12;3800:52;3871:29;3890:9;3871:29;:::i;:::-;3861:39;;3919:38;3953:2;3942:9;3938:18;3919:38;:::i;:::-;3909:48;;4004:2;3993:9;3989:18;3976:32;3966:42;;3686:328;;;;;:::o;4019:118::-;4105:5;4098:13;4091:21;4084:5;4081:32;4071:60;;4127:1;4124;4117:12;4142:241;4198:6;4251:2;4239:9;4230:7;4226:23;4222:32;4219:52;;;4267:1;4264;4257:12;4219:52;4306:9;4293:23;4325:28;4347:5;4325:28;:::i;4388:632::-;4559:2;4611:21;;;4681:13;;4584:18;;;4703:22;;;4530:4;;4559:2;4782:15;;;;4756:2;4741:18;;;4530:4;4825:169;4839:6;4836:1;4833:13;4825:169;;;4900:13;;4888:26;;4969:15;;;;4934:12;;;;4861:1;4854:9;4825:169;;;-1:-1:-1;5011:3:1;;4388:632;-1:-1:-1;;;;;;4388:632:1:o;5025:127::-;5086:10;5081:3;5077:20;5074:1;5067:31;5117:4;5114:1;5107:15;5141:4;5138:1;5131:15;5157:632;5222:5;5252:18;5293:2;5285:6;5282:14;5279:40;;;5299:18;;:::i;:::-;5374:2;5368:9;5342:2;5428:15;;-1:-1:-1;;5424:24:1;;;5450:2;5420:33;5416:42;5404:55;;;5474:18;;;5494:22;;;5471:46;5468:72;;;5520:18;;:::i;:::-;5560:10;5556:2;5549:22;5589:6;5580:15;;5619:6;5611;5604:22;5659:3;5650:6;5645:3;5641:16;5638:25;5635:45;;;5676:1;5673;5666:12;5635:45;5726:6;5721:3;5714:4;5706:6;5702:17;5689:44;5781:1;5774:4;5765:6;5757;5753:19;5749:30;5742:41;;;;5157:632;;;;;:::o;5794:451::-;5863:6;5916:2;5904:9;5895:7;5891:23;5887:32;5884:52;;;5932:1;5929;5922:12;5884:52;5972:9;5959:23;6005:18;5997:6;5994:30;5991:50;;;6037:1;6034;6027:12;5991:50;6060:22;;6113:4;6105:13;;6101:27;-1:-1:-1;6091:55:1;;6142:1;6139;6132:12;6091:55;6165:74;6231:7;6226:2;6213:16;6208:2;6204;6200:11;6165:74;:::i;6250:505::-;6345:6;6353;6361;6414:2;6402:9;6393:7;6389:23;6385:32;6382:52;;;6430:1;6427;6420:12;6382:52;6470:9;6457:23;6503:18;6495:6;6492:30;6489:50;;;6535:1;6532;6525:12;6489:50;6574:70;6636:7;6627:6;6616:9;6612:22;6574:70;:::i;:::-;6663:8;;6548:96;;-1:-1:-1;6745:2:1;6730:18;;;;6717:32;;6250:505;-1:-1:-1;;;;6250:505:1:o;6760:315::-;6825:6;6833;6886:2;6874:9;6865:7;6861:23;6857:32;6854:52;;;6902:1;6899;6892:12;6854:52;6925:29;6944:9;6925:29;:::i;:::-;6915:39;;7004:2;6993:9;6989:18;6976:32;7017:28;7039:5;7017:28;:::i;:::-;7064:5;7054:15;;;6760:315;;;;;:::o;7080:667::-;7175:6;7183;7191;7199;7252:3;7240:9;7231:7;7227:23;7223:33;7220:53;;;7269:1;7266;7259:12;7220:53;7292:29;7311:9;7292:29;:::i;:::-;7282:39;;7340:38;7374:2;7363:9;7359:18;7340:38;:::i;:::-;7330:48;;7425:2;7414:9;7410:18;7397:32;7387:42;;7480:2;7469:9;7465:18;7452:32;7507:18;7499:6;7496:30;7493:50;;;7539:1;7536;7529:12;7493:50;7562:22;;7615:4;7607:13;;7603:27;-1:-1:-1;7593:55:1;;7644:1;7641;7634:12;7593:55;7667:74;7733:7;7728:2;7715:16;7710:2;7706;7702:11;7667:74;:::i;:::-;7657:84;;;7080:667;;;;;;;:::o;7752:248::-;7820:6;7828;7881:2;7869:9;7860:7;7856:23;7852:32;7849:52;;;7897:1;7894;7887:12;7849:52;-1:-1:-1;;7920:23:1;;;7990:2;7975:18;;;7962:32;;-1:-1:-1;7752:248:1:o;8005:260::-;8073:6;8081;8134:2;8122:9;8113:7;8109:23;8105:32;8102:52;;;8150:1;8147;8140:12;8102:52;8173:29;8192:9;8173:29;:::i;:::-;8163:39;;8221:38;8255:2;8244:9;8240:18;8221:38;:::i;:::-;8211:48;;8005:260;;;;;:::o;8270:380::-;8349:1;8345:12;;;;8392;;;8413:61;;8467:4;8459:6;8455:17;8445:27;;8413:61;8520:2;8512:6;8509:14;8489:18;8486:38;8483:161;;8566:10;8561:3;8557:20;8554:1;8547:31;8601:4;8598:1;8591:15;8629:4;8626:1;8619:15;8483:161;;8270:380;;;:::o;8655:127::-;8716:10;8711:3;8707:20;8704:1;8697:31;8747:4;8744:1;8737:15;8771:4;8768:1;8761:15;9572:543;9674:2;9669:3;9666:11;9663:446;;;9710:1;9734:5;9731:1;9724:16;9778:4;9775:1;9765:18;9848:2;9836:10;9832:19;9829:1;9825:27;9819:4;9815:38;9884:4;9872:10;9869:20;9866:47;;;-1:-1:-1;9907:4:1;9866:47;9962:2;9957:3;9953:12;9950:1;9946:20;9940:4;9936:31;9926:41;;10017:82;10035:2;10028:5;10025:13;10017:82;;;10080:17;;;10061:1;10050:13;10017:82;;;10021:3;;;9572:543;;;:::o;10291:1345::-;10417:3;10411:10;10444:18;10436:6;10433:30;10430:56;;;10466:18;;:::i;:::-;10495:97;10585:6;10545:38;10577:4;10571:11;10545:38;:::i;:::-;10539:4;10495:97;:::i;:::-;10647:4;;10704:2;10693:14;;10721:1;10716:663;;;;11423:1;11440:6;11437:89;;;-1:-1:-1;11492:19:1;;;11486:26;11437:89;-1:-1:-1;;10248:1:1;10244:11;;;10240:24;10236:29;10226:40;10272:1;10268:11;;;10223:57;11539:81;;10686:944;;10716:663;9519:1;9512:14;;;9556:4;9543:18;;-1:-1:-1;;10752:20:1;;;10870:236;10884:7;10881:1;10878:14;10870:236;;;10973:19;;;10967:26;10952:42;;11065:27;;;;11033:1;11021:14;;;;10900:19;;10870:236;;;10874:3;11134:6;11125:7;11122:19;11119:201;;;11195:19;;;11189:26;-1:-1:-1;;11278:1:1;11274:14;;;11290:3;11270:24;11266:37;11262:42;11247:58;11232:74;;11119:201;-1:-1:-1;;;;;11366:1:1;11350:14;;;11346:22;11333:36;;-1:-1:-1;10291:1345:1:o;11641:343::-;11843:2;11825:21;;;11882:2;11862:18;;;11855:30;-1:-1:-1;;;11916:2:1;11901:18;;11894:49;11975:2;11960:18;;11641:343::o;11989:127::-;12050:10;12045:3;12041:20;12038:1;12031:31;12081:4;12078:1;12071:15;12105:4;12102:1;12095:15;12121:168;12194:9;;;12225;;12242:15;;;12236:22;;12222:37;12212:71;;12263:18;;:::i;12294:125::-;12359:9;;;12380:10;;;12377:36;;;12393:18;;:::i;12424:348::-;12626:2;12608:21;;;12665:2;12645:18;;;12638:30;12704:26;12699:2;12684:18;;12677:54;12763:2;12748:18;;12424:348::o;13463:843::-;13591:3;13620:1;13653:6;13647:13;13683:36;13709:9;13683:36;:::i;:::-;13738:1;13755:17;;;13781:133;;;;13928:1;13923:358;;;;13748:533;;13781:133;-1:-1:-1;;13814:24:1;;13802:37;;13887:14;;13880:22;13868:35;;13859:45;;;-1:-1:-1;13781:133:1;;13923:358;13954:6;13951:1;13944:17;13984:4;14029;14026:1;14016:18;14056:1;14070:165;14084:6;14081:1;14078:13;14070:165;;;14162:14;;14149:11;;;14142:35;14205:16;;;;14099:10;;14070:165;;;14074:3;;;14264:6;14259:3;14255:16;14248:23;;13748:533;-1:-1:-1;14297:3:1;;13463:843;-1:-1:-1;;;;;;13463:843:1:o;14311:289::-;14442:3;14480:6;14474:13;14496:66;14555:6;14550:3;14543:4;14535:6;14531:17;14496:66;:::i;:::-;14578:16;;;;;14311:289;-1:-1:-1;;14311:289:1:o;14605:128::-;14672:9;;;14693:11;;;14690:37;;;14707:18;;:::i;16747:245::-;16814:6;16867:2;16855:9;16846:7;16842:23;16838:32;16835:52;;;16883:1;16880;16873:12;16835:52;16915:9;16909:16;16934:28;16956:5;16934:28;:::i;16997:184::-;17067:6;17120:2;17108:9;17099:7;17095:23;17091:32;17088:52;;;17136:1;17133;17126:12;17088:52;-1:-1:-1;17159:16:1;;16997:184;-1:-1:-1;16997:184:1:o;18087:127::-;18148:10;18143:3;18139:20;18136:1;18129:31;18179:4;18176:1;18169:15;18203:4;18200:1;18193:15;18219:112;18251:1;18277;18267:35;;18282:18;;:::i;:::-;-1:-1:-1;18316:9:1;;18219:112::o;19166:489::-;-1:-1:-1;;;;;19435:15:1;;;19417:34;;19487:15;;19482:2;19467:18;;19460:43;19534:2;19519:18;;19512:34;;;19582:3;19577:2;19562:18;;19555:31;;;19360:4;;19603:46;;19629:19;;19621:6;19603:46;:::i;:::-;19595:54;19166:489;-1:-1:-1;;;;;;19166:489:1:o;19660:249::-;19729:6;19782:2;19770:9;19761:7;19757:23;19753:32;19750:52;;;19798:1;19795;19788:12;19750:52;19830:9;19824:16;19849:30;19873:5;19849:30;:::i;19914:496::-;20093:3;20131:6;20125:13;20147:66;20206:6;20201:3;20194:4;20186:6;20182:17;20147:66;:::i;:::-;20276:13;;20235:16;;;;20298:70;20276:13;20235:16;20345:4;20333:17;;20298:70;:::i;:::-;20384:20;;19914:496;-1:-1:-1;;;;19914:496:1:o;20415:127::-;20476:10;20471:3;20467:20;20464:1;20457:31;20507:4;20504:1;20497:15;20531:4;20528:1;20521:15;20900:135;20939:3;20960:17;;;20957:43;;20980:18;;:::i;:::-;-1:-1:-1;21027:1:1;21016:13;;20900:135::o

Swarm Source

ipfs://37faf7921b529fd918f850c3fc31cd135213810b9aae7a7d55f7600c2633b592
Loading