ETH Price: $3,372.93 (-2.46%)

Token

Sprout Academy (SPROUT)
 

Overview

Max Total Supply

5,001 SPROUT

Holders

2,222

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 SPROUT
0xf00ce3d8aaf3e3d7a299c595f12306e0bfbb3679
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
SproutAcademy

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

// File: @openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol


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

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

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

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

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

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

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

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

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

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol


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

pragma solidity ^0.8.0;


/**
 * @dev String operations.
 */
library StringsUpgradeable {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol


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

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`,
     * consuming from one or the other at each step according to the instructions given by
     * `proofFlags`.
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

// File: erc721a/contracts/IERC721A.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

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

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

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

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

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @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`,
     * 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 be 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,
        bytes calldata data
    ) external payable;

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom}
     * whenever possible.
     *
     * 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 payable;

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

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

// File: erc721a/contracts/ERC721A.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

    /**
     * @dev Returns the starting token ID.
     * To change the starting token ID, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256) {
        // Counter underflow is impossible as `_currentIndex` does not decrement,
        // and it is initialized to `_startTokenId()`.
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
    }

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
    }

    /**
     * @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, it can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return '';
    }

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & _BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an initialized ownership slot
                        // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                        // before an unintialized ownership slot
                        // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                        // Hence, `curr` will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed will be zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

    /**
     * @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) public payable virtual override {
        address owner = ownerOf(tokenId);

        if (_msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                revert ApprovalCallerNotOwnerNorApproved();
            }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId].value;
    }

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

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
            if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();

        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @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 memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token IDs
     * are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

            // Use assembly to loop and emit the `Transfer` event for gas savings.
            // The duplicated `log4` removes an extra check and reduces stack juggling.
            // The assembly, together with the surrounding Solidity code, have been
            // delicately arranged to nudge the compiler into producing optimized opcodes.
            assembly {
                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
                toMasked := and(to, _BITMASK_ADDRESS)
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    startTokenId // `tokenId`.
                )

                // The `iszero(eq(,))` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
                // The compiler will optimize the `iszero` away for performance.
                for {
                    let tokenId := add(startTokenId, 1)
                } iszero(eq(tokenId, end)) {
                    tokenId := add(tokenId, 1)
                } {
                    // Emit the `Transfer` event. Similar to above.
                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
                }
            }
            if (toMasked == 0) revert MintToZeroAddress();

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (index < end);
                // Reentrancy protection.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, '');
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        address from = address(uint160(prevOwnershipPacked));

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
                if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) revert OwnershipNotInitializedForExtraData();
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

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

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

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

// File: contracts/4_SproutsAcademy.sol


pragma solidity ^0.8.0;





interface IWLCC {
  function ownerOf(uint256 tokenId) external returns (address);

  function balanceOf(address holderAddress) external returns (uint256);
}

interface IStakingWLCC {
  function tokenOwners(uint256 tokenId) external returns (address);

  function stakedTokens(address holderAddress) external returns (uint256);
}

contract SproutAcademy is ERC721A, Ownable {
    using StringsUpgradeable for uint256;

    uint256 public constant MAX_SUPPLY = 5000;
    uint256 public constant MAX_PUBLIC_MINT = 1;
    uint256 public constant MAX_WHITELIST_MINT = 1;
    uint256 public constant MAX_WLCC_MINT = 10;

    string public baseTokenURI;

    address public wlccContractAddress;
    address public wlccStakingContractAddress;

    bool public publicSale;
    bool public whiteListSale;
    bool public wlccSale;

    bytes32 private merkleRoot;

    mapping(address => uint256) public totalPublicMint;
    mapping(address => uint256) public totalWhitelistMint;
    mapping(address => uint256) public totalWlccMint;
    mapping(uint256 => bool) internal tokenIdToClaimed;

    constructor() ERC721A("Sprout Academy", "SPROUT"){

    }

    modifier callerIsUser() {
        require(tx.origin == msg.sender, "Sprout Academy :: Cannot be called by a contract");
        _;
    }

    function mintWLCC(uint256[] memory tokenIds) external callerIsUser {
        require(wlccSale, "Sprout Academy :: Not Yet Active.");
        require((totalWlccMint[msg.sender]) <= MAX_WLCC_MINT, "Sprout Academy :: Already minted maximum times!");

        IWLCC wlcc = IWLCC(wlccContractAddress);
        IStakingWLCC stakedTokens = IStakingWLCC(wlccStakingContractAddress);

        uint256 wlccCount = wlcc.balanceOf(msg.sender);
        uint256 stakingCount = stakedTokens.stakedTokens(msg.sender);

        uint256 claimableCount = wlccCount + stakingCount;
        uint256 sproutMintCount = 0;

        if(claimableCount == 1 || claimableCount == 2) {
            sproutMintCount = 1;
        }
        else if(claimableCount > 2 && claimableCount < 5) {
            sproutMintCount = 2;
        }
        else if(claimableCount > 4 && claimableCount < 8) {
            sproutMintCount = 5;
        }
        else if(claimableCount > 7 && claimableCount < 10) {
            sproutMintCount = 6;
        }
        else if(claimableCount > 9) {
            sproutMintCount = 10;
        }

        for (uint256 i; i < sproutMintCount; i++) {
            uint256 wlccTokenId = tokenIds[i];
            if (wlcc.ownerOf(wlccTokenId) == msg.sender && !tokenIdToClaimed[wlccTokenId]) {
                _safeMint(msg.sender, 1);

                tokenIdToClaimed[wlccTokenId] = true;
            }
            else if(stakedTokens.tokenOwners(wlccTokenId) == msg.sender && !tokenIdToClaimed[wlccTokenId]) {
                _safeMint(msg.sender, 1);

                tokenIdToClaimed[wlccTokenId] = true;
            }
        }
    }

    function mint() external callerIsUser {
        require(publicSale, "Sprout Academy :: Not Yet Active.");
        require((totalSupply() + 1) <= MAX_SUPPLY, "Sprout Academy :: Cannot mint beyond max supply");
        require((totalPublicMint[msg.sender] + 1) <= MAX_PUBLIC_MINT, "Sprout Academy :: Already minted maximum times!");

        totalPublicMint[msg.sender] += 1;
        _safeMint(msg.sender, 1);
    }

    function whitelistMint(bytes32[] memory _merkleProof) external callerIsUser {
        require(whiteListSale, "Sprout Academy :: Minting is on Pause");
        require((totalSupply() + 1) <= MAX_SUPPLY, "Sprout Academy :: Cannot mint beyond max supply");
        require((totalWhitelistMint[msg.sender] + 1)  <= MAX_WHITELIST_MINT, "Sprout Academy :: Cannot mint beyond whitelist max mint!");

        //create leaf node
        bytes32 sender = keccak256(abi.encodePacked(msg.sender));
        require(MerkleProof.verify(_merkleProof, merkleRoot, sender), "Sprout Academy :: You are not on the Sproutlist");

        totalWhitelistMint[msg.sender] += 1;
        _safeMint(msg.sender, 1);
    }

    function reserveSprouts() external onlyOwner {
       _safeMint(msg.sender, 150);
    }


  /// @notice Get uri of tokens
  /// @return string Uri
  function _baseURI() internal view virtual override returns (string memory) {
    return baseTokenURI;
  }

   /// @notice Set the WLCC NFT contract address
  /// @param wlccAddress Address of the WLCC nft contract
  function setWastelandCactusCrewAddress(address wlccAddress) external onlyOwner {
    wlccContractAddress = wlccAddress;
  }

  // @notice Set the WLCC Staking contract address
  /// @param wlccStakingAddress Address of the WLCC nft contract
  function setStakingAddress(address wlccStakingAddress) external onlyOwner {
    wlccStakingContractAddress = wlccStakingAddress;
  }

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

        uint256 trueId = tokenId + 1;

        //string memory baseURI = _baseURI();
        return string(abi.encodePacked(_baseURI(), trueId.toString(), ".json"));
    }

    function setTokenUri(string memory _baseTokenUri) external onlyOwner{
        baseTokenURI = _baseTokenUri;
    }

    function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner{
        merkleRoot = _merkleRoot;
    }

    function getMerkleRoot() external view returns (bytes32){
        return merkleRoot;
    }

    function toggleWhiteListSale() external onlyOwner{
        whiteListSale = !whiteListSale;
    }

    function togglePublicSale() external onlyOwner{
        publicSale = !publicSale;
    }

    function toggleWlccSale() external onlyOwner{
        wlccSale = !wlccSale;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_PUBLIC_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WHITELIST_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WLCC_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"getMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"mintWLCC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"publicSale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveSprouts","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":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wlccStakingAddress","type":"address"}],"name":"setStakingAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseTokenUri","type":"string"}],"name":"setTokenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wlccAddress","type":"address"}],"name":"setWastelandCactusCrewAddress","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":[],"name":"togglePublicSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleWhiteListSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleWlccSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalPublicMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalWhitelistMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalWlccMint","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whiteListSale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wlccContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlccSale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlccStakingContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280600e81526020017f5370726f75742041636164656d790000000000000000000000000000000000008152506040518060400160405280600681526020017f5350524f5554000000000000000000000000000000000000000000000000000081525081600290816200008f91906200042d565b508060039081620000a191906200042d565b50620000b2620000e060201b60201c565b6000819055505050620000da620000ce620000e560201b60201c565b620000ed60201b60201c565b62000514565b600090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200023557607f821691505b6020821081036200024b576200024a620001ed565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620002b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000276565b620002c1868362000276565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006200030e620003086200030284620002d9565b620002e3565b620002d9565b9050919050565b6000819050919050565b6200032a83620002ed565b62000342620003398262000315565b84845462000283565b825550505050565b600090565b620003596200034a565b620003668184846200031f565b505050565b5b818110156200038e57620003826000826200034f565b6001810190506200036c565b5050565b601f821115620003dd57620003a78162000251565b620003b28462000266565b81016020851015620003c2578190505b620003da620003d18562000266565b8301826200036b565b50505b505050565b600082821c905092915050565b60006200040260001984600802620003e2565b1980831691505092915050565b60006200041d8383620003ef565b9150826002028217905092915050565b6200043882620001b3565b67ffffffffffffffff811115620004545762000453620001be565b5b6200046082546200021c565b6200046d82828562000392565b600060209050601f831160018114620004a5576000841562000490578287015190505b6200049c85826200040f565b8655506200050c565b601f198416620004b58662000251565b60005b82811015620004df57848901518255600182019150602085019450602081019050620004b8565b86831015620004ff5784890151620004fb601f891682620003ef565b8355505b6001600288020188555050505b505050505050565b61415d80620005246000396000f3fe6080604052600436106102515760003560e01c806365f1309711610139578063a22cb465116100b6578063d547cfb71161007a578063d547cfb714610848578063d67072d214610873578063e222c7f91461089c578063e985e9c5146108b3578063f2fde38b146108f0578063f4e0d9ac1461091957610251565b8063a22cb46514610770578063aa922c9814610799578063b88d4fde146107c4578063c08dfd3c146107e0578063c87b56dd1461080b57610251565b806386a173ee116100fd57806386a173ee146106c15780638bb64a8c146106ec5780638da5cb5b146107035780638f29a7d31461072e57806395d89b411461074557610251565b806365f13097146105f057806370a082311461061b578063715018a6146106585780637cb647591461066f578063813f767a1461069857610251565b806323bfe592116101d25780633a1fe75b116101965780633a1fe75b146104ff57806342842e0e1461052a57806349590657146105465780634dd0954d1461057157806360c243c61461059c5780636352211e146105b357610251565b806323bfe5921461041857806332cb6b0c1461045557806333bc1c5c1461048057806336bd21b6146104ab578063372f657c146104d657610251565b8063095ea7b311610219578063095ea7b3146103615780631249c58b1461037d57806318160ddd146103945780631c16521c146103bf57806323b872dd146103fc57610251565b806301ffc9a7146102565780630345e3cb146102935780630675b7c6146102d057806306fdde03146102f9578063081812fc14610324575b600080fd5b34801561026257600080fd5b5061027d60048036038101906102789190612c4f565b610942565b60405161028a9190612c97565b60405180910390f35b34801561029f57600080fd5b506102ba60048036038101906102b59190612d10565b6109d4565b6040516102c79190612d56565b60405180910390f35b3480156102dc57600080fd5b506102f760048036038101906102f29190612eb7565b6109ec565b005b34801561030557600080fd5b5061030e610a07565b60405161031b9190612f7f565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190612fcd565b610a99565b6040516103589190613009565b60405180910390f35b61037b60048036038101906103769190613024565b610b18565b005b34801561038957600080fd5b50610392610c5c565b005b3480156103a057600080fd5b506103a9610e63565b6040516103b69190612d56565b60405180910390f35b3480156103cb57600080fd5b506103e660048036038101906103e19190612d10565b610e7a565b6040516103f39190612d56565b60405180910390f35b61041660048036038101906104119190613064565b610e92565b005b34801561042457600080fd5b5061043f600480360381019061043a9190612d10565b6111b4565b60405161044c9190612d56565b60405180910390f35b34801561046157600080fd5b5061046a6111cc565b6040516104779190612d56565b60405180910390f35b34801561048c57600080fd5b506104956111d2565b6040516104a29190612c97565b60405180910390f35b3480156104b757600080fd5b506104c06111e5565b6040516104cd9190613009565b60405180910390f35b3480156104e257600080fd5b506104fd60048036038101906104f891906131b5565b61120b565b005b34801561050b57600080fd5b5061051461148b565b6040516105219190612d56565b60405180910390f35b610544600480360381019061053f9190613064565b611490565b005b34801561055257600080fd5b5061055b6114b0565b604051610568919061320d565b60405180910390f35b34801561057d57600080fd5b506105866114ba565b6040516105939190613009565b60405180910390f35b3480156105a857600080fd5b506105b16114e0565b005b3480156105bf57600080fd5b506105da60048036038101906105d59190612fcd565b6114f5565b6040516105e79190613009565b60405180910390f35b3480156105fc57600080fd5b50610605611507565b6040516106129190612d56565b60405180910390f35b34801561062757600080fd5b50610642600480360381019061063d9190612d10565b61150c565b60405161064f9190612d56565b60405180910390f35b34801561066457600080fd5b5061066d6115c4565b005b34801561067b57600080fd5b5061069660048036038101906106919190613228565b6115d8565b005b3480156106a457600080fd5b506106bf60048036038101906106ba9190613318565b6115ea565b005b3480156106cd57600080fd5b506106d6611b82565b6040516106e39190612c97565b60405180910390f35b3480156106f857600080fd5b50610701611b95565b005b34801561070f57600080fd5b50610718611bc9565b6040516107259190613009565b60405180910390f35b34801561073a57600080fd5b50610743611bf3565b005b34801561075157600080fd5b5061075a611c27565b6040516107679190612f7f565b60405180910390f35b34801561077c57600080fd5b506107976004803603810190610792919061338d565b611cb9565b005b3480156107a557600080fd5b506107ae611dc4565b6040516107bb9190612c97565b60405180910390f35b6107de60048036038101906107d9919061346e565b611dd7565b005b3480156107ec57600080fd5b506107f5611e4a565b6040516108029190612d56565b60405180910390f35b34801561081757600080fd5b50610832600480360381019061082d9190612fcd565b611e4f565b60405161083f9190612f7f565b60405180910390f35b34801561085457600080fd5b5061085d611ee3565b60405161086a9190612f7f565b60405180910390f35b34801561087f57600080fd5b5061089a60048036038101906108959190612d10565b611f71565b005b3480156108a857600080fd5b506108b1611fbd565b005b3480156108bf57600080fd5b506108da60048036038101906108d591906134f1565b611ff1565b6040516108e79190612c97565b60405180910390f35b3480156108fc57600080fd5b5061091760048036038101906109129190612d10565b612085565b005b34801561092557600080fd5b50610940600480360381019061093b9190612d10565b612108565b005b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061099d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109cd5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600e6020528060005260406000206000915090505481565b6109f4612154565b8060099081610a03919061373d565b5050565b606060028054610a1690613560565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4290613560565b8015610a8f5780601f10610a6457610100808354040283529160200191610a8f565b820191906000526020600020905b815481529060010190602001808311610a7257829003601f168201915b5050505050905090565b6000610aa4826121d2565b610ada576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b23826114f5565b90508073ffffffffffffffffffffffffffffffffffffffff16610b44612231565b73ffffffffffffffffffffffffffffffffffffffff1614610ba757610b7081610b6b612231565b611ff1565b610ba6576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc190613881565b60405180910390fd5b600b60149054906101000a900460ff16610d19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d1090613913565b60405180910390fd5b6113886001610d26610e63565b610d309190613962565b1115610d71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6890613a08565b60405180910390fd5b600180600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dbe9190613962565b1115610dff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df690613a9a565b60405180910390fd5b6001600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610e4f9190613962565b92505081905550610e61336001612239565b565b6000610e6d612257565b6001546000540303905090565b600d6020528060005260406000206000915090505481565b6000610e9d8261225c565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f04576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f1084612328565b91509150610f268187610f21612231565b61234f565b610f7257610f3b86610f36612231565b611ff1565b610f71576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610fd8576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fe58686866001612393565b8015610ff057600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154600101919050819055506110be8561109a888887612399565b7c0200000000000000000000000000000000000000000000000000000000176123c1565b600460008681526020019081526020016000208190555060007c02000000000000000000000000000000000000000000000000000000008416036111445760006001850190506000600460008381526020019081526020016000205403611142576000548114611141578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46111ac86868660016123ec565b505050505050565b600f6020528060005260406000206000915090505481565b61138881565b600b60149054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127090613881565b60405180910390fd5b600b60159054906101000a900460ff166112c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112bf90613b2c565b60405180910390fd5b61138860016112d5610e63565b6112df9190613962565b1115611320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131790613a08565b60405180910390fd5b600180600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136d9190613962565b11156113ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a590613bbe565b60405180910390fd5b6000336040516020016113c19190613c26565b6040516020818303038152906040528051906020012090506113e682600c54836123f2565b611425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141c90613cb3565b60405180910390fd5b6001600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546114759190613962565b92505081905550611487336001612239565b5050565b600a81565b6114ab83838360405180602001604052806000815250611dd7565b505050565b6000600c54905090565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6114e8612154565b6114f3336096612239565b565b60006115008261225c565b9050919050565b600181565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611573576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6115cc612154565b6115d66000612409565b565b6115e0612154565b80600c8190555050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164f90613881565b60405180910390fd5b600b60169054906101000a900460ff166116a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169e90613913565b60405180910390fd5b600a600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054111561172a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172190613a9a565b60405180910390fd5b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016117b39190613009565b6020604051808303816000875af11580156117d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f69190613ce8565b905060008273ffffffffffffffffffffffffffffffffffffffff1663a5b39cfb336040518263ffffffff1660e01b81526004016118339190613009565b6020604051808303816000875af1158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190613ce8565b9050600081836118869190613962565b9050600060018214806118995750600282145b156118a75760019050611913565b6002821180156118b75750600582105b156118c55760029050611912565b6004821180156118d55750600882105b156118e35760059050611911565b6007821180156118f35750600a82105b156119015760069050611910565b600982111561190f57600a90505b5b5b5b5b60005b81811015611b7857600088828151811061193357611932613d15565b5b602002602001015190503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b815260040161198d9190612d56565b6020604051808303816000875af11580156119ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d09190613d59565b73ffffffffffffffffffffffffffffffffffffffff16148015611a1157506010600082815260200190815260200160002060009054906101000a900460ff16155b15611a5257611a21336001612239565b60016010600083815260200190815260200160002060006101000a81548160ff021916908315150217905550611b64565b3373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1663f8a14f46836040518263ffffffff1660e01b8152600401611aa29190612d56565b6020604051808303816000875af1158015611ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae59190613d59565b73ffffffffffffffffffffffffffffffffffffffff16148015611b2657506010600082815260200190815260200160002060009054906101000a900460ff16155b15611b6357611b36336001612239565b60016010600083815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b508080611b7090613d86565b915050611916565b5050505050505050565b600b60159054906101000a900460ff1681565b611b9d612154565b600b60159054906101000a900460ff1615600b60156101000a81548160ff021916908315150217905550565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611bfb612154565b600b60169054906101000a900460ff1615600b60166101000a81548160ff021916908315150217905550565b606060038054611c3690613560565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6290613560565b8015611caf5780601f10611c8457610100808354040283529160200191611caf565b820191906000526020600020905b815481529060010190602001808311611c9257829003601f168201915b5050505050905090565b8060076000611cc6612231565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611d73612231565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611db89190612c97565b60405180910390a35050565b600b60169054906101000a900460ff1681565b611de2848484610e92565b60008373ffffffffffffffffffffffffffffffffffffffff163b14611e4457611e0d848484846124cf565b611e43576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b600181565b6060611e5a826121d2565b611e99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9090613e40565b60405180910390fd5b6000600183611ea89190613962565b9050611eb261261f565b611ebb826126b1565b604051602001611ecc929190613ee8565b604051602081830303815290604052915050919050565b60098054611ef090613560565b80601f0160208091040260200160405190810160405280929190818152602001828054611f1c90613560565b8015611f695780601f10611f3e57610100808354040283529160200191611f69565b820191906000526020600020905b815481529060010190602001808311611f4c57829003601f168201915b505050505081565b611f79612154565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611fc5612154565b600b60149054906101000a900460ff1615600b60146101000a81548160ff021916908315150217905550565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61208d612154565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f390613f89565b60405180910390fd5b61210581612409565b50565b612110612154565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61215c61277f565b73ffffffffffffffffffffffffffffffffffffffff1661217a611bc9565b73ffffffffffffffffffffffffffffffffffffffff16146121d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121c790613ff5565b60405180910390fd5b565b6000816121dd612257565b111580156121ec575060005482105b801561222a575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b612253828260405180602001604052806000815250612787565b5050565b600090565b6000808290508061226b612257565b116122f1576000548110156122f05760006004600083815260200190815260200160002054905060007c01000000000000000000000000000000000000000000000000000000008216036122ee575b600081036122e45760046000836001900393508381526020019081526020016000205490506122ba565b8092505050612323565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e86123b0868684612824565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000826123ff858461282d565b1490509392505050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026124f5612231565b8786866040518563ffffffff1660e01b8152600401612517949392919061406a565b6020604051808303816000875af192505050801561255357506040513d601f19601f8201168201806040525081019061255091906140cb565b60015b6125cc573d8060008114612583576040519150601f19603f3d011682016040523d82523d6000602084013e612588565b606091505b5060008151036125c4576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60606009805461262e90613560565b80601f016020809104026020016040519081016040528092919081815260200182805461265a90613560565b80156126a75780601f1061267c576101008083540402835291602001916126a7565b820191906000526020600020905b81548152906001019060200180831161268a57829003601f168201915b5050505050905090565b6060600060016126c084612883565b01905060008167ffffffffffffffff8111156126df576126de612d8c565b5b6040519080825280601f01601f1916602001820160405280156127115781602001600182028036833780820191505090505b509050600082602001820190505b600115612774578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612768576127676140f8565b5b0494506000850361271f575b819350505050919050565b600033905090565b61279183836129d6565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461281f57600080549050600083820390505b6127d160008683806001019450866124cf565b612807576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181106127be57816000541461281c57600080fd5b50505b505050565b60009392505050565b60008082905060005b8451811015612878576128638286838151811061285657612855613d15565b5b6020026020010151612b91565b9150808061287090613d86565b915050612836565b508091505092915050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106128e1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816128d7576128d66140f8565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061291e576d04ee2d6d415b85acef81000000008381612914576129136140f8565b5b0492506020810190505b662386f26fc10000831061294d57662386f26fc100008381612943576129426140f8565b5b0492506010810190505b6305f5e1008310612976576305f5e100838161296c5761296b6140f8565b5b0492506008810190505b612710831061299b576127108381612991576129906140f8565b5b0492506004810190505b606483106129be57606483816129b4576129b36140f8565b5b0492506002810190505b600a83106129cd576001810190505b80915050919050565b60008054905060008203612a16576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a236000848385612393565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550612a9a83612a8b6000866000612399565b612a9485612bbc565b176123c1565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b818114612b3b57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600181019050612b00565b5060008203612b76576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000819055505050612b8c60008483856123ec565b505050565b6000818310612ba957612ba48284612bcc565b612bb4565b612bb38383612bcc565b5b905092915050565b60006001821460e11b9050919050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612c2c81612bf7565b8114612c3757600080fd5b50565b600081359050612c4981612c23565b92915050565b600060208284031215612c6557612c64612bed565b5b6000612c7384828501612c3a565b91505092915050565b60008115159050919050565b612c9181612c7c565b82525050565b6000602082019050612cac6000830184612c88565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612cdd82612cb2565b9050919050565b612ced81612cd2565b8114612cf857600080fd5b50565b600081359050612d0a81612ce4565b92915050565b600060208284031215612d2657612d25612bed565b5b6000612d3484828501612cfb565b91505092915050565b6000819050919050565b612d5081612d3d565b82525050565b6000602082019050612d6b6000830184612d47565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612dc482612d7b565b810181811067ffffffffffffffff82111715612de357612de2612d8c565b5b80604052505050565b6000612df6612be3565b9050612e028282612dbb565b919050565b600067ffffffffffffffff821115612e2257612e21612d8c565b5b612e2b82612d7b565b9050602081019050919050565b82818337600083830152505050565b6000612e5a612e5584612e07565b612dec565b905082815260208101848484011115612e7657612e75612d76565b5b612e81848285612e38565b509392505050565b600082601f830112612e9e57612e9d612d71565b5b8135612eae848260208601612e47565b91505092915050565b600060208284031215612ecd57612ecc612bed565b5b600082013567ffffffffffffffff811115612eeb57612eea612bf2565b5b612ef784828501612e89565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612f3a578082015181840152602081019050612f1f565b60008484015250505050565b6000612f5182612f00565b612f5b8185612f0b565b9350612f6b818560208601612f1c565b612f7481612d7b565b840191505092915050565b60006020820190508181036000830152612f998184612f46565b905092915050565b612faa81612d3d565b8114612fb557600080fd5b50565b600081359050612fc781612fa1565b92915050565b600060208284031215612fe357612fe2612bed565b5b6000612ff184828501612fb8565b91505092915050565b61300381612cd2565b82525050565b600060208201905061301e6000830184612ffa565b92915050565b6000806040838503121561303b5761303a612bed565b5b600061304985828601612cfb565b925050602061305a85828601612fb8565b9150509250929050565b60008060006060848603121561307d5761307c612bed565b5b600061308b86828701612cfb565b935050602061309c86828701612cfb565b92505060406130ad86828701612fb8565b9150509250925092565b600067ffffffffffffffff8211156130d2576130d1612d8c565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b6130fb816130e8565b811461310657600080fd5b50565b600081359050613118816130f2565b92915050565b600061313161312c846130b7565b612dec565b90508083825260208201905060208402830185811115613154576131536130e3565b5b835b8181101561317d57806131698882613109565b845260208401935050602081019050613156565b5050509392505050565b600082601f83011261319c5761319b612d71565b5b81356131ac84826020860161311e565b91505092915050565b6000602082840312156131cb576131ca612bed565b5b600082013567ffffffffffffffff8111156131e9576131e8612bf2565b5b6131f584828501613187565b91505092915050565b613207816130e8565b82525050565b600060208201905061322260008301846131fe565b92915050565b60006020828403121561323e5761323d612bed565b5b600061324c84828501613109565b91505092915050565b600067ffffffffffffffff8211156132705761326f612d8c565b5b602082029050602081019050919050565b600061329461328f84613255565b612dec565b905080838252602082019050602084028301858111156132b7576132b66130e3565b5b835b818110156132e057806132cc8882612fb8565b8452602084019350506020810190506132b9565b5050509392505050565b600082601f8301126132ff576132fe612d71565b5b813561330f848260208601613281565b91505092915050565b60006020828403121561332e5761332d612bed565b5b600082013567ffffffffffffffff81111561334c5761334b612bf2565b5b613358848285016132ea565b91505092915050565b61336a81612c7c565b811461337557600080fd5b50565b60008135905061338781613361565b92915050565b600080604083850312156133a4576133a3612bed565b5b60006133b285828601612cfb565b92505060206133c385828601613378565b9150509250929050565b600067ffffffffffffffff8211156133e8576133e7612d8c565b5b6133f182612d7b565b9050602081019050919050565b600061341161340c846133cd565b612dec565b90508281526020810184848401111561342d5761342c612d76565b5b613438848285612e38565b509392505050565b600082601f83011261345557613454612d71565b5b81356134658482602086016133fe565b91505092915050565b6000806000806080858703121561348857613487612bed565b5b600061349687828801612cfb565b94505060206134a787828801612cfb565b93505060406134b887828801612fb8565b925050606085013567ffffffffffffffff8111156134d9576134d8612bf2565b5b6134e587828801613440565b91505092959194509250565b6000806040838503121561350857613507612bed565b5b600061351685828601612cfb565b925050602061352785828601612cfb565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061357857607f821691505b60208210810361358b5761358a613531565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135f37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826135b6565b6135fd86836135b6565b95508019841693508086168417925050509392505050565b6000819050919050565b600061363a61363561363084612d3d565b613615565b612d3d565b9050919050565b6000819050919050565b6136548361361f565b61366861366082613641565b8484546135c3565b825550505050565b600090565b61367d613670565b61368881848461364b565b505050565b5b818110156136ac576136a1600082613675565b60018101905061368e565b5050565b601f8211156136f1576136c281613591565b6136cb846135a6565b810160208510156136da578190505b6136ee6136e6856135a6565b83018261368d565b50505b505050565b600082821c905092915050565b6000613714600019846008026136f6565b1980831691505092915050565b600061372d8383613703565b9150826002028217905092915050565b61374682612f00565b67ffffffffffffffff81111561375f5761375e612d8c565b5b6137698254613560565b6137748282856136b0565b600060209050601f8311600181146137a75760008415613795578287015190505b61379f8582613721565b865550613807565b601f1984166137b586613591565b60005b828110156137dd578489015182556001820191506020850194506020810190506137b8565b868310156137fa57848901516137f6601f891682613703565b8355505b6001600288020188555050505b505050505050565b7f5370726f75742041636164656d79203a3a2043616e6e6f742062652063616c6c60008201527f6564206279206120636f6e747261637400000000000000000000000000000000602082015250565b600061386b603083612f0b565b91506138768261380f565b604082019050919050565b6000602082019050818103600083015261389a8161385e565b9050919050565b7f5370726f75742041636164656d79203a3a204e6f74205965742041637469766560008201527f2e00000000000000000000000000000000000000000000000000000000000000602082015250565b60006138fd602183612f0b565b9150613908826138a1565b604082019050919050565b6000602082019050818103600083015261392c816138f0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061396d82612d3d565b915061397883612d3d565b92508282019050808211156139905761398f613933565b5b92915050565b7f5370726f75742041636164656d79203a3a2043616e6e6f74206d696e7420626560008201527f796f6e64206d617820737570706c790000000000000000000000000000000000602082015250565b60006139f2602f83612f0b565b91506139fd82613996565b604082019050919050565b60006020820190508181036000830152613a21816139e5565b9050919050565b7f5370726f75742041636164656d79203a3a20416c7265616479206d696e74656460008201527f206d6178696d756d2074696d6573210000000000000000000000000000000000602082015250565b6000613a84602f83612f0b565b9150613a8f82613a28565b604082019050919050565b60006020820190508181036000830152613ab381613a77565b9050919050565b7f5370726f75742041636164656d79203a3a204d696e74696e67206973206f6e2060008201527f5061757365000000000000000000000000000000000000000000000000000000602082015250565b6000613b16602583612f0b565b9150613b2182613aba565b604082019050919050565b60006020820190508181036000830152613b4581613b09565b9050919050565b7f5370726f75742041636164656d79203a3a2043616e6e6f74206d696e7420626560008201527f796f6e642077686974656c697374206d6178206d696e74210000000000000000602082015250565b6000613ba8603883612f0b565b9150613bb382613b4c565b604082019050919050565b60006020820190508181036000830152613bd781613b9b565b9050919050565b60008160601b9050919050565b6000613bf682613bde565b9050919050565b6000613c0882613beb565b9050919050565b613c20613c1b82612cd2565b613bfd565b82525050565b6000613c328284613c0f565b60148201915081905092915050565b7f5370726f75742041636164656d79203a3a20596f7520617265206e6f74206f6e60008201527f20746865205370726f75746c6973740000000000000000000000000000000000602082015250565b6000613c9d602f83612f0b565b9150613ca882613c41565b604082019050919050565b60006020820190508181036000830152613ccc81613c90565b9050919050565b600081519050613ce281612fa1565b92915050565b600060208284031215613cfe57613cfd612bed565b5b6000613d0c84828501613cd3565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050613d5381612ce4565b92915050565b600060208284031215613d6f57613d6e612bed565b5b6000613d7d84828501613d44565b91505092915050565b6000613d9182612d3d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613dc357613dc2613933565b5b600182019050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613e2a602f83612f0b565b9150613e3582613dce565b604082019050919050565b60006020820190508181036000830152613e5981613e1d565b9050919050565b600081905092915050565b6000613e7682612f00565b613e808185613e60565b9350613e90818560208601612f1c565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000613ed2600583613e60565b9150613edd82613e9c565b600582019050919050565b6000613ef48285613e6b565b9150613f008284613e6b565b9150613f0b82613ec5565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000613f73602683612f0b565b9150613f7e82613f17565b604082019050919050565b60006020820190508181036000830152613fa281613f66565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000613fdf602083612f0b565b9150613fea82613fa9565b602082019050919050565b6000602082019050818103600083015261400e81613fd2565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061403c82614015565b6140468185614020565b9350614056818560208601612f1c565b61405f81612d7b565b840191505092915050565b600060808201905061407f6000830187612ffa565b61408c6020830186612ffa565b6140996040830185612d47565b81810360608301526140ab8184614031565b905095945050505050565b6000815190506140c581612c23565b92915050565b6000602082840312156140e1576140e0612bed565b5b60006140ef848285016140b6565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212203fd71cccc3897ff9bbd31b60a973fee938dc31d4a1c0232036d11628c673344064736f6c63430008110033

Deployed Bytecode

0x6080604052600436106102515760003560e01c806365f1309711610139578063a22cb465116100b6578063d547cfb71161007a578063d547cfb714610848578063d67072d214610873578063e222c7f91461089c578063e985e9c5146108b3578063f2fde38b146108f0578063f4e0d9ac1461091957610251565b8063a22cb46514610770578063aa922c9814610799578063b88d4fde146107c4578063c08dfd3c146107e0578063c87b56dd1461080b57610251565b806386a173ee116100fd57806386a173ee146106c15780638bb64a8c146106ec5780638da5cb5b146107035780638f29a7d31461072e57806395d89b411461074557610251565b806365f13097146105f057806370a082311461061b578063715018a6146106585780637cb647591461066f578063813f767a1461069857610251565b806323bfe592116101d25780633a1fe75b116101965780633a1fe75b146104ff57806342842e0e1461052a57806349590657146105465780634dd0954d1461057157806360c243c61461059c5780636352211e146105b357610251565b806323bfe5921461041857806332cb6b0c1461045557806333bc1c5c1461048057806336bd21b6146104ab578063372f657c146104d657610251565b8063095ea7b311610219578063095ea7b3146103615780631249c58b1461037d57806318160ddd146103945780631c16521c146103bf57806323b872dd146103fc57610251565b806301ffc9a7146102565780630345e3cb146102935780630675b7c6146102d057806306fdde03146102f9578063081812fc14610324575b600080fd5b34801561026257600080fd5b5061027d60048036038101906102789190612c4f565b610942565b60405161028a9190612c97565b60405180910390f35b34801561029f57600080fd5b506102ba60048036038101906102b59190612d10565b6109d4565b6040516102c79190612d56565b60405180910390f35b3480156102dc57600080fd5b506102f760048036038101906102f29190612eb7565b6109ec565b005b34801561030557600080fd5b5061030e610a07565b60405161031b9190612f7f565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190612fcd565b610a99565b6040516103589190613009565b60405180910390f35b61037b60048036038101906103769190613024565b610b18565b005b34801561038957600080fd5b50610392610c5c565b005b3480156103a057600080fd5b506103a9610e63565b6040516103b69190612d56565b60405180910390f35b3480156103cb57600080fd5b506103e660048036038101906103e19190612d10565b610e7a565b6040516103f39190612d56565b60405180910390f35b61041660048036038101906104119190613064565b610e92565b005b34801561042457600080fd5b5061043f600480360381019061043a9190612d10565b6111b4565b60405161044c9190612d56565b60405180910390f35b34801561046157600080fd5b5061046a6111cc565b6040516104779190612d56565b60405180910390f35b34801561048c57600080fd5b506104956111d2565b6040516104a29190612c97565b60405180910390f35b3480156104b757600080fd5b506104c06111e5565b6040516104cd9190613009565b60405180910390f35b3480156104e257600080fd5b506104fd60048036038101906104f891906131b5565b61120b565b005b34801561050b57600080fd5b5061051461148b565b6040516105219190612d56565b60405180910390f35b610544600480360381019061053f9190613064565b611490565b005b34801561055257600080fd5b5061055b6114b0565b604051610568919061320d565b60405180910390f35b34801561057d57600080fd5b506105866114ba565b6040516105939190613009565b60405180910390f35b3480156105a857600080fd5b506105b16114e0565b005b3480156105bf57600080fd5b506105da60048036038101906105d59190612fcd565b6114f5565b6040516105e79190613009565b60405180910390f35b3480156105fc57600080fd5b50610605611507565b6040516106129190612d56565b60405180910390f35b34801561062757600080fd5b50610642600480360381019061063d9190612d10565b61150c565b60405161064f9190612d56565b60405180910390f35b34801561066457600080fd5b5061066d6115c4565b005b34801561067b57600080fd5b5061069660048036038101906106919190613228565b6115d8565b005b3480156106a457600080fd5b506106bf60048036038101906106ba9190613318565b6115ea565b005b3480156106cd57600080fd5b506106d6611b82565b6040516106e39190612c97565b60405180910390f35b3480156106f857600080fd5b50610701611b95565b005b34801561070f57600080fd5b50610718611bc9565b6040516107259190613009565b60405180910390f35b34801561073a57600080fd5b50610743611bf3565b005b34801561075157600080fd5b5061075a611c27565b6040516107679190612f7f565b60405180910390f35b34801561077c57600080fd5b506107976004803603810190610792919061338d565b611cb9565b005b3480156107a557600080fd5b506107ae611dc4565b6040516107bb9190612c97565b60405180910390f35b6107de60048036038101906107d9919061346e565b611dd7565b005b3480156107ec57600080fd5b506107f5611e4a565b6040516108029190612d56565b60405180910390f35b34801561081757600080fd5b50610832600480360381019061082d9190612fcd565b611e4f565b60405161083f9190612f7f565b60405180910390f35b34801561085457600080fd5b5061085d611ee3565b60405161086a9190612f7f565b60405180910390f35b34801561087f57600080fd5b5061089a60048036038101906108959190612d10565b611f71565b005b3480156108a857600080fd5b506108b1611fbd565b005b3480156108bf57600080fd5b506108da60048036038101906108d591906134f1565b611ff1565b6040516108e79190612c97565b60405180910390f35b3480156108fc57600080fd5b5061091760048036038101906109129190612d10565b612085565b005b34801561092557600080fd5b50610940600480360381019061093b9190612d10565b612108565b005b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061099d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109cd5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600e6020528060005260406000206000915090505481565b6109f4612154565b8060099081610a03919061373d565b5050565b606060028054610a1690613560565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4290613560565b8015610a8f5780601f10610a6457610100808354040283529160200191610a8f565b820191906000526020600020905b815481529060010190602001808311610a7257829003601f168201915b5050505050905090565b6000610aa4826121d2565b610ada576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610b23826114f5565b90508073ffffffffffffffffffffffffffffffffffffffff16610b44612231565b73ffffffffffffffffffffffffffffffffffffffff1614610ba757610b7081610b6b612231565b611ff1565b610ba6576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b826006600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614610cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc190613881565b60405180910390fd5b600b60149054906101000a900460ff16610d19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d1090613913565b60405180910390fd5b6113886001610d26610e63565b610d309190613962565b1115610d71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6890613a08565b60405180910390fd5b600180600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dbe9190613962565b1115610dff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df690613a9a565b60405180910390fd5b6001600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610e4f9190613962565b92505081905550610e61336001612239565b565b6000610e6d612257565b6001546000540303905090565b600d6020528060005260406000206000915090505481565b6000610e9d8261225c565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f04576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f1084612328565b91509150610f268187610f21612231565b61234f565b610f7257610f3b86610f36612231565b611ff1565b610f71576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610fd8576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fe58686866001612393565b8015610ff057600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154600101919050819055506110be8561109a888887612399565b7c0200000000000000000000000000000000000000000000000000000000176123c1565b600460008681526020019081526020016000208190555060007c02000000000000000000000000000000000000000000000000000000008416036111445760006001850190506000600460008381526020019081526020016000205403611142576000548114611141578360046000838152602001908152602001600020819055505b5b505b838573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46111ac86868660016123ec565b505050505050565b600f6020528060005260406000206000915090505481565b61138881565b600b60149054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127090613881565b60405180910390fd5b600b60159054906101000a900460ff166112c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112bf90613b2c565b60405180910390fd5b61138860016112d5610e63565b6112df9190613962565b1115611320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131790613a08565b60405180910390fd5b600180600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136d9190613962565b11156113ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a590613bbe565b60405180910390fd5b6000336040516020016113c19190613c26565b6040516020818303038152906040528051906020012090506113e682600c54836123f2565b611425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141c90613cb3565b60405180910390fd5b6001600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546114759190613962565b92505081905550611487336001612239565b5050565b600a81565b6114ab83838360405180602001604052806000815250611dd7565b505050565b6000600c54905090565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6114e8612154565b6114f3336096612239565b565b60006115008261225c565b9050919050565b600181565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611573576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6115cc612154565b6115d66000612409565b565b6115e0612154565b80600c8190555050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164f90613881565b60405180910390fd5b600b60169054906101000a900460ff166116a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169e90613913565b60405180910390fd5b600a600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054111561172a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172190613a9a565b60405180910390fd5b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016117b39190613009565b6020604051808303816000875af11580156117d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f69190613ce8565b905060008273ffffffffffffffffffffffffffffffffffffffff1663a5b39cfb336040518263ffffffff1660e01b81526004016118339190613009565b6020604051808303816000875af1158015611852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118769190613ce8565b9050600081836118869190613962565b9050600060018214806118995750600282145b156118a75760019050611913565b6002821180156118b75750600582105b156118c55760029050611912565b6004821180156118d55750600882105b156118e35760059050611911565b6007821180156118f35750600a82105b156119015760069050611910565b600982111561190f57600a90505b5b5b5b5b60005b81811015611b7857600088828151811061193357611932613d15565b5b602002602001015190503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b815260040161198d9190612d56565b6020604051808303816000875af11580156119ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d09190613d59565b73ffffffffffffffffffffffffffffffffffffffff16148015611a1157506010600082815260200190815260200160002060009054906101000a900460ff16155b15611a5257611a21336001612239565b60016010600083815260200190815260200160002060006101000a81548160ff021916908315150217905550611b64565b3373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1663f8a14f46836040518263ffffffff1660e01b8152600401611aa29190612d56565b6020604051808303816000875af1158015611ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae59190613d59565b73ffffffffffffffffffffffffffffffffffffffff16148015611b2657506010600082815260200190815260200160002060009054906101000a900460ff16155b15611b6357611b36336001612239565b60016010600083815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5b508080611b7090613d86565b915050611916565b5050505050505050565b600b60159054906101000a900460ff1681565b611b9d612154565b600b60159054906101000a900460ff1615600b60156101000a81548160ff021916908315150217905550565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611bfb612154565b600b60169054906101000a900460ff1615600b60166101000a81548160ff021916908315150217905550565b606060038054611c3690613560565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6290613560565b8015611caf5780601f10611c8457610100808354040283529160200191611caf565b820191906000526020600020905b815481529060010190602001808311611c9257829003601f168201915b5050505050905090565b8060076000611cc6612231565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611d73612231565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611db89190612c97565b60405180910390a35050565b600b60169054906101000a900460ff1681565b611de2848484610e92565b60008373ffffffffffffffffffffffffffffffffffffffff163b14611e4457611e0d848484846124cf565b611e43576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b600181565b6060611e5a826121d2565b611e99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9090613e40565b60405180910390fd5b6000600183611ea89190613962565b9050611eb261261f565b611ebb826126b1565b604051602001611ecc929190613ee8565b604051602081830303815290604052915050919050565b60098054611ef090613560565b80601f0160208091040260200160405190810160405280929190818152602001828054611f1c90613560565b8015611f695780601f10611f3e57610100808354040283529160200191611f69565b820191906000526020600020905b815481529060010190602001808311611f4c57829003601f168201915b505050505081565b611f79612154565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611fc5612154565b600b60149054906101000a900460ff1615600b60146101000a81548160ff021916908315150217905550565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61208d612154565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036120fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f390613f89565b60405180910390fd5b61210581612409565b50565b612110612154565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61215c61277f565b73ffffffffffffffffffffffffffffffffffffffff1661217a611bc9565b73ffffffffffffffffffffffffffffffffffffffff16146121d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121c790613ff5565b60405180910390fd5b565b6000816121dd612257565b111580156121ec575060005482105b801561222a575060007c0100000000000000000000000000000000000000000000000000000000600460008581526020019081526020016000205416145b9050919050565b600033905090565b612253828260405180602001604052806000815250612787565b5050565b600090565b6000808290508061226b612257565b116122f1576000548110156122f05760006004600083815260200190815260200160002054905060007c01000000000000000000000000000000000000000000000000000000008216036122ee575b600081036122e45760046000836001900393508381526020019081526020016000205490506122ba565b8092505050612323565b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e86123b0868684612824565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000826123ff858461282d565b1490509392505050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026124f5612231565b8786866040518563ffffffff1660e01b8152600401612517949392919061406a565b6020604051808303816000875af192505050801561255357506040513d601f19601f8201168201806040525081019061255091906140cb565b60015b6125cc573d8060008114612583576040519150601f19603f3d011682016040523d82523d6000602084013e612588565b606091505b5060008151036125c4576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b60606009805461262e90613560565b80601f016020809104026020016040519081016040528092919081815260200182805461265a90613560565b80156126a75780601f1061267c576101008083540402835291602001916126a7565b820191906000526020600020905b81548152906001019060200180831161268a57829003601f168201915b5050505050905090565b6060600060016126c084612883565b01905060008167ffffffffffffffff8111156126df576126de612d8c565b5b6040519080825280601f01601f1916602001820160405280156127115781602001600182028036833780820191505090505b509050600082602001820190505b600115612774578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612768576127676140f8565b5b0494506000850361271f575b819350505050919050565b600033905090565b61279183836129d6565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461281f57600080549050600083820390505b6127d160008683806001019450866124cf565b612807576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181106127be57816000541461281c57600080fd5b50505b505050565b60009392505050565b60008082905060005b8451811015612878576128638286838151811061285657612855613d15565b5b6020026020010151612b91565b9150808061287090613d86565b915050612836565b508091505092915050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106128e1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816128d7576128d66140f8565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061291e576d04ee2d6d415b85acef81000000008381612914576129136140f8565b5b0492506020810190505b662386f26fc10000831061294d57662386f26fc100008381612943576129426140f8565b5b0492506010810190505b6305f5e1008310612976576305f5e100838161296c5761296b6140f8565b5b0492506008810190505b612710831061299b576127108381612991576129906140f8565b5b0492506004810190505b606483106129be57606483816129b4576129b36140f8565b5b0492506002810190505b600a83106129cd576001810190505b80915050919050565b60008054905060008203612a16576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a236000848385612393565b600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550612a9a83612a8b6000866000612399565b612a9485612bbc565b176123c1565b6004600083815260200190815260200160002081905550600080838301905073ffffffffffffffffffffffffffffffffffffffff85169150828260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600183015b818114612b3b57808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4600181019050612b00565b5060008203612b76576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000819055505050612b8c60008483856123ec565b505050565b6000818310612ba957612ba48284612bcc565b612bb4565b612bb38383612bcc565b5b905092915050565b60006001821460e11b9050919050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612c2c81612bf7565b8114612c3757600080fd5b50565b600081359050612c4981612c23565b92915050565b600060208284031215612c6557612c64612bed565b5b6000612c7384828501612c3a565b91505092915050565b60008115159050919050565b612c9181612c7c565b82525050565b6000602082019050612cac6000830184612c88565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612cdd82612cb2565b9050919050565b612ced81612cd2565b8114612cf857600080fd5b50565b600081359050612d0a81612ce4565b92915050565b600060208284031215612d2657612d25612bed565b5b6000612d3484828501612cfb565b91505092915050565b6000819050919050565b612d5081612d3d565b82525050565b6000602082019050612d6b6000830184612d47565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612dc482612d7b565b810181811067ffffffffffffffff82111715612de357612de2612d8c565b5b80604052505050565b6000612df6612be3565b9050612e028282612dbb565b919050565b600067ffffffffffffffff821115612e2257612e21612d8c565b5b612e2b82612d7b565b9050602081019050919050565b82818337600083830152505050565b6000612e5a612e5584612e07565b612dec565b905082815260208101848484011115612e7657612e75612d76565b5b612e81848285612e38565b509392505050565b600082601f830112612e9e57612e9d612d71565b5b8135612eae848260208601612e47565b91505092915050565b600060208284031215612ecd57612ecc612bed565b5b600082013567ffffffffffffffff811115612eeb57612eea612bf2565b5b612ef784828501612e89565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612f3a578082015181840152602081019050612f1f565b60008484015250505050565b6000612f5182612f00565b612f5b8185612f0b565b9350612f6b818560208601612f1c565b612f7481612d7b565b840191505092915050565b60006020820190508181036000830152612f998184612f46565b905092915050565b612faa81612d3d565b8114612fb557600080fd5b50565b600081359050612fc781612fa1565b92915050565b600060208284031215612fe357612fe2612bed565b5b6000612ff184828501612fb8565b91505092915050565b61300381612cd2565b82525050565b600060208201905061301e6000830184612ffa565b92915050565b6000806040838503121561303b5761303a612bed565b5b600061304985828601612cfb565b925050602061305a85828601612fb8565b9150509250929050565b60008060006060848603121561307d5761307c612bed565b5b600061308b86828701612cfb565b935050602061309c86828701612cfb565b92505060406130ad86828701612fb8565b9150509250925092565b600067ffffffffffffffff8211156130d2576130d1612d8c565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b6130fb816130e8565b811461310657600080fd5b50565b600081359050613118816130f2565b92915050565b600061313161312c846130b7565b612dec565b90508083825260208201905060208402830185811115613154576131536130e3565b5b835b8181101561317d57806131698882613109565b845260208401935050602081019050613156565b5050509392505050565b600082601f83011261319c5761319b612d71565b5b81356131ac84826020860161311e565b91505092915050565b6000602082840312156131cb576131ca612bed565b5b600082013567ffffffffffffffff8111156131e9576131e8612bf2565b5b6131f584828501613187565b91505092915050565b613207816130e8565b82525050565b600060208201905061322260008301846131fe565b92915050565b60006020828403121561323e5761323d612bed565b5b600061324c84828501613109565b91505092915050565b600067ffffffffffffffff8211156132705761326f612d8c565b5b602082029050602081019050919050565b600061329461328f84613255565b612dec565b905080838252602082019050602084028301858111156132b7576132b66130e3565b5b835b818110156132e057806132cc8882612fb8565b8452602084019350506020810190506132b9565b5050509392505050565b600082601f8301126132ff576132fe612d71565b5b813561330f848260208601613281565b91505092915050565b60006020828403121561332e5761332d612bed565b5b600082013567ffffffffffffffff81111561334c5761334b612bf2565b5b613358848285016132ea565b91505092915050565b61336a81612c7c565b811461337557600080fd5b50565b60008135905061338781613361565b92915050565b600080604083850312156133a4576133a3612bed565b5b60006133b285828601612cfb565b92505060206133c385828601613378565b9150509250929050565b600067ffffffffffffffff8211156133e8576133e7612d8c565b5b6133f182612d7b565b9050602081019050919050565b600061341161340c846133cd565b612dec565b90508281526020810184848401111561342d5761342c612d76565b5b613438848285612e38565b509392505050565b600082601f83011261345557613454612d71565b5b81356134658482602086016133fe565b91505092915050565b6000806000806080858703121561348857613487612bed565b5b600061349687828801612cfb565b94505060206134a787828801612cfb565b93505060406134b887828801612fb8565b925050606085013567ffffffffffffffff8111156134d9576134d8612bf2565b5b6134e587828801613440565b91505092959194509250565b6000806040838503121561350857613507612bed565b5b600061351685828601612cfb565b925050602061352785828601612cfb565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061357857607f821691505b60208210810361358b5761358a613531565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135f37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826135b6565b6135fd86836135b6565b95508019841693508086168417925050509392505050565b6000819050919050565b600061363a61363561363084612d3d565b613615565b612d3d565b9050919050565b6000819050919050565b6136548361361f565b61366861366082613641565b8484546135c3565b825550505050565b600090565b61367d613670565b61368881848461364b565b505050565b5b818110156136ac576136a1600082613675565b60018101905061368e565b5050565b601f8211156136f1576136c281613591565b6136cb846135a6565b810160208510156136da578190505b6136ee6136e6856135a6565b83018261368d565b50505b505050565b600082821c905092915050565b6000613714600019846008026136f6565b1980831691505092915050565b600061372d8383613703565b9150826002028217905092915050565b61374682612f00565b67ffffffffffffffff81111561375f5761375e612d8c565b5b6137698254613560565b6137748282856136b0565b600060209050601f8311600181146137a75760008415613795578287015190505b61379f8582613721565b865550613807565b601f1984166137b586613591565b60005b828110156137dd578489015182556001820191506020850194506020810190506137b8565b868310156137fa57848901516137f6601f891682613703565b8355505b6001600288020188555050505b505050505050565b7f5370726f75742041636164656d79203a3a2043616e6e6f742062652063616c6c60008201527f6564206279206120636f6e747261637400000000000000000000000000000000602082015250565b600061386b603083612f0b565b91506138768261380f565b604082019050919050565b6000602082019050818103600083015261389a8161385e565b9050919050565b7f5370726f75742041636164656d79203a3a204e6f74205965742041637469766560008201527f2e00000000000000000000000000000000000000000000000000000000000000602082015250565b60006138fd602183612f0b565b9150613908826138a1565b604082019050919050565b6000602082019050818103600083015261392c816138f0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061396d82612d3d565b915061397883612d3d565b92508282019050808211156139905761398f613933565b5b92915050565b7f5370726f75742041636164656d79203a3a2043616e6e6f74206d696e7420626560008201527f796f6e64206d617820737570706c790000000000000000000000000000000000602082015250565b60006139f2602f83612f0b565b91506139fd82613996565b604082019050919050565b60006020820190508181036000830152613a21816139e5565b9050919050565b7f5370726f75742041636164656d79203a3a20416c7265616479206d696e74656460008201527f206d6178696d756d2074696d6573210000000000000000000000000000000000602082015250565b6000613a84602f83612f0b565b9150613a8f82613a28565b604082019050919050565b60006020820190508181036000830152613ab381613a77565b9050919050565b7f5370726f75742041636164656d79203a3a204d696e74696e67206973206f6e2060008201527f5061757365000000000000000000000000000000000000000000000000000000602082015250565b6000613b16602583612f0b565b9150613b2182613aba565b604082019050919050565b60006020820190508181036000830152613b4581613b09565b9050919050565b7f5370726f75742041636164656d79203a3a2043616e6e6f74206d696e7420626560008201527f796f6e642077686974656c697374206d6178206d696e74210000000000000000602082015250565b6000613ba8603883612f0b565b9150613bb382613b4c565b604082019050919050565b60006020820190508181036000830152613bd781613b9b565b9050919050565b60008160601b9050919050565b6000613bf682613bde565b9050919050565b6000613c0882613beb565b9050919050565b613c20613c1b82612cd2565b613bfd565b82525050565b6000613c328284613c0f565b60148201915081905092915050565b7f5370726f75742041636164656d79203a3a20596f7520617265206e6f74206f6e60008201527f20746865205370726f75746c6973740000000000000000000000000000000000602082015250565b6000613c9d602f83612f0b565b9150613ca882613c41565b604082019050919050565b60006020820190508181036000830152613ccc81613c90565b9050919050565b600081519050613ce281612fa1565b92915050565b600060208284031215613cfe57613cfd612bed565b5b6000613d0c84828501613cd3565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050613d5381612ce4565b92915050565b600060208284031215613d6f57613d6e612bed565b5b6000613d7d84828501613d44565b91505092915050565b6000613d9182612d3d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613dc357613dc2613933565b5b600182019050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613e2a602f83612f0b565b9150613e3582613dce565b604082019050919050565b60006020820190508181036000830152613e5981613e1d565b9050919050565b600081905092915050565b6000613e7682612f00565b613e808185613e60565b9350613e90818560208601612f1c565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000613ed2600583613e60565b9150613edd82613e9c565b600582019050919050565b6000613ef48285613e6b565b9150613f008284613e6b565b9150613f0b82613ec5565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000613f73602683612f0b565b9150613f7e82613f17565b604082019050919050565b60006020820190508181036000830152613fa281613f66565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000613fdf602083612f0b565b9150613fea82613fa9565b602082019050919050565b6000602082019050818103600083015261400e81613fd2565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061403c82614015565b6140468185614020565b9350614056818560208601612f1c565b61405f81612d7b565b840191505092915050565b600060808201905061407f6000830187612ffa565b61408c6020830186612ffa565b6140996040830185612d47565b81810360608301526140ab8184614031565b905095945050505050565b6000815190506140c581612c23565b92915050565b6000602082840312156140e1576140e0612bed565b5b60006140ef848285016140b6565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212203fd71cccc3897ff9bbd31b60a973fee938dc31d4a1c0232036d11628c673344064736f6c63430008110033

Deployed Bytecode Sourcemap

79474:5607:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46021:639;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80079:53;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84456:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;46923:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53414:218;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;52847:408;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;82148:420;;;;;;;;;;;;;:::i;:::-;;42674:323;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80022:50;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;57053:2825;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;80139:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79569:41;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79897:22;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79806:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;82576:704;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79720:42;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;59974:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;84692:92;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79847:41;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83288:89;;;;;;;;;;;;;:::i;:::-;;48316:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79617:43;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;43858:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;26800:103;;;;;;;;;;;;;:::i;:::-;;84579:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;80467:1673;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79926:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84792:98;;;;;;;;;;;;;:::i;:::-;;26152:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84995:83;;;;;;;;;;;;;:::i;:::-;;47099:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53972:234;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79958:20;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60765:407;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79667:46;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84093:355;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79771:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83666:125;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;84898:89;;;;;;;;;;;;;:::i;:::-;;54363:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;27058:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;83915:134;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;46021:639;46106:4;46445:10;46430:25;;:11;:25;;;;:102;;;;46522:10;46507:25;;:11;:25;;;;46430:102;:179;;;;46599:10;46584:25;;:11;:25;;;;46430:179;46410:199;;46021:639;;;:::o;80079:53::-;;;;;;;;;;;;;;;;;:::o;84456:115::-;26038:13;:11;:13::i;:::-;84550::::1;84535:12;:28;;;;;;:::i;:::-;;84456:115:::0;:::o;46923:100::-;46977:13;47010:5;47003:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46923:100;:::o;53414:218::-;53490:7;53515:16;53523:7;53515;:16::i;:::-;53510:64;;53540:34;;;;;;;;;;;;;;53510:64;53594:15;:24;53610:7;53594:24;;;;;;;;;;;:30;;;;;;;;;;;;53587:37;;53414:218;;;:::o;52847:408::-;52936:13;52952:16;52960:7;52952;:16::i;:::-;52936:32;;53008:5;52985:28;;:19;:17;:19::i;:::-;:28;;;52981:175;;53033:44;53050:5;53057:19;:17;:19::i;:::-;53033:16;:44::i;:::-;53028:128;;53105:35;;;;;;;;;;;;;;53028:128;52981:175;53201:2;53168:15;:24;53184:7;53168:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;53239:7;53235:2;53219:28;;53228:5;53219:28;;;;;;;;;;;;52925:330;52847:408;;:::o;82148:420::-;80376:10;80363:23;;:9;:23;;;80355:84;;;;;;;;;;;;:::i;:::-;;;;;;;;;82205:10:::1;;;;;;;;;;;82197:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;79606:4;82289:1;82273:13;:11;:13::i;:::-;:17;;;;:::i;:::-;82272:33;;82264:93;;;;;;;;;;;;:::i;:::-;;;;;;;;;79659:1;82407::::0;82377:15:::1;:27;82393:10;82377:27;;;;;;;;;;;;;;;;:31;;;;:::i;:::-;82376:52;;82368:112;;;;;;;;;;;;:::i;:::-;;;;;;;;;82524:1;82493:15;:27;82509:10;82493:27;;;;;;;;;;;;;;;;:32;;;;;;;:::i;:::-;;;;;;;;82536:24;82546:10;82558:1;82536:9;:24::i;:::-;82148:420::o:0;42674:323::-;42735:7;42963:15;:13;:15::i;:::-;42948:12;;42932:13;;:28;:46;42925:53;;42674:323;:::o;80022:50::-;;;;;;;;;;;;;;;;;:::o;57053:2825::-;57195:27;57225;57244:7;57225:18;:27::i;:::-;57195:57;;57310:4;57269:45;;57285:19;57269:45;;;57265:86;;57323:28;;;;;;;;;;;;;;57265:86;57365:27;57394:23;57421:35;57448:7;57421:26;:35::i;:::-;57364:92;;;;57556:68;57581:15;57598:4;57604:19;:17;:19::i;:::-;57556:24;:68::i;:::-;57551:180;;57644:43;57661:4;57667:19;:17;:19::i;:::-;57644:16;:43::i;:::-;57639:92;;57696:35;;;;;;;;;;;;;;57639:92;57551:180;57762:1;57748:16;;:2;:16;;;57744:52;;57773:23;;;;;;;;;;;;;;57744:52;57809:43;57831:4;57837:2;57841:7;57850:1;57809:21;:43::i;:::-;57945:15;57942:160;;;58085:1;58064:19;58057:30;57942:160;58482:18;:24;58501:4;58482:24;;;;;;;;;;;;;;;;58480:26;;;;;;;;;;;;58551:18;:22;58570:2;58551:22;;;;;;;;;;;;;;;;58549:24;;;;;;;;;;;58873:146;58910:2;58959:45;58974:4;58980:2;58984:19;58959:14;:45::i;:::-;39073:8;58931:73;58873:18;:146::i;:::-;58844:17;:26;58862:7;58844:26;;;;;;;;;;;:175;;;;59190:1;39073:8;59139:19;:47;:52;59135:627;;59212:19;59244:1;59234:7;:11;59212:33;;59401:1;59367:17;:30;59385:11;59367:30;;;;;;;;;;;;:35;59363:384;;59505:13;;59490:11;:28;59486:242;;59685:19;59652:17;:30;59670:11;59652:30;;;;;;;;;;;:52;;;;59486:242;59363:384;59193:569;59135:627;59809:7;59805:2;59790:27;;59799:4;59790:27;;;;;;;;;;;;59828:42;59849:4;59855:2;59859:7;59868:1;59828:20;:42::i;:::-;57184:2694;;;57053:2825;;;:::o;80139:48::-;;;;;;;;;;;;;;;;;:::o;79569:41::-;79606:4;79569:41;:::o;79897:22::-;;;;;;;;;;;;;:::o;79806:34::-;;;;;;;;;;;;;:::o;82576:704::-;80376:10;80363:23;;:9;:23;;;80355:84;;;;;;;;;;;;:::i;:::-;;;;;;;;;82671:13:::1;;;;;;;;;;;82663:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;79606:4;82762:1;82746:13;:11;:13::i;:::-;:17;;;;:::i;:::-;82745:33;;82737:93;;;;;;;;;;;;:::i;:::-;;;;;;;;;79712:1;82883::::0;82850:18:::1;:30;82869:10;82850:30;;;;;;;;;;;;;;;;:34;;;;:::i;:::-;82849:59;;82841:128;;;;;;;;;;;;:::i;:::-;;;;;;;;;83010:14;83054:10;83037:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;83027:39;;;;;;83010:56;;83085:52;83104:12;83118:10;;83130:6;83085:18;:52::i;:::-;83077:112;;;;;;;;;;;;:::i;:::-;;;;;;;;;83236:1;83202:18;:30;83221:10;83202:30;;;;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;;;;;83248:24;83258:10;83270:1;83248:9;:24::i;:::-;82652:628;82576:704:::0;:::o;79720:42::-;79760:2;79720:42;:::o;59974:193::-;60120:39;60137:4;60143:2;60147:7;60120:39;;;;;;;;;;;;:16;:39::i;:::-;59974:193;;;:::o;84692:92::-;84740:7;84766:10;;84759:17;;84692:92;:::o;79847:41::-;;;;;;;;;;;;;:::o;83288:89::-;26038:13;:11;:13::i;:::-;83343:26:::1;83353:10;83365:3;83343:9;:26::i;:::-;83288:89::o:0;48316:152::-;48388:7;48431:27;48450:7;48431:18;:27::i;:::-;48408:52;;48316:152;;;:::o;79617:43::-;79659:1;79617:43;:::o;43858:233::-;43930:7;43971:1;43954:19;;:5;:19;;;43950:60;;43982:28;;;;;;;;;;;;;;43950:60;38017:13;44028:18;:25;44047:5;44028:25;;;;;;;;;;;;;;;;:55;44021:62;;43858:233;;;:::o;26800:103::-;26038:13;:11;:13::i;:::-;26865:30:::1;26892:1;26865:18;:30::i;:::-;26800:103::o:0;84579:105::-;26038:13;:11;:13::i;:::-;84665:11:::1;84652:10;:24;;;;84579:105:::0;:::o;80467:1673::-;80376:10;80363:23;;:9;:23;;;80355:84;;;;;;;;;;;;:::i;:::-;;;;;;;;;80553:8:::1;;;;;;;;;;;80545:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;79760:2;80619:13;:25;80633:10;80619:25;;;;;;;;;;;;;;;;80618:44;;80610:104;;;;;;;;;;;;:::i;:::-;;;;;;;;;80727:10;80746:19;;;;;;;;;;;80727:39;;80777:25;80818:26;;;;;;;;;;;80777:68;;80858:17;80878:4;:14;;;80893:10;80878:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80858:46;;80915:20;80938:12;:25;;;80964:10;80938:37;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80915:60;;80988:22;81025:12;81013:9;:24;;;;:::i;:::-;80988:49;;81048:23;81109:1;81091:14;:19;:42;;;;81132:1;81114:14;:19;81091:42;81088:497;;;81168:1;81150:19;;81088:497;;;81216:1;81199:14;:18;:40;;;;;81238:1;81221:14;:18;81199:40;81196:389;;;81274:1;81256:19;;81196:389;;;81322:1;81305:14;:18;:40;;;;;81344:1;81327:14;:18;81305:40;81302:283;;;81380:1;81362:19;;81302:283;;;81428:1;81411:14;:18;:41;;;;;81450:2;81433:14;:19;81411:41;81408:177;;;81487:1;81469:19;;81408:177;;;81535:1;81518:14;:18;81515:70;;;81571:2;81553:20;;81515:70;81408:177;81302:283;81196:389;81088:497;81602:9;81597:536;81617:15;81613:1;:19;81597:536;;;81654:19;81676:8;81685:1;81676:11;;;;;;;;:::i;:::-;;;;;;;;81654:33;;81735:10;81706:39;;:4;:12;;;81719:11;81706:25;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:39;;;:73;;;;;81750:16;:29;81767:11;81750:29;;;;;;;;;;;;;;;;;;;;;81749:30;81706:73;81702:420;;;81800:24;81810:10;81822:1;81800:9;:24::i;:::-;81877:4;81845:16;:29;81862:11;81845:29;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;81702:420;;;81960:10;81919:51;;:12;:24;;;81944:11;81919:37;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;;;:85;;;;;81975:16;:29;81992:11;81975:29;;;;;;;;;;;;;;;;;;;;;81974:30;81919:85;81916:206;;;82025:24;82035:10;82047:1;82025:9;:24::i;:::-;82102:4;82070:16;:29;82087:11;82070:29;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;81916:206;81702:420;81639:494;81634:3;;;;;:::i;:::-;;;;81597:536;;;;80534:1606;;;;;;80467:1673:::0;:::o;79926:25::-;;;;;;;;;;;;;:::o;84792:98::-;26038:13;:11;:13::i;:::-;84869::::1;;;;;;;;;;;84868:14;84852:13;;:30;;;;;;;;;;;;;;;;;;84792:98::o:0;26152:87::-;26198:7;26225:6;;;;;;;;;;;26218:13;;26152:87;:::o;84995:83::-;26038:13;:11;:13::i;:::-;85062:8:::1;;;;;;;;;;;85061:9;85050:8;;:20;;;;;;;;;;;;;;;;;;84995:83::o:0;47099:104::-;47155:13;47188:7;47181:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47099:104;:::o;53972:234::-;54119:8;54067:18;:39;54086:19;:17;:19::i;:::-;54067:39;;;;;;;;;;;;;;;:49;54107:8;54067:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;54179:8;54143:55;;54158:19;:17;:19::i;:::-;54143:55;;;54189:8;54143:55;;;;;;:::i;:::-;;;;;;;;53972:234;;:::o;79958:20::-;;;;;;;;;;;;;:::o;60765:407::-;60940:31;60953:4;60959:2;60963:7;60940:12;:31::i;:::-;61004:1;60986:2;:14;;;:19;60982:183;;61025:56;61056:4;61062:2;61066:7;61075:5;61025:30;:56::i;:::-;61020:145;;61109:40;;;;;;;;;;;;;;61020:145;60982:183;60765:407;;;;:::o;79667:46::-;79712:1;79667:46;:::o;84093:355::-;84166:13;84200:16;84208:7;84200;:16::i;:::-;84192:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;84281:14;84308:1;84298:7;:11;;;;:::i;:::-;84281:28;;84400:10;:8;:10::i;:::-;84412:17;:6;:15;:17::i;:::-;84383:56;;;;;;;;;:::i;:::-;;;;;;;;;;;;;84369:71;;;84093:355;;;:::o;79771:26::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;83666:125::-;26038:13;:11;:13::i;:::-;83774:11:::1;83752:19;;:33;;;;;;;;;;;;;;;;;;83666:125:::0;:::o;84898:89::-;26038:13;:11;:13::i;:::-;84969:10:::1;;;;;;;;;;;84968:11;84955:10;;:24;;;;;;;;;;;;;;;;;;84898:89::o:0;54363:164::-;54460:4;54484:18;:25;54503:5;54484:25;;;;;;;;;;;;;;;:35;54510:8;54484:35;;;;;;;;;;;;;;;;;;;;;;;;;54477:42;;54363:164;;;;:::o;27058:201::-;26038:13;:11;:13::i;:::-;27167:1:::1;27147:22;;:8;:22;;::::0;27139:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;27223:28;27242:8;27223:18;:28::i;:::-;27058:201:::0;:::o;83915:134::-;26038:13;:11;:13::i;:::-;84025:18:::1;83996:26;;:47;;;;;;;;;;;;;;;;;;83915:134:::0;:::o;26317:132::-;26392:12;:10;:12::i;:::-;26381:23;;:7;:5;:7::i;:::-;:23;;;26373:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;26317:132::o;54785:282::-;54850:4;54906:7;54887:15;:13;:15::i;:::-;:26;;:66;;;;;54940:13;;54930:7;:23;54887:66;:153;;;;;55039:1;38793:8;54991:17;:26;55009:7;54991:26;;;;;;;;;;;;:44;:49;54887:153;54867:173;;54785:282;;;:::o;77093:105::-;77153:7;77180:10;77173:17;;77093:105;:::o;70925:112::-;71002:27;71012:2;71016:8;71002:27;;;;;;;;;;;;:9;:27::i;:::-;70925:112;;:::o;42190:92::-;42246:7;42190:92;:::o;49471:1275::-;49538:7;49558:12;49573:7;49558:22;;49641:4;49622:15;:13;:15::i;:::-;:23;49618:1061;;49675:13;;49668:4;:20;49664:1015;;;49713:14;49730:17;:23;49748:4;49730:23;;;;;;;;;;;;49713:40;;49847:1;38793:8;49819:6;:24;:29;49815:845;;50484:113;50501:1;50491:6;:11;50484:113;;50544:17;:25;50562:6;;;;;;;50544:25;;;;;;;;;;;;50535:34;;50484:113;;;50630:6;50623:13;;;;;;49815:845;49690:989;49664:1015;49618:1061;50707:31;;;;;;;;;;;;;;49471:1275;;;;:::o;55948:485::-;56050:27;56079:23;56120:38;56161:15;:24;56177:7;56161:24;;;;;;;;;;;56120:65;;56338:18;56315:41;;56395:19;56389:26;56370:45;;56300:126;55948:485;;;:::o;55176:659::-;55325:11;55490:16;55483:5;55479:28;55470:37;;55650:16;55639:9;55635:32;55622:45;;55800:15;55789:9;55786:30;55778:5;55767:9;55764:20;55761:56;55751:66;;55176:659;;;;;:::o;61834:159::-;;;;;:::o;76402:311::-;76537:7;76557:16;39197:3;76583:19;:41;;76557:68;;39197:3;76651:31;76662:4;76668:2;76672:9;76651:10;:31::i;:::-;76643:40;;:62;;76636:69;;;76402:311;;;;;:::o;51294:450::-;51374:14;51542:16;51535:5;51531:28;51522:37;;51719:5;51705:11;51680:23;51676:41;51673:52;51666:5;51663:63;51653:73;;51294:450;;;;:::o;62658:158::-;;;;;:::o;16518:190::-;16643:4;16696;16667:25;16680:5;16687:4;16667:12;:25::i;:::-;:33;16660:40;;16518:190;;;;;:::o;27419:191::-;27493:16;27512:6;;;;;;;;;;;27493:25;;27538:8;27529:6;;:17;;;;;;;;;;;;;;;;;;27593:8;27562:40;;27583:8;27562:40;;;;;;;;;;;;27482:128;27419:191;:::o;63256:716::-;63419:4;63465:2;63440:45;;;63486:19;:17;:19::i;:::-;63507:4;63513:7;63522:5;63440:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;63436:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63740:1;63723:6;:13;:18;63719:235;;63769:40;;;;;;;;;;;;;;63719:235;63912:6;63906:13;63897:6;63893:2;63889:15;63882:38;63436:529;63609:54;;;63599:64;;;:6;:64;;;;63592:71;;;63256:716;;;;;;:::o;83444:107::-;83504:13;83533:12;83526:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83444:107;:::o;13383:727::-;13439:13;13490:14;13538:1;13507:28;13529:5;13507:21;:28::i;:::-;:32;13490:49;;13554:20;13588:6;13577:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13554:41;;13610:11;13739:6;13735:2;13731:15;13723:6;13719:28;13712:35;;13776:288;13783:4;13776:288;;;13808:5;;;;;;;;13950:8;13945:2;13938:5;13934:14;13929:30;13924:3;13916:44;14006:2;13997:11;;;;;;:::i;:::-;;;;;14040:1;14031:5;:10;13776:288;14027:21;13776:288;14085:6;14078:13;;;;;13383:727;;;:::o;24703:98::-;24756:7;24783:10;24776:17;;24703:98;:::o;70152:689::-;70283:19;70289:2;70293:8;70283:5;:19::i;:::-;70362:1;70344:2;:14;;;:19;70340:483;;70384:11;70398:13;;70384:27;;70430:13;70452:8;70446:3;:14;70430:30;;70479:233;70510:62;70549:1;70553:2;70557:7;;;;;;70566:5;70510:30;:62::i;:::-;70505:167;;70608:40;;;;;;;;;;;;;;70505:167;70707:3;70699:5;:11;70479:233;;70794:3;70777:13;;:20;70773:34;;70799:8;;;70773:34;70365:458;;70340:483;70152:689;;;:::o;76103:147::-;76240:6;76103:147;;;;;:::o;17385:296::-;17468:7;17488:20;17511:4;17488:27;;17531:9;17526:118;17550:5;:12;17546:1;:16;17526:118;;;17599:33;17609:12;17623:5;17629:1;17623:8;;;;;;;;:::i;:::-;;;;;;;;17599:9;:33::i;:::-;17584:48;;17564:3;;;;;:::i;:::-;;;;17526:118;;;;17661:12;17654:19;;;17385:296;;;;:::o;10210:922::-;10263:7;10283:14;10300:1;10283:18;;10350:6;10341:5;:15;10337:102;;10386:6;10377:15;;;;;;:::i;:::-;;;;;10421:2;10411:12;;;;10337:102;10466:6;10457:5;:15;10453:102;;10502:6;10493:15;;;;;;:::i;:::-;;;;;10537:2;10527:12;;;;10453:102;10582:6;10573:5;:15;10569:102;;10618:6;10609:15;;;;;;:::i;:::-;;;;;10653:2;10643:12;;;;10569:102;10698:5;10689;:14;10685:99;;10733:5;10724:14;;;;;;:::i;:::-;;;;;10767:1;10757:11;;;;10685:99;10811:5;10802;:14;10798:99;;10846:5;10837:14;;;;;;:::i;:::-;;;;;10880:1;10870:11;;;;10798:99;10924:5;10915;:14;10911:99;;10959:5;10950:14;;;;;;:::i;:::-;;;;;10993:1;10983:11;;;;10911:99;11037:5;11028;:14;11024:66;;11073:1;11063:11;;;;11024:66;11118:6;11111:13;;;10210:922;;;:::o;64434:2966::-;64507:20;64530:13;;64507:36;;64570:1;64558:8;:13;64554:44;;64580:18;;;;;;;;;;;;;;64554:44;64611:61;64641:1;64645:2;64649:12;64663:8;64611:21;:61::i;:::-;65155:1;38155:2;65125:1;:26;;65124:32;65112:8;:45;65086:18;:22;65105:2;65086:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;65434:139;65471:2;65525:33;65548:1;65552:2;65556:1;65525:14;:33::i;:::-;65492:30;65513:8;65492:20;:30::i;:::-;:66;65434:18;:139::i;:::-;65400:17;:31;65418:12;65400:31;;;;;;;;;;;:173;;;;65590:16;65621:11;65650:8;65635:12;:23;65621:37;;66171:16;66167:2;66163:25;66151:37;;66543:12;66503:8;66462:1;66400:25;66341:1;66280;66253:335;66914:1;66900:12;66896:20;66854:346;66955:3;66946:7;66943:16;66854:346;;67173:7;67163:8;67160:1;67133:25;67130:1;67127;67122:59;67008:1;66999:7;66995:15;66984:26;;66854:346;;;66858:77;67245:1;67233:8;:13;67229:45;;67255:19;;;;;;;;;;;;;;67229:45;67307:3;67291:13;:19;;;;64860:2462;;67332:60;67361:1;67365:2;67369:12;67383:8;67332:20;:60::i;:::-;64496:2904;64434:2966;;:::o;23592:149::-;23655:7;23686:1;23682;:5;:51;;23713:20;23728:1;23731;23713:14;:20::i;:::-;23682:51;;;23690:20;23705:1;23708;23690:14;:20::i;:::-;23682:51;23675:58;;23592:149;;;;:::o;51846:324::-;51916:14;52149:1;52139:8;52136:15;52110:24;52106:46;52096:56;;51846:324;;;:::o;23749:268::-;23817:13;23924:1;23918:4;23911:15;23953:1;23947:4;23940:15;23994:4;23988;23978:21;23969:30;;23749:268;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:126::-;1555:7;1595:42;1588:5;1584:54;1573:65;;1518:126;;;:::o;1650:96::-;1687:7;1716:24;1734:5;1716:24;:::i;:::-;1705:35;;1650:96;;;:::o;1752:122::-;1825:24;1843:5;1825:24;:::i;:::-;1818:5;1815:35;1805:63;;1864:1;1861;1854:12;1805:63;1752:122;:::o;1880:139::-;1926:5;1964:6;1951:20;1942:29;;1980:33;2007:5;1980:33;:::i;:::-;1880:139;;;;:::o;2025:329::-;2084:6;2133:2;2121:9;2112:7;2108:23;2104:32;2101:119;;;2139:79;;:::i;:::-;2101:119;2259:1;2284:53;2329:7;2320:6;2309:9;2305:22;2284:53;:::i;:::-;2274:63;;2230:117;2025:329;;;;:::o;2360:77::-;2397:7;2426:5;2415:16;;2360:77;;;:::o;2443:118::-;2530:24;2548:5;2530:24;:::i;:::-;2525:3;2518:37;2443:118;;:::o;2567:222::-;2660:4;2698:2;2687:9;2683:18;2675:26;;2711:71;2779:1;2768:9;2764:17;2755:6;2711:71;:::i;:::-;2567:222;;;;:::o;2795:117::-;2904:1;2901;2894:12;2918:117;3027:1;3024;3017:12;3041:102;3082:6;3133:2;3129:7;3124:2;3117:5;3113:14;3109:28;3099:38;;3041:102;;;:::o;3149:180::-;3197:77;3194:1;3187:88;3294:4;3291:1;3284:15;3318:4;3315:1;3308:15;3335:281;3418:27;3440:4;3418:27;:::i;:::-;3410:6;3406:40;3548:6;3536:10;3533:22;3512:18;3500:10;3497:34;3494:62;3491:88;;;3559:18;;:::i;:::-;3491:88;3599:10;3595:2;3588:22;3378:238;3335:281;;:::o;3622:129::-;3656:6;3683:20;;:::i;:::-;3673:30;;3712:33;3740:4;3732:6;3712:33;:::i;:::-;3622:129;;;:::o;3757:308::-;3819:4;3909:18;3901:6;3898:30;3895:56;;;3931:18;;:::i;:::-;3895:56;3969:29;3991:6;3969:29;:::i;:::-;3961:37;;4053:4;4047;4043:15;4035:23;;3757:308;;;:::o;4071:146::-;4168:6;4163:3;4158;4145:30;4209:1;4200:6;4195:3;4191:16;4184:27;4071:146;;;:::o;4223:425::-;4301:5;4326:66;4342:49;4384:6;4342:49;:::i;:::-;4326:66;:::i;:::-;4317:75;;4415:6;4408:5;4401:21;4453:4;4446:5;4442:16;4491:3;4482:6;4477:3;4473:16;4470:25;4467:112;;;4498:79;;:::i;:::-;4467:112;4588:54;4635:6;4630:3;4625;4588:54;:::i;:::-;4307:341;4223:425;;;;;:::o;4668:340::-;4724:5;4773:3;4766:4;4758:6;4754:17;4750:27;4740:122;;4781:79;;:::i;:::-;4740:122;4898:6;4885:20;4923:79;4998:3;4990:6;4983:4;4975:6;4971:17;4923:79;:::i;:::-;4914:88;;4730:278;4668:340;;;;:::o;5014:509::-;5083:6;5132:2;5120:9;5111:7;5107:23;5103:32;5100:119;;;5138:79;;:::i;:::-;5100:119;5286:1;5275:9;5271:17;5258:31;5316:18;5308:6;5305:30;5302:117;;;5338:79;;:::i;:::-;5302:117;5443:63;5498:7;5489:6;5478:9;5474:22;5443:63;:::i;:::-;5433:73;;5229:287;5014:509;;;;:::o;5529:99::-;5581:6;5615:5;5609:12;5599:22;;5529:99;;;:::o;5634:169::-;5718:11;5752:6;5747:3;5740:19;5792:4;5787:3;5783:14;5768:29;;5634:169;;;;:::o;5809:246::-;5890:1;5900:113;5914:6;5911:1;5908:13;5900:113;;;5999:1;5994:3;5990:11;5984:18;5980:1;5975:3;5971:11;5964:39;5936:2;5933:1;5929:10;5924:15;;5900:113;;;6047:1;6038:6;6033:3;6029:16;6022:27;5871:184;5809:246;;;:::o;6061:377::-;6149:3;6177:39;6210:5;6177:39;:::i;:::-;6232:71;6296:6;6291:3;6232:71;:::i;:::-;6225:78;;6312:65;6370:6;6365:3;6358:4;6351:5;6347:16;6312:65;:::i;:::-;6402:29;6424:6;6402:29;:::i;:::-;6397:3;6393:39;6386:46;;6153:285;6061:377;;;;:::o;6444:313::-;6557:4;6595:2;6584:9;6580:18;6572:26;;6644:9;6638:4;6634:20;6630:1;6619:9;6615:17;6608:47;6672:78;6745:4;6736:6;6672:78;:::i;:::-;6664:86;;6444:313;;;;:::o;6763:122::-;6836:24;6854:5;6836:24;:::i;:::-;6829:5;6826:35;6816:63;;6875:1;6872;6865:12;6816:63;6763:122;:::o;6891:139::-;6937:5;6975:6;6962:20;6953:29;;6991:33;7018:5;6991:33;:::i;:::-;6891:139;;;;:::o;7036:329::-;7095:6;7144:2;7132:9;7123:7;7119:23;7115:32;7112:119;;;7150:79;;:::i;:::-;7112:119;7270:1;7295:53;7340:7;7331:6;7320:9;7316:22;7295:53;:::i;:::-;7285:63;;7241:117;7036:329;;;;:::o;7371:118::-;7458:24;7476:5;7458:24;:::i;:::-;7453:3;7446:37;7371:118;;:::o;7495:222::-;7588:4;7626:2;7615:9;7611:18;7603:26;;7639:71;7707:1;7696:9;7692:17;7683:6;7639:71;:::i;:::-;7495:222;;;;:::o;7723:474::-;7791:6;7799;7848:2;7836:9;7827:7;7823:23;7819:32;7816:119;;;7854:79;;:::i;:::-;7816:119;7974:1;7999:53;8044:7;8035:6;8024:9;8020:22;7999:53;:::i;:::-;7989:63;;7945:117;8101:2;8127:53;8172:7;8163:6;8152:9;8148:22;8127:53;:::i;:::-;8117:63;;8072:118;7723:474;;;;;:::o;8203:619::-;8280:6;8288;8296;8345:2;8333:9;8324:7;8320:23;8316:32;8313:119;;;8351:79;;:::i;:::-;8313:119;8471:1;8496:53;8541:7;8532:6;8521:9;8517:22;8496:53;:::i;:::-;8486:63;;8442:117;8598:2;8624:53;8669:7;8660:6;8649:9;8645:22;8624:53;:::i;:::-;8614:63;;8569:118;8726:2;8752:53;8797:7;8788:6;8777:9;8773:22;8752:53;:::i;:::-;8742:63;;8697:118;8203:619;;;;;:::o;8828:311::-;8905:4;8995:18;8987:6;8984:30;8981:56;;;9017:18;;:::i;:::-;8981:56;9067:4;9059:6;9055:17;9047:25;;9127:4;9121;9117:15;9109:23;;8828:311;;;:::o;9145:117::-;9254:1;9251;9244:12;9268:77;9305:7;9334:5;9323:16;;9268:77;;;:::o;9351:122::-;9424:24;9442:5;9424:24;:::i;:::-;9417:5;9414:35;9404:63;;9463:1;9460;9453:12;9404:63;9351:122;:::o;9479:139::-;9525:5;9563:6;9550:20;9541:29;;9579:33;9606:5;9579:33;:::i;:::-;9479:139;;;;:::o;9641:710::-;9737:5;9762:81;9778:64;9835:6;9778:64;:::i;:::-;9762:81;:::i;:::-;9753:90;;9863:5;9892:6;9885:5;9878:21;9926:4;9919:5;9915:16;9908:23;;9979:4;9971:6;9967:17;9959:6;9955:30;10008:3;10000:6;9997:15;9994:122;;;10027:79;;:::i;:::-;9994:122;10142:6;10125:220;10159:6;10154:3;10151:15;10125:220;;;10234:3;10263:37;10296:3;10284:10;10263:37;:::i;:::-;10258:3;10251:50;10330:4;10325:3;10321:14;10314:21;;10201:144;10185:4;10180:3;10176:14;10169:21;;10125:220;;;10129:21;9743:608;;9641:710;;;;;:::o;10374:370::-;10445:5;10494:3;10487:4;10479:6;10475:17;10471:27;10461:122;;10502:79;;:::i;:::-;10461:122;10619:6;10606:20;10644:94;10734:3;10726:6;10719:4;10711:6;10707:17;10644:94;:::i;:::-;10635:103;;10451:293;10374:370;;;;:::o;10750:539::-;10834:6;10883:2;10871:9;10862:7;10858:23;10854:32;10851:119;;;10889:79;;:::i;:::-;10851:119;11037:1;11026:9;11022:17;11009:31;11067:18;11059:6;11056:30;11053:117;;;11089:79;;:::i;:::-;11053:117;11194:78;11264:7;11255:6;11244:9;11240:22;11194:78;:::i;:::-;11184:88;;10980:302;10750:539;;;;:::o;11295:118::-;11382:24;11400:5;11382:24;:::i;:::-;11377:3;11370:37;11295:118;;:::o;11419:222::-;11512:4;11550:2;11539:9;11535:18;11527:26;;11563:71;11631:1;11620:9;11616:17;11607:6;11563:71;:::i;:::-;11419:222;;;;:::o;11647:329::-;11706:6;11755:2;11743:9;11734:7;11730:23;11726:32;11723:119;;;11761:79;;:::i;:::-;11723:119;11881:1;11906:53;11951:7;11942:6;11931:9;11927:22;11906:53;:::i;:::-;11896:63;;11852:117;11647:329;;;;:::o;11982:311::-;12059:4;12149:18;12141:6;12138:30;12135:56;;;12171:18;;:::i;:::-;12135:56;12221:4;12213:6;12209:17;12201:25;;12281:4;12275;12271:15;12263:23;;11982:311;;;:::o;12316:710::-;12412:5;12437:81;12453:64;12510:6;12453:64;:::i;:::-;12437:81;:::i;:::-;12428:90;;12538:5;12567:6;12560:5;12553:21;12601:4;12594:5;12590:16;12583:23;;12654:4;12646:6;12642:17;12634:6;12630:30;12683:3;12675:6;12672:15;12669:122;;;12702:79;;:::i;:::-;12669:122;12817:6;12800:220;12834:6;12829:3;12826:15;12800:220;;;12909:3;12938:37;12971:3;12959:10;12938:37;:::i;:::-;12933:3;12926:50;13005:4;13000:3;12996:14;12989:21;;12876:144;12860:4;12855:3;12851:14;12844:21;;12800:220;;;12804:21;12418:608;;12316:710;;;;;:::o;13049:370::-;13120:5;13169:3;13162:4;13154:6;13150:17;13146:27;13136:122;;13177:79;;:::i;:::-;13136:122;13294:6;13281:20;13319:94;13409:3;13401:6;13394:4;13386:6;13382:17;13319:94;:::i;:::-;13310:103;;13126:293;13049:370;;;;:::o;13425:539::-;13509:6;13558:2;13546:9;13537:7;13533:23;13529:32;13526:119;;;13564:79;;:::i;:::-;13526:119;13712:1;13701:9;13697:17;13684:31;13742:18;13734:6;13731:30;13728:117;;;13764:79;;:::i;:::-;13728:117;13869:78;13939:7;13930:6;13919:9;13915:22;13869:78;:::i;:::-;13859:88;;13655:302;13425:539;;;;:::o;13970:116::-;14040:21;14055:5;14040:21;:::i;:::-;14033:5;14030:32;14020:60;;14076:1;14073;14066:12;14020:60;13970:116;:::o;14092:133::-;14135:5;14173:6;14160:20;14151:29;;14189:30;14213:5;14189:30;:::i;:::-;14092:133;;;;:::o;14231:468::-;14296:6;14304;14353:2;14341:9;14332:7;14328:23;14324:32;14321:119;;;14359:79;;:::i;:::-;14321:119;14479:1;14504:53;14549:7;14540:6;14529:9;14525:22;14504:53;:::i;:::-;14494:63;;14450:117;14606:2;14632:50;14674:7;14665:6;14654:9;14650:22;14632:50;:::i;:::-;14622:60;;14577:115;14231:468;;;;;:::o;14705:307::-;14766:4;14856:18;14848:6;14845:30;14842:56;;;14878:18;;:::i;:::-;14842:56;14916:29;14938:6;14916:29;:::i;:::-;14908:37;;15000:4;14994;14990:15;14982:23;;14705:307;;;:::o;15018:423::-;15095:5;15120:65;15136:48;15177:6;15136:48;:::i;:::-;15120:65;:::i;:::-;15111:74;;15208:6;15201:5;15194:21;15246:4;15239:5;15235:16;15284:3;15275:6;15270:3;15266:16;15263:25;15260:112;;;15291:79;;:::i;:::-;15260:112;15381:54;15428:6;15423:3;15418;15381:54;:::i;:::-;15101:340;15018:423;;;;;:::o;15460:338::-;15515:5;15564:3;15557:4;15549:6;15545:17;15541:27;15531:122;;15572:79;;:::i;:::-;15531:122;15689:6;15676:20;15714:78;15788:3;15780:6;15773:4;15765:6;15761:17;15714:78;:::i;:::-;15705:87;;15521:277;15460:338;;;;:::o;15804:943::-;15899:6;15907;15915;15923;15972:3;15960:9;15951:7;15947:23;15943:33;15940:120;;;15979:79;;:::i;:::-;15940:120;16099:1;16124:53;16169:7;16160:6;16149:9;16145:22;16124:53;:::i;:::-;16114:63;;16070:117;16226:2;16252:53;16297:7;16288:6;16277:9;16273:22;16252:53;:::i;:::-;16242:63;;16197:118;16354:2;16380:53;16425:7;16416:6;16405:9;16401:22;16380:53;:::i;:::-;16370:63;;16325:118;16510:2;16499:9;16495:18;16482:32;16541:18;16533:6;16530:30;16527:117;;;16563:79;;:::i;:::-;16527:117;16668:62;16722:7;16713:6;16702:9;16698:22;16668:62;:::i;:::-;16658:72;;16453:287;15804:943;;;;;;;:::o;16753:474::-;16821:6;16829;16878:2;16866:9;16857:7;16853:23;16849:32;16846:119;;;16884:79;;:::i;:::-;16846:119;17004:1;17029:53;17074:7;17065:6;17054:9;17050:22;17029:53;:::i;:::-;17019:63;;16975:117;17131:2;17157:53;17202:7;17193:6;17182:9;17178:22;17157:53;:::i;:::-;17147:63;;17102:118;16753:474;;;;;:::o;17233:180::-;17281:77;17278:1;17271:88;17378:4;17375:1;17368:15;17402:4;17399:1;17392:15;17419:320;17463:6;17500:1;17494:4;17490:12;17480:22;;17547:1;17541:4;17537:12;17568:18;17558:81;;17624:4;17616:6;17612:17;17602:27;;17558:81;17686:2;17678:6;17675:14;17655:18;17652:38;17649:84;;17705:18;;:::i;:::-;17649:84;17470:269;17419:320;;;:::o;17745:141::-;17794:4;17817:3;17809:11;;17840:3;17837:1;17830:14;17874:4;17871:1;17861:18;17853:26;;17745:141;;;:::o;17892:93::-;17929:6;17976:2;17971;17964:5;17960:14;17956:23;17946:33;;17892:93;;;:::o;17991:107::-;18035:8;18085:5;18079:4;18075:16;18054:37;;17991:107;;;;:::o;18104:393::-;18173:6;18223:1;18211:10;18207:18;18246:97;18276:66;18265:9;18246:97;:::i;:::-;18364:39;18394:8;18383:9;18364:39;:::i;:::-;18352:51;;18436:4;18432:9;18425:5;18421:21;18412:30;;18485:4;18475:8;18471:19;18464:5;18461:30;18451:40;;18180:317;;18104:393;;;;;:::o;18503:60::-;18531:3;18552:5;18545:12;;18503:60;;;:::o;18569:142::-;18619:9;18652:53;18670:34;18679:24;18697:5;18679:24;:::i;:::-;18670:34;:::i;:::-;18652:53;:::i;:::-;18639:66;;18569:142;;;:::o;18717:75::-;18760:3;18781:5;18774:12;;18717:75;;;:::o;18798:269::-;18908:39;18939:7;18908:39;:::i;:::-;18969:91;19018:41;19042:16;19018:41;:::i;:::-;19010:6;19003:4;18997:11;18969:91;:::i;:::-;18963:4;18956:105;18874:193;18798:269;;;:::o;19073:73::-;19118:3;19073:73;:::o;19152:189::-;19229:32;;:::i;:::-;19270:65;19328:6;19320;19314:4;19270:65;:::i;:::-;19205:136;19152:189;;:::o;19347:186::-;19407:120;19424:3;19417:5;19414:14;19407:120;;;19478:39;19515:1;19508:5;19478:39;:::i;:::-;19451:1;19444:5;19440:13;19431:22;;19407:120;;;19347:186;;:::o;19539:543::-;19640:2;19635:3;19632:11;19629:446;;;19674:38;19706:5;19674:38;:::i;:::-;19758:29;19776:10;19758:29;:::i;:::-;19748:8;19744:44;19941:2;19929:10;19926:18;19923:49;;;19962:8;19947:23;;19923:49;19985:80;20041:22;20059:3;20041:22;:::i;:::-;20031:8;20027:37;20014:11;19985:80;:::i;:::-;19644:431;;19629:446;19539:543;;;:::o;20088:117::-;20142:8;20192:5;20186:4;20182:16;20161:37;;20088:117;;;;:::o;20211:169::-;20255:6;20288:51;20336:1;20332:6;20324:5;20321:1;20317:13;20288:51;:::i;:::-;20284:56;20369:4;20363;20359:15;20349:25;;20262:118;20211:169;;;;:::o;20385:295::-;20461:4;20607:29;20632:3;20626:4;20607:29;:::i;:::-;20599:37;;20669:3;20666:1;20662:11;20656:4;20653:21;20645:29;;20385:295;;;;:::o;20685:1395::-;20802:37;20835:3;20802:37;:::i;:::-;20904:18;20896:6;20893:30;20890:56;;;20926:18;;:::i;:::-;20890:56;20970:38;21002:4;20996:11;20970:38;:::i;:::-;21055:67;21115:6;21107;21101:4;21055:67;:::i;:::-;21149:1;21173:4;21160:17;;21205:2;21197:6;21194:14;21222:1;21217:618;;;;21879:1;21896:6;21893:77;;;21945:9;21940:3;21936:19;21930:26;21921:35;;21893:77;21996:67;22056:6;22049:5;21996:67;:::i;:::-;21990:4;21983:81;21852:222;21187:887;;21217:618;21269:4;21265:9;21257:6;21253:22;21303:37;21335:4;21303:37;:::i;:::-;21362:1;21376:208;21390:7;21387:1;21384:14;21376:208;;;21469:9;21464:3;21460:19;21454:26;21446:6;21439:42;21520:1;21512:6;21508:14;21498:24;;21567:2;21556:9;21552:18;21539:31;;21413:4;21410:1;21406:12;21401:17;;21376:208;;;21612:6;21603:7;21600:19;21597:179;;;21670:9;21665:3;21661:19;21655:26;21713:48;21755:4;21747:6;21743:17;21732:9;21713:48;:::i;:::-;21705:6;21698:64;21620:156;21597:179;21822:1;21818;21810:6;21806:14;21802:22;21796:4;21789:36;21224:611;;;21187:887;;20777:1303;;;20685:1395;;:::o;22086:235::-;22226:34;22222:1;22214:6;22210:14;22203:58;22295:18;22290:2;22282:6;22278:15;22271:43;22086:235;:::o;22327:366::-;22469:3;22490:67;22554:2;22549:3;22490:67;:::i;:::-;22483:74;;22566:93;22655:3;22566:93;:::i;:::-;22684:2;22679:3;22675:12;22668:19;;22327:366;;;:::o;22699:419::-;22865:4;22903:2;22892:9;22888:18;22880:26;;22952:9;22946:4;22942:20;22938:1;22927:9;22923:17;22916:47;22980:131;23106:4;22980:131;:::i;:::-;22972:139;;22699:419;;;:::o;23124:220::-;23264:34;23260:1;23252:6;23248:14;23241:58;23333:3;23328:2;23320:6;23316:15;23309:28;23124:220;:::o;23350:366::-;23492:3;23513:67;23577:2;23572:3;23513:67;:::i;:::-;23506:74;;23589:93;23678:3;23589:93;:::i;:::-;23707:2;23702:3;23698:12;23691:19;;23350:366;;;:::o;23722:419::-;23888:4;23926:2;23915:9;23911:18;23903:26;;23975:9;23969:4;23965:20;23961:1;23950:9;23946:17;23939:47;24003:131;24129:4;24003:131;:::i;:::-;23995:139;;23722:419;;;:::o;24147:180::-;24195:77;24192:1;24185:88;24292:4;24289:1;24282:15;24316:4;24313:1;24306:15;24333:191;24373:3;24392:20;24410:1;24392:20;:::i;:::-;24387:25;;24426:20;24444:1;24426:20;:::i;:::-;24421:25;;24469:1;24466;24462:9;24455:16;;24490:3;24487:1;24484:10;24481:36;;;24497:18;;:::i;:::-;24481:36;24333:191;;;;:::o;24530:234::-;24670:34;24666:1;24658:6;24654:14;24647:58;24739:17;24734:2;24726:6;24722:15;24715:42;24530:234;:::o;24770:366::-;24912:3;24933:67;24997:2;24992:3;24933:67;:::i;:::-;24926:74;;25009:93;25098:3;25009:93;:::i;:::-;25127:2;25122:3;25118:12;25111:19;;24770:366;;;:::o;25142:419::-;25308:4;25346:2;25335:9;25331:18;25323:26;;25395:9;25389:4;25385:20;25381:1;25370:9;25366:17;25359:47;25423:131;25549:4;25423:131;:::i;:::-;25415:139;;25142:419;;;:::o;25567:234::-;25707:34;25703:1;25695:6;25691:14;25684:58;25776:17;25771:2;25763:6;25759:15;25752:42;25567:234;:::o;25807:366::-;25949:3;25970:67;26034:2;26029:3;25970:67;:::i;:::-;25963:74;;26046:93;26135:3;26046:93;:::i;:::-;26164:2;26159:3;26155:12;26148:19;;25807:366;;;:::o;26179:419::-;26345:4;26383:2;26372:9;26368:18;26360:26;;26432:9;26426:4;26422:20;26418:1;26407:9;26403:17;26396:47;26460:131;26586:4;26460:131;:::i;:::-;26452:139;;26179:419;;;:::o;26604:224::-;26744:34;26740:1;26732:6;26728:14;26721:58;26813:7;26808:2;26800:6;26796:15;26789:32;26604:224;:::o;26834:366::-;26976:3;26997:67;27061:2;27056:3;26997:67;:::i;:::-;26990:74;;27073:93;27162:3;27073:93;:::i;:::-;27191:2;27186:3;27182:12;27175:19;;26834:366;;;:::o;27206:419::-;27372:4;27410:2;27399:9;27395:18;27387:26;;27459:9;27453:4;27449:20;27445:1;27434:9;27430:17;27423:47;27487:131;27613:4;27487:131;:::i;:::-;27479:139;;27206:419;;;:::o;27631:243::-;27771:34;27767:1;27759:6;27755:14;27748:58;27840:26;27835:2;27827:6;27823:15;27816:51;27631:243;:::o;27880:366::-;28022:3;28043:67;28107:2;28102:3;28043:67;:::i;:::-;28036:74;;28119:93;28208:3;28119:93;:::i;:::-;28237:2;28232:3;28228:12;28221:19;;27880:366;;;:::o;28252:419::-;28418:4;28456:2;28445:9;28441:18;28433:26;;28505:9;28499:4;28495:20;28491:1;28480:9;28476:17;28469:47;28533:131;28659:4;28533:131;:::i;:::-;28525:139;;28252:419;;;:::o;28677:94::-;28710:8;28758:5;28754:2;28750:14;28729:35;;28677:94;;;:::o;28777:::-;28816:7;28845:20;28859:5;28845:20;:::i;:::-;28834:31;;28777:94;;;:::o;28877:100::-;28916:7;28945:26;28965:5;28945:26;:::i;:::-;28934:37;;28877:100;;;:::o;28983:157::-;29088:45;29108:24;29126:5;29108:24;:::i;:::-;29088:45;:::i;:::-;29083:3;29076:58;28983:157;;:::o;29146:256::-;29258:3;29273:75;29344:3;29335:6;29273:75;:::i;:::-;29373:2;29368:3;29364:12;29357:19;;29393:3;29386:10;;29146:256;;;;:::o;29408:234::-;29548:34;29544:1;29536:6;29532:14;29525:58;29617:17;29612:2;29604:6;29600:15;29593:42;29408:234;:::o;29648:366::-;29790:3;29811:67;29875:2;29870:3;29811:67;:::i;:::-;29804:74;;29887:93;29976:3;29887:93;:::i;:::-;30005:2;30000:3;29996:12;29989:19;;29648:366;;;:::o;30020:419::-;30186:4;30224:2;30213:9;30209:18;30201:26;;30273:9;30267:4;30263:20;30259:1;30248:9;30244:17;30237:47;30301:131;30427:4;30301:131;:::i;:::-;30293:139;;30020:419;;;:::o;30445:143::-;30502:5;30533:6;30527:13;30518:22;;30549:33;30576:5;30549:33;:::i;:::-;30445:143;;;;:::o;30594:351::-;30664:6;30713:2;30701:9;30692:7;30688:23;30684:32;30681:119;;;30719:79;;:::i;:::-;30681:119;30839:1;30864:64;30920:7;30911:6;30900:9;30896:22;30864:64;:::i;:::-;30854:74;;30810:128;30594:351;;;;:::o;30951:180::-;30999:77;30996:1;30989:88;31096:4;31093:1;31086:15;31120:4;31117:1;31110:15;31137:143;31194:5;31225:6;31219:13;31210:22;;31241:33;31268:5;31241:33;:::i;:::-;31137:143;;;;:::o;31286:351::-;31356:6;31405:2;31393:9;31384:7;31380:23;31376:32;31373:119;;;31411:79;;:::i;:::-;31373:119;31531:1;31556:64;31612:7;31603:6;31592:9;31588:22;31556:64;:::i;:::-;31546:74;;31502:128;31286:351;;;;:::o;31643:233::-;31682:3;31705:24;31723:5;31705:24;:::i;:::-;31696:33;;31751:66;31744:5;31741:77;31738:103;;31821:18;;:::i;:::-;31738:103;31868:1;31861:5;31857:13;31850:20;;31643:233;;;:::o;31882:234::-;32022:34;32018:1;32010:6;32006:14;31999:58;32091:17;32086:2;32078:6;32074:15;32067:42;31882:234;:::o;32122:366::-;32264:3;32285:67;32349:2;32344:3;32285:67;:::i;:::-;32278:74;;32361:93;32450:3;32361:93;:::i;:::-;32479:2;32474:3;32470:12;32463:19;;32122:366;;;:::o;32494:419::-;32660:4;32698:2;32687:9;32683:18;32675:26;;32747:9;32741:4;32737:20;32733:1;32722:9;32718:17;32711:47;32775:131;32901:4;32775:131;:::i;:::-;32767:139;;32494:419;;;:::o;32919:148::-;33021:11;33058:3;33043:18;;32919:148;;;;:::o;33073:390::-;33179:3;33207:39;33240:5;33207:39;:::i;:::-;33262:89;33344:6;33339:3;33262:89;:::i;:::-;33255:96;;33360:65;33418:6;33413:3;33406:4;33399:5;33395:16;33360:65;:::i;:::-;33450:6;33445:3;33441:16;33434:23;;33183:280;33073:390;;;;:::o;33469:155::-;33609:7;33605:1;33597:6;33593:14;33586:31;33469:155;:::o;33630:400::-;33790:3;33811:84;33893:1;33888:3;33811:84;:::i;:::-;33804:91;;33904:93;33993:3;33904:93;:::i;:::-;34022:1;34017:3;34013:11;34006:18;;33630:400;;;:::o;34036:701::-;34317:3;34339:95;34430:3;34421:6;34339:95;:::i;:::-;34332:102;;34451:95;34542:3;34533:6;34451:95;:::i;:::-;34444:102;;34563:148;34707:3;34563:148;:::i;:::-;34556:155;;34728:3;34721:10;;34036:701;;;;;:::o;34743:225::-;34883:34;34879:1;34871:6;34867:14;34860:58;34952:8;34947:2;34939:6;34935:15;34928:33;34743:225;:::o;34974:366::-;35116:3;35137:67;35201:2;35196:3;35137:67;:::i;:::-;35130:74;;35213:93;35302:3;35213:93;:::i;:::-;35331:2;35326:3;35322:12;35315:19;;34974:366;;;:::o;35346:419::-;35512:4;35550:2;35539:9;35535:18;35527:26;;35599:9;35593:4;35589:20;35585:1;35574:9;35570:17;35563:47;35627:131;35753:4;35627:131;:::i;:::-;35619:139;;35346:419;;;:::o;35771:182::-;35911:34;35907:1;35899:6;35895:14;35888:58;35771:182;:::o;35959:366::-;36101:3;36122:67;36186:2;36181:3;36122:67;:::i;:::-;36115:74;;36198:93;36287:3;36198:93;:::i;:::-;36316:2;36311:3;36307:12;36300:19;;35959:366;;;:::o;36331:419::-;36497:4;36535:2;36524:9;36520:18;36512:26;;36584:9;36578:4;36574:20;36570:1;36559:9;36555:17;36548:47;36612:131;36738:4;36612:131;:::i;:::-;36604:139;;36331:419;;;:::o;36756:98::-;36807:6;36841:5;36835:12;36825:22;;36756:98;;;:::o;36860:168::-;36943:11;36977:6;36972:3;36965:19;37017:4;37012:3;37008:14;36993:29;;36860:168;;;;:::o;37034:373::-;37120:3;37148:38;37180:5;37148:38;:::i;:::-;37202:70;37265:6;37260:3;37202:70;:::i;:::-;37195:77;;37281:65;37339:6;37334:3;37327:4;37320:5;37316:16;37281:65;:::i;:::-;37371:29;37393:6;37371:29;:::i;:::-;37366:3;37362:39;37355:46;;37124:283;37034:373;;;;:::o;37413:640::-;37608:4;37646:3;37635:9;37631:19;37623:27;;37660:71;37728:1;37717:9;37713:17;37704:6;37660:71;:::i;:::-;37741:72;37809:2;37798:9;37794:18;37785:6;37741:72;:::i;:::-;37823;37891:2;37880:9;37876:18;37867:6;37823:72;:::i;:::-;37942:9;37936:4;37932:20;37927:2;37916:9;37912:18;37905:48;37970:76;38041:4;38032:6;37970:76;:::i;:::-;37962:84;;37413:640;;;;;;;:::o;38059:141::-;38115:5;38146:6;38140:13;38131:22;;38162:32;38188:5;38162:32;:::i;:::-;38059:141;;;;:::o;38206:349::-;38275:6;38324:2;38312:9;38303:7;38299:23;38295:32;38292:119;;;38330:79;;:::i;:::-;38292:119;38450:1;38475:63;38530:7;38521:6;38510:9;38506:22;38475:63;:::i;:::-;38465:73;;38421:127;38206:349;;;;:::o;38561:180::-;38609:77;38606:1;38599:88;38706:4;38703:1;38696:15;38730:4;38727:1;38720:15

Swarm Source

ipfs://3fd71cccc3897ff9bbd31b60a973fee938dc31d4a1c0232036d11628c6733440
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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