ETH Price: $3,917.32 (+5.93%)

Token

: OP Punks (OPPUNK)

Overview

Max Total Supply

10,000 OPPUNK

Holders

5,643

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
18 OPPUNK
0xe726ba45782414824443dde516f473e053d601f5
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
OPPunks

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at optimistic.etherscan.io on 2023-09-29
*/

// File: Punk Mint Contract/Extras.sol



pragma solidity ^0.8.0;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 *
 * _Available since v4.5._
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // Loads the table into memory
        string memory table = _TABLE;

        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
        // and split into 4 numbers of 6 bits.
        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
        // - `data.length + 2`  -> Round up
        // - `/ 3`              -> Number of 3-bytes chunks
        // - `4 *`              -> 4 characters for each chunk
        string memory result = new string(4 * ((data.length + 2) / 3));

        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 32)

            // Run over the input, 3 bytes at a time
            for {
                let dataPtr := data
                let endPtr := add(data, mload(data))
            } lt(dataPtr, endPtr) {

            } {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 bytes (18 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F which is the number of
                // the previous character in the ASCII table prior to the Base64 Table
                // The result is then added to the table to get the character to write,
                // and finally write it in the result pointer but with a left shift
                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // When data `bytes` is not exactly 3 bytes long
            // it is padded with `=` characters at the end
            switch mod(mload(data), 3)
            case 1 {
                mstore8(sub(resultPtr, 1), 0x3d)
                mstore8(sub(resultPtr, 2), 0x3d)
            }
            case 2 {
                mstore8(sub(resultPtr, 1), 0x3d)
            }
        }

        return result;
    }
}

// File: Extra/StringUtils.sol


pragma solidity ^0.8.0;

/**
 * Strings Library
 * 
 * In summary this is a simple library of string functions which make simple 
 * string operations less tedious in solidity.
 * 
 * Please be aware these functions can be quite gas heavy so use them only when
 * necessary not to clog the blockchain with expensive transactions.
 * 
 * @author James Lockhart <[email protected]>
 */
library StringUtils {

    /**
     * Concat (High gas cost)
     * 
     * Appends two strings together and returns a new value
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string which will be the concatenated
     *              prefix
     * @param _value The value to be the concatenated suffix
     * @return string The resulting string from combinging the base and value
     */
    function concat(string memory _base, string memory _value)
        internal
        pure
        returns (string memory) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        assert(_valueBytes.length > 0);

        string memory _tmpValue = new string(_baseBytes.length +
            _valueBytes.length);
        bytes memory _newValue = bytes(_tmpValue);

        uint i;
        uint j;

        for (i = 0; i < _baseBytes.length; i++) {
            _newValue[j++] = _baseBytes[i];
        }

        for (i = 0; i < _valueBytes.length; i++) {
            _newValue[j++] = _valueBytes[i];
        }

        return string(_newValue);
    }

    /**
     * Index Of
     *
     * Locates and returns the position of a character within a string
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string acting as the haystack to be
     *              searched
     * @param _value The needle to search for, at present this is currently
     *               limited to one character
     * @return int The position of the needle starting from 0 and returning -1
     *             in the case of no matches found
     */
    function indexOf(string memory _base, string memory _value)
        internal
        pure
        returns (int) {
        return _indexOf(_base, _value, 0);
    }

    /**
     * Index Of
     *
     * Locates and returns the position of a character within a string starting
     * from a defined offset
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string acting as the haystack to be
     *              searched
     * @param _value The needle to search for, at present this is currently
     *               limited to one character
     * @param _offset The starting point to start searching from which can start
     *                from 0, but must not exceed the length of the string
     * @return int The position of the needle starting from 0 and returning -1
     *             in the case of no matches found
     */
    function _indexOf(string memory _base, string memory _value, uint _offset)
        internal
        pure
        returns (int) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        assert(_valueBytes.length == 1);

        for (uint i = _offset; i < _baseBytes.length; i++) {
            if (_baseBytes[i] == _valueBytes[0]) {
                return int(i);
            }
        }

        return -1;
    }

    /**
     * Length
     * 
     * Returns the length of the specified string
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string to be measured
     * @return uint The length of the passed string
     */
    function length(string memory _base)
        internal
        pure
        returns (uint) {
        bytes memory _baseBytes = bytes(_base);
        return _baseBytes.length;
    }

    /**
     * Sub String
     * 
     * Extracts the beginning part of a string based on the desired length
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string that will be used for 
     *              extracting the sub string from
     * @param _length The length of the sub string to be extracted from the base
     * @return string The extracted sub string
     */
    function substring(string memory _base, int _length)
        internal
        pure
        returns (string memory) {
        return _substring(_base, _length, 0);
    }

    /**
     * Sub String
     * 
     * Extracts the part of a string based on the desired length and offset. The
     * offset and length must not exceed the lenth of the base string.
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string that will be used for 
     *              extracting the sub string from
     * @param _length The length of the sub string to be extracted from the base
     * @param _offset The starting point to extract the sub string from
     * @return string The extracted sub string
     */
    function _substring(string memory _base, int _length, int _offset)
        internal
        pure
        returns (string memory) {
        bytes memory _baseBytes = bytes(_base);

        assert(uint(_offset + _length) <= _baseBytes.length);

        string memory _tmp = new string(uint(_length));
        bytes memory _tmpBytes = bytes(_tmp);

        uint j = 0;
        for (uint i = uint(_offset); i < uint(_offset + _length); i++) {
            _tmpBytes[j++] = _baseBytes[i];
        }

        return string(_tmpBytes);
    }


    function split(string memory _base, string memory _value)
        internal
        pure
        returns (string[] memory splitArr) {
        bytes memory _baseBytes = bytes(_base);

        uint _offset = 0;
        uint _splitsCount = 1;
        while (_offset < _baseBytes.length - 1) {
            int _limit = _indexOf(_base, _value, _offset);
            if (_limit == -1)
                break;
            else {
                _splitsCount++;
                _offset = uint(_limit) + 1;
            }
        }

        splitArr = new string[](_splitsCount);

        _offset = 0;
        _splitsCount = 0;
        while (_offset < _baseBytes.length - 1) {

            int _limit = _indexOf(_base, _value, _offset);
            if (_limit == - 1) {
                _limit = int(_baseBytes.length);
            }

            string memory _tmp = new string(uint(_limit) - _offset);
            bytes memory _tmpBytes = bytes(_tmp);

            uint j = 0;
            for (uint i = _offset; i < uint(_limit); i++) {
                _tmpBytes[j++] = _baseBytes[i];
            }
            _offset = uint(_limit) + 1;
            splitArr[_splitsCount++] = string(_tmpBytes);
        }
        return splitArr;
    }

    /**
     * Compare To
     * 
     * Compares the characters of two strings, to ensure that they have an 
     * identical footprint
     * 
     * @param _base When being used for a data type this is the extended object
     *               otherwise this is the string base to compare against
     * @param _value The string the base is being compared to
     * @return bool Simply notates if the two string have an equivalent
     */
    function compareTo(string memory _base, string memory _value)
        internal
        pure
        returns (bool) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        if (_baseBytes.length != _valueBytes.length) {
            return false;
        }

        for (uint i = 0; i < _baseBytes.length; i++) {
            if (_baseBytes[i] != _valueBytes[i]) {
                return false;
            }
        }

        return true;
    }

    /**
     * Compare To Ignore Case (High gas cost)
     * 
     * Compares the characters of two strings, converting them to the same case
     * where applicable to alphabetic characters to distinguish if the values
     * match.
     * 
     * @param _base When being used for a data type this is the extended object
     *               otherwise this is the string base to compare against
     * @param _value The string the base is being compared to
     * @return bool Simply notates if the two string have an equivalent value
     *              discarding case
     */
    function compareToIgnoreCase(string memory _base, string memory _value)
        internal
        pure
        returns (bool) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        if (_baseBytes.length != _valueBytes.length) {
            return false;
        }

        for (uint i = 0; i < _baseBytes.length; i++) {
            if (_baseBytes[i] != _valueBytes[i] &&
            _upper(_baseBytes[i]) != _upper(_valueBytes[i])) {
                return false;
            }
        }

        return true;
    }

    /**
     * Upper
     * 
     * Converts all the values of a string to their corresponding upper case
     * value.
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string base to convert to upper case
     * @return string 
     */
    function upper(string memory _base)
        internal
        pure
        returns (string memory) {
        bytes memory _baseBytes = bytes(_base);
        for (uint i = 0; i < _baseBytes.length; i++) {
            _baseBytes[i] = _upper(_baseBytes[i]);
        }
        return string(_baseBytes);
    }

    /**
     * Lower
     * 
     * Converts all the values of a string to their corresponding lower case
     * value.
     * 
     * @param _base When being used for a data type this is the extended object
     *              otherwise this is the string base to convert to lower case
     * @return string 
     */
    function lower(string memory _base)
        internal
        pure
        returns (string memory) {
        bytes memory _baseBytes = bytes(_base);
        for (uint i = 0; i < _baseBytes.length; i++) {
            _baseBytes[i] = _lower(_baseBytes[i]);
        }
        return string(_baseBytes);
    }

    /**
     * Upper
     * 
     * Convert an alphabetic character to upper case and return the original
     * value when not alphabetic
     * 
     * @param _b1 The byte to be converted to upper case
     * @return bytes1 The converted value if the passed value was alphabetic
     *                and in a lower case otherwise returns the original value
     */
    function _upper(bytes1 _b1)
        private
        pure
        returns (bytes1) {

        if (_b1 >= 0x61 && _b1 <= 0x7A) {
            return bytes1(uint8(_b1) - 32);
        }

        return _b1;
    }

    /**
     * Lower
     * 
     * Convert an alphabetic character to lower case and return the original
     * value when not alphabetic
     * 
     * @param _b1 The byte to be converted to lower case
     * @return bytes1 The converted value if the passed value was alphabetic
     *                and in a upper case otherwise returns the original value
     */
    function _lower(bytes1 _b1)
        private
        pure
        returns (bytes1) {

        if (_b1 >= 0x41 && _b1 <= 0x5A) {
            return bytes1(uint8(_b1) + 32);
        }

        return _b1;
    }
}
// File: Extra/DynamicBuffer.sol


// Copyright (c) 2021 the ethier authors (github.com/divergencetech/ethier)

pragma solidity >=0.8.0;

/// @title DynamicBuffer
/// @author David Huber (@cxkoda) and Simon Fremaux (@dievardump). See also
///         https://raw.githubusercontent.com/dievardump/solidity-dynamic-buffer
/// @notice This library is used to allocate a big amount of container memory
//          which will be subsequently filled without needing to reallocate
///         memory.
/// @dev First, allocate memory.
///      Then use `buffer.appendUnchecked(theBytes)` or `appendSafe()` if
///      bounds checking is required.
library DynamicBuffer {
    /// @notice Allocates container space for the DynamicBuffer
    /// @param capacity The intended max amount of bytes in the buffer
    /// @return buffer The memory location of the buffer
    /// @dev Allocates `capacity + 0x60` bytes of space
    ///      The buffer array starts at the first container data position,
    ///      (i.e. `buffer = container + 0x20`)
    function allocate(uint256 capacity)
        internal
        pure
        returns (bytes memory buffer)
    {
        assembly {
            // Get next-free memory address
            let container := mload(0x40)

            // Allocate memory by setting a new next-free address
            {
                // Add 2 x 32 bytes in size for the two length fields
                // Add 32 bytes safety space for 32B chunked copy
                let size := add(capacity, 0x60)
                let newNextFree := add(container, size)
                mstore(0x40, newNextFree)
            }

            // Set the correct container length
            {
                let length := add(capacity, 0x40)
                mstore(container, length)
            }

            // The buffer starts at idx 1 in the container (0 is length)
            buffer := add(container, 0x20)

            // Init content with length 0
            mstore(buffer, 0)
        }

        return buffer;
    }

    /// @notice Appends data to buffer, and update buffer length
    /// @param buffer the buffer to append the data to
    /// @param data the data to append
    /// @dev Does not perform out-of-bound checks (container capacity)
    ///      for efficiency.
    function appendUnchecked(bytes memory buffer, bytes memory data)
        internal
        pure
    {
        assembly {
            let length := mload(data)
            for {
                data := add(data, 0x20)
                let dataEnd := add(data, length)
                let copyTo := add(buffer, add(mload(buffer), 0x20))
            } lt(data, dataEnd) {
                data := add(data, 0x20)
                copyTo := add(copyTo, 0x20)
            } {
                // Copy 32B chunks from data to buffer.
                // This may read over data array boundaries and copy invalid
                // bytes, which doesn't matter in the end since we will
                // later set the correct buffer length, and have allocated an
                // additional word to avoid buffer overflow.
                mstore(copyTo, mload(data))
            }

            // Update buffer length
            mstore(buffer, add(mload(buffer), length))
        }
    }

    /// @notice Appends data to buffer, and update buffer length
    /// @param buffer the buffer to append the data to
    /// @param data the data to append
    /// @dev Performs out-of-bound checks and calls `appendUnchecked`.
    function appendSafe(bytes memory buffer, bytes memory data) internal pure {
        uint256 capacity;
        uint256 length;
        assembly {
            capacity := sub(mload(sub(buffer, 0x20)), 0x40)
            length := mload(buffer)
        }

        require(
            length + data.length <= capacity,
            "DynamicBuffer: Appending out of bounds."
        );
        appendUnchecked(buffer, data);
    }
}
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


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

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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


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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;

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

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


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

pragma solidity ^0.8.0;


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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

// File: /Contracts/ERC721R.sol



pragma solidity ^0.8.0;








/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension. This does random batch minting.
 */
contract ERC721r is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;
    
    mapping(uint => uint) private _availableTokens;
    uint256 private _numAvailableTokens;
    uint256 immutable _maxSupply;
    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

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

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

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

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_, uint maxSupply_) {
        _name = name_;
        _symbol = symbol_;
        _maxSupply = maxSupply_;
        _numAvailableTokens = maxSupply_;
    }
    
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }
    
    function totalSupply() public view virtual returns (uint256) {
        return _maxSupply - _numAvailableTokens;
    }
    
    function maxSupply() public view virtual returns (uint256) {
        return _maxSupply;
    }

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

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

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

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

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

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

    function _mintIdWithoutBalanceUpdate(address to, uint256 tokenId) private {
        _beforeTokenTransfer(address(0), to, tokenId);
        
        _owners[tokenId] = to;
        
        emit Transfer(address(0), to, tokenId);
        
        _afterTokenTransfer(address(0), to, tokenId);
    }

    function _mintRandom(address to, uint _numToMint) internal virtual {
        require(_msgSender() == tx.origin, "Contracts cannot mint");
        require(to != address(0), "ERC721: mint to the zero address");
        require(_numToMint > 0, "ERC721r: need to mint at least one token");
        
        // TODO: Probably don't need this as it will underflow and revert automatically in this case
        require(_numAvailableTokens >= _numToMint, "ERC721r: minting more tokens than available");
        
        uint updatedNumAvailableTokens = _numAvailableTokens;
        for (uint256 i; i < _numToMint; ++i) { // Do this ++ unchecked?
            uint256 tokenId = getRandomAvailableTokenId(to, updatedNumAvailableTokens);
            
            _mintIdWithoutBalanceUpdate(to, tokenId);
            
            --updatedNumAvailableTokens;
        }
        
        _numAvailableTokens = updatedNumAvailableTokens;
        _balances[to] += _numToMint;
    }
        
    function getRandomAvailableTokenId(address to, uint updatedNumAvailableTokens)
        internal
        returns (uint256)
    {
        uint256 randomNum = uint256(
            keccak256(
                abi.encode(
                    to,
                    // tx.gasprice,
                    // block.number,
                    // block.timestamp,
                    // block.difficulty,
                    // blockhash(block.number - 1),
                    address(this),
                    updatedNumAvailableTokens
                )
            )
        );
        uint256 randomIndex = randomNum % updatedNumAvailableTokens;
        return getAvailableTokenAtIndex(randomIndex, updatedNumAvailableTokens);
    }

    // Implements https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. Code taken from CryptoPhunksV2
    function getAvailableTokenAtIndex(uint256 indexToUse, uint updatedNumAvailableTokens)
        internal
        returns (uint256)
    {
        uint256 valAtIndex = _availableTokens[indexToUse];
        uint256 result;
        if (valAtIndex == 0) {
            // This means the index itself is still an available token
            result = indexToUse;
        } else {
            // This means the index itself is not an available token, but the val at that index is.
            result = valAtIndex;
        }

        uint256 lastIndex = updatedNumAvailableTokens - 1;
        uint256 lastValInArray = _availableTokens[lastIndex];
        if (indexToUse != lastIndex) {
            // Replace the value at indexToUse, now that it's been used.
            // Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.
            if (lastValInArray == 0) {
                // This means the index itself is still an available token
                _availableTokens[indexToUse] = lastIndex;
            } else {
                // This means the index itself is not an available token, but the val at that index is.
                _availableTokens[indexToUse] = lastValInArray;
            }
        }
        if (lastValInArray != 0) {
            // Gas refund courtsey of @dievardump
            delete _availableTokens[lastIndex];
        }
        
        return result;
    }
    
    // Not as good as minting a specific tokenId, but will behave the same at the start
    // allowing you to explicitly mint some tokens at launch.
    function _mintAtIndex(address to, uint index) internal virtual {
        require(_msgSender() == tx.origin, "Contracts cannot mint");
        require(to != address(0), "ERC721: mint to the zero address");
        require(_numAvailableTokens >= 1, "ERC721r: minting more tokens than available");
        
        uint tokenId = getAvailableTokenAtIndex(index, _numAvailableTokens);
        --_numAvailableTokens;
        
        _mintIdWithoutBalanceUpdate(to, tokenId);
        
        _balances[to] += 1;
    }

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

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

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

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

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * 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, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}
// File: Mint Contract/ArbiPunksOnChain.sol










pragma solidity ^0.8.17;

interface PunkDataInterface {
    function punkImage(uint16 index) external view returns (bytes memory);
    function punkAttributes(uint16 index) external view returns (string memory);
}

interface ExtendedPunkDataInterface {
        enum PunkAttributeType {SEX, HAIR, EYES, BEARD, EARS, LIPS, MOUTH, FACE, EMOTION, NECK, NOSE, CHEEKS, TEETH}

        enum PunkAttributeValue {
                NONE, ALIEN, APE, BANDANA, BEANIE, BIG_BEARD, BIG_SHADES, BLACK_LIPSTICK, BLONDE_BOB, 
                BLONDE_SHORT, BLUE_EYE_SHADOW, BUCK_TEETH, CAP, CAP_FORWARD, CHINSTRAP, CHOKER, CIGARETTE, CLASSIC_SHADES, 
                CLOWN_EYES_BLUE, CLOWN_EYES_GREEN, CLOWN_HAIR_GREEN, CLOWN_NOSE, COWBOY_HAT, CRAZY_HAIR, DARK_HAIR, DO_RAG, EARRING,
                EYE_MASK, EYE_PATCH, FEDORA, FEMALE, FRONT_BEARD, FRONT_BEARD_DARK, FROWN, FRUMPY_HAIR, GOAT, GOLD_CHAIN,
                GREEN_EYE_SHADOW, HALF_SHAVED, HANDLEBARS, HEADBAND, HOODIE, HORNED_RIM_GLASSES, HOT_LIPSTICK, KNITTED_CAP,
                LUXURIOUS_BEARD, MALE, MEDICAL_MASK, MESSY_HAIR, MOHAWK, MOHAWK_DARK, MOHAWK_THIN, MOLE, MUSTACHE, MUTTONCHOPS,
                NERD_GLASSES, NORMAL_BEARD, NORMAL_BEARD_BLACK, ORANGE_SIDE, PEAK_SPIKE, PIGTAILS, PILOT_HELMET, PINK_WITH_HAT,
                PIPE, POLICE_CAP, PURPLE_EYE_SHADOW, PURPLE_HAIR, PURPLE_LIPSTICK, RED_MOHAWK, REGULAR_SHADES, ROSY_CHEEKS,
                SHADOW_BEARD, SHAVED_HEAD, SILVER_CHAIN, SMALL_SHADES, SMILE, SPOTS, STRAIGHT_HAIR, STRAIGHT_HAIR_BLONDE,
                STRAIGHT_HAIR_DARK, STRINGY_HAIR, TASSLE_HAT, THREE_D_GLASSES, TIARA, TOP_HAT, VAMPIRE_HAIR, VAPE, VR,
                WELDING_GOGGLES, WILD_BLONDE, WILD_HAIR, WILD_WHITE_HAIR, ZOMBIE
                }


    function attrStringToEnumMapping(string memory) external view returns (ExtendedPunkDataInterface.PunkAttributeValue);
    function attrEnumToStringMapping(PunkAttributeValue) external view returns (string memory);
    function attrValueToTypeEnumMapping(PunkAttributeValue) external view returns (ExtendedPunkDataInterface.PunkAttributeType);
}
// File: Punk Mint Contract/OPPunks.sol




pragma solidity ^0.8.0;


/*
 **** OP Punks ****
 **** Metadata and SVG Images stored entirely on the Base Blockchain
 **** Total Supply 10,000 OP Punks
 **** Paid Mint Price 0.001 ETH
 **** Inspired by The OG Cryptopunks
 **** Code borrowed with love from Fashion Hat Punks
*/

contract OPPunks is ERC721r, Ownable, ReentrancyGuard  {


enum PunkAttributeType {SEX, HAIR, EYES, BEARD, EARS, LIPS, MOUTH, FACE, EMOTION, NECK, NOSE, CHEEKS, TEETH}

    enum PunkAttributeValue {
                NONE, ALIEN, APE, BANDANA, BEANIE, BIG_BEARD, BIG_SHADES, BLACK_LIPSTICK, BLONDE_BOB, 
                BLONDE_SHORT, BLUE_EYE_SHADOW, BUCK_TEETH, CAP, CAP_FORWARD, CHINSTRAP, CHOKER, CIGARETTE, CLASSIC_SHADES, 
                CLOWN_EYES_BLUE, CLOWN_EYES_GREEN, CLOWN_HAIR_GREEN, CLOWN_NOSE, COWBOY_HAT, CRAZY_HAIR, DARK_HAIR, DO_RAG, EARRING,
                EYE_MASK, EYE_PATCH, FEDORA, FEMALE, FRONT_BEARD, FRONT_BEARD_DARK, FROWN, FRUMPY_HAIR, GOAT, GOLD_CHAIN,
                GREEN_EYE_SHADOW, HALF_SHAVED, HANDLEBARS, HEADBAND, HOODIE, HORNED_RIM_GLASSES, HOT_LIPSTICK, KNITTED_CAP,
                LUXURIOUS_BEARD, MALE, MEDICAL_MASK, MESSY_HAIR, MOHAWK, MOHAWK_DARK, MOHAWK_THIN, MOLE, MUSTACHE, MUTTONCHOPS,
                NERD_GLASSES, NORMAL_BEARD, NORMAL_BEARD_BLACK, ORANGE_SIDE, PEAK_SPIKE, PIGTAILS, PILOT_HELMET, PINK_WITH_HAT,
                PIPE, POLICE_CAP, PURPLE_EYE_SHADOW, PURPLE_HAIR, PURPLE_LIPSTICK, RED_MOHAWK, REGULAR_SHADES, ROSY_CHEEKS,
                SHADOW_BEARD, SHAVED_HEAD, SILVER_CHAIN, SMALL_SHADES, SMILE, SPOTS, STRAIGHT_HAIR, STRAIGHT_HAIR_BLONDE,
                STRAIGHT_HAIR_DARK, STRINGY_HAIR, TASSLE_HAT, THREE_D_GLASSES, TIARA, TOP_HAT, VAMPIRE_HAIR, VAPE, VR,
                WELDING_GOGGLES, WILD_BLONDE, WILD_HAIR, WILD_WHITE_HAIR, ZOMBIE
    }

                
    struct Punk {
        uint16 id;
        PunkAttributeValue sex;
        PunkAttributeValue hair;
        PunkAttributeValue eyes;
        PunkAttributeValue beard;
        PunkAttributeValue ears;
        PunkAttributeValue lips;
        PunkAttributeValue mouth;
        PunkAttributeValue face;
        PunkAttributeValue emotion;
        PunkAttributeValue neck;
        PunkAttributeValue nose;
        PunkAttributeValue cheeks;
        PunkAttributeValue teeth;
    }

    using StringUtils for string;
    using Address for address;
    using DynamicBuffer for bytes;
    using Strings for uint256;
    using Strings for uint16;
    using Strings for uint8;

    bytes private constant tokenDescription = "OP Punks - Stored entirely OnChain";


    PunkDataInterface private immutable punkDataContract;
    ExtendedPunkDataInterface private immutable extendedPunkDataContract;

    uint     public mintPrice    = 0.001 ether;
    bool     public mintEnabled  = false;
    address  public deployer;

    mapping(address => bool) public FreeAddresses;

    modifier onlyDeployer() {
        require(msg.sender == deployer, "Only deployer.");
        _;
    }

    constructor(address punkDataContractAddress, address extendedPunkDataContractAddress) 
    ERC721r("OP Punks", "OPPUNK", 10000) {

        punkDataContract = PunkDataInterface(punkDataContractAddress);
        extendedPunkDataContract = ExtendedPunkDataInterface(extendedPunkDataContractAddress);
        deployer = payable(msg.sender);
    }


    function mint(uint256 count) external payable  {
        
        uint256 cost = mintPrice;

        require(mintEnabled, "Mint not ready yet");
        require(totalSupply() + count <= maxSupply(), "Sold Out!");
        require(msg.value >= count * cost, "Please send the exact ETH amount");
        require(msg.sender == tx.origin, "The minter is another contract");

        _mintRandom(msg.sender, count);

    }

    function set_Price(uint _price) public onlyOwner {
        mintPrice = _price;            
    }

    function toggle_Minting() external onlyOwner {
        mintEnabled = !mintEnabled;
    }

    function withdraw() external onlyOwner nonReentrant {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "Transfer failed.");
    }

    function team_mint() external onlyOwner nonReentrant {
        _mintRandom(msg.sender, 250);

    }

    function airdrop_Punk(address sendTo) external onlyOwner  {
        uint256 count = 1;

        require(totalSupply() + count <= maxSupply(), "Sold Out!");
        require(msg.sender == tx.origin, "The minter is another contract");
        _mintRandom(sendTo, count);

    }

    function airdrop_Punks(address[] memory recipients, uint256[] memory amounts) external onlyOwner {
        require(recipients.length == amounts.length, "Recipients and amounts array length must be same");

        for (uint256 i = 0; i < recipients.length; i++) {
            _mintRandom(recipients[i], amounts[i]);
        }
    }


    function exists(uint tokenId) external view returns (bool) {
        return _exists(tokenId);
    }

    function tokenURI(uint256 id) public view override returns (string memory) {
        require(_exists(id), "Token does not exist");
        return constructTokenURI(uint16(id));
    }

    function constructTokenURI(uint16 tokenId) private view returns (string memory) {
        bytes memory svg = bytes(tokenImage(tokenId));
        bytes memory title = abi.encodePacked("OPPunk #", tokenId.toString());
        
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{',
                                '"name":"', title, '",'
                                '"description":"', tokenDescription, '",'
                                '"background_color":"#FF0421",'
                                '"image_data":"data:image/svg+xml;base64,', Base64.encode(svg), '",'
                                '"attributes": ',
                                punkAttributesAsJSON(tokenId), 
                                '}'
                            )
                        )
                    )
                )
            );
    }

    function initializePunk(uint16 punkId) private view returns (Punk memory) {
        Punk memory punk = Punk({
            id: punkId,
            sex: PunkAttributeValue.NONE,
            hair: PunkAttributeValue.NONE,
            eyes: PunkAttributeValue.NONE,
            beard: PunkAttributeValue.NONE,
            ears: PunkAttributeValue.NONE,
            lips: PunkAttributeValue.NONE,
            mouth: PunkAttributeValue.NONE,
            face: PunkAttributeValue.NONE,
            emotion: PunkAttributeValue.NONE,
            neck: PunkAttributeValue.NONE,
            nose: PunkAttributeValue.NONE,
            cheeks: PunkAttributeValue.NONE,
            teeth: PunkAttributeValue.NONE
        });
        
        punk.id = punkId;
        
        string memory attributes = punkDataContract.punkAttributes(punk.id);

        string[] memory attributeArray = attributes.split(",");
        
        for (uint i = 0; i < attributeArray.length; i++) {
            string memory untrimmedAttribute = attributeArray[i];
            string memory trimmedAttribute;
            
            if (i < 1) {
                trimmedAttribute = untrimmedAttribute.split(' ')[0];
            } else {
                trimmedAttribute = untrimmedAttribute._substring(int(bytes(untrimmedAttribute).length - 1), 1);
            }
            
            PunkAttributeValue attrValue = PunkAttributeValue(uint(extendedPunkDataContract.attrStringToEnumMapping(trimmedAttribute)));
            PunkAttributeType attrType = PunkAttributeType(uint(extendedPunkDataContract.attrValueToTypeEnumMapping(ExtendedPunkDataInterface.PunkAttributeValue(uint(attrValue)))));
            
            if (attrType == PunkAttributeType.SEX) {
                punk.sex = attrValue;
            } else if (attrType == PunkAttributeType.HAIR) {
                punk.hair = attrValue;
            } else if (attrType == PunkAttributeType.EYES) {
                punk.eyes = attrValue;
            } else if (attrType == PunkAttributeType.BEARD) {
                punk.beard = attrValue;
            } else if (attrType == PunkAttributeType.EARS) {
                punk.ears = attrValue;
            } else if (attrType == PunkAttributeType.LIPS) {
                punk.lips = attrValue;
            } else if (attrType == PunkAttributeType.MOUTH) {
                punk.mouth = attrValue;
            } else if (attrType == PunkAttributeType.FACE) {
                punk.face = attrValue;
            } else if (attrType == PunkAttributeType.EMOTION) {
                punk.emotion = attrValue;
            } else if (attrType == PunkAttributeType.NECK) {
                punk.neck = attrValue;
            } else if (attrType == PunkAttributeType.NOSE) {
                punk.nose = attrValue;
            } else if (attrType == PunkAttributeType.CHEEKS) {
                punk.cheeks = attrValue;
            } else if (attrType == PunkAttributeType.TEETH) {
                punk.teeth = attrValue;
            }
        }
        
        return punk;
    }

    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    function tokenImage(uint16 tokenId) public view returns (string memory) {
        bytes memory pixels = punkDataContract.punkImage(uint16(tokenId));
        bytes memory svgBytes = DynamicBuffer.allocate(1024 * 128);
        
        svgBytes.appendSafe('<svg width="1200" height="1200" shape-rendering="crispEdges" xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 24 24"><style>rect{width:1px;height:1px}</style><rect x="0" y="0" style="width:100%;height:100%" fill="#FF0421" /><g style="transform: translate(calc(50% - 12px), calc(50% - 12px))">');
        
        bytes memory buffer = new bytes(8);
        for (uint256 y = 0; y < 24; y++) {
            for (uint256 x = 0; x < 24; x++) {
                uint256 p = (y * 24 + x) * 4;
                if (uint8(pixels[p + 3]) > 0) {
                    for (uint256 i = 0; i < 4; i++) {
                        uint8 value = uint8(pixels[p + i]);
                        
                        buffer[i * 2 + 1] = _HEX_SYMBOLS[value & 0xf];
                        value >>= 4;
                        buffer[i * 2] = _HEX_SYMBOLS[value & 0xf];
                    }

                    string memory oldColor = string(buffer);
                    
                    svgBytes.appendSafe(
                        abi.encodePacked(
                            '<rect x="',
                            x.toString(),
                            '" y="',
                            y.toString(),
                            '" fill="#',
                            oldColor,
                            '"/>'
                        )
                    );
                }
            }
        }
        
        svgBytes.appendSafe('</g></svg>');
        return string(svgBytes);
    }

    function punkAttributeCount(Punk memory punk) private pure returns (uint totalCount) {
        PunkAttributeValue[13] memory attrArray = [
            punk.sex,
            punk.hair,
            punk.eyes,
            punk.beard,
            punk.ears,
            punk.lips,
            punk.mouth,
            punk.face,
            punk.emotion,
            punk.neck,
            punk.nose,
            punk.cheeks,
            punk.teeth
        ];
        
        for (uint i = 0; i < 13; ++i) {
            if (attrArray[i] != PunkAttributeValue.NONE) {
                totalCount++;
            }
        }
        // Don't count sex as an attribute
        totalCount--;
    }

    function punkAttributesAsJSON(uint16 punkId) public view returns (string memory json) {
        Punk memory punk = initializePunk(punkId);
        PunkAttributeValue none = PunkAttributeValue.NONE;
        
        bytes memory output = "[";
        
        PunkAttributeValue[13] memory attrArray = [
            punk.sex,
            punk.hair,
            punk.eyes,
            punk.beard,
            punk.ears,
            punk.lips,
            punk.mouth,
            punk.face,
            punk.emotion,
            punk.neck,
            punk.nose,
            punk.cheeks,
            punk.teeth
        ];

        uint attrCount = punkAttributeCount(punk);
        uint count = 0;

        for (uint i = 0; i < 13; ++i) {
            PunkAttributeValue attrVal = attrArray[i];

            if (attrVal != none) {
                output = abi.encodePacked(output, punkAttributeAsJSON(attrVal));

                if (count < attrCount) {
                    output.appendSafe(",");
                    ++count;
                }
            }
        }
        
        return string(abi.encodePacked(output, "]"));
    }

    function punkAttributeAsJSON(PunkAttributeValue attribute) internal view returns (string memory json) {
        require(attribute != PunkAttributeValue.NONE);

        string memory attributeAsString = extendedPunkDataContract.attrEnumToStringMapping(ExtendedPunkDataInterface.PunkAttributeValue(uint(attribute)));
        string memory attributeTypeAsString;
        
        PunkAttributeType attrType = PunkAttributeType(uint(extendedPunkDataContract.attrValueToTypeEnumMapping(ExtendedPunkDataInterface.PunkAttributeValue(uint(attribute)))));

        if (attrType == PunkAttributeType.SEX) {
            attributeTypeAsString = "Sex";
        } else if (attrType == PunkAttributeType.HAIR) {
            attributeTypeAsString = "Hair";
        } else if (attrType == PunkAttributeType.EYES) {
            attributeTypeAsString = "Eyes";
        } else if (attrType == PunkAttributeType.BEARD) {
            attributeTypeAsString = "Beard";
        } else if (attrType == PunkAttributeType.EARS) {
            attributeTypeAsString = "Ears";
        } else if (attrType == PunkAttributeType.LIPS) {
            attributeTypeAsString = "Lips";
        } else if (attrType == PunkAttributeType.MOUTH) {
            attributeTypeAsString = "Mouth";
        } else if (attrType == PunkAttributeType.FACE) {
            attributeTypeAsString = "Face";
        } else if (attrType == PunkAttributeType.EMOTION) {
            attributeTypeAsString = "Emotion";
        } else if (attrType == PunkAttributeType.NECK) {
            attributeTypeAsString = "Neck";
        } else if (attrType == PunkAttributeType.NOSE) {
            attributeTypeAsString = "Nose";
        } else if (attrType == PunkAttributeType.CHEEKS) {
            attributeTypeAsString = "Cheeks";
        } else if (attrType == PunkAttributeType.TEETH) {
            attributeTypeAsString = "Teeth";
        }
        
        return string(abi.encodePacked('{"trait_type":"', attributeTypeAsString, '", "value":"', attributeAsString, '"}'));
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"punkDataContractAddress","type":"address"},{"internalType":"address","name":"extendedPunkDataContractAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"FreeAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sendTo","type":"address"}],"name":"airdrop_Punk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"airdrop_Punks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"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":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"punkId","type":"uint16"}],"name":"punkAttributesAsJSON","outputs":[{"internalType":"string","name":"json","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"set_Price","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":"team_mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggle_Minting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"tokenImage","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e060405266038d7ea4c68000600a55600b805460ff191690553480156200002657600080fd5b50604051620044e0380380620044e0833981016040819052620000499162000166565b604051806040016040528060088152602001674f502050756e6b7360c01b815250604051806040016040528060068152602001654f5050554e4b60d01b81525061271082600090816200009d919062000243565b506001620000ac838262000243565b50608081905260035550620000c3905033620000f7565b60016009556001600160a01b0391821660a0521660c052600b8054610100600160a81b03191633610100021790556200030f565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200016157600080fd5b919050565b600080604083850312156200017a57600080fd5b620001858362000149565b9150620001956020840162000149565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001c957607f821691505b602082108103620001ea57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200023e57600081815260208120601f850160051c81016020861015620002195750805b601f850160051c820191505b818110156200023a5782815560010162000225565b5050505b505050565b81516001600160401b038111156200025f576200025f6200019e565b6200027781620002708454620001b4565b84620001f0565b602080601f831160018114620002af5760008415620002965750858301515b600019600386901b1c1916600185901b1785556200023a565b600085815260208120601f198616915b82811015620002e057888601518255948401946001909101908401620002bf565b5085821015620002ff5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05161417062000370600039600081816118880152818161192601528181611f93015261204c015260008181610f7d015261172f0152600081816104f501528181610cd1015281816112d601526114ae01526141706000f3fe6080604052600436106101e35760003560e01c80638da5cb5b11610102578063d123973011610095578063db48231211610064578063db4823121461055e578063e985e9c51461057e578063ed29b76d1461059e578063f2fde38b146105ce57600080fd5b8063d1239730146104cc578063d5abeb01146104e6578063d5f3948814610519578063d9685a301461053e57600080fd5b8063a0712d68116100d1578063a0712d6814610459578063a22cb4651461046c578063b88d4fde1461048c578063c87b56dd146104ac57600080fd5b80638da5cb5b146103f157806395d89b411461040f5780639896ed11146104245780639dc823b51461044457600080fd5b80633ccfd60b1161017a5780636352211e116101495780636352211e146103865780636817c76c146103a657806370a08231146103bc578063715018a6146103dc57600080fd5b80633ccfd60b1461031c57806342842e0e146103315780634f423a9d146103515780634f558e791461036657600080fd5b8063095ea7b3116101b6578063095ea7b3146102975780630ac44210146102b957806318160ddd146102d957806323b872dd146102fc57600080fd5b806301ffc9a7146101e8578063023abe2b1461021d57806306fdde031461024a578063081812fc1461025f575b600080fd5b3480156101f457600080fd5b50610208610203366004613534565b6105ee565b60405190151581526020015b60405180910390f35b34801561022957600080fd5b5061023d610238366004613551565b610640565b60405161021491906135c5565b34801561025657600080fd5b5061023d6109bd565b34801561026b57600080fd5b5061027f61027a3660046135d8565b610a4f565b6040516001600160a01b039091168152602001610214565b3480156102a357600080fd5b506102b76102b236600461360d565b610ae9565b005b3480156102c557600080fd5b506102b76102d436600461370d565b610bfe565b3480156102e557600080fd5b506102ee610cca565b604051908152602001610214565b34801561030857600080fd5b506102b76103173660046137cd565b610cff565b34801561032857600080fd5b506102b7610d30565b34801561033d57600080fd5b506102b761034c3660046137cd565b610dd8565b34801561035d57600080fd5b506102b7610df3565b34801561037257600080fd5b506102086103813660046135d8565b610e18565b34801561039257600080fd5b5061027f6103a13660046135d8565b610e37565b3480156103b257600080fd5b506102ee600a5481565b3480156103c857600080fd5b506102ee6103d7366004613809565b610eae565b3480156103e857600080fd5b506102b7610f35565b3480156103fd57600080fd5b506008546001600160a01b031661027f565b34801561041b57600080fd5b5061023d610f47565b34801561043057600080fd5b5061023d61043f366004613551565b610f56565b34801561045057600080fd5b506102b761126e565b6102b76104673660046135d8565b61128a565b34801561047857600080fd5b506102b7610487366004613824565b6113f8565b34801561049857600080fd5b506102b76104a7366004613888565b611403565b3480156104b857600080fd5b5061023d6104c73660046135d8565b61143b565b3480156104d857600080fd5b50600b546102089060ff1681565b3480156104f257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102ee565b34801561052557600080fd5b50600b5461027f9061010090046001600160a01b031681565b34801561054a57600080fd5b506102b7610559366004613809565b6114a2565b34801561056a57600080fd5b506102b76105793660046135d8565b611573565b34801561058a57600080fd5b5061020861059936600461392e565b611580565b3480156105aa57600080fd5b506102086105b9366004613809565b600c6020526000908152604090205460ff1681565b3480156105da57600080fd5b506102b76105e9366004613809565b6115ae565b60006001600160e01b031982166380ac58cd60e01b148061061f57506001600160e01b03198216635b5e139f60e01b145b8061063a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600061064d83611627565b9050600080604051806040016040528060018152602001605b60f81b81525090506000604051806101a001604052808560200151605c81111561069257610692613961565b605c8111156106a3576106a3613961565b81526020018560400151605c8111156106be576106be613961565b605c8111156106cf576106cf613961565b81526020018560600151605c8111156106ea576106ea613961565b605c8111156106fb576106fb613961565b81526020018560800151605c81111561071657610716613961565b605c81111561072757610727613961565b81526020018560a00151605c81111561074257610742613961565b605c81111561075357610753613961565b81526020018560c00151605c81111561076e5761076e613961565b605c81111561077f5761077f613961565b81526020018560e00151605c81111561079a5761079a613961565b605c8111156107ab576107ab613961565b8152602001856101000151605c8111156107c7576107c7613961565b605c8111156107d8576107d8613961565b8152602001856101200151605c8111156107f4576107f4613961565b605c81111561080557610805613961565b8152602001856101400151605c81111561082157610821613961565b605c81111561083257610832613961565b8152602001856101600151605c81111561084e5761084e613961565b605c81111561085f5761085f613961565b8152602001856101800151605c81111561087b5761087b613961565b605c81111561088c5761088c613961565b8152602001856101a00151605c8111156108a8576108a8613961565b605c8111156108b9576108b9613961565b9052905060006108c885611cb3565b90506000805b600d81101561098f5760008482600d81106108eb576108eb613977565b6020020151905086605c81111561090457610904613961565b81605c81111561091657610916613961565b1461097e578561092582611f6f565b6040516020016109369291906139a9565b60405160208183030381529060405295508383101561097e576040805180820190915260018152600b60fa1b6020820152610972908790612465565b61097b836139ee565b92505b50610988816139ee565b90506108ce565b50836040516020016109a19190613a07565b6040516020818303038152906040529650505050505050919050565b6060600080546109cc90613a2c565b80601f01602080910402602001604051908101604052809291908181526020018280546109f890613a2c565b8015610a455780601f10610a1a57610100808354040283529160200191610a45565b820191906000526020600020905b815481529060010190602001808311610a2857829003601f168201915b5050505050905090565b6000818152600460205260408120546001600160a01b0316610acd5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610af482610e37565b9050806001600160a01b0316836001600160a01b031603610b615760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610ac4565b336001600160a01b0382161480610b7d5750610b7d8133611580565b610bef5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610ac4565b610bf983836124ea565b505050565b610c06612558565b8051825114610c705760405162461bcd60e51b815260206004820152603060248201527f526563697069656e747320616e6420616d6f756e7473206172726179206c656e60448201526f677468206d7573742062652073616d6560801b6064820152608401610ac4565b60005b8251811015610bf957610cb8838281518110610c9157610c91613977565b6020026020010151838381518110610cab57610cab613977565b60200260200101516125b2565b80610cc2816139ee565b915050610c73565b60006003547f0000000000000000000000000000000000000000000000000000000000000000610cfa9190613a66565b905090565b610d093382612791565b610d255760405162461bcd60e51b8152600401610ac490613a79565b610bf9838383612860565b610d38612558565b610d406129fc565b604051600090339047908381818185875af1925050503d8060008114610d82576040519150601f19603f3d011682016040523d82523d6000602084013e610d87565b606091505b5050905080610dcb5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610ac4565b50610dd66001600955565b565b610bf983838360405180602001604052806000815250611403565b610dfb612558565b610e036129fc565b610e0e3360fa6125b2565b610dd66001600955565b6000818152600460205260408120546001600160a01b0316151561063a565b6000818152600460205260408120546001600160a01b03168061063a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610ac4565b60006001600160a01b038216610f195760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610ac4565b506001600160a01b031660009081526005602052604090205490565b610f3d612558565b610dd66000612a55565b6060600180546109cc90613a2c565b604051631f2f054b60e11b815261ffff821660048201526060906000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633e5e0a9690602401600060405180830381865afa158015610fc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fec9190810190613afa565b6040805162020060810190915262020040815260006020909101818152919250506110336040518061016001604052806101318152602001613fca61013191398290612465565b60408051600880825281830190925260009160208201818036833701905050905060005b60188110156112395760005b60188110156112265760008161107a846018613b43565b6110849190613b5a565b61108f906004613b43565b905060008661109f836003613b5a565b815181106110af576110af613977565b016020015160f81c11156112135760005b60048110156111d0576000876110d68385613b5a565b815181106110e6576110e6613977565b016020015160f81c90506f181899199a1a9b1b9c1cb0b131b232b360811b600f82166010811061111857611118613977565b1a60f81b86611128846002613b43565b611133906001613b5a565b8151811061114357611143613977565b60200101906001600160f81b031916908160001a90535060041c600f166f181899199a1a9b1b9c1cb0b131b232b360811b816010811061118557611185613977565b1a60f81b86611195846002613b43565b815181106111a5576111a5613977565b60200101906001600160f81b031916908160001a9053505080806111c8906139ee565b9150506110c0565b50836112116111de84612aa7565b6111e786612aa7565b836040516020016111fa93929190613b6d565b60408051601f198184030181529190528790612465565b505b508061121e816139ee565b915050611063565b5080611231816139ee565b915050611057565b5060408051808201909152600a8152691e17b39f1e17b9bb339f60b11b6020820152611266908390612465565b509392505050565b611276612558565b600b805460ff19811660ff90911615179055565b600a54600b5460ff166112d45760405162461bcd60e51b8152602060048201526012602482015271135a5b9d081b9bdd081c9958591e481e595d60721b6044820152606401610ac4565b7f0000000000000000000000000000000000000000000000000000000000000000826112fe610cca565b6113089190613b5a565b11156113425760405162461bcd60e51b8152602060048201526009602482015268536f6c64204f75742160b81b6044820152606401610ac4565b61134c8183613b43565b34101561139b5760405162461bcd60e51b815260206004820181905260248201527f506c656173652073656e64207468652065786163742045544820616d6f756e746044820152606401610ac4565b3332146113ea5760405162461bcd60e51b815260206004820152601e60248201527f546865206d696e74657220697320616e6f7468657220636f6e747261637400006044820152606401610ac4565b6113f433836125b2565b5050565b6113f4338383612b38565b61140d3383612791565b6114295760405162461bcd60e51b8152600401610ac490613a79565b61143584848484612c06565b50505050565b6000818152600460205260409020546060906001600160a01b03166114995760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610ac4565b61063a82612c39565b6114aa612558565b60017f0000000000000000000000000000000000000000000000000000000000000000816114d6610cca565b6114e09190613b5a565b111561151a5760405162461bcd60e51b8152602060048201526009602482015268536f6c64204f75742160b81b6044820152606401610ac4565b3332146115695760405162461bcd60e51b815260206004820152601e60248201527f546865206d696e74657220697320616e6f7468657220636f6e747261637400006044820152606401610ac4565b6113f482826125b2565b61157b612558565b600a55565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6115b6612558565b6001600160a01b03811661161b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ac4565b61162481612a55565b50565b611699604080516101c0810190915260008082526020820190815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000905290565b604080516101c0810190915261ffff831681526000906020810182815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000905261ffff84168082526040516376dfe29760e01b815260048101919091529091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906376dfe29790602401600060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117a69190810190613afa565b905060006117d6604051806040016040528060018152602001600b60fa1b81525083612cf290919063ffffffff16565b905060005b8151811015611ca95760008282815181106117f8576117f8613977565b6020026020010151905060606001831015611851576040805180820190915260018152600160fd1b6020820152611830908390612cf2565b60008151811061184257611842613977565b6020026020010151905061186e565b61186b600183516118629190613a66565b83906001612edf565b90505b604051631a2d891b60e31b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d16c48d8906118bd9085906004016135c5565b602060405180830381865afa1580156118da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fe9190613bfe565b605c81111561190f5761190f613961565b605c81111561192057611920613961565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663683375c483605c81111561196557611965613961565b605c81111561197657611976613961565b6040518263ffffffff1660e01b81526004016119929190613c1f565b602060405180830381865afa1580156119af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d39190613c47565b600c8111156119e4576119e4613961565b600c8111156119f5576119f5613961565b9050600081600c811115611a0b57611a0b613961565b03611a41576020880182605c811115611a2657611a26613961565b9081605c811115611a3957611a39613961565b905250611c92565b600181600c811115611a5557611a55613961565b03611a70576040880182605c811115611a2657611a26613961565b600281600c811115611a8457611a84613961565b03611a9f576060880182605c811115611a2657611a26613961565b600381600c811115611ab357611ab3613961565b03611ace576080880182605c811115611a2657611a26613961565b600481600c811115611ae257611ae2613961565b03611afd5760a0880182605c811115611a2657611a26613961565b600581600c811115611b1157611b11613961565b03611b2c5760c0880182605c811115611a2657611a26613961565b600681600c811115611b4057611b40613961565b03611b5b5760e0880182605c811115611a2657611a26613961565b600781600c811115611b6f57611b6f613961565b03611b8b57610100880182605c811115611a2657611a26613961565b600881600c811115611b9f57611b9f613961565b03611bbb57610120880182605c811115611a2657611a26613961565b600981600c811115611bcf57611bcf613961565b03611beb57610140880182605c811115611a2657611a26613961565b600a81600c811115611bff57611bff613961565b03611c1b57610160880182605c811115611a2657611a26613961565b600b81600c811115611c2f57611c2f613961565b03611c4b57610180880182605c811115611a2657611a26613961565b600c81600c811115611c5f57611c5f613961565b03611c92576101a0880182605c811115611c7b57611c7b613961565b9081605c811115611c8e57611c8e613961565b9052505b505050508080611ca1906139ee565b9150506117db565b5091949350505050565b600080604051806101a001604052808460200151605c811115611cd857611cd8613961565b605c811115611ce957611ce9613961565b81526020018460400151605c811115611d0457611d04613961565b605c811115611d1557611d15613961565b81526020018460600151605c811115611d3057611d30613961565b605c811115611d4157611d41613961565b81526020018460800151605c811115611d5c57611d5c613961565b605c811115611d6d57611d6d613961565b81526020018460a00151605c811115611d8857611d88613961565b605c811115611d9957611d99613961565b81526020018460c00151605c811115611db457611db4613961565b605c811115611dc557611dc5613961565b81526020018460e00151605c811115611de057611de0613961565b605c811115611df157611df1613961565b8152602001846101000151605c811115611e0d57611e0d613961565b605c811115611e1e57611e1e613961565b8152602001846101200151605c811115611e3a57611e3a613961565b605c811115611e4b57611e4b613961565b8152602001846101400151605c811115611e6757611e67613961565b605c811115611e7857611e78613961565b8152602001846101600151605c811115611e9457611e94613961565b605c811115611ea557611ea5613961565b8152602001846101800151605c811115611ec157611ec1613961565b605c811115611ed257611ed2613961565b8152602001846101a00151605c811115611eee57611eee613961565b605c811115611eff57611eff613961565b9052905060005b600d811015611f5c5760008282600d8110611f2357611f23613977565b6020020151605c811115611f3957611f39613961565b14611f4c5782611f48816139ee565b9350505b611f55816139ee565b9050611f06565b5081611f6781613c68565b949350505050565b6060600082605c811115611f8557611f85613961565b03611f8f57600080fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc9faca584605c811115611fd257611fd2613961565b605c811115611fe357611fe3613961565b6040518263ffffffff1660e01b8152600401611fff9190613c1f565b600060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120449190810190613afa565b9050606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663683375c486605c81111561208b5761208b613961565b605c81111561209c5761209c613961565b6040518263ffffffff1660e01b81526004016120b89190613c1f565b602060405180830381865afa1580156120d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f99190613c47565b600c81111561210a5761210a613961565b600c81111561211b5761211b613961565b9050600081600c81111561213157612131613961565b0361215957604051806040016040528060038152602001620a6caf60eb1b8152509150612439565b600181600c81111561216d5761216d613961565b0361219657604051806040016040528060048152602001632430b4b960e11b8152509150612439565b600281600c8111156121aa576121aa613961565b036121d357604051806040016040528060048152602001634579657360e01b8152509150612439565b600381600c8111156121e7576121e7613961565b0361221157604051806040016040528060058152602001641099585c9960da1b8152509150612439565b600481600c81111561222557612225613961565b0361224e57604051806040016040528060048152602001634561727360e01b8152509150612439565b600581600c81111561226257612262613961565b0361228b57604051806040016040528060048152602001634c69707360e01b8152509150612439565b600681600c81111561229f5761229f613961565b036122c9576040518060400160405280600581526020016409adeeae8d60db1b8152509150612439565b600781600c8111156122dd576122dd613961565b0361230657604051806040016040528060048152602001634661636560e01b8152509150612439565b600881600c81111561231a5761231a613961565b03612346576040518060400160405280600781526020016622b6b7ba34b7b760c91b8152509150612439565b600981600c81111561235a5761235a613961565b0361238357604051806040016040528060048152602001634e65636b60e01b8152509150612439565b600a81600c81111561239757612397613961565b036123c057604051806040016040528060048152602001634e6f736560e01b8152509150612439565b600b81600c8111156123d4576123d4613961565b036123ff5760405180604001604052806006815260200165436865656b7360d01b8152509150612439565b600c81600c81111561241357612413613961565b0361243957604051806040016040528060058152602001640a8cacae8d60db1b81525091505b818360405160200161244c929190613c7f565b6040516020818303038152906040529350505050919050565b601f1982015182518251603f199092019182906124829083613b5a565b11156124e05760405162461bcd60e51b815260206004820152602760248201527f44796e616d69634275666665723a20417070656e64696e67206f7574206f66206044820152663137bab732399760c91b6064820152608401610ac4565b6114358484612fd2565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061251f82610e37565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6008546001600160a01b03163314610dd65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ac4565b3332146125f95760405162461bcd60e51b815260206004820152601560248201527410dbdb9d1c9858dd1cc818d85b9b9bdd081b5a5b9d605a1b6044820152606401610ac4565b6001600160a01b03821661264f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610ac4565b600081116126b05760405162461bcd60e51b815260206004820152602860248201527f455243373231723a206e65656420746f206d696e74206174206c65617374206f6044820152673732903a37b5b2b760c11b6064820152608401610ac4565b8060035410156127165760405162461bcd60e51b815260206004820152602b60248201527f455243373231723a206d696e74696e67206d6f726520746f6b656e732074686160448201526a6e20617661696c61626c6560a81b6064820152608401610ac4565b60035460005b828110156127595760006127308584613008565b905061273c8582613066565b61274583613c68565b92505080612752906139ee565b905061271c565b5060038190556001600160a01b03831660009081526005602052604081208054849290612787908490613b5a565b9091555050505050565b6000818152600460205260408120546001600160a01b031661280a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ac4565b600061281583610e37565b9050806001600160a01b0316846001600160a01b031614806128505750836001600160a01b031661284584610a4f565b6001600160a01b0316145b80611f675750611f678185611580565b826001600160a01b031661287382610e37565b6001600160a01b0316146128d75760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610ac4565b6001600160a01b0382166129395760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610ac4565b6129446000826124ea565b6001600160a01b038316600090815260056020526040812080546001929061296d908490613a66565b90915550506001600160a01b038216600090815260056020526040812080546001929061299b908490613b5a565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600260095403612a4e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ac4565b6002600955565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606000612ab4836130bf565b600101905060008167ffffffffffffffff811115612ad457612ad4613637565b6040519080825280601f01601f191660200182016040528015612afe576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450841561126657612b08565b816001600160a01b0316836001600160a01b031603612b995760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610ac4565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612c11848484612860565b612c1d84848484613197565b6114355760405162461bcd60e51b8152600401610ac490613d07565b60606000612c4683610f56565b90506000612c578461ffff16612aa7565b604051602001612c679190613d59565b60408051601f19818403018152606083019091526022808352909250612cca918391613fa86020830139612c9a85613298565b612ca388610640565b604051602001612cb69493929190613d89565b604051602081830303815290604052613298565b604051602001612cda9190613ea2565b60405160208183030381529060405292505050919050565b606082600060015b60018351612d089190613a66565b821015612d4b576000612d1c8787856133eb565b90508019612d2a5750612d4b565b81612d34816139ee565b9250612d439050816001613b5a565b925050612cfa565b8067ffffffffffffffff811115612d6457612d64613637565b604051908082528060200260200182016040528015612d9757816020015b6060815260200190600190039081612d825790505b50935060009150600090505b60018351612db19190613a66565b821015612ed6576000612dc58787856133eb565b90508019612dd1575082515b6000612ddd8483613a66565b67ffffffffffffffff811115612df557612df5613637565b6040519080825280601f01601f191660200182016040528015612e1f576020820181803683370190505b509050806000855b84811015612e9657878181518110612e4157612e41613977565b01602001516001600160f81b0319168383612e5b816139ee565b945081518110612e6d57612e6d613977565b60200101906001600160f81b031916908160001a90535080612e8e816139ee565b915050612e27565b50612ea2846001613b5a565b9550818886612eb0816139ee565b975081518110612ec257612ec2613977565b602002602001018190525050505050612da3565b50505092915050565b82516060908490612ef08585613ee7565b1115612efe57612efe613f0f565b60008467ffffffffffffffff811115612f1957612f19613637565b6040519080825280601f01601f191660200182016040528015612f43576020820181803683370190505b509050806000855b612f558888613ee7565b811015612fc357848181518110612f6e57612f6e613977565b01602001516001600160f81b0319168383612f88816139ee565b945081518110612f9a57612f9a613977565b60200101906001600160f81b031916908160001a90535080612fbb816139ee565b915050612f4b565b509093505050505b9392505050565b8051602082019150808201602084510184015b81841015612ffd578351815260209384019301612fe5565b505082510190915250565b604080516001600160a01b038416602080830191909152308284015260608083018590528351808403909101815260809092019092528051910120600090816130518483613f25565b905061305d8185613486565b95945050505050565b60008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106130fe5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061312a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061314857662386f26fc10000830492506010015b6305f5e1008310613160576305f5e100830492506008015b612710831061317457612710830492506004015b60648310613186576064830492506002015b600a831061063a5760010192915050565b60006001600160a01b0384163b1561328d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906131db903390899088908890600401613f39565b6020604051808303816000875af1925050508015613216575060408051601f3d908101601f1916820190925261321391810190613f76565b60015b613273573d808015613244576040519150601f19603f3d011682016040523d82523d6000602084013e613249565b606091505b50805160000361326b5760405162461bcd60e51b8152600401610ac490613d07565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611f67565b506001949350505050565b606081516000036132b757505060408051602081019091526000815290565b60006040518060600160405280604081526020016140fb60409139905060006003845160026132e69190613b5a565b6132f09190613f93565b6132fb906004613b43565b67ffffffffffffffff81111561331357613313613637565b6040519080825280601f01601f19166020018201604052801561333d576020820181803683370190505b509050600182016020820185865187015b808210156133a9576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f811685015184535060018301925061334e565b50506003865106600181146133c557600281146133d8576133e0565b603d6001830353603d60028303536133e0565b603d60018303535b509195945050505050565b81516000908490849060011461340357613403613f0f565b835b8251811015613478578160008151811061342157613421613977565b602001015160f81c60f81b6001600160f81b03191683828151811061344857613448613977565b01602001516001600160f81b03191603613466579250612fcb915050565b80613470816139ee565b915050613405565b506000199695505050505050565b600082815260026020526040812054818181036134a45750836134a7565b50805b60006134b4600186613a66565b6000818152600260205260409020549091508682146134fd57806000036134eb5760008781526002602052604090208290556134fd565b60008781526002602052604090208190555b8015613513576000828152600260205260408120555b509095945050505050565b6001600160e01b03198116811461162457600080fd5b60006020828403121561354657600080fd5b8135612fcb8161351e565b60006020828403121561356357600080fd5b813561ffff81168114612fcb57600080fd5b60005b83811015613590578181015183820152602001613578565b50506000910152565b600081518084526135b1816020860160208601613575565b601f01601f19169290920160200192915050565b602081526000612fcb6020830184613599565b6000602082840312156135ea57600080fd5b5035919050565b80356001600160a01b038116811461360857600080fd5b919050565b6000806040838503121561362057600080fd5b613629836135f1565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561367657613676613637565b604052919050565b600067ffffffffffffffff82111561369857613698613637565b5060051b60200190565b600082601f8301126136b357600080fd5b813560206136c86136c38361367e565b61364d565b82815260059290921b840181019181810190868411156136e757600080fd5b8286015b8481101561370257803583529183019183016136eb565b509695505050505050565b6000806040838503121561372057600080fd5b823567ffffffffffffffff8082111561373857600080fd5b818501915085601f83011261374c57600080fd5b8135602061375c6136c38361367e565b82815260059290921b8401810191818101908984111561377b57600080fd5b948201945b838610156137a057613791866135f1565b82529482019490820190613780565b965050860135925050808211156137b657600080fd5b506137c3858286016136a2565b9150509250929050565b6000806000606084860312156137e257600080fd5b6137eb846135f1565b92506137f9602085016135f1565b9150604084013590509250925092565b60006020828403121561381b57600080fd5b612fcb826135f1565b6000806040838503121561383757600080fd5b613840836135f1565b91506020830135801515811461385557600080fd5b809150509250929050565b600067ffffffffffffffff82111561387a5761387a613637565b50601f01601f191660200190565b6000806000806080858703121561389e57600080fd5b6138a7856135f1565b93506138b5602086016135f1565b925060408501359150606085013567ffffffffffffffff8111156138d857600080fd5b8501601f810187136138e957600080fd5b80356138f76136c382613860565b81815288602083850101111561390c57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561394157600080fd5b61394a836135f1565b9150613958602084016135f1565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000815161399f818560208601613575565b9290920192915050565b600083516139bb818460208801613575565b8351908301906139cf818360208801613575565b01949350505050565b634e487b7160e01b600052601160045260246000fd5b600060018201613a0057613a006139d8565b5060010190565b60008251613a19818460208701613575565b605d60f81b920191825250600101919050565b600181811c90821680613a4057607f821691505b602082108103613a6057634e487b7160e01b600052602260045260246000fd5b50919050565b8181038181111561063a5761063a6139d8565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000613ad86136c384613860565b9050828152838383011115613aec57600080fd5b612fcb836020830184613575565b600060208284031215613b0c57600080fd5b815167ffffffffffffffff811115613b2357600080fd5b8201601f81018413613b3457600080fd5b611f6784825160208401613aca565b808202811582820484141761063a5761063a6139d8565b8082018082111561063a5761063a6139d8565b681e3932b1ba103c1e9160b91b81528351600090613b92816009850160208901613575565b6411103c9e9160d91b6009918401918201528451613bb781600e840160208901613575565b68222066696c6c3d222360b81b600e92909101918201528351613be1816017840160208801613575565b6211179f60e91b60179290910191820152601a0195945050505050565b600060208284031215613c1057600080fd5b8151605d8110612fcb57600080fd5b60208101605d8310613c4157634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215613c5957600080fd5b8151600d8110612fcb57600080fd5b600081613c7757613c776139d8565b506000190190565b6e3d913a3930b4ba2fba3cb832911d1160891b81528251600090613caa81600f850160208801613575565b6b111610113b30b63ab2911d1160a11b600f918401918201528351613cd681601b840160208801613575565b61227d60f01b601b9290910191820152601d01949350505050565b634e487b7160e01b600052601260045260246000fd5b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b674f5050756e6b202360c01b815260008251613d7c816008850160208701613575565b9190910160080192915050565b607b60f81b815267113730b6b2911d1160c11b60018201528451600090613db7816009850160208a01613575565b701116113232b9b1b934b83a34b7b7111d1160791b6009918401918201528551613de881601a840160208a01613575565b7f222c226261636b67726f756e645f636f6c6f72223a2223464630343231222c22601a92909101918201527f696d6167655f64617461223a22646174613a696d6167652f7376672b786d6c3b603a8201526618985cd94d8d0b60ca1b605a8201528451613e5c816061840160208901613575565b6f011161130ba3a3934b13aba32b9911d160851b60619290910191820152613e97613e8a607183018661398d565b607d60f81b815260010190565b979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251613eda81601d850160208701613575565b91909101601d0192915050565b8082018281126000831280158216821582161715613f0757613f076139d8565b505092915050565b634e487b7160e01b600052600160045260246000fd5b600082613f3457613f34613cf1565b500690565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613f6c90830184613599565b9695505050505050565b600060208284031215613f8857600080fd5b8151612fcb8161351e565b600082613fa257613fa2613cf1565b50049056fe4f502050756e6b73202d2053746f72656420656e746972656c79204f6e436861696e3c7376672077696474683d223132303022206865696768743d2231323030222073686170652d72656e646572696e673d22637269737045646765732220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d22312e32222076696577426f783d22302030203234203234223e3c7374796c653e726563747b77696474683a3170783b6865696768743a3170787d3c2f7374796c653e3c7265637420783d22302220793d223022207374796c653d2277696474683a313030253b6865696768743a31303025222066696c6c3d222346463034323122202f3e3c67207374796c653d227472616e73666f726d3a207472616e736c6174652863616c6328353025202d2031327078292c2063616c6328353025202d20313270782929223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220fa74a49fe22b1f8949afda47f597bf38c0a878ea58e95c98da72dbb6b236a9cc64736f6c63430008120033000000000000000000000000544cb9ccc57f10ebf230aeaeaef0e76cdc90b866000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c4

Deployed Bytecode

0x6080604052600436106101e35760003560e01c80638da5cb5b11610102578063d123973011610095578063db48231211610064578063db4823121461055e578063e985e9c51461057e578063ed29b76d1461059e578063f2fde38b146105ce57600080fd5b8063d1239730146104cc578063d5abeb01146104e6578063d5f3948814610519578063d9685a301461053e57600080fd5b8063a0712d68116100d1578063a0712d6814610459578063a22cb4651461046c578063b88d4fde1461048c578063c87b56dd146104ac57600080fd5b80638da5cb5b146103f157806395d89b411461040f5780639896ed11146104245780639dc823b51461044457600080fd5b80633ccfd60b1161017a5780636352211e116101495780636352211e146103865780636817c76c146103a657806370a08231146103bc578063715018a6146103dc57600080fd5b80633ccfd60b1461031c57806342842e0e146103315780634f423a9d146103515780634f558e791461036657600080fd5b8063095ea7b3116101b6578063095ea7b3146102975780630ac44210146102b957806318160ddd146102d957806323b872dd146102fc57600080fd5b806301ffc9a7146101e8578063023abe2b1461021d57806306fdde031461024a578063081812fc1461025f575b600080fd5b3480156101f457600080fd5b50610208610203366004613534565b6105ee565b60405190151581526020015b60405180910390f35b34801561022957600080fd5b5061023d610238366004613551565b610640565b60405161021491906135c5565b34801561025657600080fd5b5061023d6109bd565b34801561026b57600080fd5b5061027f61027a3660046135d8565b610a4f565b6040516001600160a01b039091168152602001610214565b3480156102a357600080fd5b506102b76102b236600461360d565b610ae9565b005b3480156102c557600080fd5b506102b76102d436600461370d565b610bfe565b3480156102e557600080fd5b506102ee610cca565b604051908152602001610214565b34801561030857600080fd5b506102b76103173660046137cd565b610cff565b34801561032857600080fd5b506102b7610d30565b34801561033d57600080fd5b506102b761034c3660046137cd565b610dd8565b34801561035d57600080fd5b506102b7610df3565b34801561037257600080fd5b506102086103813660046135d8565b610e18565b34801561039257600080fd5b5061027f6103a13660046135d8565b610e37565b3480156103b257600080fd5b506102ee600a5481565b3480156103c857600080fd5b506102ee6103d7366004613809565b610eae565b3480156103e857600080fd5b506102b7610f35565b3480156103fd57600080fd5b506008546001600160a01b031661027f565b34801561041b57600080fd5b5061023d610f47565b34801561043057600080fd5b5061023d61043f366004613551565b610f56565b34801561045057600080fd5b506102b761126e565b6102b76104673660046135d8565b61128a565b34801561047857600080fd5b506102b7610487366004613824565b6113f8565b34801561049857600080fd5b506102b76104a7366004613888565b611403565b3480156104b857600080fd5b5061023d6104c73660046135d8565b61143b565b3480156104d857600080fd5b50600b546102089060ff1681565b3480156104f257600080fd5b507f00000000000000000000000000000000000000000000000000000000000027106102ee565b34801561052557600080fd5b50600b5461027f9061010090046001600160a01b031681565b34801561054a57600080fd5b506102b7610559366004613809565b6114a2565b34801561056a57600080fd5b506102b76105793660046135d8565b611573565b34801561058a57600080fd5b5061020861059936600461392e565b611580565b3480156105aa57600080fd5b506102086105b9366004613809565b600c6020526000908152604090205460ff1681565b3480156105da57600080fd5b506102b76105e9366004613809565b6115ae565b60006001600160e01b031982166380ac58cd60e01b148061061f57506001600160e01b03198216635b5e139f60e01b145b8061063a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600061064d83611627565b9050600080604051806040016040528060018152602001605b60f81b81525090506000604051806101a001604052808560200151605c81111561069257610692613961565b605c8111156106a3576106a3613961565b81526020018560400151605c8111156106be576106be613961565b605c8111156106cf576106cf613961565b81526020018560600151605c8111156106ea576106ea613961565b605c8111156106fb576106fb613961565b81526020018560800151605c81111561071657610716613961565b605c81111561072757610727613961565b81526020018560a00151605c81111561074257610742613961565b605c81111561075357610753613961565b81526020018560c00151605c81111561076e5761076e613961565b605c81111561077f5761077f613961565b81526020018560e00151605c81111561079a5761079a613961565b605c8111156107ab576107ab613961565b8152602001856101000151605c8111156107c7576107c7613961565b605c8111156107d8576107d8613961565b8152602001856101200151605c8111156107f4576107f4613961565b605c81111561080557610805613961565b8152602001856101400151605c81111561082157610821613961565b605c81111561083257610832613961565b8152602001856101600151605c81111561084e5761084e613961565b605c81111561085f5761085f613961565b8152602001856101800151605c81111561087b5761087b613961565b605c81111561088c5761088c613961565b8152602001856101a00151605c8111156108a8576108a8613961565b605c8111156108b9576108b9613961565b9052905060006108c885611cb3565b90506000805b600d81101561098f5760008482600d81106108eb576108eb613977565b6020020151905086605c81111561090457610904613961565b81605c81111561091657610916613961565b1461097e578561092582611f6f565b6040516020016109369291906139a9565b60405160208183030381529060405295508383101561097e576040805180820190915260018152600b60fa1b6020820152610972908790612465565b61097b836139ee565b92505b50610988816139ee565b90506108ce565b50836040516020016109a19190613a07565b6040516020818303038152906040529650505050505050919050565b6060600080546109cc90613a2c565b80601f01602080910402602001604051908101604052809291908181526020018280546109f890613a2c565b8015610a455780601f10610a1a57610100808354040283529160200191610a45565b820191906000526020600020905b815481529060010190602001808311610a2857829003601f168201915b5050505050905090565b6000818152600460205260408120546001600160a01b0316610acd5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600660205260409020546001600160a01b031690565b6000610af482610e37565b9050806001600160a01b0316836001600160a01b031603610b615760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610ac4565b336001600160a01b0382161480610b7d5750610b7d8133611580565b610bef5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610ac4565b610bf983836124ea565b505050565b610c06612558565b8051825114610c705760405162461bcd60e51b815260206004820152603060248201527f526563697069656e747320616e6420616d6f756e7473206172726179206c656e60448201526f677468206d7573742062652073616d6560801b6064820152608401610ac4565b60005b8251811015610bf957610cb8838281518110610c9157610c91613977565b6020026020010151838381518110610cab57610cab613977565b60200260200101516125b2565b80610cc2816139ee565b915050610c73565b60006003547f0000000000000000000000000000000000000000000000000000000000002710610cfa9190613a66565b905090565b610d093382612791565b610d255760405162461bcd60e51b8152600401610ac490613a79565b610bf9838383612860565b610d38612558565b610d406129fc565b604051600090339047908381818185875af1925050503d8060008114610d82576040519150601f19603f3d011682016040523d82523d6000602084013e610d87565b606091505b5050905080610dcb5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610ac4565b50610dd66001600955565b565b610bf983838360405180602001604052806000815250611403565b610dfb612558565b610e036129fc565b610e0e3360fa6125b2565b610dd66001600955565b6000818152600460205260408120546001600160a01b0316151561063a565b6000818152600460205260408120546001600160a01b03168061063a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610ac4565b60006001600160a01b038216610f195760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610ac4565b506001600160a01b031660009081526005602052604090205490565b610f3d612558565b610dd66000612a55565b6060600180546109cc90613a2c565b604051631f2f054b60e11b815261ffff821660048201526060906000906001600160a01b037f000000000000000000000000544cb9ccc57f10ebf230aeaeaef0e76cdc90b8661690633e5e0a9690602401600060405180830381865afa158015610fc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fec9190810190613afa565b6040805162020060810190915262020040815260006020909101818152919250506110336040518061016001604052806101318152602001613fca61013191398290612465565b60408051600880825281830190925260009160208201818036833701905050905060005b60188110156112395760005b60188110156112265760008161107a846018613b43565b6110849190613b5a565b61108f906004613b43565b905060008661109f836003613b5a565b815181106110af576110af613977565b016020015160f81c11156112135760005b60048110156111d0576000876110d68385613b5a565b815181106110e6576110e6613977565b016020015160f81c90506f181899199a1a9b1b9c1cb0b131b232b360811b600f82166010811061111857611118613977565b1a60f81b86611128846002613b43565b611133906001613b5a565b8151811061114357611143613977565b60200101906001600160f81b031916908160001a90535060041c600f166f181899199a1a9b1b9c1cb0b131b232b360811b816010811061118557611185613977565b1a60f81b86611195846002613b43565b815181106111a5576111a5613977565b60200101906001600160f81b031916908160001a9053505080806111c8906139ee565b9150506110c0565b50836112116111de84612aa7565b6111e786612aa7565b836040516020016111fa93929190613b6d565b60408051601f198184030181529190528790612465565b505b508061121e816139ee565b915050611063565b5080611231816139ee565b915050611057565b5060408051808201909152600a8152691e17b39f1e17b9bb339f60b11b6020820152611266908390612465565b509392505050565b611276612558565b600b805460ff19811660ff90911615179055565b600a54600b5460ff166112d45760405162461bcd60e51b8152602060048201526012602482015271135a5b9d081b9bdd081c9958591e481e595d60721b6044820152606401610ac4565b7f0000000000000000000000000000000000000000000000000000000000002710826112fe610cca565b6113089190613b5a565b11156113425760405162461bcd60e51b8152602060048201526009602482015268536f6c64204f75742160b81b6044820152606401610ac4565b61134c8183613b43565b34101561139b5760405162461bcd60e51b815260206004820181905260248201527f506c656173652073656e64207468652065786163742045544820616d6f756e746044820152606401610ac4565b3332146113ea5760405162461bcd60e51b815260206004820152601e60248201527f546865206d696e74657220697320616e6f7468657220636f6e747261637400006044820152606401610ac4565b6113f433836125b2565b5050565b6113f4338383612b38565b61140d3383612791565b6114295760405162461bcd60e51b8152600401610ac490613a79565b61143584848484612c06565b50505050565b6000818152600460205260409020546060906001600160a01b03166114995760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610ac4565b61063a82612c39565b6114aa612558565b60017f0000000000000000000000000000000000000000000000000000000000002710816114d6610cca565b6114e09190613b5a565b111561151a5760405162461bcd60e51b8152602060048201526009602482015268536f6c64204f75742160b81b6044820152606401610ac4565b3332146115695760405162461bcd60e51b815260206004820152601e60248201527f546865206d696e74657220697320616e6f7468657220636f6e747261637400006044820152606401610ac4565b6113f482826125b2565b61157b612558565b600a55565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6115b6612558565b6001600160a01b03811661161b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ac4565b61162481612a55565b50565b611699604080516101c0810190915260008082526020820190815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000905290565b604080516101c0810190915261ffff831681526000906020810182815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000905261ffff84168082526040516376dfe29760e01b815260048101919091529091506000907f000000000000000000000000544cb9ccc57f10ebf230aeaeaef0e76cdc90b8666001600160a01b0316906376dfe29790602401600060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117a69190810190613afa565b905060006117d6604051806040016040528060018152602001600b60fa1b81525083612cf290919063ffffffff16565b905060005b8151811015611ca95760008282815181106117f8576117f8613977565b6020026020010151905060606001831015611851576040805180820190915260018152600160fd1b6020820152611830908390612cf2565b60008151811061184257611842613977565b6020026020010151905061186e565b61186b600183516118629190613a66565b83906001612edf565b90505b604051631a2d891b60e31b81526000906001600160a01b037f000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c4169063d16c48d8906118bd9085906004016135c5565b602060405180830381865afa1580156118da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fe9190613bfe565b605c81111561190f5761190f613961565b605c81111561192057611920613961565b905060007f000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c46001600160a01b031663683375c483605c81111561196557611965613961565b605c81111561197657611976613961565b6040518263ffffffff1660e01b81526004016119929190613c1f565b602060405180830381865afa1580156119af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d39190613c47565b600c8111156119e4576119e4613961565b600c8111156119f5576119f5613961565b9050600081600c811115611a0b57611a0b613961565b03611a41576020880182605c811115611a2657611a26613961565b9081605c811115611a3957611a39613961565b905250611c92565b600181600c811115611a5557611a55613961565b03611a70576040880182605c811115611a2657611a26613961565b600281600c811115611a8457611a84613961565b03611a9f576060880182605c811115611a2657611a26613961565b600381600c811115611ab357611ab3613961565b03611ace576080880182605c811115611a2657611a26613961565b600481600c811115611ae257611ae2613961565b03611afd5760a0880182605c811115611a2657611a26613961565b600581600c811115611b1157611b11613961565b03611b2c5760c0880182605c811115611a2657611a26613961565b600681600c811115611b4057611b40613961565b03611b5b5760e0880182605c811115611a2657611a26613961565b600781600c811115611b6f57611b6f613961565b03611b8b57610100880182605c811115611a2657611a26613961565b600881600c811115611b9f57611b9f613961565b03611bbb57610120880182605c811115611a2657611a26613961565b600981600c811115611bcf57611bcf613961565b03611beb57610140880182605c811115611a2657611a26613961565b600a81600c811115611bff57611bff613961565b03611c1b57610160880182605c811115611a2657611a26613961565b600b81600c811115611c2f57611c2f613961565b03611c4b57610180880182605c811115611a2657611a26613961565b600c81600c811115611c5f57611c5f613961565b03611c92576101a0880182605c811115611c7b57611c7b613961565b9081605c811115611c8e57611c8e613961565b9052505b505050508080611ca1906139ee565b9150506117db565b5091949350505050565b600080604051806101a001604052808460200151605c811115611cd857611cd8613961565b605c811115611ce957611ce9613961565b81526020018460400151605c811115611d0457611d04613961565b605c811115611d1557611d15613961565b81526020018460600151605c811115611d3057611d30613961565b605c811115611d4157611d41613961565b81526020018460800151605c811115611d5c57611d5c613961565b605c811115611d6d57611d6d613961565b81526020018460a00151605c811115611d8857611d88613961565b605c811115611d9957611d99613961565b81526020018460c00151605c811115611db457611db4613961565b605c811115611dc557611dc5613961565b81526020018460e00151605c811115611de057611de0613961565b605c811115611df157611df1613961565b8152602001846101000151605c811115611e0d57611e0d613961565b605c811115611e1e57611e1e613961565b8152602001846101200151605c811115611e3a57611e3a613961565b605c811115611e4b57611e4b613961565b8152602001846101400151605c811115611e6757611e67613961565b605c811115611e7857611e78613961565b8152602001846101600151605c811115611e9457611e94613961565b605c811115611ea557611ea5613961565b8152602001846101800151605c811115611ec157611ec1613961565b605c811115611ed257611ed2613961565b8152602001846101a00151605c811115611eee57611eee613961565b605c811115611eff57611eff613961565b9052905060005b600d811015611f5c5760008282600d8110611f2357611f23613977565b6020020151605c811115611f3957611f39613961565b14611f4c5782611f48816139ee565b9350505b611f55816139ee565b9050611f06565b5081611f6781613c68565b949350505050565b6060600082605c811115611f8557611f85613961565b03611f8f57600080fd5b60007f000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c46001600160a01b031663fc9faca584605c811115611fd257611fd2613961565b605c811115611fe357611fe3613961565b6040518263ffffffff1660e01b8152600401611fff9190613c1f565b600060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120449190810190613afa565b9050606060007f000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c46001600160a01b031663683375c486605c81111561208b5761208b613961565b605c81111561209c5761209c613961565b6040518263ffffffff1660e01b81526004016120b89190613c1f565b602060405180830381865afa1580156120d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f99190613c47565b600c81111561210a5761210a613961565b600c81111561211b5761211b613961565b9050600081600c81111561213157612131613961565b0361215957604051806040016040528060038152602001620a6caf60eb1b8152509150612439565b600181600c81111561216d5761216d613961565b0361219657604051806040016040528060048152602001632430b4b960e11b8152509150612439565b600281600c8111156121aa576121aa613961565b036121d357604051806040016040528060048152602001634579657360e01b8152509150612439565b600381600c8111156121e7576121e7613961565b0361221157604051806040016040528060058152602001641099585c9960da1b8152509150612439565b600481600c81111561222557612225613961565b0361224e57604051806040016040528060048152602001634561727360e01b8152509150612439565b600581600c81111561226257612262613961565b0361228b57604051806040016040528060048152602001634c69707360e01b8152509150612439565b600681600c81111561229f5761229f613961565b036122c9576040518060400160405280600581526020016409adeeae8d60db1b8152509150612439565b600781600c8111156122dd576122dd613961565b0361230657604051806040016040528060048152602001634661636560e01b8152509150612439565b600881600c81111561231a5761231a613961565b03612346576040518060400160405280600781526020016622b6b7ba34b7b760c91b8152509150612439565b600981600c81111561235a5761235a613961565b0361238357604051806040016040528060048152602001634e65636b60e01b8152509150612439565b600a81600c81111561239757612397613961565b036123c057604051806040016040528060048152602001634e6f736560e01b8152509150612439565b600b81600c8111156123d4576123d4613961565b036123ff5760405180604001604052806006815260200165436865656b7360d01b8152509150612439565b600c81600c81111561241357612413613961565b0361243957604051806040016040528060058152602001640a8cacae8d60db1b81525091505b818360405160200161244c929190613c7f565b6040516020818303038152906040529350505050919050565b601f1982015182518251603f199092019182906124829083613b5a565b11156124e05760405162461bcd60e51b815260206004820152602760248201527f44796e616d69634275666665723a20417070656e64696e67206f7574206f66206044820152663137bab732399760c91b6064820152608401610ac4565b6114358484612fd2565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061251f82610e37565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6008546001600160a01b03163314610dd65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ac4565b3332146125f95760405162461bcd60e51b815260206004820152601560248201527410dbdb9d1c9858dd1cc818d85b9b9bdd081b5a5b9d605a1b6044820152606401610ac4565b6001600160a01b03821661264f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610ac4565b600081116126b05760405162461bcd60e51b815260206004820152602860248201527f455243373231723a206e65656420746f206d696e74206174206c65617374206f6044820152673732903a37b5b2b760c11b6064820152608401610ac4565b8060035410156127165760405162461bcd60e51b815260206004820152602b60248201527f455243373231723a206d696e74696e67206d6f726520746f6b656e732074686160448201526a6e20617661696c61626c6560a81b6064820152608401610ac4565b60035460005b828110156127595760006127308584613008565b905061273c8582613066565b61274583613c68565b92505080612752906139ee565b905061271c565b5060038190556001600160a01b03831660009081526005602052604081208054849290612787908490613b5a565b9091555050505050565b6000818152600460205260408120546001600160a01b031661280a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ac4565b600061281583610e37565b9050806001600160a01b0316846001600160a01b031614806128505750836001600160a01b031661284584610a4f565b6001600160a01b0316145b80611f675750611f678185611580565b826001600160a01b031661287382610e37565b6001600160a01b0316146128d75760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610ac4565b6001600160a01b0382166129395760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610ac4565b6129446000826124ea565b6001600160a01b038316600090815260056020526040812080546001929061296d908490613a66565b90915550506001600160a01b038216600090815260056020526040812080546001929061299b908490613b5a565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600260095403612a4e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ac4565b6002600955565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606000612ab4836130bf565b600101905060008167ffffffffffffffff811115612ad457612ad4613637565b6040519080825280601f01601f191660200182016040528015612afe576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450841561126657612b08565b816001600160a01b0316836001600160a01b031603612b995760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610ac4565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612c11848484612860565b612c1d84848484613197565b6114355760405162461bcd60e51b8152600401610ac490613d07565b60606000612c4683610f56565b90506000612c578461ffff16612aa7565b604051602001612c679190613d59565b60408051601f19818403018152606083019091526022808352909250612cca918391613fa86020830139612c9a85613298565b612ca388610640565b604051602001612cb69493929190613d89565b604051602081830303815290604052613298565b604051602001612cda9190613ea2565b60405160208183030381529060405292505050919050565b606082600060015b60018351612d089190613a66565b821015612d4b576000612d1c8787856133eb565b90508019612d2a5750612d4b565b81612d34816139ee565b9250612d439050816001613b5a565b925050612cfa565b8067ffffffffffffffff811115612d6457612d64613637565b604051908082528060200260200182016040528015612d9757816020015b6060815260200190600190039081612d825790505b50935060009150600090505b60018351612db19190613a66565b821015612ed6576000612dc58787856133eb565b90508019612dd1575082515b6000612ddd8483613a66565b67ffffffffffffffff811115612df557612df5613637565b6040519080825280601f01601f191660200182016040528015612e1f576020820181803683370190505b509050806000855b84811015612e9657878181518110612e4157612e41613977565b01602001516001600160f81b0319168383612e5b816139ee565b945081518110612e6d57612e6d613977565b60200101906001600160f81b031916908160001a90535080612e8e816139ee565b915050612e27565b50612ea2846001613b5a565b9550818886612eb0816139ee565b975081518110612ec257612ec2613977565b602002602001018190525050505050612da3565b50505092915050565b82516060908490612ef08585613ee7565b1115612efe57612efe613f0f565b60008467ffffffffffffffff811115612f1957612f19613637565b6040519080825280601f01601f191660200182016040528015612f43576020820181803683370190505b509050806000855b612f558888613ee7565b811015612fc357848181518110612f6e57612f6e613977565b01602001516001600160f81b0319168383612f88816139ee565b945081518110612f9a57612f9a613977565b60200101906001600160f81b031916908160001a90535080612fbb816139ee565b915050612f4b565b509093505050505b9392505050565b8051602082019150808201602084510184015b81841015612ffd578351815260209384019301612fe5565b505082510190915250565b604080516001600160a01b038416602080830191909152308284015260608083018590528351808403909101815260809092019092528051910120600090816130518483613f25565b905061305d8185613486565b95945050505050565b60008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106130fe5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061312a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061314857662386f26fc10000830492506010015b6305f5e1008310613160576305f5e100830492506008015b612710831061317457612710830492506004015b60648310613186576064830492506002015b600a831061063a5760010192915050565b60006001600160a01b0384163b1561328d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906131db903390899088908890600401613f39565b6020604051808303816000875af1925050508015613216575060408051601f3d908101601f1916820190925261321391810190613f76565b60015b613273573d808015613244576040519150601f19603f3d011682016040523d82523d6000602084013e613249565b606091505b50805160000361326b5760405162461bcd60e51b8152600401610ac490613d07565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611f67565b506001949350505050565b606081516000036132b757505060408051602081019091526000815290565b60006040518060600160405280604081526020016140fb60409139905060006003845160026132e69190613b5a565b6132f09190613f93565b6132fb906004613b43565b67ffffffffffffffff81111561331357613313613637565b6040519080825280601f01601f19166020018201604052801561333d576020820181803683370190505b509050600182016020820185865187015b808210156133a9576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f811685015184535060018301925061334e565b50506003865106600181146133c557600281146133d8576133e0565b603d6001830353603d60028303536133e0565b603d60018303535b509195945050505050565b81516000908490849060011461340357613403613f0f565b835b8251811015613478578160008151811061342157613421613977565b602001015160f81c60f81b6001600160f81b03191683828151811061344857613448613977565b01602001516001600160f81b03191603613466579250612fcb915050565b80613470816139ee565b915050613405565b506000199695505050505050565b600082815260026020526040812054818181036134a45750836134a7565b50805b60006134b4600186613a66565b6000818152600260205260409020549091508682146134fd57806000036134eb5760008781526002602052604090208290556134fd565b60008781526002602052604090208190555b8015613513576000828152600260205260408120555b509095945050505050565b6001600160e01b03198116811461162457600080fd5b60006020828403121561354657600080fd5b8135612fcb8161351e565b60006020828403121561356357600080fd5b813561ffff81168114612fcb57600080fd5b60005b83811015613590578181015183820152602001613578565b50506000910152565b600081518084526135b1816020860160208601613575565b601f01601f19169290920160200192915050565b602081526000612fcb6020830184613599565b6000602082840312156135ea57600080fd5b5035919050565b80356001600160a01b038116811461360857600080fd5b919050565b6000806040838503121561362057600080fd5b613629836135f1565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561367657613676613637565b604052919050565b600067ffffffffffffffff82111561369857613698613637565b5060051b60200190565b600082601f8301126136b357600080fd5b813560206136c86136c38361367e565b61364d565b82815260059290921b840181019181810190868411156136e757600080fd5b8286015b8481101561370257803583529183019183016136eb565b509695505050505050565b6000806040838503121561372057600080fd5b823567ffffffffffffffff8082111561373857600080fd5b818501915085601f83011261374c57600080fd5b8135602061375c6136c38361367e565b82815260059290921b8401810191818101908984111561377b57600080fd5b948201945b838610156137a057613791866135f1565b82529482019490820190613780565b965050860135925050808211156137b657600080fd5b506137c3858286016136a2565b9150509250929050565b6000806000606084860312156137e257600080fd5b6137eb846135f1565b92506137f9602085016135f1565b9150604084013590509250925092565b60006020828403121561381b57600080fd5b612fcb826135f1565b6000806040838503121561383757600080fd5b613840836135f1565b91506020830135801515811461385557600080fd5b809150509250929050565b600067ffffffffffffffff82111561387a5761387a613637565b50601f01601f191660200190565b6000806000806080858703121561389e57600080fd5b6138a7856135f1565b93506138b5602086016135f1565b925060408501359150606085013567ffffffffffffffff8111156138d857600080fd5b8501601f810187136138e957600080fd5b80356138f76136c382613860565b81815288602083850101111561390c57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561394157600080fd5b61394a836135f1565b9150613958602084016135f1565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000815161399f818560208601613575565b9290920192915050565b600083516139bb818460208801613575565b8351908301906139cf818360208801613575565b01949350505050565b634e487b7160e01b600052601160045260246000fd5b600060018201613a0057613a006139d8565b5060010190565b60008251613a19818460208701613575565b605d60f81b920191825250600101919050565b600181811c90821680613a4057607f821691505b602082108103613a6057634e487b7160e01b600052602260045260246000fd5b50919050565b8181038181111561063a5761063a6139d8565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000613ad86136c384613860565b9050828152838383011115613aec57600080fd5b612fcb836020830184613575565b600060208284031215613b0c57600080fd5b815167ffffffffffffffff811115613b2357600080fd5b8201601f81018413613b3457600080fd5b611f6784825160208401613aca565b808202811582820484141761063a5761063a6139d8565b8082018082111561063a5761063a6139d8565b681e3932b1ba103c1e9160b91b81528351600090613b92816009850160208901613575565b6411103c9e9160d91b6009918401918201528451613bb781600e840160208901613575565b68222066696c6c3d222360b81b600e92909101918201528351613be1816017840160208801613575565b6211179f60e91b60179290910191820152601a0195945050505050565b600060208284031215613c1057600080fd5b8151605d8110612fcb57600080fd5b60208101605d8310613c4157634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215613c5957600080fd5b8151600d8110612fcb57600080fd5b600081613c7757613c776139d8565b506000190190565b6e3d913a3930b4ba2fba3cb832911d1160891b81528251600090613caa81600f850160208801613575565b6b111610113b30b63ab2911d1160a11b600f918401918201528351613cd681601b840160208801613575565b61227d60f01b601b9290910191820152601d01949350505050565b634e487b7160e01b600052601260045260246000fd5b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b674f5050756e6b202360c01b815260008251613d7c816008850160208701613575565b9190910160080192915050565b607b60f81b815267113730b6b2911d1160c11b60018201528451600090613db7816009850160208a01613575565b701116113232b9b1b934b83a34b7b7111d1160791b6009918401918201528551613de881601a840160208a01613575565b7f222c226261636b67726f756e645f636f6c6f72223a2223464630343231222c22601a92909101918201527f696d6167655f64617461223a22646174613a696d6167652f7376672b786d6c3b603a8201526618985cd94d8d0b60ca1b605a8201528451613e5c816061840160208901613575565b6f011161130ba3a3934b13aba32b9911d160851b60619290910191820152613e97613e8a607183018661398d565b607d60f81b815260010190565b979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251613eda81601d850160208701613575565b91909101601d0192915050565b8082018281126000831280158216821582161715613f0757613f076139d8565b505092915050565b634e487b7160e01b600052600160045260246000fd5b600082613f3457613f34613cf1565b500690565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613f6c90830184613599565b9695505050505050565b600060208284031215613f8857600080fd5b8151612fcb8161351e565b600082613fa257613fa2613cf1565b50049056fe4f502050756e6b73202d2053746f72656420656e746972656c79204f6e436861696e3c7376672077696474683d223132303022206865696768743d2231323030222073686170652d72656e646572696e673d22637269737045646765732220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d22312e32222076696577426f783d22302030203234203234223e3c7374796c653e726563747b77696474683a3170783b6865696768743a3170787d3c2f7374796c653e3c7265637420783d22302220793d223022207374796c653d2277696474683a313030253b6865696768743a31303025222066696c6c3d222346463034323122202f3e3c67207374796c653d227472616e73666f726d3a207472616e736c6174652863616c6328353025202d2031327078292c2063616c6328353025202d20313270782929223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220fa74a49fe22b1f8949afda47f597bf38c0a878ea58e95c98da72dbb6b236a9cc64736f6c63430008120033

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

000000000000000000000000544cb9ccc57f10ebf230aeaeaef0e76cdc90b866000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c4

-----Decoded View---------------
Arg [0] : punkDataContractAddress (address): 0x544cB9Ccc57f10EBf230aeaEaEF0E76cdc90b866
Arg [1] : extendedPunkDataContractAddress (address): 0x926d6A45cd710B67b6a99A51D36BBB19182f82C4

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000544cb9ccc57f10ebf230aeaeaef0e76cdc90b866
Arg [1] : 000000000000000000000000926d6a45cd710b67b6a99a51d36bbb19182f82c4


Deployed Bytecode Sourcemap

78910:15038:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61116:305;;;;;;;;;;-1:-1:-1;61116:305:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;61116:305:0;;;;;;;;90710:1172;;;;;;;;;;-1:-1:-1;90710:1172:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;62299:100::-;;;;;;;;;;;;;:::i;63860:221::-;;;;;;;;;;-1:-1:-1;63860:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1974:32:1;;;1956:51;;1944:2;1929:18;63860:221:0;1810:203:1;63382:412:0;;;;;;;;;;-1:-1:-1;63382:412:0;;;;;:::i;:::-;;:::i;:::-;;83266:337;;;;;;;;;;-1:-1:-1;83266:337:0;;;;;:::i;:::-;;:::i;61433:119::-;;;;;;;;;;;;;:::i;:::-;;;5019:25:1;;;5007:2;4992:18;61433:119:0;4873:177:1;64610:339:0;;;;;;;;;;-1:-1:-1;64610:339:0;;;;;:::i;:::-;;:::i;82673:186::-;;;;;;;;;;;;;:::i;65020:185::-;;;;;;;;;;-1:-1:-1;65020:185:0;;;;;:::i;:::-;;:::i;82867:102::-;;;;;;;;;;;;;:::i;83613:101::-;;;;;;;;;;-1:-1:-1;83613:101:0;;;;;:::i;:::-;;:::i;61993:239::-;;;;;;;;;;-1:-1:-1;61993:239:0;;;;;:::i;:::-;;:::i;81385:42::-;;;;;;;;;;;;;;;;61723:208;;;;;;;;;;-1:-1:-1;61723:208:0;;;;;:::i;:::-;;:::i;40439:103::-;;;;;;;;;;;;;:::i;39791:87::-;;;;;;;;;;-1:-1:-1;39864:6:0;;-1:-1:-1;;;;;39864:6:0;39791:87;;62468:104;;;;;;;;;;;;;:::i;88186:1797::-;;;;;;;;;;-1:-1:-1;88186:1797:0;;;;;:::i;:::-;;:::i;82575:90::-;;;;;;;;;;;;;:::i;82034:427::-;;;;;;:::i;:::-;;:::i;64153:155::-;;;;;;;;;;-1:-1:-1;64153:155:0;;;;;:::i;:::-;;:::i;65276:328::-;;;;;;;;;;-1:-1:-1;65276:328:0;;;;;:::i;:::-;;:::i;83722:185::-;;;;;;;;;;-1:-1:-1;83722:185:0;;;;;:::i;:::-;;:::i;81434:36::-;;;;;;;;;;-1:-1:-1;81434:36:0;;;;;;;;61564:95;;;;;;;;;;-1:-1:-1;61641:10:0;61564:95;;81477:24;;;;;;;;;;-1:-1:-1;81477:24:0;;;;;;;-1:-1:-1;;;;;81477:24:0;;;82977:281;;;;;;;;;;-1:-1:-1;82977:281:0;;;;;:::i;:::-;;:::i;82469:98::-;;;;;;;;;;-1:-1:-1;82469:98:0;;;;;:::i;:::-;;:::i;64379:164::-;;;;;;;;;;-1:-1:-1;64379:164:0;;;;;:::i;:::-;;:::i;81510:45::-;;;;;;;;;;-1:-1:-1;81510:45:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;40697:201;;;;;;;;;;-1:-1:-1;40697:201:0;;;;;:::i;:::-;;:::i;61116:305::-;61218:4;-1:-1:-1;;;;;;61255:40:0;;-1:-1:-1;;;61255:40:0;;:105;;-1:-1:-1;;;;;;;61312:48:0;;-1:-1:-1;;;61312:48:0;61255:105;:158;;;-1:-1:-1;;;;;;;;;;53629:40:0;;;61377:36;61235:178;61116:305;-1:-1:-1;;61116:305:0:o;90710:1172::-;90776:18;90807:16;90826:22;90841:6;90826:14;:22::i;:::-;90807:41;;90859:23;90929:19;:25;;;;;;;;;;;;;-1:-1:-1;;;90929:25:0;;;;;90975:39;:372;;;;;;;;91032:4;:8;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91055:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91079:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91103:4;:10;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91128:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91152:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91176:4;:10;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91201:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91225:4;:12;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91252:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91276:4;:9;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91300:4;:11;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;91326:4;:10;;;90975:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;-1:-1:-1;91360:14:0;91377:24;91396:4;91377:18;:24::i;:::-;91360:41;;91412:10;91444:6;91439:371;91460:2;91456:1;:6;91439:371;;;91484:26;91513:9;91523:1;91513:12;;;;;;;:::i;:::-;;;;;91484:41;;91557:4;91546:15;;;;;;;;:::i;:::-;:7;:15;;;;;;;;:::i;:::-;;91542:257;;91608:6;91616:28;91636:7;91616:19;:28::i;:::-;91591:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;91582:63;;91678:9;91670:5;:17;91666:118;;;91712:22;;;;;;;;;;;;-1:-1:-1;;;91712:22:0;;;;;;:6;;:17;:22::i;:::-;91757:7;;;:::i;:::-;;;91666:118;-1:-1:-1;91464:3:0;;;:::i;:::-;;;91439:371;;;;91861:6;91844:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;91830:44;;;;;;;;90710:1172;;;:::o;62299:100::-;62353:13;62386:5;62379:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62299:100;:::o;63860:221::-;63936:7;67203:16;;;:7;:16;;;;;;-1:-1:-1;;;;;67203:16:0;63956:73;;;;-1:-1:-1;;;63956:73:0;;9559:2:1;63956:73:0;;;9541:21:1;9598:2;9578:18;;;9571:30;9637:34;9617:18;;;9610:62;-1:-1:-1;;;9688:18:1;;;9681:42;9740:19;;63956:73:0;;;;;;;;;-1:-1:-1;64049:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;64049:24:0;;63860:221::o;63382:412::-;63463:13;63479:24;63495:7;63479:15;:24::i;:::-;63463:40;;63528:5;-1:-1:-1;;;;;63522:11:0;:2;-1:-1:-1;;;;;63522:11:0;;63514:57;;;;-1:-1:-1;;;63514:57:0;;9972:2:1;63514:57:0;;;9954:21:1;10011:2;9991:18;;;9984:30;10050:34;10030:18;;;10023:62;-1:-1:-1;;;10101:18:1;;;10094:31;10142:19;;63514:57:0;9770:397:1;63514:57:0;38422:10;-1:-1:-1;;;;;63606:21:0;;;;:62;;-1:-1:-1;63631:37:0;63648:5;38422:10;64379:164;:::i;63631:37::-;63584:168;;;;-1:-1:-1;;;63584:168:0;;10374:2:1;63584:168:0;;;10356:21:1;10413:2;10393:18;;;10386:30;10452:34;10432:18;;;10425:62;10523:26;10503:18;;;10496:54;10567:19;;63584:168:0;10172:420:1;63584:168:0;63765:21;63774:2;63778:7;63765:8;:21::i;:::-;63452:342;63382:412;;:::o;83266:337::-;39677:13;:11;:13::i;:::-;83403:7:::1;:14;83382:10;:17;:35;83374:96;;;::::0;-1:-1:-1;;;83374:96:0;;10799:2:1;83374:96:0::1;::::0;::::1;10781:21:1::0;10838:2;10818:18;;;10811:30;10877:34;10857:18;;;10850:62;-1:-1:-1;;;10928:18:1;;;10921:46;10984:19;;83374:96:0::1;10597:412:1::0;83374:96:0::1;83488:9;83483:113;83507:10;:17;83503:1;:21;83483:113;;;83546:38;83558:10;83569:1;83558:13;;;;;;;;:::i;:::-;;;;;;;83573:7;83581:1;83573:10;;;;;;;;:::i;:::-;;;;;;;83546:11;:38::i;:::-;83526:3:::0;::::1;::::0;::::1;:::i;:::-;;;;83483:113;;61433:119:::0;61485:7;61525:19;;61512:10;:32;;;;:::i;:::-;61505:39;;61433:119;:::o;64610:339::-;64805:41;38422:10;64838:7;64805:18;:41::i;:::-;64797:103;;;;-1:-1:-1;;;64797:103:0;;;;;;;:::i;:::-;64913:28;64923:4;64929:2;64933:7;64913:9;:28::i;82673:186::-;39677:13;:11;:13::i;:::-;21863:21:::1;:19;:21::i;:::-;82755:49:::2;::::0;82737:12:::2;::::0;82755:10:::2;::::0;82778:21:::2;::::0;82737:12;82755:49;82737:12;82755:49;82778:21;82755:10;:49:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82736:68;;;82823:7;82815:36;;;::::0;-1:-1:-1;;;82815:36:0;;11977:2:1;82815:36:0::2;::::0;::::2;11959:21:1::0;12016:2;11996:18;;;11989:30;-1:-1:-1;;;12035:18:1;;;12028:46;12091:18;;82815:36:0::2;11775:340:1::0;82815:36:0::2;82725:134;21907:20:::1;21301:1:::0;22427:7;:22;22244:213;21907:20:::1;82673:186::o:0;65020:185::-;65158:39;65175:4;65181:2;65185:7;65158:39;;;;;;;;;;;;:16;:39::i;82867:102::-;39677:13;:11;:13::i;:::-;21863:21:::1;:19;:21::i;:::-;82931:28:::2;82943:10;82955:3;82931:11;:28::i;:::-;21907:20:::1;21301:1:::0;22427:7;:22;22244:213;83613:101;83666:4;67203:16;;;:7;:16;;;;;;-1:-1:-1;;;;;67203:16:0;:30;;83690:16;67114:127;61993:239;62065:7;62101:16;;;:7;:16;;;;;;-1:-1:-1;;;;;62101:16:0;;62128:73;;;;-1:-1:-1;;;62128:73:0;;12322:2:1;62128:73:0;;;12304:21:1;12361:2;12341:18;;;12334:30;12400:34;12380:18;;;12373:62;-1:-1:-1;;;12451:18:1;;;12444:39;12500:19;;62128:73:0;12120:405:1;61723:208:0;61795:7;-1:-1:-1;;;;;61823:19:0;;61815:74;;;;-1:-1:-1;;;61815:74:0;;12732:2:1;61815:74:0;;;12714:21:1;12771:2;12751:18;;;12744:30;12810:34;12790:18;;;12783:62;-1:-1:-1;;;12861:18:1;;;12854:40;12911:19;;61815:74:0;12530:406:1;61815:74:0;-1:-1:-1;;;;;;61907:16:0;;;;;:9;:16;;;;;;;61723:208::o;40439:103::-;39677:13;:11;:13::i;:::-;40504:30:::1;40531:1;40504:18;:30::i;62468:104::-:0;62524:13;62557:7;62550:14;;;;;:::i;88186:1797::-;88291:43;;-1:-1:-1;;;88291:43:0;;13115:6:1;13103:19;;88291:43:0;;;13085:38:1;88243:13:0;;88269:19;;-1:-1:-1;;;;;88291:16:0;:26;;;;13058:18:1;;88291:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;88291:43:0;;;;;;;;;;;;:::i;:::-;16755:4;16749:11;;17068:20;;;17106:25;;;17244:19;17281:25;;88345:21;17436:4;17421:20;;;17500:17;;;88269:65;;-1:-1:-1;88345:58:0;88424:328;;;;;;;;;;;;;;;;;;:8;;:19;:328::i;:::-;88795:12;;;88805:1;88795:12;;;;;;;;;88773:19;;88795:12;;;;;;;;;;-1:-1:-1;88795:12:0;88773:34;;88823:9;88818:1070;88842:2;88838:1;:6;88818:1070;;;88871:9;88866:1011;88890:2;88886:1;:6;88866:1011;;;88918:9;88940:1;88931:6;:1;88935:2;88931:6;:::i;:::-;:10;;;;:::i;:::-;88930:16;;88945:1;88930:16;:::i;:::-;88918:28;-1:-1:-1;88992:1:0;88975:6;88982:5;88918:28;88986:1;88982:5;:::i;:::-;88975:13;;;;;;;;:::i;:::-;;;;;;;88969:24;88965:897;;;89023:9;89018:321;89042:1;89038;:5;89018:321;;;89077:11;89097:6;89104:5;89108:1;89104;:5;:::i;:::-;89097:13;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;89205:3:0;89197:11;;89184:25;;;;;;;:::i;:::-;;;;89164:6;89171:5;:1;89175;89171:5;:::i;:::-;:9;;89179:1;89171:9;:::i;:::-;89164:17;;;;;;;;:::i;:::-;;;;:45;-1:-1:-1;;;;;89164:45:0;;;;;;;;-1:-1:-1;89246:1:0;89236:11;;;-1:-1:-1;;;89236:11:0;89290:25;;;;;;;:::i;:::-;;;;89274:6;89281:5;:1;89285;89281:5;:::i;:::-;89274:13;;;;;;;;:::i;:::-;;;;:41;-1:-1:-1;;;;;89274:41:0;;;;;;;;;89050:289;89045:3;;;;;:::i;:::-;;;;89018:321;;;-1:-1:-1;89395:6:0;89447:395;89582:12;:1;:10;:12::i;:::-;89663;:1;:10;:12::i;:::-;89748:8;89493:326;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;89493:326:0;;;;;;;;;89447:8;;:19;:395::i;:::-;88995:867;88965:897;-1:-1:-1;88894:3:0;;;;:::i;:::-;;;;88866:1011;;;-1:-1:-1;88846:3:0;;;;:::i;:::-;;;;88818:1070;;;-1:-1:-1;89908:33:0;;;;;;;;;;;;-1:-1:-1;;;89908:33:0;;;;;;:8;;:19;:33::i;:::-;-1:-1:-1;89966:8:0;88186:1797;-1:-1:-1;;;88186:1797:0:o;82575:90::-;39677:13;:11;:13::i;:::-;82646:11:::1;::::0;;-1:-1:-1;;82631:26:0;::::1;82646:11;::::0;;::::1;82645:12;82631:26;::::0;;82575:90::o;82034:427::-;82117:9;;82147:11;;;;82139:42;;;;-1:-1:-1;;;82139:42:0;;15786:2:1;82139:42:0;;;15768:21:1;15825:2;15805:18;;;15798:30;-1:-1:-1;;;15844:18:1;;;15837:48;15902:18;;82139:42:0;15584:342:1;82139:42:0;61641:10;82216:5;82200:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:36;;82192:58;;;;-1:-1:-1;;;82192:58:0;;16133:2:1;82192:58:0;;;16115:21:1;16172:1;16152:18;;;16145:29;-1:-1:-1;;;16190:18:1;;;16183:39;16239:18;;82192:58:0;15931:332:1;82192:58:0;82282:12;82290:4;82282:5;:12;:::i;:::-;82269:9;:25;;82261:70;;;;-1:-1:-1;;;82261:70:0;;16470:2:1;82261:70:0;;;16452:21:1;;;16489:18;;;16482:30;16548:34;16528:18;;;16521:62;16600:18;;82261:70:0;16268:356:1;82261:70:0;82350:10;82364:9;82350:23;82342:66;;;;-1:-1:-1;;;82342:66:0;;16831:2:1;82342:66:0;;;16813:21:1;16870:2;16850:18;;;16843:30;16909:32;16889:18;;;16882:60;16959:18;;82342:66:0;16629:354:1;82342:66:0;82421:30;82433:10;82445:5;82421:11;:30::i;:::-;82081:380;82034:427;:::o;64153:155::-;64248:52;38422:10;64281:8;64291;64248:18;:52::i;65276:328::-;65451:41;38422:10;65484:7;65451:18;:41::i;:::-;65443:103;;;;-1:-1:-1;;;65443:103:0;;;;;;;:::i;:::-;65557:39;65571:4;65577:2;65581:7;65590:5;65557:13;:39::i;:::-;65276:328;;;;:::o;83722:185::-;67179:4;67203:16;;;:7;:16;;;;;;83782:13;;-1:-1:-1;;;;;67203:16:0;83808:44;;;;-1:-1:-1;;;83808:44:0;;17190:2:1;83808:44:0;;;17172:21:1;17229:2;17209:18;;;17202:30;-1:-1:-1;;;17248:18:1;;;17241:50;17308:18;;83808:44:0;16988:344:1;83808:44:0;83870:29;83895:2;83870:17;:29::i;82977:281::-;39677:13;:11;:13::i;:::-;83062:1:::1;61641:10:::0;83100:5:::1;83084:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:36;;83076:58;;;::::0;-1:-1:-1;;;83076:58:0;;16133:2:1;83076:58:0::1;::::0;::::1;16115:21:1::0;16172:1;16152:18;;;16145:29;-1:-1:-1;;;16190:18:1;;;16183:39;16239:18;;83076:58:0::1;15931:332:1::0;83076:58:0::1;83153:10;83167:9;83153:23;83145:66;;;::::0;-1:-1:-1;;;83145:66:0;;16831:2:1;83145:66:0::1;::::0;::::1;16813:21:1::0;16870:2;16850:18;;;16843:30;16909:32;16889:18;;;16882:60;16959:18;;83145:66:0::1;16629:354:1::0;83145:66:0::1;83222:26;83234:6;83242:5;83222:11;:26::i;82469:98::-:0;39677:13;:11;:13::i;:::-;82529:9:::1;:18:::0;82469:98::o;64379:164::-;-1:-1:-1;;;;;64500:25:0;;;64476:4;64500:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;64379:164::o;40697:201::-;39677:13;:11;:13::i;:::-;-1:-1:-1;;;;;40786:22:0;::::1;40778:73;;;::::0;-1:-1:-1;;;40778:73:0;;17539:2:1;40778:73:0::1;::::0;::::1;17521:21:1::0;17578:2;17558:18;;;17551:30;17617:34;17597:18;;;17590:62;-1:-1:-1;;;17668:18:1;;;17661:36;17714:19;;40778:73:0::1;17337:402:1::0;40778:73:0::1;40862:28;40881:8;40862:18;:28::i;:::-;40697:201:::0;:::o;85004:3107::-;85065:11;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85065:11:0;85108:621;;;;;;;;;;;;;;85089:16;;85108:621;;;85089:16;85108:621;;;;85202:23;85108:621;;;;85246:23;85108:621;;;;85291:23;85108:621;;;;85335:23;85108:621;;;;85379:23;85108:621;;;;85424:23;85108:621;;;;85468:23;85108:621;;;;85515:23;85108:621;;;;85559:23;85108:621;;;;85603:23;85108:621;;;;85649:23;85108:621;;;;85694:23;85108:621;;85750:16;;;;;;85814:40;;-1:-1:-1;;;85814:40:0;;;;;13085:38:1;;;;85750:16:0;;-1:-1:-1;85750:7:0;;85814:16;-1:-1:-1;;;;;85814:31:0;;;;13058:18:1;;85814:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;85814:40:0;;;;;;;;;;;;:::i;:::-;85787:67;;85867:30;85900:21;;;;;;;;;;;;;;-1:-1:-1;;;85900:21:0;;;:10;:16;;:21;;;;:::i;:::-;85867:54;;85947:6;85942:2130;85963:14;:21;85959:1;:25;85942:2130;;;86006:32;86041:14;86056:1;86041:17;;;;;;;;:::i;:::-;;;;;;;86006:52;;86073:30;86140:1;86136;:5;86132:232;;;86181:29;;;;;;;;;;;;-1:-1:-1;;;86181:29:0;;;;;;:18;;:24;:29::i;:::-;86211:1;86181:32;;;;;;;;:::i;:::-;;;;;;;86162:51;;86132:232;;;86273:75;86342:1;86313:18;86307:32;:36;;;;:::i;:::-;86273:18;;86346:1;86273:29;:75::i;:::-;86254:94;;86132:232;86447:66;;-1:-1:-1;;;86447:66:0;;86392:28;;-1:-1:-1;;;;;86447:24:0;:48;;;;:66;;86496:16;;86447:66;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86442:72;;;;;;;;:::i;:::-;86423:92;;;;;;;;:::i;:::-;86392:123;;86530:26;86582:24;-1:-1:-1;;;;;86582:51:0;;86684:9;86679:15;;;;;;;;:::i;:::-;86634:61;;;;;;;;:::i;:::-;86582:114;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86577:120;;;;;;;;:::i;:::-;86559:139;;;;;;;;:::i;:::-;86530:168;-1:-1:-1;86743:21:0;86731:8;:33;;;;;;;;:::i;:::-;;86727:1334;;86785:8;;;86796:9;86785:20;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;86727:1334:0;;;86843:22;86831:8;:34;;;;;;;;:::i;:::-;;86827:1234;;86886:9;;;86898;86886:21;;;;;;;;:::i;86827:1234::-;86945:22;86933:8;:34;;;;;;;;:::i;:::-;;86929:1132;;86988:9;;;87000;86988:21;;;;;;;;:::i;86929:1132::-;87047:23;87035:8;:35;;;;;;;;:::i;:::-;;87031:1030;;87091:10;;;87104:9;87091:22;;;;;;;;:::i;87031:1030::-;87151:22;87139:8;:34;;;;;;;;:::i;:::-;;87135:926;;87194:9;;;87206;87194:21;;;;;;;;:::i;87135:926::-;87253:22;87241:8;:34;;;;;;;;:::i;:::-;;87237:824;;87296:9;;;87308;87296:21;;;;;;;;:::i;87237:824::-;87355:23;87343:8;:35;;;;;;;;:::i;:::-;;87339:722;;87399:10;;;87412:9;87399:22;;;;;;;;:::i;87339:722::-;87459:22;87447:8;:34;;;;;;;;:::i;:::-;;87443:618;;87502:9;;;87514;87502:21;;;;;;;;:::i;87443:618::-;87561:25;87549:8;:37;;;;;;;;:::i;:::-;;87545:516;;87607:12;;;87622:9;87607:24;;;;;;;;:::i;87545:516::-;87669:22;87657:8;:34;;;;;;;;:::i;:::-;;87653:408;;87712:9;;;87724;87712:21;;;;;;;;:::i;87653:408::-;87771:22;87759:8;:34;;;;;;;;:::i;:::-;;87755:306;;87814:9;;;87826;87814:21;;;;;;;;:::i;87755:306::-;87873:24;87861:8;:36;;;;;;;;:::i;:::-;;87857:204;;87918:11;;;87932:9;87918:23;;;;;;;;:::i;87857:204::-;87979:23;87967:8;:35;;;;;;;;:::i;:::-;;87963:98;;88023:10;;;88036:9;88023:22;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;87963:98:0;85991:2081;;;;85986:3;;;;;:::i;:::-;;;;85942:2130;;;-1:-1:-1;88099:4:0;;85004:3107;-1:-1:-1;;;;85004:3107:0:o;89991:711::-;90059:15;90087:39;:372;;;;;;;;90144:4;:8;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90167:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90191:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90215:4;:10;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90240:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90264:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90288:4;:10;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90313:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90337:4;:12;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90364:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90388:4;:9;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90412:4;:11;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;90438:4;:10;;;90087:372;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;-1:-1:-1;90485:6:0;90480:148;90501:2;90497:1;:6;90480:148;;;90545:23;90529:9;90539:1;90529:12;;;;;;;:::i;:::-;;;;;:39;;;;;;;;:::i;:::-;;90525:92;;90589:12;;;;:::i;:::-;;;;90525:92;90505:3;;;:::i;:::-;;;90480:148;;;-1:-1:-1;90682:12:0;;;;:::i;:::-;;89991:711;-1:-1:-1;;;;89991:711:0:o;91890:2053::-;91972:18;92024:23;92011:9;:36;;;;;;;;:::i;:::-;;92003:45;;;;;;92061:31;92095:24;-1:-1:-1;;;;;92095:48:0;;92194:9;92189:15;;;;;;;;:::i;:::-;92144:61;;;;;;;;:::i;:::-;92095:111;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;92095:111:0;;;;;;;;;;;;:::i;:::-;92061:145;;92217:35;92273:26;92325:24;-1:-1:-1;;;;;92325:51:0;;92427:9;92422:15;;;;;;;;:::i;:::-;92377:61;;;;;;;;:::i;:::-;92325:114;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92320:120;;;;;;;;:::i;:::-;92302:139;;;;;;;;:::i;:::-;92273:168;-1:-1:-1;92470:21:0;92458:8;:33;;;;;;;;:::i;:::-;;92454:1347;;92508:29;;;;;;;;;;;;;-1:-1:-1;;;92508:29:0;;;;;92454:1347;;;92571:22;92559:8;:34;;;;;;;;:::i;:::-;;92555:1246;;92610:30;;;;;;;;;;;;;-1:-1:-1;;;92610:30:0;;;;;92555:1246;;;92674:22;92662:8;:34;;;;;;;;:::i;:::-;;92658:1143;;92713:30;;;;;;;;;;;;;-1:-1:-1;;;92713:30:0;;;;;92658:1143;;;92777:23;92765:8;:35;;;;;;;;:::i;:::-;;92761:1040;;92817:31;;;;;;;;;;;;;-1:-1:-1;;;92817:31:0;;;;;92761:1040;;;92882:22;92870:8;:34;;;;;;;;:::i;:::-;;92866:935;;92921:30;;;;;;;;;;;;;-1:-1:-1;;;92921:30:0;;;;;92866:935;;;92985:22;92973:8;:34;;;;;;;;:::i;:::-;;92969:832;;93024:30;;;;;;;;;;;;;-1:-1:-1;;;93024:30:0;;;;;92969:832;;;93088:23;93076:8;:35;;;;;;;;:::i;:::-;;93072:729;;93128:31;;;;;;;;;;;;;-1:-1:-1;;;93128:31:0;;;;;93072:729;;;93193:22;93181:8;:34;;;;;;;;:::i;:::-;;93177:624;;93232:30;;;;;;;;;;;;;-1:-1:-1;;;93232:30:0;;;;;93177:624;;;93296:25;93284:8;:37;;;;;;;;:::i;:::-;;93280:521;;93338:33;;;;;;;;;;;;;-1:-1:-1;;;93338:33:0;;;;;93280:521;;;93405:22;93393:8;:34;;;;;;;;:::i;:::-;;93389:412;;93444:30;;;;;;;;;;;;;-1:-1:-1;;;93444:30:0;;;;;93389:412;;;93508:22;93496:8;:34;;;;;;;;:::i;:::-;;93492:309;;93547:30;;;;;;;;;;;;;-1:-1:-1;;;93547:30:0;;;;;93492:309;;;93611:24;93599:8;:36;;;;;;;;:::i;:::-;;93595:206;;93652:32;;;;;;;;;;;;;-1:-1:-1;;;93652:32:0;;;;;93595:206;;;93718:23;93706:8;:35;;;;;;;;:::i;:::-;;93702:99;;93758:31;;;;;;;;;;;;;-1:-1:-1;;;93758:31:0;;;;;93702:99;93871:21;93910:17;93835:99;;;;;;;;;:::i;:::-;;;;;;;;;;;;;93821:114;;;;;91890:2053;;;:::o;19076:437::-;-1:-1:-1;;19259:17:0;;19253:24;19308:13;;19375:11;;-1:-1:-1;;19249:35:0;;;;;;19366:20;;19308:13;19366:20;:::i;:::-;:32;;19344:121;;;;-1:-1:-1;;;19344:121:0;;20501:2:1;19344:121:0;;;20483:21:1;20540:2;20520:18;;;20513:30;20579:34;20559:18;;;20552:62;-1:-1:-1;;;20630:18:1;;;20623:37;20677:19;;19344:121:0;20299:403:1;19344:121:0;19476:29;19492:6;19500:4;19476:15;:29::i;73185:175::-;73260:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;73260:29:0;-1:-1:-1;;;;;73260:29:0;;;;;;;;:24;;73314;73260;73314:15;:24::i;:::-;-1:-1:-1;;;;;73305:47:0;;;;;;;;;;;73185:175;;:::o;39956:132::-;39864:6;;-1:-1:-1;;;;;39864:6:0;38422:10;40020:23;40012:68;;;;-1:-1:-1;;;40012:68:0;;20909:2:1;40012:68:0;;;20891:21:1;;;20928:18;;;20921:30;20987:34;20967:18;;;20960:62;21039:18;;40012:68:0;20707:356:1;68077:984:0;38422:10;68179:9;68163:25;68155:59;;;;-1:-1:-1;;;68155:59:0;;21270:2:1;68155:59:0;;;21252:21:1;21309:2;21289:18;;;21282:30;-1:-1:-1;;;21328:18:1;;;21321:51;21389:18;;68155:59:0;21068:345:1;68155:59:0;-1:-1:-1;;;;;68233:16:0;;68225:61;;;;-1:-1:-1;;;68225:61:0;;21620:2:1;68225:61:0;;;21602:21:1;;;21639:18;;;21632:30;21698:34;21678:18;;;21671:62;21750:18;;68225:61:0;21418:356:1;68225:61:0;68318:1;68305:10;:14;68297:67;;;;-1:-1:-1;;;68297:67:0;;21981:2:1;68297:67:0;;;21963:21:1;22020:2;22000:18;;;21993:30;22059:34;22039:18;;;22032:62;-1:-1:-1;;;22110:18:1;;;22103:38;22158:19;;68297:67:0;21779:404:1;68297:67:0;68518:10;68495:19;;:33;;68487:89;;;;-1:-1:-1;;;68487:89:0;;22390:2:1;68487:89:0;;;22372:21:1;22429:2;22409:18;;;22402:30;22468:34;22448:18;;;22441:62;-1:-1:-1;;;22519:18:1;;;22512:41;22570:19;;68487:89:0;22188:407:1;68487:89:0;68630:19;;68597:30;68660:288;68680:10;68676:1;:14;68660:288;;;68737:15;68755:56;68781:2;68785:25;68755;:56::i;:::-;68737:74;;68840:40;68868:2;68872:7;68840:27;:40::i;:::-;68909:27;;;:::i;:::-;;;68697:251;68692:3;;;;:::i;:::-;;;68660:288;;;-1:-1:-1;68968:19:0;:47;;;-1:-1:-1;;;;;69026:13:0;;;;;;:9;:13;;;;;:27;;69043:10;;69026:13;:27;;69043:10;;69026:27;:::i;:::-;;;;-1:-1:-1;;;;;68077:984:0:o;67408:349::-;67501:4;67203:16;;;:7;:16;;;;;;-1:-1:-1;;;;;67203:16:0;67518:73;;;;-1:-1:-1;;;67518:73:0;;22802:2:1;67518:73:0;;;22784:21:1;22841:2;22821:18;;;22814:30;22880:34;22860:18;;;22853:62;-1:-1:-1;;;22931:18:1;;;22924:42;22983:19;;67518:73:0;22600:408:1;67518:73:0;67602:13;67618:24;67634:7;67618:15;:24::i;:::-;67602:40;;67672:5;-1:-1:-1;;;;;67661:16:0;:7;-1:-1:-1;;;;;67661:16:0;;:51;;;;67705:7;-1:-1:-1;;;;;67681:31:0;:20;67693:7;67681:11;:20::i;:::-;-1:-1:-1;;;;;67681:31:0;;67661:51;:87;;;;67716:32;67733:5;67740:7;67716:16;:32::i;72441:626::-;72601:4;-1:-1:-1;;;;;72573:32:0;:24;72589:7;72573:15;:24::i;:::-;-1:-1:-1;;;;;72573:32:0;;72565:82;;;;-1:-1:-1;;;72565:82:0;;23215:2:1;72565:82:0;;;23197:21:1;23254:2;23234:18;;;23227:30;23293:34;23273:18;;;23266:62;-1:-1:-1;;;23344:18:1;;;23337:35;23389:19;;72565:82:0;23013:401:1;72565:82:0;-1:-1:-1;;;;;72666:16:0;;72658:65;;;;-1:-1:-1;;;72658:65:0;;23621:2:1;72658:65:0;;;23603:21:1;23660:2;23640:18;;;23633:30;23699:34;23679:18;;;23672:62;-1:-1:-1;;;23750:18:1;;;23743:34;23794:19;;72658:65:0;23419:400:1;72658:65:0;72840:29;72857:1;72861:7;72840:8;:29::i;:::-;-1:-1:-1;;;;;72882:15:0;;;;;;:9;:15;;;;;:20;;72901:1;;72882:15;:20;;72901:1;;72882:20;:::i;:::-;;;;-1:-1:-1;;;;;;;72913:13:0;;;;;;:9;:13;;;;;:18;;72930:1;;72913:13;:18;;72930:1;;72913:18;:::i;:::-;;;;-1:-1:-1;;72942:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;72942:21:0;-1:-1:-1;;;;;72942:21:0;;;;;;;;;72981:27;;72942:16;;72981:27;;;;;;;63452:342;63382:412;;:::o;21943:293::-;21345:1;22077:7;;:19;22069:63;;;;-1:-1:-1;;;22069:63:0;;24026:2:1;22069:63:0;;;24008:21:1;24065:2;24045:18;;;24038:30;24104:33;24084:18;;;24077:61;24155:18;;22069:63:0;23824:355:1;22069:63:0;21345:1;22210:7;:18;21943:293::o;41058:191::-;41151:6;;;-1:-1:-1;;;;;41168:17:0;;;-1:-1:-1;;;;;;41168:17:0;;;;;;;41201:40;;41151:6;;;41168:17;41151:6;;41201:40;;41132:16;;41201:40;41121:128;41058:191;:::o;35769:716::-;35825:13;35876:14;35893:17;35904:5;35893:10;:17::i;:::-;35913:1;35893:21;35876:38;;35929:20;35963:6;35952:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35952:18:0;-1:-1:-1;35929:41:0;-1:-1:-1;36094:28:0;;;36110:2;36094:28;36151:288;-1:-1:-1;;36183:5:0;-1:-1:-1;;;36320:2:0;36309:14;;36304:30;36183:5;36291:44;36381:2;36372:11;;;-1:-1:-1;36402:21:0;;36418:5;36402:21;36151:288;;73502:315;73657:8;-1:-1:-1;;;;;73648:17:0;:5;-1:-1:-1;;;;;73648:17:0;;73640:55;;;;-1:-1:-1;;;73640:55:0;;24518:2:1;73640:55:0;;;24500:21:1;24557:2;24537:18;;;24530:30;24596:27;24576:18;;;24569:55;24641:18;;73640:55:0;24316:349:1;73640:55:0;-1:-1:-1;;;;;73706:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;73706:46:0;;;;;;;;;;73768:41;;540::1;;;73768::0;;513:18:1;73768:41:0;;;;;;;73502:315;;;:::o;66486:::-;66643:28;66653:4;66659:2;66663:7;66643:9;:28::i;:::-;66690:48;66713:4;66719:2;66723:7;66732:5;66690:22;:48::i;:::-;66682:111;;;;-1:-1:-1;;;66682:111:0;;;;;;;:::i;83915:1081::-;83980:13;84006:16;84031:19;84042:7;84031:10;:19::i;:::-;84006:45;;84062:18;84112;:7;:16;;;:18::i;:::-;84083:48;;;;;;;;:::i;:::-;;;;-1:-1:-1;;84083:48:0;;;;;;84531:16;;;;;;;;;;84083:48;;-1:-1:-1;84290:664:0;;84083:48;;84531:16;84083:48;84531:16;;;84696:18;84710:3;84696:13;:18::i;:::-;84805:29;84826:7;84805:20;:29::i;:::-;84366:538;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;84290:13;:664::i;:::-;84197:776;;;;;;;;:::i;:::-;;;;;;;;;;;;;84152:836;;;;83915:1081;;;:::o;9542:1267::-;9650:24;9719:5;9687:23;9785:1;9797:280;9834:1;9814:10;:17;:21;;;;:::i;:::-;9804:7;:31;9797:280;;;9852:10;9865:32;9874:5;9881:6;9889:7;9865:8;:32::i;:::-;9852:45;-1:-1:-1;9916:12:0;;9912:154;;9947:5;;;9912:154;9991:14;;;;:::i;:::-;;-1:-1:-1;10034:16:0;;-1:-1:-1;10039:6:0;10049:1;10034:16;:::i;:::-;10024:26;;9837:240;9797:280;;;10113:12;10100:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10089:37;;10149:1;10139:11;;10176:1;10161:16;;10188:588;10225:1;10205:10;:17;:21;;;;:::i;:::-;10195:7;:31;10188:588;;;10245:10;10258:32;10267:5;10274:6;10282:7;10258:8;:32::i;:::-;10245:45;-1:-1:-1;10309:13:0;;10305:85;;-1:-1:-1;10356:17:0;;10305:85;10406:18;10438:22;10453:7;10443:6;10438:22;:::i;:::-;10427:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10427:34:0;-1:-1:-1;10406:55:0;-1:-1:-1;10406:55:0;10476:22;10568:7;10554:111;10586:6;10577:1;:16;10554:111;;;10636:10;10647:1;10636:13;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;10636:13:0;10619:9;10629:3;;;;:::i;:::-;;;10619:14;;;;;;;;:::i;:::-;;;;:30;-1:-1:-1;;;;;10619:30:0;;;;;;;;-1:-1:-1;10595:3:0;;;;:::i;:::-;;;;10554:111;;;-1:-1:-1;10689:16:0;10694:6;10704:1;10689:16;:::i;:::-;10679:26;-1:-1:-1;10754:9:0;10720:8;10729:14;;;;:::i;:::-;;;10720:24;;;;;;;;:::i;:::-;;;;;;:44;;;;10228:548;;;;10188:588;;;10786:15;;;9542:1267;;;;:::o;8982:550::-;9210:17;;9099:13;;9157:5;;9188:17;9198:7;9188;:17;:::i;:::-;9183:44;;9176:52;;;;:::i;:::-;9241:18;9278:7;9262:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9262:25:0;-1:-1:-1;9241:46:0;-1:-1:-1;9241:46:0;9298:22;9387:7;9368:120;9406:17;9416:7;9406;:17;:::i;:::-;9397:1;:27;9368:120;;;9463:10;9474:1;9463:13;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;9463:13:0;9446:9;9456:3;;;;:::i;:::-;;;9446:14;;;;;;;;:::i;:::-;;;;:30;-1:-1:-1;;;;;9446:30:0;;;;;;;;-1:-1:-1;9426:3:0;;;;:::i;:::-;;;;9368:120;;;-1:-1:-1;9514:9:0;;-1:-1:-1;;;;8982:550:0;;;;;;:::o;17833:1001::-;17990:4;17984:11;18050:4;18044;18040:15;18032:23;;18098:6;18092:4;18088:17;18168:4;18159:6;18153:13;18149:24;18141:6;18137:37;18009:712;18199:7;18193:4;18190:17;18009:712;;;18694:11;;18679:27;;18245:4;18235:15;;;;18278:17;18009:712;;;-1:-1:-1;;18793:13:0;;18789:26;18774:42;;;-1:-1:-1;17833:1001:0:o;69077:745::-;69287:349;;;-1:-1:-1;;;;;28645:15:1;;69287:349:0;;;;28627:34:1;;;;69564:4:0;28677:18:1;;;28670:43;28729:18;;;;28722:34;;;69287:349:0;;;;;;;;;;28562:18:1;;;;69287:349:0;;;69259:392;;;;;-1:-1:-1;;;69695:37:0;28722:34:1;69259:392:0;69695:37;:::i;:::-;69673:59;;69750:64;69775:11;69788:25;69750:24;:64::i;:::-;69743:71;69077:745;-1:-1:-1;;;;;69077:745:0:o;67765:304::-;67916:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;67916:21:0;-1:-1:-1;;;;;67916:21:0;;;;;;;;67963:33;;67916:16;;;67963:33;;67916:16;;67963:33;82081:380;82034:427;:::o;32635:922::-;32688:7;;-1:-1:-1;;;32766:15:0;;32762:102;;-1:-1:-1;;;32802:15:0;;;-1:-1:-1;32846:2:0;32836:12;32762:102;32891:6;32882:5;:15;32878:102;;32927:6;32918:15;;;-1:-1:-1;32962:2:0;32952:12;32878:102;33007:6;32998:5;:15;32994:102;;33043:6;33034:15;;;-1:-1:-1;33078:2:0;33068:12;32994:102;33123:5;33114;:14;33110:99;;33158:5;33149:14;;;-1:-1:-1;33192:1:0;33182:11;33110:99;33236:5;33227;:14;33223:99;;33271:5;33262:14;;;-1:-1:-1;33305:1:0;33295:11;33223:99;33349:5;33340;:14;33336:99;;33384:5;33375:14;;;-1:-1:-1;33418:1:0;33408:11;33336:99;33462:5;33453;:14;33449:66;;33498:1;33488:11;33543:6;32635:922;-1:-1:-1;;32635:922:0:o;74382:799::-;74537:4;-1:-1:-1;;;;;74558:13:0;;42784:19;:23;74554:620;;74594:72;;-1:-1:-1;;;74594:72:0;;-1:-1:-1;;;;;74594:36:0;;;;;:72;;38422:10;;74645:4;;74651:7;;74660:5;;74594:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74594:72:0;;;;;;;;-1:-1:-1;;74594:72:0;;;;;;;;;;;;:::i;:::-;;;74590:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74836:6;:13;74853:1;74836:18;74832:272;;74879:60;;-1:-1:-1;;;74879:60:0;;;;;;;:::i;74832:272::-;75054:6;75048:13;75039:6;75035:2;75031:15;75024:38;74590:529;-1:-1:-1;;;;;;74717:51:0;-1:-1:-1;;;74717:51:0;;-1:-1:-1;74710:58:0;;74554:620;-1:-1:-1;75158:4:0;74382:799;;;;;;:::o;467:3097::-;525:13;762:4;:11;777:1;762:16;758:31;;-1:-1:-1;;780:9:0;;;;;;;;;-1:-1:-1;780:9:0;;;467:3097::o;758:31::-;842:19;864:6;;;;;;;;;;;;;;;;;842:28;;1281:20;1340:1;1321:4;:11;1335:1;1321:15;;;;:::i;:::-;1320:21;;;;:::i;:::-;1315:27;;:1;:27;:::i;:::-;1304:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1304:39:0;;1281:62;;1523:1;1516:5;1512:13;1627:2;1619:6;1615:15;1738:4;1790;1784:11;1778:4;1774:22;1700:1432;1824:6;1815:7;1812:19;1700:1432;;;1930:1;1921:7;1917:15;1906:26;;1969:7;1963:14;2622:4;2614:5;2610:2;2606:14;2602:25;2592:8;2588:40;2582:47;2571:9;2563:67;2676:1;2665:9;2661:17;2648:30;;2768:4;2760:5;2756:2;2752:14;2748:25;2738:8;2734:40;2728:47;2717:9;2709:67;2822:1;2811:9;2807:17;2794:30;;2913:4;2905:5;2902:1;2898:13;2894:24;2884:8;2880:39;2874:46;2863:9;2855:66;2967:1;2956:9;2952:17;2939:30;;3050:4;3043:5;3039:16;3029:8;3025:31;3019:38;3008:9;3000:58;;3104:1;3093:9;3089:17;3076:30;;1700:1432;;;1704:107;;3294:1;3287:4;3281:11;3277:19;3315:1;3310:123;;;;3452:1;3447:73;;;;3270:250;;3310:123;3363:4;3359:1;3348:9;3344:17;3336:32;3413:4;3409:1;3398:9;3394:17;3386:32;3310:123;;3447:73;3500:4;3496:1;3485:9;3481:17;3473:32;3270:250;-1:-1:-1;3550:6:0;;467:3097;-1:-1:-1;;;;;467:3097:0:o;6736:478::-;6986:18;;6861:3;;6909:5;;6959:6;;7008:1;6986:23;6979:31;;;;:::i;:::-;7037:7;7023:162;7050:10;:17;7046:1;:21;7023:162;;;7110:11;7122:1;7110:14;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;7093:31:0;;:10;7104:1;7093:13;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;7093:13:0;:31;7089:85;;7156:1;-1:-1:-1;7145:13:0;;-1:-1:-1;;7145:13:0;7089:85;7069:3;;;;:::i;:::-;;;;7023:162;;;-1:-1:-1;;;7204:2:0;6736:478;-1:-1:-1;;;;;;6736:478:0:o;69940:1476::-;70062:7;70108:28;;;:16;:28;;;;;;70062:7;70176:15;;;70172:292;;-1:-1:-1;70289:10:0;70172:292;;;-1:-1:-1;70442:10:0;70172:292;70476:17;70496:29;70524:1;70496:25;:29;:::i;:::-;70536:22;70561:27;;;:16;:27;;;;;;70476:49;;-1:-1:-1;70603:23:0;;;70599:629;;70854:14;70872:1;70854:19;70850:367;;70970:28;;;;:16;:28;;;;;:40;;;70850:367;;;71156:28;;;;:16;:28;;;;;:45;;;70850:367;71242:19;;71238:137;;71336:27;;;;:16;:27;;;;;71329:34;71238:137;-1:-1:-1;71402:6:0;;69940:1476;-1:-1:-1;;;;;69940:1476:0:o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:272::-;650:6;703:2;691:9;682:7;678:23;674:32;671:52;;;719:1;716;709:12;671:52;758:9;745:23;808:6;801:5;797:18;790:5;787:29;777:57;;830:1;827;820:12;869:250;954:1;964:113;978:6;975:1;972:13;964:113;;;1054:11;;;1048:18;1035:11;;;1028:39;1000:2;993:10;964:113;;;-1:-1:-1;;1111:1:1;1093:16;;1086:27;869:250::o;1124:271::-;1166:3;1204:5;1198:12;1231:6;1226:3;1219:19;1247:76;1316:6;1309:4;1304:3;1300:14;1293:4;1286:5;1282:16;1247:76;:::i;:::-;1377:2;1356:15;-1:-1:-1;;1352:29:1;1343:39;;;;1384:4;1339:50;;1124:271;-1:-1:-1;;1124:271:1:o;1400:220::-;1549:2;1538:9;1531:21;1512:4;1569:45;1610:2;1599:9;1595:18;1587:6;1569:45;:::i;1625:180::-;1684:6;1737:2;1725:9;1716:7;1712:23;1708:32;1705:52;;;1753:1;1750;1743:12;1705:52;-1:-1:-1;1776:23:1;;1625:180;-1:-1:-1;1625:180:1:o;2018:173::-;2086:20;;-1:-1:-1;;;;;2135:31:1;;2125:42;;2115:70;;2181:1;2178;2171:12;2115:70;2018:173;;;:::o;2196:254::-;2264:6;2272;2325:2;2313:9;2304:7;2300:23;2296:32;2293:52;;;2341:1;2338;2331:12;2293:52;2364:29;2383:9;2364:29;:::i;:::-;2354:39;2440:2;2425:18;;;;2412:32;;-1:-1:-1;;;2196:254:1:o;2455:127::-;2516:10;2511:3;2507:20;2504:1;2497:31;2547:4;2544:1;2537:15;2571:4;2568:1;2561:15;2587:275;2658:2;2652:9;2723:2;2704:13;;-1:-1:-1;;2700:27:1;2688:40;;2758:18;2743:34;;2779:22;;;2740:62;2737:88;;;2805:18;;:::i;:::-;2841:2;2834:22;2587:275;;-1:-1:-1;2587:275:1:o;2867:183::-;2927:4;2960:18;2952:6;2949:30;2946:56;;;2982:18;;:::i;:::-;-1:-1:-1;3027:1:1;3023:14;3039:4;3019:25;;2867:183::o;3055:662::-;3109:5;3162:3;3155:4;3147:6;3143:17;3139:27;3129:55;;3180:1;3177;3170:12;3129:55;3216:6;3203:20;3242:4;3266:60;3282:43;3322:2;3282:43;:::i;:::-;3266:60;:::i;:::-;3360:15;;;3446:1;3442:10;;;;3430:23;;3426:32;;;3391:12;;;;3470:15;;;3467:35;;;3498:1;3495;3488:12;3467:35;3534:2;3526:6;3522:15;3546:142;3562:6;3557:3;3554:15;3546:142;;;3628:17;;3616:30;;3666:12;;;;3579;;3546:142;;;-1:-1:-1;3706:5:1;3055:662;-1:-1:-1;;;;;;3055:662:1:o;3722:1146::-;3840:6;3848;3901:2;3889:9;3880:7;3876:23;3872:32;3869:52;;;3917:1;3914;3907:12;3869:52;3957:9;3944:23;3986:18;4027:2;4019:6;4016:14;4013:34;;;4043:1;4040;4033:12;4013:34;4081:6;4070:9;4066:22;4056:32;;4126:7;4119:4;4115:2;4111:13;4107:27;4097:55;;4148:1;4145;4138:12;4097:55;4184:2;4171:16;4206:4;4230:60;4246:43;4286:2;4246:43;:::i;4230:60::-;4324:15;;;4406:1;4402:10;;;;4394:19;;4390:28;;;4355:12;;;;4430:19;;;4427:39;;;4462:1;4459;4452:12;4427:39;4486:11;;;;4506:148;4522:6;4517:3;4514:15;4506:148;;;4588:23;4607:3;4588:23;:::i;:::-;4576:36;;4539:12;;;;4632;;;;4506:148;;;4673:5;-1:-1:-1;;4716:18:1;;4703:32;;-1:-1:-1;;4747:16:1;;;4744:36;;;4776:1;4773;4766:12;4744:36;;4799:63;4854:7;4843:8;4832:9;4828:24;4799:63;:::i;:::-;4789:73;;;3722:1146;;;;;:::o;5055:328::-;5132:6;5140;5148;5201:2;5189:9;5180:7;5176:23;5172:32;5169:52;;;5217:1;5214;5207:12;5169:52;5240:29;5259:9;5240:29;:::i;:::-;5230:39;;5288:38;5322:2;5311:9;5307:18;5288:38;:::i;:::-;5278:48;;5373:2;5362:9;5358:18;5345:32;5335:42;;5055:328;;;;;:::o;5388:186::-;5447:6;5500:2;5488:9;5479:7;5475:23;5471:32;5468:52;;;5516:1;5513;5506:12;5468:52;5539:29;5558:9;5539:29;:::i;5579:347::-;5644:6;5652;5705:2;5693:9;5684:7;5680:23;5676:32;5673:52;;;5721:1;5718;5711:12;5673:52;5744:29;5763:9;5744:29;:::i;:::-;5734:39;;5823:2;5812:9;5808:18;5795:32;5870:5;5863:13;5856:21;5849:5;5846:32;5836:60;;5892:1;5889;5882:12;5836:60;5915:5;5905:15;;;5579:347;;;;;:::o;5931:186::-;5979:4;6012:18;6004:6;6001:30;5998:56;;;6034:18;;:::i;:::-;-1:-1:-1;6100:2:1;6079:15;-1:-1:-1;;6075:29:1;6106:4;6071:40;;5931:186::o;6122:888::-;6217:6;6225;6233;6241;6294:3;6282:9;6273:7;6269:23;6265:33;6262:53;;;6311:1;6308;6301:12;6262:53;6334:29;6353:9;6334:29;:::i;:::-;6324:39;;6382:38;6416:2;6405:9;6401:18;6382:38;:::i;:::-;6372:48;;6467:2;6456:9;6452:18;6439:32;6429:42;;6522:2;6511:9;6507:18;6494:32;6549:18;6541:6;6538:30;6535:50;;;6581:1;6578;6571:12;6535:50;6604:22;;6657:4;6649:13;;6645:27;-1:-1:-1;6635:55:1;;6686:1;6683;6676:12;6635:55;6722:2;6709:16;6747:48;6763:31;6791:2;6763:31;:::i;6747:48::-;6818:2;6811:5;6804:17;6858:7;6853:2;6848;6844;6840:11;6836:20;6833:33;6830:53;;;6879:1;6876;6869:12;6830:53;6934:2;6929;6925;6921:11;6916:2;6909:5;6905:14;6892:45;6978:1;6973:2;6968;6961:5;6957:14;6953:23;6946:34;6999:5;6989:15;;;;;6122:888;;;;;;;:::o;7015:260::-;7083:6;7091;7144:2;7132:9;7123:7;7119:23;7115:32;7112:52;;;7160:1;7157;7150:12;7112:52;7183:29;7202:9;7183:29;:::i;:::-;7173:39;;7231:38;7265:2;7254:9;7250:18;7231:38;:::i;:::-;7221:48;;7015:260;;;;;:::o;7280:127::-;7341:10;7336:3;7332:20;7329:1;7322:31;7372:4;7369:1;7362:15;7396:4;7393:1;7386:15;7412:127;7473:10;7468:3;7464:20;7461:1;7454:31;7504:4;7501:1;7494:15;7528:4;7525:1;7518:15;7544:197;7585:3;7623:5;7617:12;7638:65;7696:6;7691:3;7684:4;7677:5;7673:16;7638:65;:::i;:::-;7719:16;;;;;7544:197;-1:-1:-1;;7544:197:1:o;7746:494::-;7923:3;7961:6;7955:13;7977:66;8036:6;8031:3;8024:4;8016:6;8012:17;7977:66;:::i;:::-;8106:13;;8065:16;;;;8128:70;8106:13;8065:16;8175:4;8163:17;;8128:70;:::i;:::-;8214:20;;7746:494;-1:-1:-1;;;;7746:494:1:o;8245:127::-;8306:10;8301:3;8297:20;8294:1;8287:31;8337:4;8334:1;8327:15;8361:4;8358:1;8351:15;8377:135;8416:3;8437:17;;;8434:43;;8457:18;;:::i;:::-;-1:-1:-1;8504:1:1;8493:13;;8377:135::o;8517:450::-;8747:3;8785:6;8779:13;8801:66;8860:6;8855:3;8848:4;8840:6;8836:17;8801:66;:::i;:::-;-1:-1:-1;;;8889:16:1;;8914:18;;;-1:-1:-1;8959:1:1;8948:13;;8517:450;-1:-1:-1;8517:450:1:o;8972:380::-;9051:1;9047:12;;;;9094;;;9115:61;;9169:4;9161:6;9157:17;9147:27;;9115:61;9222:2;9214:6;9211:14;9191:18;9188:38;9185:161;;9268:10;9263:3;9259:20;9256:1;9249:31;9303:4;9300:1;9293:15;9331:4;9328:1;9321:15;9185:161;;8972:380;;;:::o;11014:128::-;11081:9;;;11102:11;;;11099:37;;;11116:18;;:::i;11147:413::-;11349:2;11331:21;;;11388:2;11368:18;;;11361:30;11427:34;11422:2;11407:18;;11400:62;-1:-1:-1;;;11493:2:1;11478:18;;11471:47;11550:3;11535:19;;11147:413::o;13134:320::-;13209:5;13238:52;13254:35;13282:6;13254:35;:::i;13238:52::-;13229:61;;13313:6;13306:5;13299:21;13353:3;13344:6;13339:3;13335:16;13332:25;13329:45;;;13370:1;13367;13360:12;13329:45;13383:65;13441:6;13434:4;13427:5;13423:16;13418:3;13383:65;:::i;13459:457::-;13538:6;13591:2;13579:9;13570:7;13566:23;13562:32;13559:52;;;13607:1;13604;13597:12;13559:52;13640:9;13634:16;13673:18;13665:6;13662:30;13659:50;;;13705:1;13702;13695:12;13659:50;13728:22;;13781:4;13773:13;;13769:27;-1:-1:-1;13759:55:1;;13810:1;13807;13800:12;13759:55;13833:77;13902:7;13897:2;13891:9;13886:2;13882;13878:11;13833:77;:::i;13921:168::-;13994:9;;;14025;;14042:15;;;14036:22;;14022:37;14012:71;;14063:18;;:::i;14094:125::-;14159:9;;;14180:10;;;14177:36;;;14193:18;;:::i;14224:1355::-;-1:-1:-1;;;14873:43:1;;14939:13;;14855:3;;14961:74;14939:13;15024:1;15015:11;;15008:4;14996:17;;14961:74;:::i;:::-;-1:-1:-1;;;15094:1:1;15054:16;;;15086:10;;;15079:42;15146:13;;15168:76;15146:13;15230:2;15222:11;;15215:4;15203:17;;15168:76;:::i;:::-;-1:-1:-1;;;15304:2:1;15263:17;;;;15296:11;;;15289:51;15365:13;;15387:76;15365:13;15449:2;15441:11;;15434:4;15422:17;;15387:76;:::i;:::-;-1:-1:-1;;;15523:2:1;15482:17;;;;15515:11;;;15508:38;15570:2;15562:11;;14224:1355;-1:-1:-1;;;;;14224:1355:1:o;18207:284::-;18300:6;18353:2;18341:9;18332:7;18328:23;18324:32;18321:52;;;18369:1;18366;18359:12;18321:52;18401:9;18395:16;18440:2;18433:5;18430:13;18420:41;;18457:1;18454;18447:12;18496:352;18651:2;18636:18;;18684:2;18673:14;;18663:145;;18730:10;18725:3;18721:20;18718:1;18711:31;18765:4;18762:1;18755:15;18793:4;18790:1;18783:15;18663:145;18817:25;;;18496:352;:::o;18853:283::-;18945:6;18998:2;18986:9;18977:7;18973:23;18969:32;18966:52;;;19014:1;19011;19004:12;18966:52;19046:9;19040:16;19085:2;19078:5;19075:13;19065:41;;19102:1;19099;19092:12;19141:136;19180:3;19208:5;19198:39;;19217:18;;:::i;:::-;-1:-1:-1;;;19253:18:1;;19141:136::o;19282:1012::-;-1:-1:-1;;;19782:55:1;;19860:13;;19764:3;;19882:75;19860:13;19945:2;19936:12;;19929:4;19917:17;;19882:75;:::i;:::-;-1:-1:-1;;;20016:2:1;19976:16;;;20008:11;;;20001:57;20083:13;;20105:76;20083:13;20167:2;20159:11;;20152:4;20140:17;;20105:76;:::i;:::-;-1:-1:-1;;;20241:2:1;20200:17;;;;20233:11;;;20226:35;20285:2;20277:11;;19282:1012;-1:-1:-1;;;;19282:1012:1:o;24184:127::-;24245:10;24240:3;24236:20;24233:1;24226:31;24276:4;24273:1;24266:15;24300:4;24297:1;24290:15;24670:414;24872:2;24854:21;;;24911:2;24891:18;;;24884:30;24950:34;24945:2;24930:18;;24923:62;-1:-1:-1;;;25016:2:1;25001:18;;24994:48;25074:3;25059:19;;24670:414::o;25089:438::-;-1:-1:-1;;;25346:3:1;25339:23;25321:3;25391:6;25385:13;25407:74;25474:6;25470:1;25465:3;25461:11;25454:4;25446:6;25442:17;25407:74;:::i;:::-;25501:16;;;;25519:1;25497:24;;25089:438;-1:-1:-1;;25089:438:1:o;25651:1912::-;-1:-1:-1;;;26546:16:1;;-1:-1:-1;;;26587:1:1;26578:11;;26571:49;26643:13;;-1:-1:-1;;26665:74:1;26643:13;26728:1;26719:11;;26712:4;26700:17;;26665:74;:::i;:::-;-1:-1:-1;;;26798:1:1;26758:16;;;26790:10;;;26783:66;26874:13;;26896:76;26874:13;26958:2;26950:11;;26943:4;26931:17;;26896:76;:::i;:::-;27037:66;27032:2;26991:17;;;;27024:11;;;27017:87;27133:66;27128:2;27120:11;;27113:87;-1:-1:-1;;;27224:2:1;27216:11;;27209:30;27264:13;;27286:76;27264:13;27348:2;27340:11;;27333:4;27321:17;;27286:76;:::i;:::-;-1:-1:-1;;;27422:2:1;27381:17;;;;27414:11;;;27407:65;27488:69;27518:38;27551:3;27543:12;;27535:6;27518:38;:::i;:::-;-1:-1:-1;;;25597:16:1;;25638:1;25629:11;;25532:114;27488:69;27481:76;25651:1912;-1:-1:-1;;;;;;;25651:1912:1:o;27568:461::-;27830:31;27825:3;27818:44;27800:3;27891:6;27885:13;27907:75;27975:6;27970:2;27965:3;27961:12;27954:4;27946:6;27942:17;27907:75;:::i;:::-;28002:16;;;;28020:2;27998:25;;27568:461;-1:-1:-1;;27568:461:1:o;28034:216::-;28098:9;;;28126:11;;;28073:3;28156:9;;28184:10;;28180:19;;28209:10;;28201:19;;28177:44;28174:70;;;28224:18;;:::i;:::-;28174:70;;28034:216;;;;:::o;28255:127::-;28316:10;28311:3;28307:20;28304:1;28297:31;28347:4;28344:1;28337:15;28371:4;28368:1;28361:15;28767:112;28799:1;28825;28815:35;;28830:18;;:::i;:::-;-1:-1:-1;28864:9:1;;28767:112::o;28884:489::-;-1:-1:-1;;;;;29153:15:1;;;29135:34;;29205:15;;29200:2;29185:18;;29178:43;29252:2;29237:18;;29230:34;;;29300:3;29295:2;29280:18;;29273:31;;;29078:4;;29321:46;;29347:19;;29339:6;29321:46;:::i;:::-;29313:54;28884:489;-1:-1:-1;;;;;;28884:489:1:o;29378:249::-;29447:6;29500:2;29488:9;29479:7;29475:23;29471:32;29468:52;;;29516:1;29513;29506:12;29468:52;29548:9;29542:16;29567:30;29591:5;29567:30;:::i;29632:120::-;29672:1;29698;29688:35;;29703:18;;:::i;:::-;-1:-1:-1;29737:9:1;;29632:120::o

Swarm Source

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