ETH Price: $3,361.21 (-1.62%)
Gas: 6 Gwei

Token

GRAYCRAFT2 (GRAY2)
 

Overview

Max Total Supply

0 GRAY2

Holders

1,418

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 GRAY2
0xd83c7bced50ba86f1c1fbf29abba278e3659f72a
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

GRAYCRAFT2 brings us one step closer to our dreams. This is the first ever generative 3D spaceship project of its kind, a collection of 5,200 unique creations that represents the freedom, exploration and progress that is the spirit of this generation’s space entrepreneurs.

# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
GRAYCRAFT2

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-08-16
*/

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

/// @credits: manifold.xyz

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                           //
//                                                                                                                           //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ..... MMMMMMMMMMMMMM  MMMMMMMMMMM ..MMMM..MMMM ...MMMM .,MMMMMMMMMM .MMMNMMMMMMM,..MMMM..MMMMMMMMMMMMMMMMMMMMMMMMN..   //
//    .... :MMM........... MMMM... MMM  ...MMMM .MMMM ..MMM.. MMMM....... MMMM....MMMM....MMMM..MMMM ........ MMM ........   //
//    .....MMMM...................MMMM......MMMM. MMMM MMMM  MMMM ...............MMMM .....MMMM. MMMMMMMMMM ...MMMM.......   //
//    ....MMMM...:::MMM,.MMMM:MMMM  ...:MMM,.MMM......MMMM .MMMM ....... MMMM:MMMM .. .MMMM,MMMM..MMM .........MMMM.......   //
//    ...MMMM .....MMMM..MMM . MMMM ...MMMM..MMMM....MMMM..MMMM.........MMMM . MMM ...MMMM.. MMMM.MMMM..........MMMM......   //
//    ..MMMMMMMMM.MMMM  MMMM... MMMM  MMMM....MMMM..MMMM .MMMMMMMMMMM .MMMM... MMMM. MMMM...  MMM..MMMM ........ MMMM.....   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//    ....................................................................................................................   //
//                                                                                                                           //
//                                                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pragma solidity ^0.8.0;

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


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



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/utils/structs/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}


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



pragma solidity ^0.8.0;

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

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


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



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() {
        _setOwner(_msgSender());
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}


// File contracts/creator/access/IAdminControl.sol



pragma solidity ^0.8.0;

/**
 * @dev Interface for admin control
 */
interface IAdminControl is IERC165 {

    event AdminApproved(address indexed account, address indexed sender);
    event AdminRevoked(address indexed account, address indexed sender);

    /**
     * @dev gets address of all admins
     */
    function getAdmins() external view returns (address[] memory);

    /**
     * @dev add an admin.  Can only be called by contract owner.
     */
    function approveAdmin(address admin) external;

    /**
     * @dev remove an admin.  Can only be called by contract owner.
     */
    function revokeAdmin(address admin) external;

    /**
     * @dev checks whether or not given address is an admin
     * Returns True if they are
     */
    function isAdmin(address admin) external view returns (bool);

}


// File contracts/creator/access/AdminControl.sol



pragma solidity ^0.8.0;






abstract contract AdminControl is Ownable, IAdminControl, ERC165 {
    using EnumerableSet for EnumerableSet.AddressSet;

    // Track registered admins
    EnumerableSet.AddressSet private _admins;

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

    /**
     * @dev Only allows approved admins to call the specified function
     */
    modifier adminRequired() {
        require(owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin");
        _;
    }   

    /**
     * @dev See {IAdminControl-getAdmins}.
     */
    function getAdmins() external view override returns (address[] memory admins) {
        admins = new address[](_admins.length());
        for (uint i = 0; i < _admins.length(); i++) {
            admins[i] = _admins.at(i);
        }
        return admins;
    }

    /**
     * @dev See {IAdminControl-approveAdmin}.
     */
    function approveAdmin(address admin) external override onlyOwner {
        if (!_admins.contains(admin)) {
            emit AdminApproved(admin, msg.sender);
            _admins.add(admin);
        }
    }

    /**
     * @dev See {IAdminControl-revokeAdmin}.
     */
    function revokeAdmin(address admin) external override onlyOwner {
        if (_admins.contains(admin)) {
            emit AdminRevoked(admin, msg.sender);
            _admins.remove(admin);
        }
    }

    /**
     * @dev See {IAdminControl-isAdmin}.
     */
    function isAdmin(address admin) public override view returns (bool) {
        return (owner() == admin || _admins.contains(admin));
    }

}


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



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 make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

        // 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/[email protected]



pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @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] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}


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



pragma solidity ^0.8.0;

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            _supportsERC165Interface(account, type(IERC165).interfaceId) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
        internal
        view
        returns (bool[] memory)
    {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        bytes memory encodedParams = abi.encodeWithSelector(IERC165(account).supportsInterface.selector, interfaceId);
        (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);
        if (result.length < 32) return false;
        return success && abi.decode(result, (bool));
    }
}


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



pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 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 functionCall(target, data, "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");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return _verifyCallResult(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) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // 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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File contracts/creator/extensions/ICreatorExtensionTokenURI.sol



pragma solidity ^0.8.0;



/**
 * @dev Implement this if you want your extension to have overloadable URI's
 */
interface ICreatorExtensionTokenURI is IERC165 {

    /**
     * Get the uri for a given creator/tokenId
     */
    function tokenURI(address creator, uint256 tokenId) external view returns (string memory);
}


// File contracts/creator/core/ICreatorCore.sol



pragma solidity ^0.8.0;



/**
 * @dev Core creator interface
 */
interface ICreatorCore is IERC165 {

    event ExtensionRegistered(address indexed extension, address indexed sender);
    event ExtensionUnregistered(address indexed extension, address indexed sender);
    event ExtensionBlacklisted(address indexed extension, address indexed sender);
    event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender);
    event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints);
    event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints);
    event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints);
    event ExtensionApproveTransferUpdated(address indexed extension, bool enabled);

    /**
     * @dev gets address of all extensions
     */
    function getExtensions() external view returns (address[] memory);

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * extension address must point to a contract implementing ICreatorExtension.
     * Returns True if newly added, False if already added.
     */
    function registerExtension(address extension, string calldata baseURI) external;

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * extension address must point to a contract implementing ICreatorExtension.
     * Returns True if newly added, False if already added.
     */
    function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external;

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * Returns True if removed, False if already removed.
     */
    function unregisterExtension(address extension) external;

    /**
     * @dev blacklist an extension.  Can only be called by contract owner or admin.
     * This function will destroy all ability to reference the metadata of any tokens created
     * by the specified extension. It will also unregister the extension if needed.
     * Returns True if removed, False if already removed.
     */
    function blacklistExtension(address extension) external;

    /**
     * @dev set the baseTokenURI of an extension.  Can only be called by extension.
     */
    function setBaseTokenURIExtension(string calldata uri) external;

    /**
     * @dev set the baseTokenURI of an extension.  Can only be called by extension.
     * For tokens with no uri configured, tokenURI will return "uri+tokenId"
     */
    function setBaseTokenURIExtension(string calldata uri, bool identical) external;

    /**
     * @dev set the common prefix of an extension.  Can only be called by extension.
     * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
     * Useful if you want to use ipfs/arweave
     */
    function setTokenURIPrefixExtension(string calldata prefix) external;

    /**
     * @dev set the tokenURI of a token extension.  Can only be called by extension that minted token.
     */
    function setTokenURIExtension(uint256 tokenId, string calldata uri) external;

    /**
     * @dev set the tokenURI of a token extension for multiple tokens.  Can only be called by extension that minted token.
     */
    function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;

    /**
     * @dev set the baseTokenURI for tokens with no extension.  Can only be called by owner/admin.
     * For tokens with no uri configured, tokenURI will return "uri+tokenId"
     */
    function setBaseTokenURI(string calldata uri) external;

    /**
     * @dev set the common prefix for tokens with no extension.  Can only be called by owner/admin.
     * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
     * Useful if you want to use ipfs/arweave
     */
    function setTokenURIPrefix(string calldata prefix) external;

    /**
     * @dev set the tokenURI of a token with no extension.  Can only be called by owner/admin.
     */
    function setTokenURI(uint256 tokenId, string calldata uri) external;

    /**
     * @dev set the tokenURI of multiple tokens with no extension.  Can only be called by owner/admin.
     */
    function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;

    /**
     * @dev set a permissions contract for an extension.  Used to control minting.
     */
    function setMintPermissions(address extension, address permissions) external;

    /**
     * @dev Configure so transfers of tokens created by the caller (must be extension) gets approval
     * from the extension before transferring
     */
    function setApproveTransferExtension(bool enabled) external;

    /**
     * @dev get the extension of a given token
     */
    function tokenExtension(uint256 tokenId) external view returns (address);

    /**
     * @dev Set default royalties
     */
    function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Set royalties of a token
     */
    function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Set royalties of an extension
     */
    function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Get royalites of a token.  Returns list of receivers and basisPoints
     */
    function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
    
    // Royalty support for various other standards
    function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory);
    function getFeeBps(uint256 tokenId) external view returns (uint[] memory);
    function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
    function royaltyInfo(uint256 tokenId, uint256 value, bytes calldata data) external view returns (address, uint256, bytes memory);

}


// File contracts/creator/core/CreatorCore.sol



pragma solidity ^0.8.0;








/**
 * @dev Core creator implementation
 */
abstract contract CreatorCore is ReentrancyGuard, ICreatorCore, ERC165 {
    using Strings for uint256;
    using EnumerableSet for EnumerableSet.AddressSet;
    using AddressUpgradeable for address;

    uint256 _tokenCount = 0;

    // Track registered extensions data
    EnumerableSet.AddressSet internal _extensions;
    EnumerableSet.AddressSet internal _blacklistedExtensions;
    mapping (address => address) internal _extensionPermissions;
    mapping (address => bool) internal _extensionApproveTransfers;
    
    // For tracking which extension a token was minted by
    mapping (uint256 => address) internal _tokensExtension;

    // The baseURI for a given extension
    mapping (address => string) private _extensionBaseURI;
    mapping (address => bool) private _extensionBaseURIIdentical;

    // The prefix for any tokens with a uri configured
    mapping (address => string) private _extensionURIPrefix;

    // Mapping for individual token URIs
    mapping (uint256 => string) internal _tokenURIs;

    
    // Royalty configurations
    mapping (address => address payable[]) internal _extensionRoyaltyReceivers;
    mapping (address => uint256[]) internal _extensionRoyaltyBPS;
    mapping (uint256 => address payable[]) internal _tokenRoyaltyReceivers;
    mapping (uint256 => uint256[]) internal _tokenRoyaltyBPS;

    /**
     * External interface identifiers for royalties
     */

    /**
     *  @dev CreatorCore
     *
     *  bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6
     *
     *  => 0xbb3bafd6 = 0xbb3bafd6
     */
    bytes4 private constant _INTERFACE_ID_ROYALTIES_CREATORCORE = 0xbb3bafd6;

    /**
     *  @dev Rarible: RoyaltiesV1
     *
     *  bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb
     *  bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f
     *
     *  => 0xb9c4d9fb ^ 0x0ebd4c7f = 0xb7799584
     */
    bytes4 private constant _INTERFACE_ID_ROYALTIES_RARIBLE = 0xb7799584;

    /**
     *  @dev Foundation
     *
     *  bytes4(keccak256('getFees(uint256)')) == 0xd5a06d4c
     *
     *  => 0xd5a06d4c = 0xd5a06d4c
     */
    bytes4 private constant _INTERFACE_ID_ROYALTIES_FOUNDATION = 0xd5a06d4c;

    /**
     *  @dev EIP-2981
     *
     * bytes4(keccak256("royaltyInfo(uint256,uint256,bytes)")) == 0x6057361d
     *
     * => 0x6057361d = 0x6057361d
     */
    bytes4 private constant _INTERFACE_ID_ROYALTIES_EIP2981 = 0x6057361d;

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

    /**
     * @dev Only allows registered extensions to call the specified function
     */
    modifier extensionRequired() {
        require(_extensions.contains(msg.sender), "CreatorCore: Must be registered extension");
        _;
    }

    /**
     * @dev Only allows non-blacklisted extensions
     */
    modifier nonBlacklistRequired(address extension) {
        require(!_blacklistedExtensions.contains(extension), "CreatorCore: Extension blacklisted");
        _;
    }   

    /**
     * @dev See {ICreatorCore-getExtensions}.
     */
    function getExtensions() external view override returns (address[] memory extensions) {
        extensions = new address[](_extensions.length());
        for (uint i = 0; i < _extensions.length(); i++) {
            extensions[i] = _extensions.at(i);
        }
        return extensions;
    }

    /**
     * @dev Register an extension
     */
    function _registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) internal {
        require(extension.isContract(), "Creator: Extension must be a contract");
        if (!_extensions.contains(extension)) {
            _extensionBaseURI[extension] = baseURI;
            _extensionBaseURIIdentical[extension] = baseURIIdentical;
            emit ExtensionRegistered(extension, msg.sender);
            _extensions.add(extension);
        }
    }

    /**
     * @dev Unregister an extension
     */
    function _unregisterExtension(address extension) internal {
       if (_extensions.contains(extension)) {
           emit ExtensionUnregistered(extension, msg.sender);
           _extensions.remove(extension);
       }
    }

    /**
     * @dev Blacklist an extension
     */
    function _blacklistExtension(address extension) internal {
       require(extension != address(this), "CreatorCore: Cannot blacklist yourself");
       if (_extensions.contains(extension)) {
           emit ExtensionUnregistered(extension, msg.sender);
           _extensions.remove(extension);
       }
       if (!_blacklistedExtensions.contains(extension)) {
           emit ExtensionBlacklisted(extension, msg.sender);
           _blacklistedExtensions.add(extension);
       }
    }

    /**
     * @dev Set base token uri for an extension
     */
    function _setBaseTokenURIExtension(string calldata uri, bool identical) internal {
        _extensionBaseURI[msg.sender] = uri;
        _extensionBaseURIIdentical[msg.sender] = identical;
    }

    /**
     * @dev Set token uri prefix for an extension
     */
    function _setTokenURIPrefixExtension(string calldata prefix) internal {
        _extensionURIPrefix[msg.sender] = prefix;
    }

    /**
     * @dev Set token uri for a token of an extension
     */
    function _setTokenURIExtension(uint256 tokenId, string calldata uri) internal {
        require(_tokensExtension[tokenId] == msg.sender, "CreatorCore: Invalid token");
        _tokenURIs[tokenId] = uri;
    }

    /**
     * @dev Set base token uri for tokens with no extension
     */
    function _setBaseTokenURI(string memory uri) internal {
        _extensionBaseURI[address(this)] = uri;
    }

    /**
     * @dev Set token uri prefix for tokens with no extension
     */
    function _setTokenURIPrefix(string calldata prefix) internal {
        _extensionURIPrefix[address(this)] = prefix;
    }


    /**
     * @dev Set token uri for a token with no extension
     */
    function _setTokenURI(uint256 tokenId, string calldata uri) internal {
        require(_tokensExtension[tokenId] == address(this), "CreatorCore: Invalid token");
        _tokenURIs[tokenId] = uri;
    }

    /**
     * @dev Retrieve a token's URI
     */
    function _tokenURI(uint256 tokenId) internal view returns (string memory) {
        address extension = _tokensExtension[tokenId];
        require(!_blacklistedExtensions.contains(extension), "CreatorCore: Extension blacklisted");

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            if (bytes(_extensionURIPrefix[extension]).length != 0) {
                return string(abi.encodePacked(_extensionURIPrefix[extension],_tokenURIs[tokenId]));
            }
            return _tokenURIs[tokenId];
        }

        if (ERC165Checker.supportsInterface(extension, type(ICreatorExtensionTokenURI).interfaceId)) {
            return ICreatorExtensionTokenURI(extension).tokenURI(address(this), tokenId);
        }

        if (!_extensionBaseURIIdentical[extension]) {
            return string(abi.encodePacked(_extensionBaseURI[extension], tokenId.toString()));
        } else {
            return _extensionBaseURI[extension];
        }
    }

    /**
     * Get token extension
     */
    function _tokenExtension(uint256 tokenId) internal view returns (address extension) {
        extension = _tokensExtension[tokenId];

        require(extension != address(this), "CreatorCore: No extension for token");
        require(!_blacklistedExtensions.contains(extension), "CreatorCore: Extension blacklisted");

        return extension;
    }

    /**
     * Helper to get royalties for a token
     */
    function _getRoyalties(uint256 tokenId) view internal returns (address payable[] storage, uint256[] storage) {
        return (_getRoyaltyReceivers(tokenId), _getRoyaltyBPS(tokenId));
    }

    /**
     * Helper to get royalty receivers for a token
     */
    function _getRoyaltyReceivers(uint256 tokenId) view internal returns (address payable[] storage) {
        if (_tokenRoyaltyReceivers[tokenId].length > 0) {
            return _tokenRoyaltyReceivers[tokenId];
        } else if (_extensionRoyaltyReceivers[_tokensExtension[tokenId]].length > 0) {
            return _extensionRoyaltyReceivers[_tokensExtension[tokenId]];
        }
        return _extensionRoyaltyReceivers[address(this)];        
    }

    /**
     * Helper to get royalty basis points for a token
     */
    function _getRoyaltyBPS(uint256 tokenId) view internal returns (uint256[] storage) {
        if (_tokenRoyaltyBPS[tokenId].length > 0) {
            return _tokenRoyaltyBPS[tokenId];
        } else if (_extensionRoyaltyBPS[_tokensExtension[tokenId]].length > 0) {
            return _extensionRoyaltyBPS[_tokensExtension[tokenId]];
        }
        return _extensionRoyaltyBPS[address(this)];        
    }

    function _getRoyaltyInfo(uint256 tokenId, uint256 value) view internal returns (address receiver, uint256 amount, bytes memory data){
        address payable[] storage receivers = _getRoyaltyReceivers(tokenId);
        require(receivers.length <= 1, "CreatorCore: Only works if there are at most 1 royalty receivers");
        
        if (receivers.length == 0) {
            return (address(this), 0, data);
        }
        return (receivers[0], _getRoyaltyBPS(tokenId)[0]*value/10000, data);
    }

    /**
     * Set royalties for a token
     */
    function _setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) internal {
        require(receivers.length == basisPoints.length, "CreatorCore: Invalid input");
        uint256 totalBasisPoints;
        for (uint i = 0; i < basisPoints.length; i++) {
            totalBasisPoints += basisPoints[i];
        }
        require(totalBasisPoints < 10000, "CreatorCore: Invalid total royalties");
        _tokenRoyaltyReceivers[tokenId] = receivers;
        _tokenRoyaltyBPS[tokenId] = basisPoints;
        emit RoyaltiesUpdated(tokenId, receivers, basisPoints);
    }

    /**
     * Set royalties for all tokens of an extension
     */
    function _setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) internal {
        require(receivers.length == basisPoints.length, "CreatorCore: Invalid input");
        uint256 totalBasisPoints;
        for (uint i = 0; i < basisPoints.length; i++) {
            totalBasisPoints += basisPoints[i];
        }
        require(totalBasisPoints < 10000, "CreatorCore: Invalid total royalties");
        _extensionRoyaltyReceivers[extension] = receivers;
        _extensionRoyaltyBPS[extension] = basisPoints;
        if (extension == address(this)) {
            emit DefaultRoyaltiesUpdated(receivers, basisPoints);
        } else {
            emit ExtensionRoyaltiesUpdated(extension, receivers, basisPoints);
        }
    }


}


// File contracts/creator/extensions/ERC721/IERC721CreatorExtensionApproveTransfer.sol



pragma solidity ^0.8.0;



/**
 * Implement this if you want your extension to approve a transfer
 */
interface IERC721CreatorExtensionApproveTransfer is IERC165 {

    /**
     * @dev Set whether or not the creator will check the extension for approval of token transfer
     */
    function setApproveTransfer(address creator, bool enabled) external;

    /**
     * @dev Called by creator contract to approve a transfer
     */
    function approveTransfer(address from, address to, uint256 tokenId) external returns (bool);
}


// File contracts/creator/extensions/ERC721/IERC721CreatorExtensionBurnable.sol



pragma solidity ^0.8.0;



/**
 * @dev Your extension is required to implement this interface if it wishes
 * to receive the onBurn callback whenever a token the extension created is
 * burned
 */
interface IERC721CreatorExtensionBurnable is IERC165 {
    /**
     * @dev callback handler for burn events
     */
    function onBurn(address owner, uint256 tokenId) external;
}


// File contracts/creator/permissions/ERC721/IERC721CreatorMintPermissions.sol



pragma solidity ^0.8.0;



/**
 * @dev Required interface of an ERC721Creator compliant extension contracts.
 */
interface IERC721CreatorMintPermissions is IERC165 {

    /**
     * @dev get approval to mint
     */
    function approveMint(address extension, address to, uint256 tokenId) external;
}


// File contracts/creator/core/IERC721CreatorCore.sol



pragma solidity ^0.8.0;



/**
 * @dev Core ERC721 creator interface
 */
interface IERC721CreatorCore is ICreatorCore {

    /**
     * @dev mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBase(address to) external returns (uint256);

    /**
     * @dev mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBase(address to, string calldata uri) external returns (uint256);

    /**
     * @dev batch mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory);

    /**
     * @dev batch mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory);

    /**
     * @dev mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtension(address to) external returns (uint256);

    /**
     * @dev mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtension(address to, string calldata uri) external returns (uint256);

    /**
     * @dev batch mint a token. Can only be called by a registered extension.
     * Returns tokenIds minted
     */
    function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory);

    /**
     * @dev batch mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory);

    /**
     * @dev burn a token. Can only be called by token owner or approved address.
     * On burn, calls back to the registered extension's onBurn method
     */
    function burn(uint256 tokenId) external;

}


// File contracts/creator/core/ERC721CreatorCore.sol



pragma solidity ^0.8.0;







/**
 * @dev Core ERC721 creator implementation
 */
abstract contract ERC721CreatorCore is CreatorCore, IERC721CreatorCore {

    using EnumerableSet for EnumerableSet.AddressSet;

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

    /**
     * @dev See {ICreatorCore-setApproveTransferExtension}.
     */
    function setApproveTransferExtension(bool enabled) external override extensionRequired {
        require(!enabled || ERC165Checker.supportsInterface(msg.sender, type(IERC721CreatorExtensionApproveTransfer).interfaceId), "ERC721CreatorCore: Requires extension to implement IERC721CreatorExtensionApproveTransfer");
        if (_extensionApproveTransfers[msg.sender] != enabled) {
            _extensionApproveTransfers[msg.sender] = enabled;
            emit ExtensionApproveTransferUpdated(msg.sender, enabled);
        }
    }

    /**
     * @dev Set mint permissions for an extension
     */
    function _setMintPermissions(address extension, address permissions) internal {
        require(_extensions.contains(extension), "CreatorCore: Invalid extension");
        require(permissions == address(0x0) || ERC165Checker.supportsInterface(permissions, type(IERC721CreatorMintPermissions).interfaceId), "ERC721CreatorCore: Invalid address");
        if (_extensionPermissions[extension] != permissions) {
            _extensionPermissions[extension] = permissions;
            emit MintPermissionsUpdated(extension, permissions, msg.sender);
        }
    }

    /**
     * Check if an extension can mint
     */
    function _checkMintPermissions(address to, uint256 tokenId) internal {
        if (_extensionPermissions[msg.sender] != address(0x0)) {
            IERC721CreatorMintPermissions(_extensionPermissions[msg.sender]).approveMint(msg.sender, to, tokenId);
        }
    }

    /**
     * Override for post mint actions
     */
    function _postMintBase(address, uint256) internal virtual {}

    
    /**
     * Override for post mint actions
     */
    function _postMintExtension(address, uint256) internal virtual {}

    /**
     * Post-burning callback and metadata cleanup
     */
    function _postBurn(address owner, uint256 tokenId) internal virtual {
        // Callback to originating extension if needed
        if (_tokensExtension[tokenId] != address(this)) {
           if (ERC165Checker.supportsInterface(_tokensExtension[tokenId], type(IERC721CreatorExtensionBurnable).interfaceId)) {
               IERC721CreatorExtensionBurnable(_tokensExtension[tokenId]).onBurn(owner, tokenId);
           }
        }
        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }    
        // Delete token origin extension tracking
        delete _tokensExtension[tokenId];    
    }

    /**
     * Approve a transfer
     */
    function _approveTransfer(address from, address to, uint256 tokenId) internal {
       if (_extensionApproveTransfers[_tokensExtension[tokenId]]) {
           require(IERC721CreatorExtensionApproveTransfer(_tokensExtension[tokenId]).approveTransfer(from, to, tokenId), "ERC721Creator: Extension approval failure");
       }
    }

}


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



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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @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 Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

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

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


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



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 `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}


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



pragma solidity ^0.8.0;

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

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

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


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



pragma solidity ^0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 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 functionCall(target, data, "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");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return _verifyCallResult(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) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(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) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // 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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


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



pragma solidity ^0.8.0;







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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: 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 overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

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

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not 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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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 = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

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

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

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

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

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

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

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

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

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        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);
    }

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

    /**
     * @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(to).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 {}
}


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



pragma solidity ^0.8.0;

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

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

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


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



pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

    /**
     * @dev 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` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * 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 override {
        super._beforeTokenTransfer(from, to, tokenId);

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

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

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

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

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

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

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

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

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

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

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

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

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


// File contracts/creator/ERC721Creator.sol



pragma solidity ^0.8.0;




/**
 * @dev ERC721Creator implementation
 */
contract ERC721Creator is AdminControl, ERC721Enumerable, ERC721CreatorCore {

    constructor (string memory _name, string memory _symbol) ERC721(_name, _symbol) {
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable, ERC721CreatorCore, AdminControl) returns (bool) {
        return ERC721CreatorCore.supportsInterface(interfaceId) || ERC721.supportsInterface(interfaceId) || AdminControl.supportsInterface(interfaceId);
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
        _approveTransfer(from, to, tokenId);    
    }

    /**
     * @dev See {ICreatorCore-registerExtension}.
     */
    function registerExtension(address extension, string calldata baseURI) external override adminRequired nonBlacklistRequired(extension) {
        _registerExtension(extension, baseURI, false);
    }

    /**
     * @dev See {ICreatorCore-registerExtension}.
     */
    function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external override adminRequired nonBlacklistRequired(extension) {
        _registerExtension(extension, baseURI, baseURIIdentical);
    }


    /**
     * @dev See {ICreatorCore-unregisterExtension}.
     */
    function unregisterExtension(address extension) external override adminRequired {
        _unregisterExtension(extension);
    }

    /**
     * @dev See {ICreatorCore-blacklistExtension}.
     */
    function blacklistExtension(address extension) external override adminRequired {
        _blacklistExtension(extension);
    }

    /**
     * @dev See {ICreatorCore-setBaseTokenURIExtension}.
     */
    function setBaseTokenURIExtension(string calldata uri) external override extensionRequired {
        _setBaseTokenURIExtension(uri, false);
    }

    /**
     * @dev See {ICreatorCore-setBaseTokenURIExtension}.
     */
    function setBaseTokenURIExtension(string calldata uri, bool identical) external override extensionRequired {
        _setBaseTokenURIExtension(uri, identical);
    }

    /**
     * @dev See {ICreatorCore-setTokenURIPrefixExtension}.
     */
    function setTokenURIPrefixExtension(string calldata prefix) external override extensionRequired {
        _setTokenURIPrefixExtension(prefix);
    }

    /**
     * @dev See {ICreatorCore-setTokenURIExtension}.
     */
    function setTokenURIExtension(uint256 tokenId, string calldata uri) external override extensionRequired {
        _setTokenURIExtension(tokenId, uri);
    }

    /**
     * @dev See {ICreatorCore-setTokenURIExtension}.
     */
    function setTokenURIExtension(uint256[] memory tokenIds, string[] calldata uris) external override extensionRequired {
        require(tokenIds.length == uris.length, "ERC721Creator: Invalid input");
        for (uint i = 0; i < tokenIds.length; i++) {
            _setTokenURIExtension(tokenIds[i], uris[i]);            
        }
    }

    /**
     * @dev See {ICreatorCore-setBaseTokenURI}.
     */
    function setBaseTokenURI(string calldata uri) external override adminRequired {
        _setBaseTokenURI(uri);
    }

    /**
     * @dev See {ICreatorCore-setTokenURIPrefix}.
     */
    function setTokenURIPrefix(string calldata prefix) external override adminRequired {
        _setTokenURIPrefix(prefix);
    }

    /**
     * @dev See {ICreatorCore-setTokenURI}.
     */
    function setTokenURI(uint256 tokenId, string calldata uri) external override adminRequired {
        _setTokenURI(tokenId, uri);
    }

    /**
     * @dev See {ICreatorCore-setTokenURI}.
     */
    function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external override adminRequired {
        require(tokenIds.length == uris.length, "ERC721Creator: Invalid input");
        for (uint i = 0; i < tokenIds.length; i++) {
            _setTokenURI(tokenIds[i], uris[i]);            
        }
    }

    /**
     * @dev See {ICreatorCore-setMintPermissions}.
     */
    function setMintPermissions(address extension, address permissions) external override adminRequired {
        _setMintPermissions(extension, permissions);
    }

    /**
     * @dev See {IERC721CreatorCore-mintBase}.
     */
    function mintBase(address to) public virtual override nonReentrant adminRequired returns(uint256) {
        return _mintBase(to, "");
    }

    /**
     * @dev See {IERC721CreatorCore-mintBase}.
     */
    function mintBase(address to, string calldata uri) public virtual override nonReentrant adminRequired returns(uint256) {
        return _mintBase(to, uri);
    }

    /**
     * @dev See {IERC721CreatorCore-mintBaseBatch}.
     */
    function mintBaseBatch(address to, uint16 count) public virtual override nonReentrant adminRequired returns(uint256[] memory tokenIds) {
        tokenIds = new uint256[](count);
        for (uint16 i = 0; i < count; i++) {
            tokenIds[i] = _mintBase(to, "");
        }
        return tokenIds;
    }

    /**
     * @dev See {IERC721CreatorCore-mintBaseBatch}.
     */
    function mintBaseBatch(address to, string[] calldata uris) public virtual override nonReentrant adminRequired returns(uint256[] memory tokenIds) {
        tokenIds = new uint256[](uris.length);
        for (uint i = 0; i < uris.length; i++) {
            tokenIds[i] = _mintBase(to, uris[i]);
        }
        return tokenIds;
    }

    /**
     * @dev Mint token with no extension
     */
    function _mintBase(address to, string memory uri) internal virtual returns(uint256 tokenId) {
        _tokenCount++;
        tokenId = _tokenCount;

        // Track the extension that minted the token
        _tokensExtension[tokenId] = address(this);

        _safeMint(to, tokenId);

        if (bytes(uri).length > 0) {
            _tokenURIs[tokenId] = uri;
        }

        // Call post mint
        _postMintBase(to, tokenId);
        return tokenId;
    }


    /**
     * @dev See {IERC721CreatorCore-mintExtension}.
     */
    function mintExtension(address to) public virtual override nonReentrant extensionRequired returns(uint256) {
        return _mintExtension(to, "");
    }

    /**
     * @dev See {IERC721CreatorCore-mintExtension}.
     */
    function mintExtension(address to, string calldata uri) public virtual override nonReentrant extensionRequired returns(uint256) {
        return _mintExtension(to, uri);
    }

    /**
     * @dev See {IERC721CreatorCore-mintExtensionBatch}.
     */
    function mintExtensionBatch(address to, uint16 count) public virtual override nonReentrant extensionRequired returns(uint256[] memory tokenIds) {
        tokenIds = new uint256[](count);
        for (uint16 i = 0; i < count; i++) {
            tokenIds[i] = _mintExtension(to, "");
        }
        return tokenIds;
    }

    /**
     * @dev See {IERC721CreatorCore-mintExtensionBatch}.
     */
    function mintExtensionBatch(address to, string[] calldata uris) public virtual override nonReentrant extensionRequired returns(uint256[] memory tokenIds) {
        tokenIds = new uint256[](uris.length);
        for (uint i = 0; i < uris.length; i++) {
            tokenIds[i] = _mintExtension(to, uris[i]);
        }
    }
    
    /**
     * @dev Mint token via extension
     */
    function _mintExtension(address to, string memory uri) internal virtual returns(uint256 tokenId) {
        _tokenCount++;
        tokenId = _tokenCount;

        _checkMintPermissions(to, tokenId);

        // Track the extension that minted the token
        _tokensExtension[tokenId] = msg.sender;

        _safeMint(to, tokenId);

        if (bytes(uri).length > 0) {
            _tokenURIs[tokenId] = uri;
        }
        
        // Call post mint
        _postMintExtension(to, tokenId);
        return tokenId;
    }

    /**
     * @dev See {IERC721CreatorCore-tokenExtension}.
     */
    function tokenExtension(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "Nonexistent token");
        return _tokenExtension(tokenId);
    }

    /**
     * @dev See {IERC721CreatorCore-burn}.
     */
    function burn(uint256 tokenId) public virtual override nonReentrant {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721Creator: caller is not owner nor approved");
        address owner = ownerOf(tokenId);
        _burn(tokenId);
        _postBurn(owner, tokenId);
    }

    /**
     * @dev See {ICreatorCore-setRoyalties}.
     */
    function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired {
        _setRoyaltiesExtension(address(this), receivers, basisPoints);
    }

    /**
     * @dev See {ICreatorCore-setRoyalties}.
     */
    function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired {
        require(_exists(tokenId), "Nonexistent token");
        _setRoyalties(tokenId, receivers, basisPoints);
    }

    /**
     * @dev See {ICreatorCore-setRoyaltiesExtension}.
     */
    function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired {
        _setRoyaltiesExtension(extension, receivers, basisPoints);
    }

    /**
     * @dev {See ICreatorCore-getRoyalties}.
     */
    function getRoyalties(uint256 tokenId) external view virtual override returns (address payable[] memory, uint256[] memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _getRoyalties(tokenId);
    }

    /**
     * @dev {See ICreatorCore-getFees}.
     */
    function getFees(uint256 tokenId) external view virtual override returns (address payable[] memory, uint256[] memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _getRoyalties(tokenId);
    }

    /**
     * @dev {See ICreatorCore-getFeeRecipients}.
     */
    function getFeeRecipients(uint256 tokenId) external view virtual override returns (address payable[] memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _getRoyaltyReceivers(tokenId);
    }

    /**
     * @dev {See ICreatorCore-getFeeBps}.
     */
    function getFeeBps(uint256 tokenId) external view virtual override returns (uint[] memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _getRoyaltyBPS(tokenId);
    }
    
    /**
     * @dev {See ICreatorCore-royaltyInfo}.
     */
    function royaltyInfo(uint256 tokenId, uint256 value, bytes calldata) external view virtual override returns (address, uint256, bytes memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _getRoyaltyInfo(tokenId, value);
    } 

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "Nonexistent token");
        return _tokenURI(tokenId);
    }
    
}


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



pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// File contracts/GrayCraft2.sol

pragma solidity ^0.8.0;


contract GRAYCRAFT2 is ERC721Creator {
    using SafeMath for uint256;
    string public constant GRAYCRAFT_PROVENANCE = "9128513b2c6a083408da8815a69ab3c617c2116350b790ac6ab299aeef2e3d4d";
    address public constant GRAYCRAFT_ADDRESS = 0x9030807ba4C71831808408CbF892bfA1261A6E7D; // GrayCraft 1 address
    uint256 public constant CRAFT_PRICE = 80000000000000000; // 0.08 ETH
    uint256 public constant MAX_CRAFT_PURCHASE = 20; // max purchase per txn
    uint256 public constant EXCLUSIVE_EXPIRY_DATE = 1633003200; // 30th Sep 2021
    uint256 public constant MAX_GRAYCRAFT = 10000; // max of 10,000 Gray Craft 2

    bool public saleIsActive = false; // determines whether sales is active
    uint256 reservedGrayCraft = 500; // reserved for owner/giveaway
    uint256 exclusiveOwnership = 77; // reserved for graycraft 1 owners
    mapping (uint256 => bool) exclusiveClaim; // tokenId => hasClaimed

    event AssetMinted(uint256 indexed tokenId, address owner);

    constructor() ERC721Creator("GRAYCRAFT2", "GRAY2") {}

    /* ========== External public sales functions ========== */

    // @dev give away exclusive supply to owners of GrayCraft1
    function claimExclusive(uint256 tokenId) external nonReentrant {
        require(saleIsActive); // Sale must be active
        require(exclusiveOwnership > 0); // Exceeds exclusive ownership supply
        require(!exclusiveClaim[tokenId], "Has claimed before");
        require(ERC721(GRAYCRAFT_ADDRESS).ownerOf(tokenId) == msg.sender); // Not authorised

        exclusiveClaim[tokenId] = true;

        _mintBase(msg.sender, Strings.toString(_tokenCount+1));
        emit AssetMinted(_tokenCount, msg.sender);

        exclusiveOwnership = exclusiveOwnership.sub(1);
    }

    // @dev mints graycrafts for the general public
    function mintGraycraft(uint numberOfTokens) external payable {
        require(saleIsActive); // Sale must be active
        require(numberOfTokens <= MAX_CRAFT_PURCHASE); // Max mint of 20
        // we ensure that this function mints a maximum of (10000 - 77 = 9923) graycrafts
        // `exclusiveOwnership` decrements with each mint
        // 50 <= 10000 - 76
        require(totalSupply().add(numberOfTokens) <= MAX_GRAYCRAFT.sub(exclusiveOwnership)); // Max supply exceeded
        require(CRAFT_PRICE.mul(numberOfTokens) <= msg.value); // Value sent is not correct
        
        for (uint i = 0; i < numberOfTokens; i++) {
            if (totalSupply() < MAX_GRAYCRAFT) {
                _mintBase(msg.sender, Strings.toString(_tokenCount+1));
                emit AssetMinted(_tokenCount, msg.sender);
            }
        }
    }

    /* ========== External owner functions ========== */

    // @dev withdraw funds
    function withdraw() external onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    // @dev reserve GrayCraft for owner, max of 500
    function reserveGrayCraft(uint256 amount) external onlyOwner {        
        require(amount <= reservedGrayCraft); // Exceeds reserved supply
        uint i;
        for (i = 0; i < amount; i++) {
            _mintBase(msg.sender, Strings.toString(_tokenCount+1));
            emit AssetMinted(_tokenCount, msg.sender);
        }
        reservedGrayCraft = reservedGrayCraft.sub(amount);
    }

    // @dev owners can force claim GrayCraft1 exclusive
    function ownerClaimExclusive(uint256 tokenId) external onlyOwner {
        require(block.timestamp > EXCLUSIVE_EXPIRY_DATE); // Not allowed to claim
        require(saleIsActive); // Sale must be active
        require(exclusiveOwnership > 0); // Exceeds exclusive ownership supply
        require(!exclusiveClaim[tokenId], "Has claimed before");

        exclusiveClaim[tokenId] = true;

        _mintBase(msg.sender, Strings.toString(_tokenCount+1));
        emit AssetMinted(_tokenCount, msg.sender);

        exclusiveOwnership = exclusiveOwnership.sub(1);
    }

    // @dev flips the state for sales
    function flipSaleState() external onlyOwner {
        saleIsActive = !saleIsActive;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"AssetMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"DefaultRoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"ExtensionApproveTransferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"ExtensionRoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"permissions","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"MintPermissionsUpdated","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":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"RoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CRAFT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCLUSIVE_EXPIRY_DATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GRAYCRAFT_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GRAYCRAFT_PROVENANCE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CRAFT_PURCHASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_GRAYCRAFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"approveAdmin","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":[{"internalType":"address","name":"extension","type":"address"}],"name":"blacklistExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimExclusive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmins","outputs":[{"internalType":"address[]","name":"admins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExtensions","outputs":[{"internalType":"address[]","name":"extensions","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFeeBps","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFeeRecipients","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFees","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getRoyalties","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"mintBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"mintBaseBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"name":"mintBaseBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintExtension","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"mintExtension","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"mintExtensionBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"name":"mintExtensionBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mintGraycraft","outputs":[],"stateMutability":"payable","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":"ownerClaimExclusive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"string","name":"baseURI","type":"string"}],"name":"registerExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"bool","name":"baseURIIdentical","type":"bool"}],"name":"registerExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reserveGrayCraft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"revokeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setApproveTransferExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"bool","name":"identical","type":"bool"}],"name":"setBaseTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"address","name":"permissions","type":"address"}],"name":"setMintPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyaltiesExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"setTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefixExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenExtension","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"}],"name":"unregisterExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526000600e55601e805460ff191690556101f4601f55604d6020553480156200002b57600080fd5b506040518060400160405280600a81526020016923a920aca1a920a32a1960b11b8152506040518060400160405280600581526020016423a920ac9960d91b81525081816200008962000083620000c360201b60201c565b620000c7565b600180558151620000a290600490602085019062000117565b508051620000b890600590602084019062000117565b5050505050620001fa565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280546200012590620001bd565b90600052602060002090601f01602090048101928262000149576000855562000194565b82601f106200016457805160ff191683800117855562000194565b8280016001018555821562000194579182015b828111156200019457825182559160200191906001019062000177565b50620001a2929150620001a6565b5090565b5b80821115620001a25760008155600101620001a7565b600181811c90821680620001d257607f821691505b60208210811415620001f457634e487b7160e01b600052602260045260246000fd5b50919050565b615d9e806200020a6000396000f3fe6080604052600436106104055760003560e01c806367f19d1211610213578063b88d4fde11610123578063e01bbdaf116100ab578063eeb943d01161007a578063eeb943d014610c37578063f0cdc49914610c4c578063f2fde38b14610c6c578063fe2e1f5814610c8c578063ff345c7414610cac57600080fd5b8063e01bbdaf14610b98578063e92a89f614610bb4578063e985e9c514610bd4578063eb8d244414610c1d57600080fd5b8063c87b56dd116100f2578063c87b56dd14610b18578063ce8aee9d14610b38578063d5a06d4c14610abb578063dda4bfd214610b58578063e00aab4b14610b7857600080fd5b8063b88d4fde14610a6e578063b9c4d9fb14610a8e578063bb3bafd614610abb578063c155531d14610ae957600080fd5b806383b7db63116101a6578063a22cb46511610175578063a22cb465146109ce578063aafb2d44146109ee578063ac0c8cfa14610a0e578063ad2d0ddd14610a2e578063b0fe87c914610a4e57600080fd5b806383b7db63146109665780638da5cb5b1461097b57806395d89b411461099957806399e0dd7c146109ae57600080fd5b806372ff03d3116101e257806372ff03d3146108e65780637884af44146109065780637aa15f161461092657806382dcc0c81461094657600080fd5b806367f19d12146108695780636d73e6691461089157806370a08231146108b1578063715018a6146108d157600080fd5b80633071a0f91161031957806342966c68116102a15780634f6ccce7116102705780634f6ccce7146107d357806353131426146107f357806361e5bc6b146108095780636352211e1461082957806366d1e9d01461084957600080fd5b806342966c681461076b578063440ec94c1461078b5780634752d15b1461079e5780634b57789f146107b357600080fd5b806338e52e78116102e857806338e52e78146106d65780633ccfd60b146106f65780633e6134b81461070b5780633f0f37f61461072b57806342842e0e1461074b57600080fd5b80633071a0f91461065f57806331ae450b1461067f578063332dd1ae146106a157806334918dfd146106c157600080fd5b806318a2c1281161039c57806324d7806c1161036b57806324d7806c146105bf5780632928ca58146105df5780632d345670146105ff5780632f745c591461061f57806330176e131461063f57600080fd5b806318a2c1281461054757806320e4afe21461055f578063239be3171461057f57806323b872dd1461059f57600080fd5b8063095ea7b3116103d8578063095ea7b3146104bb5780630ebd4c7f146104db578063162094c41461050857806318160ddd1461052857600080fd5b806301ffc9a71461040a57806302e7afb71461043f57806306fdde0314610461578063081812fc14610483575b600080fd5b34801561041657600080fd5b5061042a610425366004615384565b610ccc565b60405190151581526020015b60405180910390f35b34801561044b57600080fd5b5061045f61045a366004614ec8565b610cfb565b005b34801561046d57600080fd5b50610476610d5a565b604051610436919061587e565b34801561048f57600080fd5b506104a361049e3660046154c1565b610dec565b6040516001600160a01b039091168152602001610436565b3480156104c757600080fd5b5061045f6104d63660046151f9565b610e74565b3480156104e757600080fd5b506104fb6104f63660046154c1565b610f8a565b604051610436919061586b565b34801561051457600080fd5b5061045f61052336600461550d565b611010565b34801561053457600080fd5b50600c545b604051908152602001610436565b34801561055357600080fd5b50610539636155a6c081565b34801561056b57600080fd5b5061045f61057a3660046154d9565b611065565b34801561058b57600080fd5b506104a361059a3660046154c1565b6110e8565b3480156105ab57600080fd5b5061045f6105ba366004614f38565b611118565b3480156105cb57600080fd5b5061042a6105da366004614ec8565b611149565b3480156105eb57600080fd5b506105396105fa366004614ec8565b611182565b34801561060b57600080fd5b5061045f61061a366004614ec8565b6111f6565b34801561062b57600080fd5b5061053961063a3660046151f9565b611275565b34801561064b57600080fd5b5061045f61065a3660046153bc565b61130b565b34801561066b57600080fd5b5061045f61067a36600461511c565b611394565b34801561068b57600080fd5b5061069461141a565b6040516104369190615767565b3480156106ad57600080fd5b5061045f6106bc366004615224565b6114e4565b3480156106cd57600080fd5b5061045f61153b565b3480156106e257600080fd5b506104fb6106f136600461509d565b611579565b34801561070257600080fd5b5061045f6116e0565b34801561071757600080fd5b5061045f6107263660046153bc565b611739565b34801561073757600080fd5b5061045f610746366004615161565b61176c565b34801561075757600080fd5b5061045f610766366004614f38565b6117eb565b34801561077757600080fd5b5061045f6107863660046154c1565b611806565b61045f6107993660046154c1565b6118c4565b3480156107aa57600080fd5b50610539601481565b3480156107bf57600080fd5b5061045f6107ce3660046154c1565b6119a2565b3480156107df57600080fd5b506105396107ee3660046154c1565b611b44565b3480156107ff57600080fd5b5061053961271081565b34801561081557600080fd5b5061045f61082436600461528c565b611be5565b34801561083557600080fd5b506104a36108443660046154c1565b611cdc565b34801561085557600080fd5b5061045f6108643660046153bc565b611d53565b34801561087557600080fd5b506104a3739030807ba4c71831808408cbf892bfa1261a6e7d81565b34801561089d57600080fd5b5061045f6108ac366004614ec8565b611d84565b3480156108bd57600080fd5b506105396108cc366004614ec8565b611dfe565b3480156108dd57600080fd5b5061045f611e85565b3480156108f257600080fd5b50610539610901366004614ec8565b611ebb565b34801561091257600080fd5b5061053961092136600461511c565b611f48565b34801561093257600080fd5b506104fb61094136600461509d565b612008565b34801561095257600080fd5b5061045f6109613660046153fb565b612186565b34801561097257600080fd5b506106946121b8565b34801561098757600080fd5b506000546001600160a01b03166104a3565b3480156109a557600080fd5b5061047661227e565b3480156109ba57600080fd5b5061045f6109c93660046153bc565b61228d565b3480156109da57600080fd5b5061045f6109e93660046150ef565b6122e1565b3480156109fa57600080fd5b5061045f610a0936600461528c565b6123a6565b348015610a1a57600080fd5b5061045f610a2936600461534c565b6124c0565b348015610a3a57600080fd5b506104fb610a493660046151c6565b61260a565b348015610a5a57600080fd5b5061045f610a6936600461501e565b61274c565b348015610a7a57600080fd5b5061045f610a89366004614f78565b6127a3565b348015610a9a57600080fd5b50610aae610aa93660046154c1565b6127d5565b6040516104369190615833565b348015610ac757600080fd5b50610adb610ad63660046154c1565b612864565b604051610436929190615846565b348015610af557600080fd5b50610b09610b0436600461553d565b612948565b60405161043693929190615740565b348015610b2457600080fd5b50610476610b333660046154c1565b61298c565b348015610b4457600080fd5b5061045f610b53366004614ec8565b6129bc565b348015610b6457600080fd5b5061045f610b733660046154c1565b612a0f565b348015610b8457600080fd5b506104fb610b933660046151c6565b612b27565b348015610ba457600080fd5b5061053967011c37937e08000081565b348015610bc057600080fd5b5061045f610bcf36600461550d565b612c3b565b348015610be057600080fd5b5061042a610bef366004614f00565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b348015610c2957600080fd5b50601e5461042a9060ff1681565b348015610c4357600080fd5b50610476612c6d565b348015610c5857600080fd5b5061045f610c67366004614f00565b612c89565b348015610c7857600080fd5b5061045f610c87366004614ec8565b612cdd565b348015610c9857600080fd5b50610539610ca736600461511c565b612d75565b348015610cb857600080fd5b5061045f610cc73660046154c1565b612e06565b6000610cd782612eab565b80610ce65750610ce682612ed0565b80610cf55750610cf582612f0b565b92915050565b33610d0e6000546001600160a01b031690565b6001600160a01b03161480610d295750610d29600233612f40565b610d4e5760405162461bcd60e51b8152600401610d45906159dd565b60405180910390fd5b610d5781612f65565b50565b606060048054610d6990615c07565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9590615c07565b8015610de25780601f10610db757610100808354040283529160200191610de2565b820191906000526020600020905b815481529060010190602001808311610dc557829003601f168201915b5050505050905090565b6000610df782613070565b610e585760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d45565b506000908152600860205260409020546001600160a01b031690565b6000610e7f82611cdc565b9050806001600160a01b0316836001600160a01b03161415610eed5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610d45565b336001600160a01b0382161480610f095750610f098133610bef565b610f7b5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610d45565b610f85838361308d565b505050565b6060610f9582613070565b610fb15760405162461bcd60e51b8152600401610d45906158e3565b610fba826130fb565b80548060200260200160405190810160405280929190818152602001828054801561100457602002820191906000526020600020905b815481526020019060010190808311610ff0575b50505050509050919050565b336110236000546001600160a01b031690565b6001600160a01b0316148061103e575061103e600233612f40565b61105a5760405162461bcd60e51b8152600401610d45906159dd565b610f85838383613187565b336110786000546001600160a01b031690565b6001600160a01b031614806110935750611093600233612f40565b6110af5760405162461bcd60e51b8152600401610d45906159dd565b6110b885613070565b6110d45760405162461bcd60e51b8152600401610d45906158e3565b6110e18585858585613206565b5050505050565b60006110f382613070565b61110f5760405162461bcd60e51b8152600401610d45906158e3565b610cf582613343565b61112233826133e4565b61113e5760405162461bcd60e51b8152600401610d459061598c565b610f858383836134ce565b6000816001600160a01b03166111676000546001600160a01b031690565b6001600160a01b03161480610cf55750610cf5600283612f40565b6000600260015414156111a75760405162461bcd60e51b8152600401610d4590615a63565b60026001556111b7600f33612f40565b6111d35760405162461bcd60e51b8152600401610d4590615943565b6111ec8260405180602001604052806000815250613679565b6001805592915050565b6000546001600160a01b031633146112205760405162461bcd60e51b8152600401610d459061590e565b61122b600282612f40565b15610d575760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a36112716002826136f3565b5050565b600061128083611dfe565b82106112e25760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610d45565b506001600160a01b03919091166000908152600a60209081526040808320938352929052205490565b3361131e6000546001600160a01b031690565b6001600160a01b031614806113395750611339600233612f40565b6113555760405162461bcd60e51b8152600401610d45906159dd565b61127182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370892505050565b336113a76000546001600160a01b031690565b6001600160a01b031614806113c257506113c2600233612f40565b6113de5760405162461bcd60e51b8152600401610d45906159dd565b826113ea601182612f40565b156114075760405162461bcd60e51b8152600401610d4590615a21565b6114148484846000613728565b50505050565b60606114266002613817565b6001600160401b0381111561144b57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611474578160200160208202803683370190505b50905060005b6114846002613817565b8110156114e057611496600282613821565b8282815181106114b657634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806114d881615c5e565b91505061147a565b5090565b336114f76000546001600160a01b031690565b6001600160a01b031614806115125750611512600233612f40565b61152e5760405162461bcd60e51b8152600401610d45906159dd565b611414308585858561382d565b6000546001600160a01b031633146115655760405162461bcd60e51b8152600401610d459061590e565b601e805460ff19811660ff90911615179055565b60606002600154141561159e5760405162461bcd60e51b8152600401610d4590615a63565b60026001556115ae600f33612f40565b6115ca5760405162461bcd60e51b8152600401610d4590615943565b816001600160401b038111156115f057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611619578160200160208202803683370190505b50905060005b828110156116d4576116978585858481811061164b57634e487b7160e01b600052603260045260246000fd5b905060200281019061165d9190615ade565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061367992505050565b8282815181106116b757634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806116cc81615c5e565b91505061161f565b50600180559392505050565b6000546001600160a01b0316331461170a5760405162461bcd60e51b8152600401610d459061590e565b6040514790339082156108fc029083906000818181858888f19350505050158015611271573d6000803e3d6000fd5b611744600f33612f40565b6117605760405162461bcd60e51b8152600401610d4590615943565b611271828260006139d2565b3361177f6000546001600160a01b031690565b6001600160a01b0316148061179a575061179a600233612f40565b6117b65760405162461bcd60e51b8152600401610d45906159dd565b836117c2601182612f40565b156117df5760405162461bcd60e51b8152600401610d4590615a21565b6110e185858585613728565b610f85838383604051806020016040528060008152506127a3565b600260015414156118295760405162461bcd60e51b8152600401610d4590615a63565b600260015561183833826133e4565b61189c5760405162461bcd60e51b815260206004820152602f60248201527f45524337323143726561746f723a2063616c6c6572206973206e6f74206f776e60448201526e195c881b9bdc88185c1c1c9bdd9959608a1b6064820152608401610d45565b60006118a782611cdc565b90506118b282613a0f565b6118bc8183613ab6565b505060018055565b601e5460ff166118d357600080fd5b60148111156118e157600080fd5b6020546118f19061271090613bcc565b611904826118fe600c5490565b90613bd8565b111561190f57600080fd5b3461192267011c37937e08000083613be4565b111561192d57600080fd5b60005b8181101561127157612710611944600c5490565b10156119905761196a33611965600e5460016119609190615b79565b613bf0565b613d09565b50600e54604051338152600080516020615d498339815191529060200160405180910390a25b8061199a81615c5e565b915050611930565b600260015414156119c55760405162461bcd60e51b8152600401610d4590615a63565b6002600155601e5460ff166119d957600080fd5b6000602054116119e857600080fd5b60008181526021602052604090205460ff1615611a3c5760405162461bcd60e51b815260206004820152601260248201527148617320636c61696d6564206265666f726560701b6044820152606401610d45565b6040516331a9108f60e11b8152600481018290523390739030807ba4c71831808408cbf892bfa1261a6e7d90636352211e9060240160206040518083038186803b158015611a8957600080fd5b505afa158015611a9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac19190614ee4565b6001600160a01b031614611ad457600080fd5b6000818152602160205260409020805460ff19166001908117909155600e54611b07913391611965916119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a2602054611b3a906001613bcc565b6020555060018055565b6000611b4f600c5490565b8210611bb25760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610d45565b600c8281548110611bd357634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b611bf0600f33612f40565b611c0c5760405162461bcd60e51b8152600401610d4590615943565b82518114611c5c5760405162461bcd60e51b815260206004820152601c60248201527f45524337323143726561746f723a20496e76616c696420696e707574000000006044820152606401610d45565b60005b835181101561141457611cca848281518110611c8b57634e487b7160e01b600052603260045260246000fd5b6020026020010151848484818110611cb357634e487b7160e01b600052603260045260246000fd5b9050602002810190611cc59190615ade565b613d4c565b80611cd481615c5e565b915050611c5f565b6000818152600660205260408120546001600160a01b031680610cf55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610d45565b611d5e600f33612f40565b611d7a5760405162461bcd60e51b8152600401610d4590615943565b6112718282613db2565b6000546001600160a01b03163314611dae5760405162461bcd60e51b8152600401610d459061590e565b611db9600282612f40565b610d575760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3611271600282613dcc565b60006001600160a01b038216611e695760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610d45565b506001600160a01b031660009081526007602052604090205490565b6000546001600160a01b03163314611eaf5760405162461bcd60e51b8152600401610d459061590e565b611eb96000613de1565b565b600060026001541415611ee05760405162461bcd60e51b8152600401610d4590615a63565b600260015533611ef86000546001600160a01b031690565b6001600160a01b03161480611f135750611f13600233612f40565b611f2f5760405162461bcd60e51b8152600401610d45906159dd565b6111ec8260405180602001604052806000815250613d09565b600060026001541415611f6d5760405162461bcd60e51b8152600401610d4590615a63565b600260015533611f856000546001600160a01b031690565b6001600160a01b03161480611fa05750611fa0600233612f40565b611fbc5760405162461bcd60e51b8152600401610d45906159dd565b611ffc8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d0992505050565b60018055949350505050565b60606002600154141561202d5760405162461bcd60e51b8152600401610d4590615a63565b6002600155336120456000546001600160a01b031690565b6001600160a01b031614806120605750612060600233612f40565b61207c5760405162461bcd60e51b8152600401610d45906159dd565b816001600160401b038111156120a257634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156120cb578160200160208202803683370190505b50905060005b828110156116d457612149858585848181106120fd57634e487b7160e01b600052603260045260246000fd5b905060200281019061210f9190615ade565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d0992505050565b82828151811061216957634e487b7160e01b600052603260045260246000fd5b60209081029190910101528061217e81615c5e565b9150506120d1565b612191600f33612f40565b6121ad5760405162461bcd60e51b8152600401610d4590615943565b610f858383836139d2565b60606121c4600f613817565b6001600160401b038111156121e957634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612212578160200160208202803683370190505b50905060005b612222600f613817565b8110156114e057612234600f82613821565b82828151811061225457634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528061227681615c5e565b915050612218565b606060058054610d6990615c07565b336122a06000546001600160a01b031690565b6001600160a01b031614806122bb57506122bb600233612f40565b6122d75760405162461bcd60e51b8152600401610d45906159dd565b6112718282613e31565b6001600160a01b03821633141561233a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610d45565b3360008181526009602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b336123b96000546001600160a01b031690565b6001600160a01b031614806123d457506123d4600233612f40565b6123f05760405162461bcd60e51b8152600401610d45906159dd565b825181146124405760405162461bcd60e51b815260206004820152601c60248201527f45524337323143726561746f723a20496e76616c696420696e707574000000006044820152606401610d45565b60005b8351811015611414576124ae84828151811061246f57634e487b7160e01b600052603260045260246000fd5b602002602001015184848481811061249757634e487b7160e01b600052603260045260246000fd5b90506020028101906124a99190615ade565b613187565b806124b881615c5e565b915050612443565b6124cb600f33612f40565b6124e75760405162461bcd60e51b8152600401610d4590615943565b801580612500575061250033634ce6d51160e11b613e4b565b6125985760405162461bcd60e51b815260206004820152605960248201527f45524337323143726561746f72436f72653a205265717569726573206578746560448201527f6e73696f6e20746f20696d706c656d656e74204945524337323143726561746f60648201527f72457874656e73696f6e417070726f76655472616e7366657200000000000000608482015260a401610d45565b3360009081526014602052604090205460ff16151581151514610d575733600081815260146020908152604091829020805460ff191685151590811790915591519182527f072a7592283e2c2d1d56d21517ff6013325e0f55483f4828373ff4d98b0a1a36910160405180910390a250565b60606002600154141561262f5760405162461bcd60e51b8152600401610d4590615a63565b6002600155336126476000546001600160a01b031690565b6001600160a01b031614806126625750612662600233612f40565b61267e5760405162461bcd60e51b8152600401610d45906159dd565b8161ffff166001600160401b038111156126a857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156126d1578160200160208202803683370190505b50905060005b8261ffff168161ffff161015612741576127008460405180602001604052806000815250613d09565b828261ffff168151811061272457634e487b7160e01b600052603260045260246000fd5b60209081029190910101528061273981615c3c565b9150506126d7565b506001805592915050565b3361275f6000546001600160a01b031690565b6001600160a01b0316148061277a575061277a600233612f40565b6127965760405162461bcd60e51b8152600401610d45906159dd565b6110e1858585858561382d565b6127ad33836133e4565b6127c95760405162461bcd60e51b8152600401610d459061598c565b61141484848484613e67565b60606127e082613070565b6127fc5760405162461bcd60e51b8152600401610d45906158e3565b61280582613e9a565b80548060200260200160405190810160405280929190818152602001828054801561100457602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161283b5750505050509050919050565b60608061287083613070565b61288c5760405162461bcd60e51b8152600401610d45906158e3565b61289583613f26565b8154604080516020808402820181019092528281529184918301828280156128e657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128c8575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561293857602002820191906000526020600020905b815481526020019060010190808311612924575b5050505050905091509150915091565b600080606061295687613070565b6129725760405162461bcd60e51b8152600401610d45906158e3565b61297c8787613f44565b9250925092509450945094915050565b606061299782613070565b6129b35760405162461bcd60e51b8152600401610d45906158e3565b610cf582614073565b336129cf6000546001600160a01b031690565b6001600160a01b031614806129ea57506129ea600233612f40565b612a065760405162461bcd60e51b8152600401610d45906159dd565b610d57816142fc565b6000546001600160a01b03163314612a395760405162461bcd60e51b8152600401610d459061590e565b636155a6c04211612a4957600080fd5b601e5460ff16612a5857600080fd5b600060205411612a6757600080fd5b60008181526021602052604090205460ff1615612abb5760405162461bcd60e51b815260206004820152601260248201527148617320636c61696d6564206265666f726560701b6044820152606401610d45565b6000818152602160205260409020805460ff19166001908117909155600e54612aee913391611965916119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a2602054612b21906001613bcc565b60205550565b606060026001541415612b4c5760405162461bcd60e51b8152600401610d4590615a63565b6002600155612b5c600f33612f40565b612b785760405162461bcd60e51b8152600401610d4590615943565b8161ffff166001600160401b03811115612ba257634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612bcb578160200160208202803683370190505b50905060005b8261ffff168161ffff16101561274157612bfa8460405180602001604052806000815250613679565b828261ffff1681518110612c1e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280612c3381615c3c565b915050612bd1565b612c46600f33612f40565b612c625760405162461bcd60e51b8152600401610d4590615943565b610f85838383613d4c565b604051806060016040528060408152602001615d096040913981565b33612c9c6000546001600160a01b031690565b6001600160a01b03161480612cb75750612cb7600233612f40565b612cd35760405162461bcd60e51b8152600401610d45906159dd565b611271828261434d565b6000546001600160a01b03163314612d075760405162461bcd60e51b8152600401610d459061590e565b6001600160a01b038116612d6c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d45565b610d5781613de1565b600060026001541415612d9a5760405162461bcd60e51b8152600401610d4590615a63565b6002600155612daa600f33612f40565b612dc65760405162461bcd60e51b8152600401610d4590615943565b611ffc8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061367992505050565b6000546001600160a01b03163314612e305760405162461bcd60e51b8152600401610d459061590e565b601f54811115612e3f57600080fd5b60005b81811015612e9757612e6033611965600e5460016119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a280612e8f81615c5e565b915050612e42565b601f54612ea49083613bcc565b601f555050565b60006001600160e01b03198216639088c20760e01b1480610cf55750610cf58261449b565b60006001600160e01b031982166380ac58cd60e01b1480610ce657506001600160e01b03198216635b5e139f60e01b1480610cf55750610cf5825b60006001600160e01b03198216632a9f3abf60e11b1480610cf557506301ffc9a760e01b6001600160e01b0319831614610cf5565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6001600160a01b038116301415612fcd5760405162461bcd60e51b815260206004820152602660248201527f43726561746f72436f72653a2043616e6e6f7420626c61636b6c69737420796f6044820152653ab939b2b63360d11b6064820152608401610d45565b612fd8600f82612f40565b156130205760405133906001600160a01b038316907fd19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a7890147990600090a361301e600f826136f3565b505b61302b601182612f40565b610d575760405133906001600160a01b038316907f05ac7bc5a606cd92a63365f9fda244499b9add0526b22d99937b6bd88181059c90600090a3611271601182613dcc565b6000908152600660205260409020546001600160a01b0316151590565b600081815260086020526040902080546001600160a01b0319166001600160a01b03841690811790915581906130c282611cdc565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152601d60205260408120541561312157506000908152601d6020526040902090565b6000828152601560209081526040808320546001600160a01b03168352601b9091529020541561317357506000908152601560209081526040808320546001600160a01b03168352601b909152902090565b5050306000908152601b6020526040902090565b6000838152601560205260409020546001600160a01b031630146131ed5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420746f6b656e0000000000006044820152606401610d45565b6000838152601960205260409020611414908383614c74565b8281146132555760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420696e7075740000000000006044820152606401610d45565b6000805b828110156132a75783838281811061328157634e487b7160e01b600052603260045260246000fd5b90506020020135826132939190615b79565b91508061329f81615c5e565b915050613259565b5061271081106132c95760405162461bcd60e51b8152600401610d4590615a9a565b6000868152601c602052604090206132e2908686614cf4565b506000868152601d602052604090206132fc908484614d47565b50857fabb46fe0761d77584bde75697647804ffd8113abd4d8d06bc664150395eccdee8686868660405161333394939291906157b4565b60405180910390a2505050505050565b6000818152601560205260409020546001600160a01b0316308114156133b75760405162461bcd60e51b815260206004820152602360248201527f43726561746f72436f72653a204e6f20657874656e73696f6e20666f7220746f60448201526235b2b760e91b6064820152608401610d45565b6133c2601182612f40565b156133df5760405162461bcd60e51b8152600401610d4590615a21565b919050565b60006133ef82613070565b6134505760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d45565b600061345b83611cdc565b9050806001600160a01b0316846001600160a01b031614806134965750836001600160a01b031661348b84610dec565b6001600160a01b0316145b806134c657506001600160a01b0380821660009081526009602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b03166134e182611cdc565b6001600160a01b0316146135495760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610d45565b6001600160a01b0382166135ab5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610d45565b6135b6838383614531565b6135c160008261308d565b6001600160a01b03831660009081526007602052604081208054600192906135ea908490615bc4565b90915550506001600160a01b0382166000908152600760205260408120805460019290613618908490615b79565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600e80546000918261368a83615c5e565b9190505550600e54905061369e838261453c565b600081815260156020526040902080546001600160a01b031916331790556136c683826145d0565b8151156136ee57600081815260196020908152604090912083516136ec92850190614d81565b505b610cf5565b6000612f5e836001600160a01b0384166145ea565b306000908152601660209081526040909120825161127192840190614d81565b6001600160a01b0384163b61378d5760405162461bcd60e51b815260206004820152602560248201527f43726561746f723a20457874656e73696f6e206d757374206265206120636f6e6044820152641d1c9858dd60da1b6064820152608401610d45565b613798600f85612f40565b611414576001600160a01b03841660009081526016602052604090206137bf908484614c74565b506001600160a01b038416600081815260176020526040808220805460ff1916851515179055513392917fd8cb8ba4086944eabf43c5535b7712015e4d4c714b24bf812c040ea5b7a3e42a91a36110e1600f85613dcc565b6000610cf5825490565b6000612f5e8383614707565b82811461387c5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420696e7075740000000000006044820152606401610d45565b6000805b828110156138ce578383828181106138a857634e487b7160e01b600052603260045260246000fd5b90506020020135826138ba9190615b79565b9150806138c681615c5e565b915050613880565b5061271081106138f05760405162461bcd60e51b8152600401610d4590615a9a565b6001600160a01b0386166000908152601a60205260409020613913908686614cf4565b506001600160a01b0386166000908152601b60205260409020613937908484614d47565b506001600160a01b03861630141561398b577f2b6849d5976d799a5b0ca4dfd6b40a3d7afe9ea72c091fa01a958594f9a2659b8585858560405161397e94939291906157b4565b60405180910390a16139ca565b856001600160a01b03167f535a93d2cb000582c0ebeaa9be4890ec6a287f98eb2df00c54c300612fd78d8f8686868660405161333394939291906157b4565b505050505050565b3360009081526016602052604090206139ec908484614c74565b50336000908152601760205260409020805460ff19169115159190911790555050565b6000613a1a82611cdc565b9050613a2881600084614531565b613a3360008361308d565b6001600160a01b0381166000908152600760205260408120805460019290613a5c908490615bc4565b909155505060008281526006602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000818152601560205260409020546001600160a01b03163014613b7657600081815260156020526040902054613afd906001600160a01b03166311686e4b60e21b613e4b565b15613b7657600081815260156020526040908190205490516311686e4b60e21b81526001600160a01b03848116600483015260248201849052909116906345a1b92c90604401600060405180830381600087803b158015613b5d57600080fd5b505af1158015613b71573d6000803e3d6000fd5b505050505b60008181526019602052604090208054613b8f90615c07565b159050613bad576000818152601960205260408120613bad91614df5565b600090815260156020526040902080546001600160a01b031916905550565b6000612f5e8284615bc4565b6000612f5e8284615b79565b6000612f5e8284615ba5565b606081613c145750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613c3e5780613c2881615c5e565b9150613c379050600a83615b91565b9150613c18565b6000816001600160401b03811115613c6657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c90576020820181803683370190505b5090505b84156134c657613ca5600183615bc4565b9150613cb2600a86615c79565b613cbd906030615b79565b60f81b818381518110613ce057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350613d02600a86615b91565b9450613c94565b600e805460009182613d1a83615c5e565b9091555050600e54600081815260156020526040902080546001600160a01b0319163017905590506136c683826145d0565b6000838152601560205260409020546001600160a01b031633146131ed5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420746f6b656e0000000000006044820152606401610d45565b336000908152601860205260409020610f85908383614c74565b6000612f5e836001600160a01b03841661473f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b306000908152601860205260409020610f85908383614c74565b6000613e568361478e565b8015612f5e5750612f5e83836147c1565b613e728484846134ce565b613e7e848484846148aa565b6114145760405162461bcd60e51b8152600401610d4590615891565b6000818152601c602052604081205415613ec057506000908152601c6020526040902090565b6000828152601560209081526040808320546001600160a01b03168352601a90915290205415613f1257506000908152601560209081526040808320546001600160a01b03168352601a909152902090565b5050306000908152601a6020526040902090565b600080613f3283613e9a565b613f3b846130fb565b91509150915091565b60008060606000613f5486613e9a565b805490915060011015613fd1576040805162461bcd60e51b81526020600482015260248101919091527f43726561746f72436f72653a204f6e6c7920776f726b7320696620746865726560448201527f20617265206174206d6f7374203120726f79616c7479207265636569766572736064820152608401610d45565b8054613fe457306000935093505061406c565b8060008154811061400557634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031661271086614027896130fb565b60008154811061404757634e487b7160e01b600052603260045260246000fd5b906000526020600020015461405c9190615ba5565b6140669190615b91565b93509350505b9250925092565b6000818152601560205260409020546060906001600160a01b0316614099601182612f40565b156140b65760405162461bcd60e51b8152600401610d4590615a21565b600083815260196020526040902080546140cf90615c07565b1590506141e9576001600160a01b038116600090815260186020526040902080546140f990615c07565b15905061414a576001600160a01b0381166000908152601860209081526040808320868452601983529281902090516141339392016156f8565b604051602081830303815290604052915050919050565b6000838152601960205260409020805461416390615c07565b80601f016020809104026020016040519081016040528092919081815260200182805461418f90615c07565b80156141dc5780601f106141b1576101008083540402835291602001916141dc565b820191906000526020600020905b8154815290600101906020018083116141bf57829003601f168201915b5050505050915050919050565b6141fa8163e9dc637560e01b613e4b565b156142815760405163e9dc637560e01b8152306004820152602481018490526001600160a01b0382169063e9dc63759060440160006040518083038186803b15801561424557600080fd5b505afa158015614259573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f5e919081019061544f565b6001600160a01b03811660009081526017602052604090205460ff166142d3576001600160a01b03811660009081526016602052604090206142c284613bf0565b6040516020016141339291906156d3565b6001600160a01b0381166000908152601660205260409020805461416390615c07565b50919050565b614307600f82612f40565b15610d575760405133906001600160a01b038316907fd19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a7890147990600090a3611271600f826136f3565b614358600f83612f40565b6143a45760405162461bcd60e51b815260206004820152601e60248201527f43726561746f72436f72653a20496e76616c696420657874656e73696f6e00006044820152606401610d45565b6001600160a01b03811615806143c657506143c681631e05385b60e31b613e4b565b61441d5760405162461bcd60e51b815260206004820152602260248201527f45524337323143726561746f72436f72653a20496e76616c6964206164647265604482015261737360f01b6064820152608401610d45565b6001600160a01b03828116600090815260136020526040902054811690821614611271576001600160a01b0382811660008181526013602052604080822080546001600160a01b031916948616948517905551339392917f6a835c4fcf7e0d398db3762332fdaa1471814ad39f1e2d6d0b3fdabf8efee3e091a45050565b60006001600160e01b031982166361f8bcb360e11b14806144c057506144c0826149b7565b806144db57506001600160e01b03198216635d9dd7eb60e11b145b806144f657506001600160e01b03198216632dde656160e21b145b8061451157506001600160e01b031982166335681b5360e21b145b80610cf557506001600160e01b03198216636057361d60e01b1492915050565b610f858383836149dc565b336000908152601360205260409020546001600160a01b031615611271573360008181526013602052604090819020549051631e05385b60e31b815260048101929092526001600160a01b03848116602484015260448301849052169063f029c2d890606401600060405180830381600087803b1580156145bc57600080fd5b505af11580156139ca573d6000803e3d6000fd5b611271828260405180602001604052806000815250614b02565b600081815260018301602052604081205480156146fd57600061460e600183615bc4565b855490915060009061462290600190615bc4565b90508181146146a357600086600001828154811061465057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061468157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b85548690806146c257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610cf5565b6000915050610cf5565b600082600001828154811061472c57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600081815260018301602052604081205461478657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610cf5565b506000610cf5565b60006147a1826301ffc9a760e01b6147c1565b8015610cf557506147ba826001600160e01b03196147c1565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b03871690617530906148289086906156b7565b6000604051808303818686fa925050503d8060008114614864576040519150601f19603f3d011682016040523d82523d6000602084013e614869565b606091505b50915091506020815110156148845760009350505050610cf5565b8180156148a05750808060200190518101906148a09190615368565b9695505050505050565b60006001600160a01b0384163b156149ac57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906148ee90339089908890889060040161570d565b602060405180830381600087803b15801561490857600080fd5b505af1925050508015614938575060408051601f3d908101601f19168201909252614935918101906153a0565b60015b614992573d808015614966576040519150601f19603f3d011682016040523d82523d6000602084013e61496b565b606091505b50805161498a5760405162461bcd60e51b8152600401610d4590615891565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506134c6565b506001949350505050565b60006001600160e01b0319821663780e9d6360e01b1480610cf55750610cf582612ed0565b6000818152601560209081526040808320546001600160a01b03168352601490915290205460ff1615610f855760008181526015602052604090819020549051638258080560e01b81526001600160a01b03858116600483015284811660248301526044820184905290911690638258080590606401602060405180830381600087803b158015614a6c57600080fd5b505af1158015614a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614aa49190615368565b610f855760405162461bcd60e51b815260206004820152602960248201527f45524337323143726561746f723a20457874656e73696f6e20617070726f76616044820152686c206661696c75726560b81b6064820152608401610d45565b614b0c8383614b35565b614b1960008484846148aa565b610f855760405162461bcd60e51b8152600401610d4590615891565b6001600160a01b038216614b8b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610d45565b614b9481613070565b15614be15760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610d45565b614bed60008383614531565b6001600160a01b0382166000908152600760205260408120805460019290614c16908490615b79565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054614c8090615c07565b90600052602060002090601f016020900481019282614ca25760008555614ce8565b82601f10614cbb5782800160ff19823516178555614ce8565b82800160010185558215614ce8579182015b82811115614ce8578235825591602001919060010190614ccd565b506114e0929150614e2b565b828054828255906000526020600020908101928215614ce8579160200282015b82811115614ce85781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614d14565b828054828255906000526020600020908101928215614ce85791602002820182811115614ce8578235825591602001919060010190614ccd565b828054614d8d90615c07565b90600052602060002090601f016020900481019282614daf5760008555614ce8565b82601f10614dc857805160ff1916838001178555614ce8565b82800160010185558215614ce8579182015b82811115614ce8578251825591602001919060010190614dda565b508054614e0190615c07565b6000825580601f10614e11575050565b601f016020900490600052602060002090810190610d5791905b5b808211156114e05760008155600101614e2c565b60008083601f840112614e51578182fd5b5081356001600160401b03811115614e67578182fd5b6020830191508360208260051b8501011115614e8257600080fd5b9250929050565b60008083601f840112614e9a578182fd5b5081356001600160401b03811115614eb0578182fd5b602083019150836020828501011115614e8257600080fd5b600060208284031215614ed9578081fd5b8135612f5e81615ccf565b600060208284031215614ef5578081fd5b8151612f5e81615ccf565b60008060408385031215614f12578081fd5b8235614f1d81615ccf565b91506020830135614f2d81615ccf565b809150509250929050565b600080600060608486031215614f4c578081fd5b8335614f5781615ccf565b92506020840135614f6781615ccf565b929592945050506040919091013590565b60008060008060808587031215614f8d578081fd5b8435614f9881615ccf565b93506020850135614fa881615ccf565b92506040850135915060608501356001600160401b03811115614fc9578182fd5b8501601f81018713614fd9578182fd5b8035614fec614fe782615b52565b615b22565b818152886020838501011115615000578384fd5b81602084016020830137908101602001929092525092959194509250565b600080600080600060608688031215615035578081fd5b853561504081615ccf565b945060208601356001600160401b038082111561505b578283fd5b61506789838a01614e40565b9096509450604088013591508082111561507f578283fd5b5061508c88828901614e40565b969995985093965092949392505050565b6000806000604084860312156150b1578081fd5b83356150bc81615ccf565b925060208401356001600160401b038111156150d6578182fd5b6150e286828701614e40565b9497909650939450505050565b60008060408385031215615101578182fd5b823561510c81615ccf565b91506020830135614f2d81615ce4565b600080600060408486031215615130578081fd5b833561513b81615ccf565b925060208401356001600160401b03811115615155578182fd5b6150e286828701614e89565b60008060008060608587031215615176578182fd5b843561518181615ccf565b935060208501356001600160401b0381111561519b578283fd5b6151a787828801614e89565b90945092505060408501356151bb81615ce4565b939692955090935050565b600080604083850312156151d8578182fd5b82356151e381615ccf565b9150602083013561ffff81168114614f2d578182fd5b6000806040838503121561520b578182fd5b823561521681615ccf565b946020939093013593505050565b60008060008060408587031215615239578182fd5b84356001600160401b038082111561524f578384fd5b61525b88838901614e40565b90965094506020870135915080821115615273578384fd5b5061528087828801614e40565b95989497509550505050565b6000806000604084860312156152a0578081fd5b83356001600160401b03808211156152b6578283fd5b818601915086601f8301126152c9578283fd5b81356020828211156152dd576152dd615cb9565b8160051b6152ec828201615b22565b8381528281019086840183880185018d1015615306578889fd5b8897505b8588101561532857803583526001979097019691840191840161530a565b50985050508701359250508082111561533f578283fd5b506150e286828701614e40565b60006020828403121561535d578081fd5b8135612f5e81615ce4565b600060208284031215615379578081fd5b8151612f5e81615ce4565b600060208284031215615395578081fd5b8135612f5e81615cf2565b6000602082840312156153b1578081fd5b8151612f5e81615cf2565b600080602083850312156153ce578182fd5b82356001600160401b038111156153e3578283fd5b6153ef85828601614e89565b90969095509350505050565b60008060006040848603121561540f578081fd5b83356001600160401b03811115615424578182fd5b61543086828701614e89565b909450925050602084013561544481615ce4565b809150509250925092565b600060208284031215615460578081fd5b81516001600160401b03811115615475578182fd5b8201601f81018413615485578182fd5b8051615493614fe782615b52565b8181528560208385010111156154a7578384fd5b6154b8826020830160208601615bdb565b95945050505050565b6000602082840312156154d2578081fd5b5035919050565b6000806000806000606086880312156154f0578283fd5b8535945060208601356001600160401b038082111561505b578485fd5b600080600060408486031215615521578081fd5b8335925060208401356001600160401b03811115615155578182fd5b60008060008060608587031215615552578182fd5b843593506020850135925060408501356001600160401b03811115615575578283fd5b61528087828801614e89565b6000815180845260208085019450808401835b838110156155b95781516001600160a01b031687529582019590820190600101615594565b509495945050505050565b6000815180845260208085019450808401835b838110156155b9578151875295820195908201906001016155d7565b6000815180845261560b816020860160208601615bdb565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061563957607f831692505b602080841082141561565957634e487b7160e01b86526022600452602486fd5b81801561566d576001811461567e576156ab565b60ff198616895284890196506156ab565b60008881526020902060005b868110156156a35781548b82015290850190830161568a565b505084890196505b50505050505092915050565b600082516156c9818460208701615bdb565b9190910192915050565b60006156df828561561f565b83516156ef818360208801615bdb565b01949350505050565b60006134c6615707838661561f565b8461561f565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906148a0908301846155f3565b60018060a01b03841681528260208201526060604082015260006154b860608301846155f3565b6020808252825182820181905260009190848201906040850190845b818110156157a85783516001600160a01b031683529284019291840191600101615783565b50909695505050505050565b6040808252810184905260008560608301825b878110156157f75782356157da81615ccf565b6001600160a01b03168252602092830192909101906001016157c7565b5083810360208501528481526001600160fb1b03851115615816578283fd5b8460051b9150818660208301370160200190815295945050505050565b602081526000612f5e6020830184615581565b6040815260006158596040830185615581565b82810360208401526154b881856155c4565b602081526000612f5e60208301846155c4565b602081526000612f5e60208301846155f3565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601190820152702737b732bc34b9ba32b73a103a37b5b2b760791b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f43726561746f72436f72653a204d75737420626520726567697374657265642060408201526832bc3a32b739b4b7b760b91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b60208082526022908201527f43726561746f72436f72653a20457874656e73696f6e20626c61636b6c697374604082015261195960f21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f43726561746f72436f72653a20496e76616c696420746f74616c20726f79616c6040820152637469657360e01b606082015260800190565b6000808335601e19843603018112615af4578283fd5b8301803591506001600160401b03821115615b0d578283fd5b602001915036819003821315614e8257600080fd5b604051601f8201601f191681016001600160401b0381118282101715615b4a57615b4a615cb9565b604052919050565b60006001600160401b03821115615b6b57615b6b615cb9565b50601f01601f191660200190565b60008219821115615b8c57615b8c615c8d565b500190565b600082615ba057615ba0615ca3565b500490565b6000816000190483118215151615615bbf57615bbf615c8d565b500290565b600082821015615bd657615bd6615c8d565b500390565b60005b83811015615bf6578181015183820152602001615bde565b838111156114145750506000910152565b600181811c90821680615c1b57607f821691505b602082108114156142f657634e487b7160e01b600052602260045260246000fd5b600061ffff80831681811415615c5457615c54615c8d565b6001019392505050565b6000600019821415615c7257615c72615c8d565b5060010190565b600082615c8857615c88615ca3565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610d5757600080fd5b8015158114610d5757600080fd5b6001600160e01b031981168114610d5757600080fdfe3931323835313362326336613038333430386461383831356136396162336336313763323131363335306237393061633661623239396165656632653364346455f284809f4c5b7377fbe62f2feeb9686e3834dcae5f3ca955140fe6547cd355a26469706673582212207774ff44d2129ea986c9b42c450517cf528fb3ad6dd97428367437b9df8d7f6664736f6c63430008040033

Deployed Bytecode

0x6080604052600436106104055760003560e01c806367f19d1211610213578063b88d4fde11610123578063e01bbdaf116100ab578063eeb943d01161007a578063eeb943d014610c37578063f0cdc49914610c4c578063f2fde38b14610c6c578063fe2e1f5814610c8c578063ff345c7414610cac57600080fd5b8063e01bbdaf14610b98578063e92a89f614610bb4578063e985e9c514610bd4578063eb8d244414610c1d57600080fd5b8063c87b56dd116100f2578063c87b56dd14610b18578063ce8aee9d14610b38578063d5a06d4c14610abb578063dda4bfd214610b58578063e00aab4b14610b7857600080fd5b8063b88d4fde14610a6e578063b9c4d9fb14610a8e578063bb3bafd614610abb578063c155531d14610ae957600080fd5b806383b7db63116101a6578063a22cb46511610175578063a22cb465146109ce578063aafb2d44146109ee578063ac0c8cfa14610a0e578063ad2d0ddd14610a2e578063b0fe87c914610a4e57600080fd5b806383b7db63146109665780638da5cb5b1461097b57806395d89b411461099957806399e0dd7c146109ae57600080fd5b806372ff03d3116101e257806372ff03d3146108e65780637884af44146109065780637aa15f161461092657806382dcc0c81461094657600080fd5b806367f19d12146108695780636d73e6691461089157806370a08231146108b1578063715018a6146108d157600080fd5b80633071a0f91161031957806342966c68116102a15780634f6ccce7116102705780634f6ccce7146107d357806353131426146107f357806361e5bc6b146108095780636352211e1461082957806366d1e9d01461084957600080fd5b806342966c681461076b578063440ec94c1461078b5780634752d15b1461079e5780634b57789f146107b357600080fd5b806338e52e78116102e857806338e52e78146106d65780633ccfd60b146106f65780633e6134b81461070b5780633f0f37f61461072b57806342842e0e1461074b57600080fd5b80633071a0f91461065f57806331ae450b1461067f578063332dd1ae146106a157806334918dfd146106c157600080fd5b806318a2c1281161039c57806324d7806c1161036b57806324d7806c146105bf5780632928ca58146105df5780632d345670146105ff5780632f745c591461061f57806330176e131461063f57600080fd5b806318a2c1281461054757806320e4afe21461055f578063239be3171461057f57806323b872dd1461059f57600080fd5b8063095ea7b3116103d8578063095ea7b3146104bb5780630ebd4c7f146104db578063162094c41461050857806318160ddd1461052857600080fd5b806301ffc9a71461040a57806302e7afb71461043f57806306fdde0314610461578063081812fc14610483575b600080fd5b34801561041657600080fd5b5061042a610425366004615384565b610ccc565b60405190151581526020015b60405180910390f35b34801561044b57600080fd5b5061045f61045a366004614ec8565b610cfb565b005b34801561046d57600080fd5b50610476610d5a565b604051610436919061587e565b34801561048f57600080fd5b506104a361049e3660046154c1565b610dec565b6040516001600160a01b039091168152602001610436565b3480156104c757600080fd5b5061045f6104d63660046151f9565b610e74565b3480156104e757600080fd5b506104fb6104f63660046154c1565b610f8a565b604051610436919061586b565b34801561051457600080fd5b5061045f61052336600461550d565b611010565b34801561053457600080fd5b50600c545b604051908152602001610436565b34801561055357600080fd5b50610539636155a6c081565b34801561056b57600080fd5b5061045f61057a3660046154d9565b611065565b34801561058b57600080fd5b506104a361059a3660046154c1565b6110e8565b3480156105ab57600080fd5b5061045f6105ba366004614f38565b611118565b3480156105cb57600080fd5b5061042a6105da366004614ec8565b611149565b3480156105eb57600080fd5b506105396105fa366004614ec8565b611182565b34801561060b57600080fd5b5061045f61061a366004614ec8565b6111f6565b34801561062b57600080fd5b5061053961063a3660046151f9565b611275565b34801561064b57600080fd5b5061045f61065a3660046153bc565b61130b565b34801561066b57600080fd5b5061045f61067a36600461511c565b611394565b34801561068b57600080fd5b5061069461141a565b6040516104369190615767565b3480156106ad57600080fd5b5061045f6106bc366004615224565b6114e4565b3480156106cd57600080fd5b5061045f61153b565b3480156106e257600080fd5b506104fb6106f136600461509d565b611579565b34801561070257600080fd5b5061045f6116e0565b34801561071757600080fd5b5061045f6107263660046153bc565b611739565b34801561073757600080fd5b5061045f610746366004615161565b61176c565b34801561075757600080fd5b5061045f610766366004614f38565b6117eb565b34801561077757600080fd5b5061045f6107863660046154c1565b611806565b61045f6107993660046154c1565b6118c4565b3480156107aa57600080fd5b50610539601481565b3480156107bf57600080fd5b5061045f6107ce3660046154c1565b6119a2565b3480156107df57600080fd5b506105396107ee3660046154c1565b611b44565b3480156107ff57600080fd5b5061053961271081565b34801561081557600080fd5b5061045f61082436600461528c565b611be5565b34801561083557600080fd5b506104a36108443660046154c1565b611cdc565b34801561085557600080fd5b5061045f6108643660046153bc565b611d53565b34801561087557600080fd5b506104a3739030807ba4c71831808408cbf892bfa1261a6e7d81565b34801561089d57600080fd5b5061045f6108ac366004614ec8565b611d84565b3480156108bd57600080fd5b506105396108cc366004614ec8565b611dfe565b3480156108dd57600080fd5b5061045f611e85565b3480156108f257600080fd5b50610539610901366004614ec8565b611ebb565b34801561091257600080fd5b5061053961092136600461511c565b611f48565b34801561093257600080fd5b506104fb61094136600461509d565b612008565b34801561095257600080fd5b5061045f6109613660046153fb565b612186565b34801561097257600080fd5b506106946121b8565b34801561098757600080fd5b506000546001600160a01b03166104a3565b3480156109a557600080fd5b5061047661227e565b3480156109ba57600080fd5b5061045f6109c93660046153bc565b61228d565b3480156109da57600080fd5b5061045f6109e93660046150ef565b6122e1565b3480156109fa57600080fd5b5061045f610a0936600461528c565b6123a6565b348015610a1a57600080fd5b5061045f610a2936600461534c565b6124c0565b348015610a3a57600080fd5b506104fb610a493660046151c6565b61260a565b348015610a5a57600080fd5b5061045f610a6936600461501e565b61274c565b348015610a7a57600080fd5b5061045f610a89366004614f78565b6127a3565b348015610a9a57600080fd5b50610aae610aa93660046154c1565b6127d5565b6040516104369190615833565b348015610ac757600080fd5b50610adb610ad63660046154c1565b612864565b604051610436929190615846565b348015610af557600080fd5b50610b09610b0436600461553d565b612948565b60405161043693929190615740565b348015610b2457600080fd5b50610476610b333660046154c1565b61298c565b348015610b4457600080fd5b5061045f610b53366004614ec8565b6129bc565b348015610b6457600080fd5b5061045f610b733660046154c1565b612a0f565b348015610b8457600080fd5b506104fb610b933660046151c6565b612b27565b348015610ba457600080fd5b5061053967011c37937e08000081565b348015610bc057600080fd5b5061045f610bcf36600461550d565b612c3b565b348015610be057600080fd5b5061042a610bef366004614f00565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b348015610c2957600080fd5b50601e5461042a9060ff1681565b348015610c4357600080fd5b50610476612c6d565b348015610c5857600080fd5b5061045f610c67366004614f00565b612c89565b348015610c7857600080fd5b5061045f610c87366004614ec8565b612cdd565b348015610c9857600080fd5b50610539610ca736600461511c565b612d75565b348015610cb857600080fd5b5061045f610cc73660046154c1565b612e06565b6000610cd782612eab565b80610ce65750610ce682612ed0565b80610cf55750610cf582612f0b565b92915050565b33610d0e6000546001600160a01b031690565b6001600160a01b03161480610d295750610d29600233612f40565b610d4e5760405162461bcd60e51b8152600401610d45906159dd565b60405180910390fd5b610d5781612f65565b50565b606060048054610d6990615c07565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9590615c07565b8015610de25780601f10610db757610100808354040283529160200191610de2565b820191906000526020600020905b815481529060010190602001808311610dc557829003601f168201915b5050505050905090565b6000610df782613070565b610e585760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d45565b506000908152600860205260409020546001600160a01b031690565b6000610e7f82611cdc565b9050806001600160a01b0316836001600160a01b03161415610eed5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610d45565b336001600160a01b0382161480610f095750610f098133610bef565b610f7b5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610d45565b610f85838361308d565b505050565b6060610f9582613070565b610fb15760405162461bcd60e51b8152600401610d45906158e3565b610fba826130fb565b80548060200260200160405190810160405280929190818152602001828054801561100457602002820191906000526020600020905b815481526020019060010190808311610ff0575b50505050509050919050565b336110236000546001600160a01b031690565b6001600160a01b0316148061103e575061103e600233612f40565b61105a5760405162461bcd60e51b8152600401610d45906159dd565b610f85838383613187565b336110786000546001600160a01b031690565b6001600160a01b031614806110935750611093600233612f40565b6110af5760405162461bcd60e51b8152600401610d45906159dd565b6110b885613070565b6110d45760405162461bcd60e51b8152600401610d45906158e3565b6110e18585858585613206565b5050505050565b60006110f382613070565b61110f5760405162461bcd60e51b8152600401610d45906158e3565b610cf582613343565b61112233826133e4565b61113e5760405162461bcd60e51b8152600401610d459061598c565b610f858383836134ce565b6000816001600160a01b03166111676000546001600160a01b031690565b6001600160a01b03161480610cf55750610cf5600283612f40565b6000600260015414156111a75760405162461bcd60e51b8152600401610d4590615a63565b60026001556111b7600f33612f40565b6111d35760405162461bcd60e51b8152600401610d4590615943565b6111ec8260405180602001604052806000815250613679565b6001805592915050565b6000546001600160a01b031633146112205760405162461bcd60e51b8152600401610d459061590e565b61122b600282612f40565b15610d575760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a36112716002826136f3565b5050565b600061128083611dfe565b82106112e25760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610d45565b506001600160a01b03919091166000908152600a60209081526040808320938352929052205490565b3361131e6000546001600160a01b031690565b6001600160a01b031614806113395750611339600233612f40565b6113555760405162461bcd60e51b8152600401610d45906159dd565b61127182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370892505050565b336113a76000546001600160a01b031690565b6001600160a01b031614806113c257506113c2600233612f40565b6113de5760405162461bcd60e51b8152600401610d45906159dd565b826113ea601182612f40565b156114075760405162461bcd60e51b8152600401610d4590615a21565b6114148484846000613728565b50505050565b60606114266002613817565b6001600160401b0381111561144b57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611474578160200160208202803683370190505b50905060005b6114846002613817565b8110156114e057611496600282613821565b8282815181106114b657634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806114d881615c5e565b91505061147a565b5090565b336114f76000546001600160a01b031690565b6001600160a01b031614806115125750611512600233612f40565b61152e5760405162461bcd60e51b8152600401610d45906159dd565b611414308585858561382d565b6000546001600160a01b031633146115655760405162461bcd60e51b8152600401610d459061590e565b601e805460ff19811660ff90911615179055565b60606002600154141561159e5760405162461bcd60e51b8152600401610d4590615a63565b60026001556115ae600f33612f40565b6115ca5760405162461bcd60e51b8152600401610d4590615943565b816001600160401b038111156115f057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611619578160200160208202803683370190505b50905060005b828110156116d4576116978585858481811061164b57634e487b7160e01b600052603260045260246000fd5b905060200281019061165d9190615ade565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061367992505050565b8282815181106116b757634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806116cc81615c5e565b91505061161f565b50600180559392505050565b6000546001600160a01b0316331461170a5760405162461bcd60e51b8152600401610d459061590e565b6040514790339082156108fc029083906000818181858888f19350505050158015611271573d6000803e3d6000fd5b611744600f33612f40565b6117605760405162461bcd60e51b8152600401610d4590615943565b611271828260006139d2565b3361177f6000546001600160a01b031690565b6001600160a01b0316148061179a575061179a600233612f40565b6117b65760405162461bcd60e51b8152600401610d45906159dd565b836117c2601182612f40565b156117df5760405162461bcd60e51b8152600401610d4590615a21565b6110e185858585613728565b610f85838383604051806020016040528060008152506127a3565b600260015414156118295760405162461bcd60e51b8152600401610d4590615a63565b600260015561183833826133e4565b61189c5760405162461bcd60e51b815260206004820152602f60248201527f45524337323143726561746f723a2063616c6c6572206973206e6f74206f776e60448201526e195c881b9bdc88185c1c1c9bdd9959608a1b6064820152608401610d45565b60006118a782611cdc565b90506118b282613a0f565b6118bc8183613ab6565b505060018055565b601e5460ff166118d357600080fd5b60148111156118e157600080fd5b6020546118f19061271090613bcc565b611904826118fe600c5490565b90613bd8565b111561190f57600080fd5b3461192267011c37937e08000083613be4565b111561192d57600080fd5b60005b8181101561127157612710611944600c5490565b10156119905761196a33611965600e5460016119609190615b79565b613bf0565b613d09565b50600e54604051338152600080516020615d498339815191529060200160405180910390a25b8061199a81615c5e565b915050611930565b600260015414156119c55760405162461bcd60e51b8152600401610d4590615a63565b6002600155601e5460ff166119d957600080fd5b6000602054116119e857600080fd5b60008181526021602052604090205460ff1615611a3c5760405162461bcd60e51b815260206004820152601260248201527148617320636c61696d6564206265666f726560701b6044820152606401610d45565b6040516331a9108f60e11b8152600481018290523390739030807ba4c71831808408cbf892bfa1261a6e7d90636352211e9060240160206040518083038186803b158015611a8957600080fd5b505afa158015611a9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac19190614ee4565b6001600160a01b031614611ad457600080fd5b6000818152602160205260409020805460ff19166001908117909155600e54611b07913391611965916119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a2602054611b3a906001613bcc565b6020555060018055565b6000611b4f600c5490565b8210611bb25760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610d45565b600c8281548110611bd357634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b611bf0600f33612f40565b611c0c5760405162461bcd60e51b8152600401610d4590615943565b82518114611c5c5760405162461bcd60e51b815260206004820152601c60248201527f45524337323143726561746f723a20496e76616c696420696e707574000000006044820152606401610d45565b60005b835181101561141457611cca848281518110611c8b57634e487b7160e01b600052603260045260246000fd5b6020026020010151848484818110611cb357634e487b7160e01b600052603260045260246000fd5b9050602002810190611cc59190615ade565b613d4c565b80611cd481615c5e565b915050611c5f565b6000818152600660205260408120546001600160a01b031680610cf55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610d45565b611d5e600f33612f40565b611d7a5760405162461bcd60e51b8152600401610d4590615943565b6112718282613db2565b6000546001600160a01b03163314611dae5760405162461bcd60e51b8152600401610d459061590e565b611db9600282612f40565b610d575760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3611271600282613dcc565b60006001600160a01b038216611e695760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610d45565b506001600160a01b031660009081526007602052604090205490565b6000546001600160a01b03163314611eaf5760405162461bcd60e51b8152600401610d459061590e565b611eb96000613de1565b565b600060026001541415611ee05760405162461bcd60e51b8152600401610d4590615a63565b600260015533611ef86000546001600160a01b031690565b6001600160a01b03161480611f135750611f13600233612f40565b611f2f5760405162461bcd60e51b8152600401610d45906159dd565b6111ec8260405180602001604052806000815250613d09565b600060026001541415611f6d5760405162461bcd60e51b8152600401610d4590615a63565b600260015533611f856000546001600160a01b031690565b6001600160a01b03161480611fa05750611fa0600233612f40565b611fbc5760405162461bcd60e51b8152600401610d45906159dd565b611ffc8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d0992505050565b60018055949350505050565b60606002600154141561202d5760405162461bcd60e51b8152600401610d4590615a63565b6002600155336120456000546001600160a01b031690565b6001600160a01b031614806120605750612060600233612f40565b61207c5760405162461bcd60e51b8152600401610d45906159dd565b816001600160401b038111156120a257634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156120cb578160200160208202803683370190505b50905060005b828110156116d457612149858585848181106120fd57634e487b7160e01b600052603260045260246000fd5b905060200281019061210f9190615ade565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d0992505050565b82828151811061216957634e487b7160e01b600052603260045260246000fd5b60209081029190910101528061217e81615c5e565b9150506120d1565b612191600f33612f40565b6121ad5760405162461bcd60e51b8152600401610d4590615943565b610f858383836139d2565b60606121c4600f613817565b6001600160401b038111156121e957634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612212578160200160208202803683370190505b50905060005b612222600f613817565b8110156114e057612234600f82613821565b82828151811061225457634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528061227681615c5e565b915050612218565b606060058054610d6990615c07565b336122a06000546001600160a01b031690565b6001600160a01b031614806122bb57506122bb600233612f40565b6122d75760405162461bcd60e51b8152600401610d45906159dd565b6112718282613e31565b6001600160a01b03821633141561233a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610d45565b3360008181526009602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b336123b96000546001600160a01b031690565b6001600160a01b031614806123d457506123d4600233612f40565b6123f05760405162461bcd60e51b8152600401610d45906159dd565b825181146124405760405162461bcd60e51b815260206004820152601c60248201527f45524337323143726561746f723a20496e76616c696420696e707574000000006044820152606401610d45565b60005b8351811015611414576124ae84828151811061246f57634e487b7160e01b600052603260045260246000fd5b602002602001015184848481811061249757634e487b7160e01b600052603260045260246000fd5b90506020028101906124a99190615ade565b613187565b806124b881615c5e565b915050612443565b6124cb600f33612f40565b6124e75760405162461bcd60e51b8152600401610d4590615943565b801580612500575061250033634ce6d51160e11b613e4b565b6125985760405162461bcd60e51b815260206004820152605960248201527f45524337323143726561746f72436f72653a205265717569726573206578746560448201527f6e73696f6e20746f20696d706c656d656e74204945524337323143726561746f60648201527f72457874656e73696f6e417070726f76655472616e7366657200000000000000608482015260a401610d45565b3360009081526014602052604090205460ff16151581151514610d575733600081815260146020908152604091829020805460ff191685151590811790915591519182527f072a7592283e2c2d1d56d21517ff6013325e0f55483f4828373ff4d98b0a1a36910160405180910390a250565b60606002600154141561262f5760405162461bcd60e51b8152600401610d4590615a63565b6002600155336126476000546001600160a01b031690565b6001600160a01b031614806126625750612662600233612f40565b61267e5760405162461bcd60e51b8152600401610d45906159dd565b8161ffff166001600160401b038111156126a857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156126d1578160200160208202803683370190505b50905060005b8261ffff168161ffff161015612741576127008460405180602001604052806000815250613d09565b828261ffff168151811061272457634e487b7160e01b600052603260045260246000fd5b60209081029190910101528061273981615c3c565b9150506126d7565b506001805592915050565b3361275f6000546001600160a01b031690565b6001600160a01b0316148061277a575061277a600233612f40565b6127965760405162461bcd60e51b8152600401610d45906159dd565b6110e1858585858561382d565b6127ad33836133e4565b6127c95760405162461bcd60e51b8152600401610d459061598c565b61141484848484613e67565b60606127e082613070565b6127fc5760405162461bcd60e51b8152600401610d45906158e3565b61280582613e9a565b80548060200260200160405190810160405280929190818152602001828054801561100457602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161283b5750505050509050919050565b60608061287083613070565b61288c5760405162461bcd60e51b8152600401610d45906158e3565b61289583613f26565b8154604080516020808402820181019092528281529184918301828280156128e657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128c8575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561293857602002820191906000526020600020905b815481526020019060010190808311612924575b5050505050905091509150915091565b600080606061295687613070565b6129725760405162461bcd60e51b8152600401610d45906158e3565b61297c8787613f44565b9250925092509450945094915050565b606061299782613070565b6129b35760405162461bcd60e51b8152600401610d45906158e3565b610cf582614073565b336129cf6000546001600160a01b031690565b6001600160a01b031614806129ea57506129ea600233612f40565b612a065760405162461bcd60e51b8152600401610d45906159dd565b610d57816142fc565b6000546001600160a01b03163314612a395760405162461bcd60e51b8152600401610d459061590e565b636155a6c04211612a4957600080fd5b601e5460ff16612a5857600080fd5b600060205411612a6757600080fd5b60008181526021602052604090205460ff1615612abb5760405162461bcd60e51b815260206004820152601260248201527148617320636c61696d6564206265666f726560701b6044820152606401610d45565b6000818152602160205260409020805460ff19166001908117909155600e54612aee913391611965916119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a2602054612b21906001613bcc565b60205550565b606060026001541415612b4c5760405162461bcd60e51b8152600401610d4590615a63565b6002600155612b5c600f33612f40565b612b785760405162461bcd60e51b8152600401610d4590615943565b8161ffff166001600160401b03811115612ba257634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612bcb578160200160208202803683370190505b50905060005b8261ffff168161ffff16101561274157612bfa8460405180602001604052806000815250613679565b828261ffff1681518110612c1e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280612c3381615c3c565b915050612bd1565b612c46600f33612f40565b612c625760405162461bcd60e51b8152600401610d4590615943565b610f85838383613d4c565b604051806060016040528060408152602001615d096040913981565b33612c9c6000546001600160a01b031690565b6001600160a01b03161480612cb75750612cb7600233612f40565b612cd35760405162461bcd60e51b8152600401610d45906159dd565b611271828261434d565b6000546001600160a01b03163314612d075760405162461bcd60e51b8152600401610d459061590e565b6001600160a01b038116612d6c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d45565b610d5781613de1565b600060026001541415612d9a5760405162461bcd60e51b8152600401610d4590615a63565b6002600155612daa600f33612f40565b612dc65760405162461bcd60e51b8152600401610d4590615943565b611ffc8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061367992505050565b6000546001600160a01b03163314612e305760405162461bcd60e51b8152600401610d459061590e565b601f54811115612e3f57600080fd5b60005b81811015612e9757612e6033611965600e5460016119609190615b79565b50600e54604051338152600080516020615d498339815191529060200160405180910390a280612e8f81615c5e565b915050612e42565b601f54612ea49083613bcc565b601f555050565b60006001600160e01b03198216639088c20760e01b1480610cf55750610cf58261449b565b60006001600160e01b031982166380ac58cd60e01b1480610ce657506001600160e01b03198216635b5e139f60e01b1480610cf55750610cf5825b60006001600160e01b03198216632a9f3abf60e11b1480610cf557506301ffc9a760e01b6001600160e01b0319831614610cf5565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6001600160a01b038116301415612fcd5760405162461bcd60e51b815260206004820152602660248201527f43726561746f72436f72653a2043616e6e6f7420626c61636b6c69737420796f6044820152653ab939b2b63360d11b6064820152608401610d45565b612fd8600f82612f40565b156130205760405133906001600160a01b038316907fd19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a7890147990600090a361301e600f826136f3565b505b61302b601182612f40565b610d575760405133906001600160a01b038316907f05ac7bc5a606cd92a63365f9fda244499b9add0526b22d99937b6bd88181059c90600090a3611271601182613dcc565b6000908152600660205260409020546001600160a01b0316151590565b600081815260086020526040902080546001600160a01b0319166001600160a01b03841690811790915581906130c282611cdc565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152601d60205260408120541561312157506000908152601d6020526040902090565b6000828152601560209081526040808320546001600160a01b03168352601b9091529020541561317357506000908152601560209081526040808320546001600160a01b03168352601b909152902090565b5050306000908152601b6020526040902090565b6000838152601560205260409020546001600160a01b031630146131ed5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420746f6b656e0000000000006044820152606401610d45565b6000838152601960205260409020611414908383614c74565b8281146132555760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420696e7075740000000000006044820152606401610d45565b6000805b828110156132a75783838281811061328157634e487b7160e01b600052603260045260246000fd5b90506020020135826132939190615b79565b91508061329f81615c5e565b915050613259565b5061271081106132c95760405162461bcd60e51b8152600401610d4590615a9a565b6000868152601c602052604090206132e2908686614cf4565b506000868152601d602052604090206132fc908484614d47565b50857fabb46fe0761d77584bde75697647804ffd8113abd4d8d06bc664150395eccdee8686868660405161333394939291906157b4565b60405180910390a2505050505050565b6000818152601560205260409020546001600160a01b0316308114156133b75760405162461bcd60e51b815260206004820152602360248201527f43726561746f72436f72653a204e6f20657874656e73696f6e20666f7220746f60448201526235b2b760e91b6064820152608401610d45565b6133c2601182612f40565b156133df5760405162461bcd60e51b8152600401610d4590615a21565b919050565b60006133ef82613070565b6134505760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d45565b600061345b83611cdc565b9050806001600160a01b0316846001600160a01b031614806134965750836001600160a01b031661348b84610dec565b6001600160a01b0316145b806134c657506001600160a01b0380821660009081526009602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b03166134e182611cdc565b6001600160a01b0316146135495760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610d45565b6001600160a01b0382166135ab5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610d45565b6135b6838383614531565b6135c160008261308d565b6001600160a01b03831660009081526007602052604081208054600192906135ea908490615bc4565b90915550506001600160a01b0382166000908152600760205260408120805460019290613618908490615b79565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600e80546000918261368a83615c5e565b9190505550600e54905061369e838261453c565b600081815260156020526040902080546001600160a01b031916331790556136c683826145d0565b8151156136ee57600081815260196020908152604090912083516136ec92850190614d81565b505b610cf5565b6000612f5e836001600160a01b0384166145ea565b306000908152601660209081526040909120825161127192840190614d81565b6001600160a01b0384163b61378d5760405162461bcd60e51b815260206004820152602560248201527f43726561746f723a20457874656e73696f6e206d757374206265206120636f6e6044820152641d1c9858dd60da1b6064820152608401610d45565b613798600f85612f40565b611414576001600160a01b03841660009081526016602052604090206137bf908484614c74565b506001600160a01b038416600081815260176020526040808220805460ff1916851515179055513392917fd8cb8ba4086944eabf43c5535b7712015e4d4c714b24bf812c040ea5b7a3e42a91a36110e1600f85613dcc565b6000610cf5825490565b6000612f5e8383614707565b82811461387c5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420696e7075740000000000006044820152606401610d45565b6000805b828110156138ce578383828181106138a857634e487b7160e01b600052603260045260246000fd5b90506020020135826138ba9190615b79565b9150806138c681615c5e565b915050613880565b5061271081106138f05760405162461bcd60e51b8152600401610d4590615a9a565b6001600160a01b0386166000908152601a60205260409020613913908686614cf4565b506001600160a01b0386166000908152601b60205260409020613937908484614d47565b506001600160a01b03861630141561398b577f2b6849d5976d799a5b0ca4dfd6b40a3d7afe9ea72c091fa01a958594f9a2659b8585858560405161397e94939291906157b4565b60405180910390a16139ca565b856001600160a01b03167f535a93d2cb000582c0ebeaa9be4890ec6a287f98eb2df00c54c300612fd78d8f8686868660405161333394939291906157b4565b505050505050565b3360009081526016602052604090206139ec908484614c74565b50336000908152601760205260409020805460ff19169115159190911790555050565b6000613a1a82611cdc565b9050613a2881600084614531565b613a3360008361308d565b6001600160a01b0381166000908152600760205260408120805460019290613a5c908490615bc4565b909155505060008281526006602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000818152601560205260409020546001600160a01b03163014613b7657600081815260156020526040902054613afd906001600160a01b03166311686e4b60e21b613e4b565b15613b7657600081815260156020526040908190205490516311686e4b60e21b81526001600160a01b03848116600483015260248201849052909116906345a1b92c90604401600060405180830381600087803b158015613b5d57600080fd5b505af1158015613b71573d6000803e3d6000fd5b505050505b60008181526019602052604090208054613b8f90615c07565b159050613bad576000818152601960205260408120613bad91614df5565b600090815260156020526040902080546001600160a01b031916905550565b6000612f5e8284615bc4565b6000612f5e8284615b79565b6000612f5e8284615ba5565b606081613c145750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613c3e5780613c2881615c5e565b9150613c379050600a83615b91565b9150613c18565b6000816001600160401b03811115613c6657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c90576020820181803683370190505b5090505b84156134c657613ca5600183615bc4565b9150613cb2600a86615c79565b613cbd906030615b79565b60f81b818381518110613ce057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350613d02600a86615b91565b9450613c94565b600e805460009182613d1a83615c5e565b9091555050600e54600081815260156020526040902080546001600160a01b0319163017905590506136c683826145d0565b6000838152601560205260409020546001600160a01b031633146131ed5760405162461bcd60e51b815260206004820152601a60248201527f43726561746f72436f72653a20496e76616c696420746f6b656e0000000000006044820152606401610d45565b336000908152601860205260409020610f85908383614c74565b6000612f5e836001600160a01b03841661473f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b306000908152601860205260409020610f85908383614c74565b6000613e568361478e565b8015612f5e5750612f5e83836147c1565b613e728484846134ce565b613e7e848484846148aa565b6114145760405162461bcd60e51b8152600401610d4590615891565b6000818152601c602052604081205415613ec057506000908152601c6020526040902090565b6000828152601560209081526040808320546001600160a01b03168352601a90915290205415613f1257506000908152601560209081526040808320546001600160a01b03168352601a909152902090565b5050306000908152601a6020526040902090565b600080613f3283613e9a565b613f3b846130fb565b91509150915091565b60008060606000613f5486613e9a565b805490915060011015613fd1576040805162461bcd60e51b81526020600482015260248101919091527f43726561746f72436f72653a204f6e6c7920776f726b7320696620746865726560448201527f20617265206174206d6f7374203120726f79616c7479207265636569766572736064820152608401610d45565b8054613fe457306000935093505061406c565b8060008154811061400557634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031661271086614027896130fb565b60008154811061404757634e487b7160e01b600052603260045260246000fd5b906000526020600020015461405c9190615ba5565b6140669190615b91565b93509350505b9250925092565b6000818152601560205260409020546060906001600160a01b0316614099601182612f40565b156140b65760405162461bcd60e51b8152600401610d4590615a21565b600083815260196020526040902080546140cf90615c07565b1590506141e9576001600160a01b038116600090815260186020526040902080546140f990615c07565b15905061414a576001600160a01b0381166000908152601860209081526040808320868452601983529281902090516141339392016156f8565b604051602081830303815290604052915050919050565b6000838152601960205260409020805461416390615c07565b80601f016020809104026020016040519081016040528092919081815260200182805461418f90615c07565b80156141dc5780601f106141b1576101008083540402835291602001916141dc565b820191906000526020600020905b8154815290600101906020018083116141bf57829003601f168201915b5050505050915050919050565b6141fa8163e9dc637560e01b613e4b565b156142815760405163e9dc637560e01b8152306004820152602481018490526001600160a01b0382169063e9dc63759060440160006040518083038186803b15801561424557600080fd5b505afa158015614259573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f5e919081019061544f565b6001600160a01b03811660009081526017602052604090205460ff166142d3576001600160a01b03811660009081526016602052604090206142c284613bf0565b6040516020016141339291906156d3565b6001600160a01b0381166000908152601660205260409020805461416390615c07565b50919050565b614307600f82612f40565b15610d575760405133906001600160a01b038316907fd19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a7890147990600090a3611271600f826136f3565b614358600f83612f40565b6143a45760405162461bcd60e51b815260206004820152601e60248201527f43726561746f72436f72653a20496e76616c696420657874656e73696f6e00006044820152606401610d45565b6001600160a01b03811615806143c657506143c681631e05385b60e31b613e4b565b61441d5760405162461bcd60e51b815260206004820152602260248201527f45524337323143726561746f72436f72653a20496e76616c6964206164647265604482015261737360f01b6064820152608401610d45565b6001600160a01b03828116600090815260136020526040902054811690821614611271576001600160a01b0382811660008181526013602052604080822080546001600160a01b031916948616948517905551339392917f6a835c4fcf7e0d398db3762332fdaa1471814ad39f1e2d6d0b3fdabf8efee3e091a45050565b60006001600160e01b031982166361f8bcb360e11b14806144c057506144c0826149b7565b806144db57506001600160e01b03198216635d9dd7eb60e11b145b806144f657506001600160e01b03198216632dde656160e21b145b8061451157506001600160e01b031982166335681b5360e21b145b80610cf557506001600160e01b03198216636057361d60e01b1492915050565b610f858383836149dc565b336000908152601360205260409020546001600160a01b031615611271573360008181526013602052604090819020549051631e05385b60e31b815260048101929092526001600160a01b03848116602484015260448301849052169063f029c2d890606401600060405180830381600087803b1580156145bc57600080fd5b505af11580156139ca573d6000803e3d6000fd5b611271828260405180602001604052806000815250614b02565b600081815260018301602052604081205480156146fd57600061460e600183615bc4565b855490915060009061462290600190615bc4565b90508181146146a357600086600001828154811061465057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061468157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b85548690806146c257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610cf5565b6000915050610cf5565b600082600001828154811061472c57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600081815260018301602052604081205461478657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610cf5565b506000610cf5565b60006147a1826301ffc9a760e01b6147c1565b8015610cf557506147ba826001600160e01b03196147c1565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b03871690617530906148289086906156b7565b6000604051808303818686fa925050503d8060008114614864576040519150601f19603f3d011682016040523d82523d6000602084013e614869565b606091505b50915091506020815110156148845760009350505050610cf5565b8180156148a05750808060200190518101906148a09190615368565b9695505050505050565b60006001600160a01b0384163b156149ac57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906148ee90339089908890889060040161570d565b602060405180830381600087803b15801561490857600080fd5b505af1925050508015614938575060408051601f3d908101601f19168201909252614935918101906153a0565b60015b614992573d808015614966576040519150601f19603f3d011682016040523d82523d6000602084013e61496b565b606091505b50805161498a5760405162461bcd60e51b8152600401610d4590615891565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506134c6565b506001949350505050565b60006001600160e01b0319821663780e9d6360e01b1480610cf55750610cf582612ed0565b6000818152601560209081526040808320546001600160a01b03168352601490915290205460ff1615610f855760008181526015602052604090819020549051638258080560e01b81526001600160a01b03858116600483015284811660248301526044820184905290911690638258080590606401602060405180830381600087803b158015614a6c57600080fd5b505af1158015614a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614aa49190615368565b610f855760405162461bcd60e51b815260206004820152602960248201527f45524337323143726561746f723a20457874656e73696f6e20617070726f76616044820152686c206661696c75726560b81b6064820152608401610d45565b614b0c8383614b35565b614b1960008484846148aa565b610f855760405162461bcd60e51b8152600401610d4590615891565b6001600160a01b038216614b8b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610d45565b614b9481613070565b15614be15760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610d45565b614bed60008383614531565b6001600160a01b0382166000908152600760205260408120805460019290614c16908490615b79565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054614c8090615c07565b90600052602060002090601f016020900481019282614ca25760008555614ce8565b82601f10614cbb5782800160ff19823516178555614ce8565b82800160010185558215614ce8579182015b82811115614ce8578235825591602001919060010190614ccd565b506114e0929150614e2b565b828054828255906000526020600020908101928215614ce8579160200282015b82811115614ce85781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614d14565b828054828255906000526020600020908101928215614ce85791602002820182811115614ce8578235825591602001919060010190614ccd565b828054614d8d90615c07565b90600052602060002090601f016020900481019282614daf5760008555614ce8565b82601f10614dc857805160ff1916838001178555614ce8565b82800160010185558215614ce8579182015b82811115614ce8578251825591602001919060010190614dda565b508054614e0190615c07565b6000825580601f10614e11575050565b601f016020900490600052602060002090810190610d5791905b5b808211156114e05760008155600101614e2c565b60008083601f840112614e51578182fd5b5081356001600160401b03811115614e67578182fd5b6020830191508360208260051b8501011115614e8257600080fd5b9250929050565b60008083601f840112614e9a578182fd5b5081356001600160401b03811115614eb0578182fd5b602083019150836020828501011115614e8257600080fd5b600060208284031215614ed9578081fd5b8135612f5e81615ccf565b600060208284031215614ef5578081fd5b8151612f5e81615ccf565b60008060408385031215614f12578081fd5b8235614f1d81615ccf565b91506020830135614f2d81615ccf565b809150509250929050565b600080600060608486031215614f4c578081fd5b8335614f5781615ccf565b92506020840135614f6781615ccf565b929592945050506040919091013590565b60008060008060808587031215614f8d578081fd5b8435614f9881615ccf565b93506020850135614fa881615ccf565b92506040850135915060608501356001600160401b03811115614fc9578182fd5b8501601f81018713614fd9578182fd5b8035614fec614fe782615b52565b615b22565b818152886020838501011115615000578384fd5b81602084016020830137908101602001929092525092959194509250565b600080600080600060608688031215615035578081fd5b853561504081615ccf565b945060208601356001600160401b038082111561505b578283fd5b61506789838a01614e40565b9096509450604088013591508082111561507f578283fd5b5061508c88828901614e40565b969995985093965092949392505050565b6000806000604084860312156150b1578081fd5b83356150bc81615ccf565b925060208401356001600160401b038111156150d6578182fd5b6150e286828701614e40565b9497909650939450505050565b60008060408385031215615101578182fd5b823561510c81615ccf565b91506020830135614f2d81615ce4565b600080600060408486031215615130578081fd5b833561513b81615ccf565b925060208401356001600160401b03811115615155578182fd5b6150e286828701614e89565b60008060008060608587031215615176578182fd5b843561518181615ccf565b935060208501356001600160401b0381111561519b578283fd5b6151a787828801614e89565b90945092505060408501356151bb81615ce4565b939692955090935050565b600080604083850312156151d8578182fd5b82356151e381615ccf565b9150602083013561ffff81168114614f2d578182fd5b6000806040838503121561520b578182fd5b823561521681615ccf565b946020939093013593505050565b60008060008060408587031215615239578182fd5b84356001600160401b038082111561524f578384fd5b61525b88838901614e40565b90965094506020870135915080821115615273578384fd5b5061528087828801614e40565b95989497509550505050565b6000806000604084860312156152a0578081fd5b83356001600160401b03808211156152b6578283fd5b818601915086601f8301126152c9578283fd5b81356020828211156152dd576152dd615cb9565b8160051b6152ec828201615b22565b8381528281019086840183880185018d1015615306578889fd5b8897505b8588101561532857803583526001979097019691840191840161530a565b50985050508701359250508082111561533f578283fd5b506150e286828701614e40565b60006020828403121561535d578081fd5b8135612f5e81615ce4565b600060208284031215615379578081fd5b8151612f5e81615ce4565b600060208284031215615395578081fd5b8135612f5e81615cf2565b6000602082840312156153b1578081fd5b8151612f5e81615cf2565b600080602083850312156153ce578182fd5b82356001600160401b038111156153e3578283fd5b6153ef85828601614e89565b90969095509350505050565b60008060006040848603121561540f578081fd5b83356001600160401b03811115615424578182fd5b61543086828701614e89565b909450925050602084013561544481615ce4565b809150509250925092565b600060208284031215615460578081fd5b81516001600160401b03811115615475578182fd5b8201601f81018413615485578182fd5b8051615493614fe782615b52565b8181528560208385010111156154a7578384fd5b6154b8826020830160208601615bdb565b95945050505050565b6000602082840312156154d2578081fd5b5035919050565b6000806000806000606086880312156154f0578283fd5b8535945060208601356001600160401b038082111561505b578485fd5b600080600060408486031215615521578081fd5b8335925060208401356001600160401b03811115615155578182fd5b60008060008060608587031215615552578182fd5b843593506020850135925060408501356001600160401b03811115615575578283fd5b61528087828801614e89565b6000815180845260208085019450808401835b838110156155b95781516001600160a01b031687529582019590820190600101615594565b509495945050505050565b6000815180845260208085019450808401835b838110156155b9578151875295820195908201906001016155d7565b6000815180845261560b816020860160208601615bdb565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061563957607f831692505b602080841082141561565957634e487b7160e01b86526022600452602486fd5b81801561566d576001811461567e576156ab565b60ff198616895284890196506156ab565b60008881526020902060005b868110156156a35781548b82015290850190830161568a565b505084890196505b50505050505092915050565b600082516156c9818460208701615bdb565b9190910192915050565b60006156df828561561f565b83516156ef818360208801615bdb565b01949350505050565b60006134c6615707838661561f565b8461561f565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906148a0908301846155f3565b60018060a01b03841681528260208201526060604082015260006154b860608301846155f3565b6020808252825182820181905260009190848201906040850190845b818110156157a85783516001600160a01b031683529284019291840191600101615783565b50909695505050505050565b6040808252810184905260008560608301825b878110156157f75782356157da81615ccf565b6001600160a01b03168252602092830192909101906001016157c7565b5083810360208501528481526001600160fb1b03851115615816578283fd5b8460051b9150818660208301370160200190815295945050505050565b602081526000612f5e6020830184615581565b6040815260006158596040830185615581565b82810360208401526154b881856155c4565b602081526000612f5e60208301846155c4565b602081526000612f5e60208301846155f3565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601190820152702737b732bc34b9ba32b73a103a37b5b2b760791b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f43726561746f72436f72653a204d75737420626520726567697374657265642060408201526832bc3a32b739b4b7b760b91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b60208082526022908201527f43726561746f72436f72653a20457874656e73696f6e20626c61636b6c697374604082015261195960f21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f43726561746f72436f72653a20496e76616c696420746f74616c20726f79616c6040820152637469657360e01b606082015260800190565b6000808335601e19843603018112615af4578283fd5b8301803591506001600160401b03821115615b0d578283fd5b602001915036819003821315614e8257600080fd5b604051601f8201601f191681016001600160401b0381118282101715615b4a57615b4a615cb9565b604052919050565b60006001600160401b03821115615b6b57615b6b615cb9565b50601f01601f191660200190565b60008219821115615b8c57615b8c615c8d565b500190565b600082615ba057615ba0615ca3565b500490565b6000816000190483118215151615615bbf57615bbf615c8d565b500290565b600082821015615bd657615bd6615c8d565b500390565b60005b83811015615bf6578181015183820152602001615bde565b838111156114145750506000910152565b600181811c90821680615c1b57607f821691505b602082108114156142f657634e487b7160e01b600052602260045260246000fd5b600061ffff80831681811415615c5457615c54615c8d565b6001019392505050565b6000600019821415615c7257615c72615c8d565b5060010190565b600082615c8857615c88615ca3565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610d5757600080fd5b8015158114610d5757600080fd5b6001600160e01b031981168114610d5757600080fdfe3931323835313362326336613038333430386461383831356136396162336336313763323131363335306237393061633661623239396165656632653364346455f284809f4c5b7377fbe62f2feeb9686e3834dcae5f3ca955140fe6547cd355a26469706673582212207774ff44d2129ea986c9b42c450517cf528fb3ad6dd97428367437b9df8d7f6664736f6c63430008040033

Deployed Bytecode Sourcemap

117821:4175:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99653:304;;;;;;;;;;-1:-1:-1;99653:304:0;;;;;:::i;:::-;;:::i;:::-;;;22241:14:1;;22234:22;22216:41;;22204:2;22189:18;99653:304:0;;;;;;;;100997:128;;;;;;;;;;-1:-1:-1;100997:128:0;;;;;:::i;:::-;;:::i;:::-;;80011:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;81570:221::-;;;;;;;;;;-1:-1:-1;81570:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;17639:32:1;;;17621:51;;17609:2;17594:18;81570:221:0;17576:102:1;81093:411:0;;;;;;;;;;-1:-1:-1;81093:411:0;;;;;:::i;:::-;;:::i;109988:197::-;;;;;;;;;;-1:-1:-1;109988:197:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;102972:136::-;;;;;;;;;;-1:-1:-1;102972:136:0;;;;;:::i;:::-;;:::i;93766:113::-;;;;;;;;;;-1:-1:-1;93854:10:0;:17;93766:113;;;37115:25:1;;;37103:2;37088:18;93766:113:0;37070:76:1;118285:58:0;;;;;;;;;;;;118333:10;118285:58;;108460:263;;;;;;;;;;-1:-1:-1;108460:263:0;;;;;:::i;:::-;;:::i;107557:195::-;;;;;;;;;;-1:-1:-1;107557:195:0;;;;;:::i;:::-;;:::i;82460:339::-;;;;;;;;;;-1:-1:-1;82460:339:0;;;;;:::i;:::-;;:::i;20950:139::-;;;;;;;;;;-1:-1:-1;20950:139:0;;;;;:::i;:::-;;:::i;105632:155::-;;;;;;;;;;-1:-1:-1;105632:155:0;;;;;:::i;:::-;;:::i;20672:210::-;;;;;;;;;;-1:-1:-1;20672:210:0;;;;;:::i;:::-;;:::i;93434:256::-;;;;;;;;;;-1:-1:-1;93434:256:0;;;;;:::i;:::-;;:::i;102578:118::-;;;;;;;;;;-1:-1:-1;102578:118:0;;;;;:::i;:::-;;:::i;100199:199::-;;;;;;;;;;-1:-1:-1;100199:199:0;;;;;:::i;:::-;;:::i;20050:267::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;108184:204::-;;;;;;;;;;-1:-1:-1;108184:204:0;;;;;:::i;:::-;;:::i;121902:91::-;;;;;;;;;;;;;:::i;106539:327::-;;;;;;;;;;-1:-1:-1;106539:327:0;;;;;:::i;:::-;;:::i;120605:142::-;;;;;;;;;;;;;:::i;101209:147::-;;;;;;;;;;-1:-1:-1;101209:147:0;;;;;:::i;:::-;;:::i;100475:233::-;;;;;;;;;;-1:-1:-1;100475:233:0;;;;;:::i;:::-;;:::i;82870:185::-;;;;;;;;;;-1:-1:-1;82870:185:0;;;;;:::i;:::-;;:::i;107822:290::-;;;;;;;;;;-1:-1:-1;107822:290:0;;;;;:::i;:::-;;:::i;119650:859::-;;;;;;:::i;:::-;;:::i;118207:47::-;;;;;;;;;;;;118252:2;118207:47;;119002:587;;;;;;;;;;-1:-1:-1;119002:587:0;;;;;:::i;:::-;;:::i;93956:233::-;;;;;;;;;;-1:-1:-1;93956:233:0;;;;;:::i;:::-;;:::i;118367:45::-;;;;;;;;;;;;118407:5;118367:45;;102161:342;;;;;;;;;;-1:-1:-1;102161:342:0;;;;;:::i;:::-;;:::i;79705:239::-;;;;;;;;;;-1:-1:-1;79705:239:0;;;;;:::i;:::-;;:::i;101693:150::-;;;;;;;;;;-1:-1:-1;101693:150:0;;;;;:::i;:::-;;:::i;118017:86::-;;;;;;;;;;;;118061:42;118017:86;;20390:210;;;;;;;;;;-1:-1:-1;20390:210:0;;;;;:::i;:::-;;:::i;79435:208::-;;;;;;;;;;-1:-1:-1;79435:208:0;;;;;:::i;:::-;;:::i;17572:94::-;;;;;;;;;;;;;:::i;103813:141::-;;;;;;;;;;-1:-1:-1;103813:141:0;;;;;:::i;:::-;;:::i;104028:163::-;;;;;;;;;;-1:-1:-1;104028:163:0;;;;;:::i;:::-;;:::i;104663:339::-;;;;;;;;;;-1:-1:-1;104663:339:0;;;;;:::i;:::-;;:::i;101440:167::-;;;;;;;;;;-1:-1:-1;101440:167:0;;;;;:::i;:::-;;:::i;48046:299::-;;;;;;;;;;;;;:::i;16921:87::-;;;;;;;;;;-1:-1:-1;16967:7:0;16994:6;-1:-1:-1;;;;;16994:6:0;16921:87;;80180:104;;;;;;;;;;;;;:::i;102773:128::-;;;;;;;;;;-1:-1:-1;102773:128:0;;;;;:::i;:::-;;:::i;81863:295::-;;;;;;;;;;-1:-1:-1;81863:295:0;;;;;:::i;:::-;;:::i;103179:320::-;;;;;;;;;;-1:-1:-1;103179:320:0;;;;;:::i;:::-;;:::i;60390:533::-;;;;;;;;;;-1:-1:-1;60390:533:0;;;;;:::i;:::-;;:::i;104270:314::-;;;;;;;;;;-1:-1:-1;104270:314:0;;;;;:::i;:::-;;:::i;108804:228::-;;;;;;;;;;-1:-1:-1;108804:228:0;;;;;:::i;:::-;;:::i;83126:328::-;;;;;;;;;;-1:-1:-1;83126:328:0;;;;;:::i;:::-;;:::i;109698:221::-;;;;;;;;;;-1:-1:-1;109698:221:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;109104:228::-;;;;;;;;;;-1:-1:-1;109104:228:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;110260:255::-;;;;;;;;;;-1:-1:-1;110260:255:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;110587:189::-;;;;;;;;;;-1:-1:-1;110587:189:0;;;;;:::i;:::-;;:::i;100789:130::-;;;;;;;;;;-1:-1:-1;100789:130:0;;;;;:::i;:::-;;:::i;121277:578::-;;;;;;;;;;-1:-1:-1;121277:578:0;;;;;:::i;:::-;;:::i;106127:328::-;;;;;;;;;;-1:-1:-1;106127:328:0;;;;;:::i;:::-;;:::i;118133:55::-;;;;;;;;;;;;118171:17;118133:55;;101923:158;;;;;;;;;;-1:-1:-1;101923:158:0;;;;;:::i;:::-;;:::i;82229:164::-;;;;;;;;;;-1:-1:-1;82229:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;82350:25:0;;;82326:4;82350:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;82229:164;118451:32;;;;;;;;;;-1:-1:-1;118451:32:0;;;;;;;;117898:112;;;;;;;;;;;;;:::i;103577:162::-;;;;;;;;;;-1:-1:-1;103577:162:0;;;;;:::i;:::-;;:::i;17821:192::-;;;;;;;;;;-1:-1:-1;17821:192:0;;;;;:::i;:::-;;:::i;105866:177::-;;;;;;;;;;-1:-1:-1;105866:177:0;;;;;:::i;:::-;;:::i;120808:404::-;;;;;;;;;;-1:-1:-1;120808:404:0;;;;;:::i;:::-;;:::i;99653:304::-;99789:4;99813:48;99849:11;99813:35;:48::i;:::-;:89;;;;99865:37;99890:11;99865:24;:37::i;:::-;99813:136;;;;99906:43;99937:11;99906:30;:43::i;:::-;99806:143;99653:304;-1:-1:-1;;99653:304:0:o;100997:128::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;;;;;;;;;101087:30:::1;101107:9;101087:19;:30::i;:::-;100997:128:::0;:::o;80011:100::-;80065:13;80098:5;80091:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80011:100;:::o;81570:221::-;81646:7;81674:16;81682:7;81674;:16::i;:::-;81666:73;;;;-1:-1:-1;;;81666:73:0;;30472:2:1;81666:73:0;;;30454:21:1;30511:2;30491:18;;;30484:30;30550:34;30530:18;;;30523:62;-1:-1:-1;;;30601:18:1;;;30594:42;30653:19;;81666:73:0;30444:234:1;81666:73:0;-1:-1:-1;81759:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;81759:24:0;;81570:221::o;81093:411::-;81174:13;81190:23;81205:7;81190:14;:23::i;:::-;81174:39;;81238:5;-1:-1:-1;;;;;81232:11:0;:2;-1:-1:-1;;;;;81232:11:0;;;81224:57;;;;-1:-1:-1;;;81224:57:0;;33655:2:1;81224:57:0;;;33637:21:1;33694:2;33674:18;;;33667:30;33733:34;33713:18;;;33706:62;-1:-1:-1;;;33784:18:1;;;33777:31;33825:19;;81224:57:0;33627:223:1;81224:57:0;15783:10;-1:-1:-1;;;;;81316:21:0;;;;:62;;-1:-1:-1;81341:37:0;81358:5;15783:10;82229:164;:::i;81341:37::-;81294:168;;;;-1:-1:-1;;;81294:168:0;;28519:2:1;81294:168:0;;;28501:21:1;28558:2;28538:18;;;28531:30;28597:34;28577:18;;;28570:62;28668:26;28648:18;;;28641:54;28712:19;;81294:168:0;28491:246:1;81294:168:0;81475:21;81484:2;81488:7;81475:8;:21::i;:::-;81093:411;;;:::o;109988:197::-;110064:13;110098:16;110106:7;110098;:16::i;:::-;110090:46;;;;-1:-1:-1;;;110090:46:0;;;;;;;:::i;:::-;110154:23;110169:7;110154:14;:23::i;:::-;110147:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109988:197;;;:::o;102972:136::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;103074:26:::1;103087:7;103096:3;;103074:12;:26::i;108460:263::-:0;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;108620:16:::1;108628:7;108620;:16::i;:::-;108612:46;;;;-1:-1:-1::0;;;108612:46:0::1;;;;;;;:::i;:::-;108669;108683:7;108692:9;;108703:11;;108669:13;:46::i;:::-;108460:263:::0;;;;;:::o;107557:195::-;107636:7;107664:16;107672:7;107664;:16::i;:::-;107656:46;;;;-1:-1:-1;;;107656:46:0;;;;;;;:::i;:::-;107720:24;107736:7;107720:15;:24::i;82460:339::-;82655:41;15783:10;82688:7;82655:18;:41::i;:::-;82647:103;;;;-1:-1:-1;;;82647:103:0;;;;;;;:::i;:::-;82763:28;82773:4;82779:2;82783:7;82763:9;:28::i;20950:139::-;21012:4;21048:5;-1:-1:-1;;;;;21037:16:0;:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;21037:7;-1:-1:-1;;;;;21037:16:0;;:43;;;-1:-1:-1;21057:23:0;:7;21074:5;21057:16;:23::i;105632:155::-;105730:7;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;47624:32:::1;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1::0;;;47616:86:0::1;;;;;;;:::i;:::-;105757:22:::2;105772:2;105757:22;;;;;;;;;;;::::0;:14:::2;:22::i;:::-;22809:1:::0;23761:22;;105750:29;105632:155;-1:-1:-1;;105632:155:0:o;20672:210::-;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;20751:23:::1;:7;20768:5:::0;20751:16:::1;:23::i;:::-;20747:128;;;20796:31;::::0;20816:10:::1;::::0;-1:-1:-1;;;;;20796:31:0;::::1;::::0;::::1;::::0;;;::::1;20842:21;:7;20857:5:::0;20842:14:::1;:21::i;:::-;;20672:210:::0;:::o;93434:256::-;93531:7;93567:23;93584:5;93567:16;:23::i;:::-;93559:5;:31;93551:87;;;;-1:-1:-1;;;93551:87:0;;22901:2:1;93551:87:0;;;22883:21:1;22940:2;22920:18;;;22913:30;22979:34;22959:18;;;22952:62;-1:-1:-1;;;23030:18:1;;;23023:41;23081:19;;93551:87:0;22873:233:1;93551:87:0;-1:-1:-1;;;;;;93656:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;93434:256::o;102578:118::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;102667:21:::1;102684:3;;102667:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;102667:16:0::1;::::0;-1:-1:-1;;;102667:21:0:i:1;100199:199::-:0;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;100323:9;47869:42:::1;:22;100323:9:::0;47869:31:::1;:42::i;:::-;47868:43;47860:90;;;;-1:-1:-1::0;;;47860:90:0::1;;;;;;;:::i;:::-;100345:45:::2;100364:9;100375:7;;100384:5;100345:18;:45::i;:::-;19968:1:::1;100199:199:::0;;;:::o;20050:267::-;20103:23;20162:16;:7;:14;:16::i;:::-;-1:-1:-1;;;;;20148:31:0;;;;;-1:-1:-1;;;20148:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20148:31:0;;20139:40;;20195:6;20190:96;20211:16;:7;:14;:16::i;:::-;20207:1;:20;20190:96;;;20261:13;:7;20272:1;20261:10;:13::i;:::-;20249:6;20256:1;20249:9;;;;;;-1:-1:-1;;;20249:9:0;;;;;;;;;-1:-1:-1;;;;;20249:25:0;;;:9;;;;;;;;;;;:25;20229:3;;;;:::i;:::-;;;;20190:96;;;;20050:267;:::o;108184:204::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;108319:61:::1;108350:4;108357:9;;108368:11;;108319:22;:61::i;121902:91::-:0;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;121973:12:::1;::::0;;-1:-1:-1;;121957:28:0;::::1;121973:12;::::0;;::::1;121972:13;121957:28;::::0;;121902:91::o;106539:327::-;106666:25;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;47624:32:::1;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1::0;;;47616:86:0::1;;;;;;;:::i;:::-;106729:4:::0;-1:-1:-1;;;;;106715:26:0;::::2;;;;-1:-1:-1::0;;;106715:26:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;106715:26:0::2;;106704:37;;106757:6;106752:107;106769:15:::0;;::::2;106752:107;;;106820:27;106835:2;106839:4;;106844:1;106839:7;;;;;-1:-1:-1::0;;;106839:7:0::2;;;;;;;;;;;;;;;;;;;;:::i;:::-;106820:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;106820:14:0::2;::::0;-1:-1:-1;;;106820:27:0:i:2;:::-;106806:8;106815:1;106806:11;;;;;;-1:-1:-1::0;;;106806:11:0::2;;;;;;;;;;::::0;;::::2;::::0;;;;;:41;106786:3;::::2;::::0;::::2;:::i;:::-;;;;106752:107;;;-1:-1:-1::0;22809:1:0;23761:22;;106539:327;;-1:-1:-1;;;106539:327:0:o;120605:142::-;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;120702:37:::1;::::0;120670:21:::1;::::0;120710:10:::1;::::0;120702:37;::::1;;;::::0;120670:21;;120655:12:::1;120702:37:::0;120655:12;120702:37;120670:21;120710:10;120702:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;101209:147:::0;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;101311:37:::1;101337:3;;101342:5;101311:25;:37::i;100475:233::-:0;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;100622:9;47869:42:::1;:22;100622:9:::0;47869:31:::1;:42::i;:::-;47868:43;47860:90;;;;-1:-1:-1::0;;;47860:90:0::1;;;;;;;:::i;:::-;100644:56:::2;100663:9;100674:7;;100683:16;100644:18;:56::i;82870:185::-:0;83008:39;83025:4;83031:2;83035:7;83008:39;;;;;;;;;;;;:16;:39::i;107822:290::-;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;107909:39:::1;107928:10;107940:7:::0;107909:18:::1;:39::i;:::-;107901:99;;;::::0;-1:-1:-1;;;107901:99:0;;23732:2:1;107901:99:0::1;::::0;::::1;23714:21:1::0;23771:2;23751:18;;;23744:30;23810:34;23790:18;;;23783:62;-1:-1:-1;;;23861:18:1;;;23854:45;23916:19;;107901:99:0::1;23704:237:1::0;107901:99:0::1;108011:13;108027:16;108035:7;108027;:16::i;:::-;108011:32;;108054:14;108060:7;108054:5;:14::i;:::-;108079:25;108089:5;108096:7;108079:9;:25::i;:::-;-1:-1:-1::0;;22809:1:0;23761:22;;107822:290::o;119650:859::-;119730:12;;;;119722:21;;;;;;118252:2;119785:14;:36;;119777:45;;;;;;120093:18;;120075:37;;118407:5;;120075:17;:37::i;:::-;120038:33;120056:14;120038:13;93854:10;:17;;93766:113;120038:13;:17;;:33::i;:::-;:74;;120030:83;;;;;;120190:9;120155:31;118171:17;120171:14;120155:15;:31::i;:::-;:44;;120147:53;;;;;;120255:6;120250:252;120271:14;120267:1;:18;120250:252;;;118407:5;120311:13;93854:10;:17;;93766:113;120311:13;:29;120307:184;;;120361:54;120371:10;120383:31;120400:11;;120412:1;120400:13;;;;:::i;:::-;120383:16;:31::i;:::-;120361:9;:54::i;:::-;-1:-1:-1;120451:11:0;;120439:36;;120464:10;17621:51:1;;-1:-1:-1;;;;;;;;;;;120439:36:0;17609:2:1;17594:18;120439:36:0;;;;;;;120307:184;120287:3;;;;:::i;:::-;;;;120250:252;;119002:587;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;119084:12:::1;::::0;::::1;;119076:21;;;::::0;::::1;;119160:1;119139:18;;:22;119131:31;;;::::0;::::1;;119220:23;::::0;;;:14:::1;:23;::::0;;;;;::::1;;119219:24;119211:55;;;::::0;-1:-1:-1;;;119211:55:0;;32898:2:1;119211:55:0::1;::::0;::::1;32880:21:1::0;32937:2;32917:18;;;32910:30;-1:-1:-1;;;32956:18:1;;;32949:48;33014:18;;119211:55:0::1;32870:168:1::0;119211:55:0::1;119285:42;::::0;-1:-1:-1;;;119285:42:0;;::::1;::::0;::::1;37115:25:1::0;;;119331:10:0::1;::::0;118061:42:::1;::::0;119285:33:::1;::::0;37088:18:1;;119285:42:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;119285:56:0::1;;119277:65;;;::::0;::::1;;119373:23;::::0;;;:14:::1;:23;::::0;;;;:30;;-1:-1:-1;;119373:30:0::1;119399:4;119373:30:::0;;::::1;::::0;;;119455:11:::1;::::0;119416:54:::1;::::0;119426:10:::1;::::0;119438:31:::1;::::0;119455:13:::1;::::0;:11;:13:::1;:::i;119416:54::-;-1:-1:-1::0;119498:11:0::1;::::0;119486:36:::1;::::0;119511:10:::1;17621:51:1::0;;-1:-1:-1;;;;;;;;;;;119486:36:0;17609:2:1;17594:18;119486:36:0::1;;;;;;;119556:18;::::0;:25:::1;::::0;119579:1:::1;119556:22;:25::i;:::-;119535:18;:46:::0;-1:-1:-1;22809:1:0;23761:22;;119002:587::o;93956:233::-;94031:7;94067:30;93854:10;:17;;93766:113;94067:30;94059:5;:38;94051:95;;;;-1:-1:-1;;;94051:95:0;;35590:2:1;94051:95:0;;;35572:21:1;35629:2;35609:18;;;35602:30;35668:34;35648:18;;;35641:62;-1:-1:-1;;;35719:18:1;;;35712:42;35771:19;;94051:95:0;35562:234:1;94051:95:0;94164:10;94175:5;94164:17;;;;;;-1:-1:-1;;;94164:17:0;;;;;;;;;;;;;;;;;94157:24;;93956:233;;;:::o;102161:342::-;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;102297:15;;:30;::::1;102289:71;;;::::0;-1:-1:-1;;;102289:71:0;;27251:2:1;102289:71:0::1;::::0;::::1;27233:21:1::0;27290:2;27270:18;;;27263:30;27329;27309:18;;;27302:58;27377:18;;102289:71:0::1;27223:178:1::0;102289:71:0::1;102376:6;102371:125;102392:8;:15;102388:1;:19;102371:125;;;102429:43;102451:8;102460:1;102451:11;;;;;;-1:-1:-1::0;;;102451:11:0::1;;;;;;;;;;;;;;;102464:4;;102469:1;102464:7;;;;;-1:-1:-1::0;;;102464:7:0::1;;;;;;;;;;;;;;;;;;;;:::i;:::-;102429:21;:43::i;:::-;102409:3:::0;::::1;::::0;::::1;:::i;:::-;;;;102371:125;;79705:239:::0;79777:7;79813:16;;;:7;:16;;;;;;-1:-1:-1;;;;;79813:16:0;79848:19;79840:73;;;;-1:-1:-1;;;79840:73:0;;29701:2:1;79840:73:0;;;29683:21:1;29740:2;29720:18;;;29713:30;29779:34;29759:18;;;29752:62;-1:-1:-1;;;29830:18:1;;;29823:39;29879:19;;79840:73:0;29673:231:1;101693:150:0;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;101800:35:::1;101828:6;;101800:27;:35::i;20390:210::-:0;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;20471:23:::1;:7;20488:5:::0;20471:16:::1;:23::i;:::-;20466:127;;20516:32;::::0;20537:10:::1;::::0;-1:-1:-1;;;;;20516:32:0;::::1;::::0;::::1;::::0;;;::::1;20563:18;:7;20575:5:::0;20563:11:::1;:18::i;79435:208::-:0;79507:7;-1:-1:-1;;;;;79535:19:0;;79527:74;;;;-1:-1:-1;;;79527:74:0;;29290:2:1;79527:74:0;;;29272:21:1;29329:2;29309:18;;;29302:30;29368:34;29348:18;;;29341:62;-1:-1:-1;;;29419:18:1;;;29412:40;29469:19;;79527:74:0;29262:232:1;79527:74:0;-1:-1:-1;;;;;;79619:16:0;;;;;:9;:16;;;;;;;79435:208::o;17572:94::-;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;17637:21:::1;17655:1;17637:9;:21::i;:::-;17572:94::o:0;103813:141::-;103902:7;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;19874:10:::1;19863:7;16967::::0;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7:::1;-1:-1:-1::0;;;;;19863:21:0::1;;:53;;;-1:-1:-1::0;19888:28:0::1;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1::0;;;19855:102:0::1;;;;;;;:::i;:::-;103929:17:::2;103939:2;103929:17;;;;;;;;;;;::::0;:9:::2;:17::i;104028:163::-:0;104138:7;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;19874:10:::1;19863:7;16967::::0;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7:::1;-1:-1:-1::0;;;;;19863:21:0::1;;:53;;;-1:-1:-1::0;19888:28:0::1;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1::0;;;19855:102:0::1;;;;;;;:::i;:::-;104165:18:::2;104175:2;104179:3;;104165:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;104165:9:0::2;::::0;-1:-1:-1;;;104165:18:0:i:2;:::-;22809:1:::0;23761:22;;104158:25;104028:163;-1:-1:-1;;;;104028:163:0:o;104663:339::-;104781:25;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;19874:10:::1;19863:7;16967::::0;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7:::1;-1:-1:-1::0;;;;;19863:21:0::1;;:53;;;-1:-1:-1::0;19888:28:0::1;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1::0;;;19855:102:0::1;;;;;;;:::i;:::-;104844:4:::0;-1:-1:-1;;;;;104830:26:0;::::2;;;;-1:-1:-1::0;;;104830:26:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;104830:26:0::2;;104819:37;;104872:6;104867:102;104884:15:::0;;::::2;104867:102;;;104935:22;104945:2;104949:4;;104954:1;104949:7;;;;;-1:-1:-1::0;;;104949:7:0::2;;;;;;;;;;;;;;;;;;;;:::i;:::-;104935:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;104935:9:0::2;::::0;-1:-1:-1;;;104935:22:0:i:2;:::-;104921:8;104930:1;104921:11;;;;;;-1:-1:-1::0;;;104921:11:0::2;;;;;;;;;;::::0;;::::2;::::0;;;;;:36;104901:3;::::2;::::0;::::2;:::i;:::-;;;;104867:102;;101440:167:::0;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;101558:41:::1;101584:3;;101589:9;101558:25;:41::i;48046:299::-:0;48103:27;48170:20;:11;:18;:20::i;:::-;-1:-1:-1;;;;;48156:35:0;;;;;-1:-1:-1;;;48156:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48156:35:0;;48143:48;;48207:6;48202:108;48223:20;:11;:18;:20::i;:::-;48219:1;:24;48202:108;;;48281:17;:11;48296:1;48281:14;:17::i;:::-;48265:10;48276:1;48265:13;;;;;;-1:-1:-1;;;48265:13:0;;;;;;;;;-1:-1:-1;;;;;48265:33:0;;;:13;;;;;;;;;;;:33;48245:3;;;;:::i;:::-;;;;48202:108;;80180:104;80236:13;80269:7;80262:14;;;;;:::i;102773:128::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;102867:26:::1;102886:6;;102867:18;:26::i;81863:295::-:0;-1:-1:-1;;;;;81966:24:0;;15783:10;81966:24;;81958:62;;;;-1:-1:-1;;;81958:62:0;;26897:2:1;81958:62:0;;;26879:21:1;26936:2;26916:18;;;26909:30;26975:27;26955:18;;;26948:55;27020:18;;81958:62:0;26869:175:1;81958:62:0;15783:10;82033:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;82033:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;82033:53:0;;;;;;;;;;82102:48;;22216:41:1;;;82033:42:0;;15783:10;82102:48;;22189:18:1;82102:48:0;;;;;;;81863:295;;:::o;103179:320::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;103302:15;;:30;::::1;103294:71;;;::::0;-1:-1:-1;;;103294:71:0;;27251:2:1;103294:71:0::1;::::0;::::1;27233:21:1::0;27290:2;27270:18;;;27263:30;27329;27309:18;;;27302:58;27377:18;;103294:71:0::1;27223:178:1::0;103294:71:0::1;103381:6;103376:116;103397:8;:15;103393:1;:19;103376:116;;;103434:34;103447:8;103456:1;103447:11;;;;;;-1:-1:-1::0;;;103447:11:0::1;;;;;;;;;;;;;;;103460:4;;103465:1;103460:7;;;;;-1:-1:-1::0;;;103460:7:0::1;;;;;;;;;;;;;;;;;;;;:::i;:::-;103434:12;:34::i;:::-;103414:3:::0;::::1;::::0;::::1;:::i;:::-;;;;103376:116;;60390:533:::0;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;60497:7:::1;60496:8;:113;;;;60508:101;60540:10;-1:-1:-1::0;;;60508:31:0::1;:101::i;:::-;60488:215;;;::::0;-1:-1:-1;;;60488:215:0;;28021:2:1;60488:215:0::1;::::0;::::1;28003:21:1::0;28060:2;28040:18;;;28033:30;28099:34;28079:18;;;28072:62;28170:34;28150:18;;;28143:62;28242:27;28221:19;;;28214:56;28287:19;;60488:215:0::1;27993:319:1::0;60488:215:0::1;60745:10;60718:38;::::0;;;:26:::1;:38;::::0;;;;;::::1;;:49;;::::0;::::1;;;60714:202;;60811:10;60784:38;::::0;;;:26:::1;:38;::::0;;;;;;;;:48;;-1:-1:-1;;60784:48:0::1;::::0;::::1;;::::0;;::::1;::::0;;;60852:52;;22216:41:1;;;60852:52:0::1;::::0;22189:18:1;60852:52:0::1;;;;;;;60390:533:::0;:::o;104270:314::-;104378:25;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;19874:10:::1;19863:7;16967::::0;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7:::1;-1:-1:-1::0;;;;;19863:21:0::1;;:53;;;-1:-1:-1::0;19888:28:0::1;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1::0;;;19855:102:0::1;;;;;;;:::i;:::-;104441:5:::2;104427:20;;-1:-1:-1::0;;;;;104427:20:0::2;;;;;-1:-1:-1::0;;;104427:20:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;104427:20:0::2;;104416:31;;104463:8;104458:93;104481:5;104477:9;;:1;:9;;;104458:93;;;104522:17;104532:2;104522:17;;;;;;;;;;;::::0;:9:::2;:17::i;:::-;104508:8;104517:1;104508:11;;;;;;;;-1:-1:-1::0;;;104508:11:0::2;;;;;;;;;;::::0;;::::2;::::0;;;;;:31;104488:3;::::2;::::0;::::2;:::i;:::-;;;;104458:93;;;;22809:1:::0;23761:22;;104270:314;;-1:-1:-1;;104270:314:0:o;108804:228::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;108967:57:::1;108990:9;109001;;109012:11;;108967:22;:57::i;83126:328::-:0;83301:41;15783:10;83334:7;83301:18;:41::i;:::-;83293:103;;;;-1:-1:-1;;;83293:103:0;;;;;;;:::i;:::-;83407:39;83421:4;83427:2;83431:7;83440:5;83407:13;:39::i;109698:221::-;109781:24;109826:16;109834:7;109826;:16::i;:::-;109818:46;;;;-1:-1:-1;;;109818:46:0;;;;;;;:::i;:::-;109882:29;109903:7;109882:20;:29::i;:::-;109875:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109875:36:0;;;;;;;;;;;;;;;;;;;;;;109698:221;;;:::o;109104:228::-;109183:24;109209:16;109246;109254:7;109246;:16::i;:::-;109238:46;;;;-1:-1:-1;;;109238:46:0;;;;;;;:::i;:::-;109302:22;109316:7;109302:13;:22::i;:::-;109295:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109295:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109104:228;;;:::o;110260:255::-;110369:7;110378;110387:12;110420:16;110428:7;110420;:16::i;:::-;110412:46;;;;-1:-1:-1;;;110412:46:0;;;;;;;:::i;:::-;110476:31;110492:7;110501:5;110476:15;:31::i;:::-;110469:38;;;;;;110260:255;;;;;;;;:::o;110587:189::-;110660:13;110694:16;110702:7;110694;:16::i;:::-;110686:46;;;;-1:-1:-1;;;110686:46:0;;;;;;;:::i;:::-;110750:18;110760:7;110750:9;:18::i;100789:130::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;100880:31:::1;100901:9;100880:20;:31::i;121277:578::-:0;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;118333:10:::1;121361:15;:39;121353:48;;;::::0;::::1;;121444:12;::::0;::::1;;121436:21;;;::::0;::::1;;121520:1;121499:18;;:22;121491:31;;;::::0;::::1;;121580:23;::::0;;;:14:::1;:23;::::0;;;;;::::1;;121579:24;121571:55;;;::::0;-1:-1:-1;;;121571:55:0;;32898:2:1;121571:55:0::1;::::0;::::1;32880:21:1::0;32937:2;32917:18;;;32910:30;-1:-1:-1;;;32956:18:1;;;32949:48;33014:18;;121571:55:0::1;32870:168:1::0;121571:55:0::1;121639:23;::::0;;;:14:::1;:23;::::0;;;;:30;;-1:-1:-1;;121639:30:0::1;121665:4;121639:30:::0;;::::1;::::0;;;121721:11:::1;::::0;121682:54:::1;::::0;121692:10:::1;::::0;121704:31:::1;::::0;121721:13:::1;::::0;:11;:13:::1;:::i;121682:54::-;-1:-1:-1::0;121764:11:0::1;::::0;121752:36:::1;::::0;121777:10:::1;17621:51:1::0;;-1:-1:-1;;;;;;;;;;;121752:36:0;17609:2:1;17594:18;121752:36:0::1;;;;;;;121822:18;::::0;:25:::1;::::0;121845:1:::1;121822:22;:25::i;:::-;121801:18;:46:::0;-1:-1:-1;121277:578:0:o;106127:328::-;106244:25;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;47624:32:::1;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1::0;;;47616:86:0::1;;;;;;;:::i;:::-;106307:5:::2;106293:20;;-1:-1:-1::0;;;;;106293:20:0::2;;;;;-1:-1:-1::0;;;106293:20:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;106293:20:0::2;;106282:31;;106329:8;106324:98;106347:5;106343:9;;:1;:9;;;106324:98;;;106388:22;106403:2;106388:22;;;;;;;;;;;::::0;:14:::2;:22::i;:::-;106374:8;106383:1;106374:11;;;;;;;;-1:-1:-1::0;;;106374:11:0::2;;;;;;;;;;::::0;;::::2;::::0;;;;;:36;106354:3;::::2;::::0;::::2;:::i;:::-;;;;106324:98;;101923:158:::0;47624:32;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1;;;47616:86:0;;;;;;;:::i;:::-;102038:35:::1;102060:7;102069:3;;102038:21;:35::i;117898:112::-:0;;;;;;;;;;;;;;;;;;;:::o;103577:162::-;19874:10;19863:7;16967;16994:6;-1:-1:-1;;;;;16994:6:0;;16921:87;19863:7;-1:-1:-1;;;;;19863:21:0;;:53;;;-1:-1:-1;19888:28:0;:7;19905:10;19888:16;:28::i;:::-;19855:102;;;;-1:-1:-1;;;19855:102:0;;;;;;;:::i;:::-;103688:43:::1;103708:9;103719:11;103688:19;:43::i;17821:192::-:0;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;17910:22:0;::::1;17902:73;;;::::0;-1:-1:-1;;;17902:73:0;;24148:2:1;17902:73:0::1;::::0;::::1;24130:21:1::0;24187:2;24167:18;;;24160:30;24226:34;24206:18;;;24199:62;-1:-1:-1;;;24277:18:1;;;24270:36;24323:19;;17902:73:0::1;24120:228:1::0;17902:73:0::1;17986:19;17996:8;17986:9;:19::i;105866:177::-:0;105985:7;22853:1;23449:7;;:19;;23441:63;;;;-1:-1:-1;;;23441:63:0;;;;;;;:::i;:::-;22853:1;23582:7;:18;47624:32:::1;:11;47645:10;47624:20;:32::i;:::-;47616:86;;;;-1:-1:-1::0;;;47616:86:0::1;;;;;;;:::i;:::-;106012:23:::2;106027:2;106031:3;;106012:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;106012:14:0::2;::::0;-1:-1:-1;;;106012:23:0:i:2;120808:404::-:0;16967:7;16994:6;-1:-1:-1;;;;;16994:6:0;15783:10;17141:23;17133:68;;;;-1:-1:-1;;;17133:68:0;;;;;;;:::i;:::-;120906:17:::1;;120896:6;:27;;120888:36;;;::::0;::::1;;120962:6;120979:166;120995:6;120991:1;:10;120979:166;;;121023:54;121033:10;121045:31;121062:11;;121074:1;121062:13;;;;:::i;121023:54::-;-1:-1:-1::0;121109:11:0::1;::::0;121097:36:::1;::::0;121122:10:::1;17621:51:1::0;;-1:-1:-1;;;;;;;;;;;121097:36:0;17609:2:1;17594:18;121097:36:0::1;;;;;;;121003:3:::0;::::1;::::0;::::1;:::i;:::-;;;;120979:166;;;121175:17;::::0;:29:::1;::::0;121197:6;121175:21:::1;:29::i;:::-;121155:17;:49:::0;-1:-1:-1;;120808:404:0:o;60073:230::-;60180:4;-1:-1:-1;;;;;;60204:51:0;;-1:-1:-1;;;60204:51:0;;:91;;;60259:36;60283:11;60259:23;:36::i;79066:305::-;79168:4;-1:-1:-1;;;;;;79205:40:0;;-1:-1:-1;;;79205:40:0;;:105;;-1:-1:-1;;;;;;;79262:48:0;;-1:-1:-1;;;79262:48:0;79205:158;;;;79327:36;79351:11;19488:233;19590:4;-1:-1:-1;;;;;;19614:46:0;;-1:-1:-1;;;19614:46:0;;:99;;-1:-1:-1;;;;;;;;;;5465:40:0;;;19677:36;5356:157;12567:167;-1:-1:-1;;;;;12701:23:0;;12647:4;9440:19;;;:12;;;:19;;;;;;:24;;12671:55;12664:62;12567:167;-1:-1:-1;;;12567:167:0:o;49242:497::-;-1:-1:-1;;;;;49317:26:0;;49338:4;49317:26;;49309:77;;;;-1:-1:-1;;;49309:77:0;;25681:2:1;49309:77:0;;;25663:21:1;25720:2;25700:18;;;25693:30;25759:34;25739:18;;;25732:62;-1:-1:-1;;;25810:18:1;;;25803:36;25856:19;;49309:77:0;25653:228:1;49309:77:0;49400:31;:11;49421:9;49400:20;:31::i;:::-;49396:154;;;49452:44;;49485:10;;-1:-1:-1;;;;;49452:44:0;;;;;;;;49510:29;:11;49529:9;49510:18;:29::i;:::-;;49396:154;49564:42;:22;49596:9;49564:31;:42::i;:::-;49559:173;;49627:43;;49659:10;;-1:-1:-1;;;;;49627:43:0;;;;;;;;49684:37;:22;49711:9;49684:26;:37::i;84964:127::-;85029:4;85053:16;;;:7;:16;;;;;;-1:-1:-1;;;;;85053:16:0;:30;;;84964:127::o;88946:174::-;89021:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;89021:29:0;-1:-1:-1;;;;;89021:29:0;;;;;;;;:24;;89075:23;89021:24;89075:14;:23::i;:::-;-1:-1:-1;;;;;89066:46:0;;;;;;;;;;;88946:174;;:::o;53534:414::-;53598:17;53632:25;;;:16;:25;;;;;:32;:36;53628:252;;-1:-1:-1;53692:25:0;;;;:16;:25;;;;;;53534:414::o;53628:252::-;53796:1;53760:25;;;:16;:25;;;;;;;;;-1:-1:-1;;;;;53760:25:0;53739:47;;:20;:47;;;;;:54;:58;53735:145;;-1:-1:-1;53821:47:0;53842:25;;;:16;:25;;;;;;;;;-1:-1:-1;;;;;53842:25:0;53821:47;;:20;:47;;;;;;53534:414::o;53735:145::-;-1:-1:-1;;53926:4:0;53897:35;;;;:20;:35;;;;;;53534:414::o;51003:205::-;51091:25;;;;:16;:25;;;;;;-1:-1:-1;;;;;51091:25:0;51128:4;51091:42;51083:81;;;;-1:-1:-1;;;51083:81:0;;34475:2:1;51083:81:0;;;34457:21:1;34514:2;34494:18;;;34487:30;34553:28;34533:18;;;34526:56;34599:18;;51083:81:0;34447:176:1;51083:81:0;51175:19;;;;:10;:19;;;;;:25;;51197:3;;51175:25;:::i;54526:620::-;54664:38;;;54656:77;;;;-1:-1:-1;;;54656:77:0;;35235:2:1;54656:77:0;;;35217:21:1;35274:2;35254:18;;;35247:30;35313:28;35293:18;;;35286:56;35359:18;;54656:77:0;35207:176:1;54656:77:0;54744:24;;54779:107;54796:22;;;54779:107;;;54860:11;;54872:1;54860:14;;;;;-1:-1:-1;;;54860:14:0;;;;;;;;;;;;;;;54840:34;;;;;:::i;:::-;;-1:-1:-1;54820:3:0;;;;:::i;:::-;;;;54779:107;;;;54923:5;54904:16;:24;54896:73;;;;-1:-1:-1;;;54896:73:0;;;;;;;:::i;:::-;54980:31;;;;:22;:31;;;;;:43;;55014:9;;54980:43;:::i;:::-;-1:-1:-1;55034:25:0;;;;:16;:25;;;;;:39;;55062:11;;55034:39;:::i;:::-;;55106:7;55089:49;55115:9;;55126:11;;55089:49;;;;;;;;;:::i;:::-;;;;;;;;54526:620;;;;;;:::o;52299:357::-;52364:17;52406:25;;;:16;:25;;;;;;-1:-1:-1;;;;;52406:25:0;52473:4;52452:26;;;52444:74;;;;-1:-1:-1;;;52444:74:0;;26088:2:1;52444:74:0;;;26070:21:1;26127:2;26107:18;;;26100:30;26166:34;26146:18;;;26139:62;-1:-1:-1;;;26217:18:1;;;26210:33;26260:19;;52444:74:0;26060:225:1;52444:74:0;52538:42;:22;52570:9;52538:31;:42::i;:::-;52537:43;52529:90;;;;-1:-1:-1;;;52529:90:0;;;;;;;:::i;:::-;52299:357;;;:::o;85258:348::-;85351:4;85376:16;85384:7;85376;:16::i;:::-;85368:73;;;;-1:-1:-1;;;85368:73:0;;27608:2:1;85368:73:0;;;27590:21:1;27647:2;27627:18;;;27620:30;27686:34;27666:18;;;27659:62;-1:-1:-1;;;27737:18:1;;;27730:42;27789:19;;85368:73:0;27580:234:1;85368:73:0;85452:13;85468:23;85483:7;85468:14;:23::i;:::-;85452:39;;85521:5;-1:-1:-1;;;;;85510:16:0;:7;-1:-1:-1;;;;;85510:16:0;;:51;;;;85554:7;-1:-1:-1;;;;;85530:31:0;:20;85542:7;85530:11;:20::i;:::-;-1:-1:-1;;;;;85530:31:0;;85510:51;:87;;;-1:-1:-1;;;;;;82350:25:0;;;82326:4;82350:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;85565:32;85502:96;85258:348;-1:-1:-1;;;;85258:348:0:o;88250:578::-;88409:4;-1:-1:-1;;;;;88382:31:0;:23;88397:7;88382:14;:23::i;:::-;-1:-1:-1;;;;;88382:31:0;;88374:85;;;;-1:-1:-1;;;88374:85:0;;32488:2:1;88374:85:0;;;32470:21:1;32527:2;32507:18;;;32500:30;32566:34;32546:18;;;32539:62;-1:-1:-1;;;32617:18:1;;;32610:39;32666:19;;88374:85:0;32460:231:1;88374:85:0;-1:-1:-1;;;;;88478:16:0;;88470:65;;;;-1:-1:-1;;;88470:65:0;;26492:2:1;88470:65:0;;;26474:21:1;26531:2;26511:18;;;26504:30;26570:34;26550:18;;;26543:62;-1:-1:-1;;;26621:18:1;;;26614:34;26665:19;;88470:65:0;26464:226:1;88470:65:0;88548:39;88569:4;88575:2;88579:7;88548:20;:39::i;:::-;88652:29;88669:1;88673:7;88652:8;:29::i;:::-;-1:-1:-1;;;;;88694:15:0;;;;;;:9;:15;;;;;:20;;88713:1;;88694:15;:20;;88713:1;;88694:20;:::i;:::-;;;;-1:-1:-1;;;;;;;88725:13:0;;;;;;:9;:13;;;;;:18;;88742:1;;88725:13;:18;;88742:1;;88725:18;:::i;:::-;;;;-1:-1:-1;;88754:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;88754:21:0;-1:-1:-1;;;;;88754:21:0;;;;;;;;;88793:27;;88754:16;;88793:27;;;;;;;88250:578;;;:::o;106934:543::-;107042:11;:13;;107014:15;;;107042:13;;;:::i;:::-;;;;;;107076:11;;107066:21;;107100:34;107122:2;107126:7;107100:21;:34::i;:::-;107201:25;;;;:16;:25;;;;;:38;;-1:-1:-1;;;;;;107201:38:0;107229:10;107201:38;;;107252:22;107262:2;107218:7;107252:9;:22::i;:::-;107291:17;;:21;107287:79;;107329:19;;;;:10;:19;;;;;;;;:25;;;;;;;;:::i;:::-;;107287:79;107413:31;20672:210;12323:158;12396:4;12420:53;12428:3;-1:-1:-1;;;;;12448:23:0;;12420:7;:53::i;50595:111::-;50686:4;50660:32;;;;:17;:32;;;;;;;;:38;;;;;;;;:::i;48406:482::-;-1:-1:-1;;;;;48529:20:0;;31701;48521:72;;;;-1:-1:-1;;;48521:72:0;;30885:2:1;48521:72:0;;;30867:21:1;30924:2;30904:18;;;30897:30;30963:34;30943:18;;;30936:62;-1:-1:-1;;;31014:18:1;;;31007:35;31059:19;;48521:72:0;30857:227:1;48521:72:0;48609:31;:11;48630:9;48609:20;:31::i;:::-;48604:277;;-1:-1:-1;;;;;48657:28:0;;;;;;:17;:28;;;;;:38;;48688:7;;48657:38;:::i;:::-;-1:-1:-1;;;;;;48710:37:0;;;;;;:26;:37;;;;;;:56;;-1:-1:-1;;48710:56:0;;;;;;;48786:42;48817:10;;48710:37;48786:42;;;48843:26;:11;48859:9;48843:15;:26::i;12820:117::-;12883:7;12910:19;12918:3;9641:18;;9558:109;13291:158;13365:7;13416:22;13420:3;13432:5;13416:3;:22::i;55225:797::-;55374:38;;;55366:77;;;;-1:-1:-1;;;55366:77:0;;35235:2:1;55366:77:0;;;35217:21:1;35274:2;35254:18;;;35247:30;35313:28;35293:18;;;35286:56;35359:18;;55366:77:0;35207:176:1;55366:77:0;55454:24;;55489:107;55506:22;;;55489:107;;;55570:11;;55582:1;55570:14;;;;;-1:-1:-1;;;55570:14:0;;;;;;;;;;;;;;;55550:34;;;;;:::i;:::-;;-1:-1:-1;55530:3:0;;;;:::i;:::-;;;;55489:107;;;;55633:5;55614:16;:24;55606:73;;;;-1:-1:-1;;;55606:73:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;55690:37:0;;;;;;:26;:37;;;;;:49;;55730:9;;55690:49;:::i;:::-;-1:-1:-1;;;;;;55750:31:0;;;;;;:20;:31;;;;;:45;;55784:11;;55750:45;:::i;:::-;-1:-1:-1;;;;;;55810:26:0;;55831:4;55810:26;55806:209;;;55858:47;55882:9;;55893:11;;55858:47;;;;;;;;;:::i;:::-;;;;;;;;55806:209;;;55969:9;-1:-1:-1;;;;;55943:60:0;;55980:9;;55991:11;;55943:60;;;;;;;;;:::i;55806:209::-;55225:797;;;;;;:::o;49814:196::-;49924:10;49906:29;;;;:17;:29;;;;;:35;;49938:3;;49906:35;:::i;:::-;-1:-1:-1;49979:10:0;49952:38;;;;:26;:38;;;;;:50;;-1:-1:-1;;49952:50:0;;;;;;;;;;-1:-1:-1;;49814:196:0:o;87553:360::-;87613:13;87629:23;87644:7;87629:14;:23::i;:::-;87613:39;;87665:48;87686:5;87701:1;87705:7;87665:20;:48::i;:::-;87754:29;87771:1;87775:7;87754:8;:29::i;:::-;-1:-1:-1;;;;;87796:16:0;;;;;;:9;:16;;;;;:21;;87816:1;;87796:16;:21;;87816:1;;87796:21;:::i;:::-;;;;-1:-1:-1;;87835:16:0;;;;:7;:16;;;;;;87828:23;;-1:-1:-1;;;;;;87828:23:0;;;87869:36;87843:7;;87835:16;-1:-1:-1;;;;;87869:36:0;;;;;87835:16;;87869:36;87553:360;;:::o;62240:689::-;62379:25;;;;:16;:25;;;;;;-1:-1:-1;;;;;62379:25:0;62416:4;62379:42;62375:302;;62473:25;;;;:16;:25;;;;;;62441:109;;-1:-1:-1;;;;;62473:25:0;-1:-1:-1;;;62441:31:0;:109::i;:::-;62437:229;;;62602:25;;;;:16;:25;;;;;;;;62570:81;;-1:-1:-1;;;62570:81:0;;-1:-1:-1;;;;;18748:32:1;;;62570:81:0;;;18730:51:1;18797:18;;;18790:34;;;62602:25:0;;;;62570:65;;18703:18:1;;62570:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62437:229;62733:19;;;;:10;:19;;;;;62727:33;;;;;:::i;:::-;:38;;-1:-1:-1;62723:97:0;;62789:19;;;;:10;:19;;;;;62782:26;;;:::i;:::-;62892:25;;;;:16;:25;;;;;62885:32;;-1:-1:-1;;;;;;62885:32:0;;;-1:-1:-1;62240:689:0:o;113970:98::-;114028:7;114055:5;114059:1;114055;:5;:::i;113589:98::-;113647:7;113674:5;113678:1;113674;:5;:::i;114327:98::-;114385:7;114412:5;114416:1;114412;:5;:::i;24117:723::-;24173:13;24394:10;24390:53;;-1:-1:-1;;24421:10:0;;;;;;;;;;;;-1:-1:-1;;;24421:10:0;;;;;24117:723::o;24390:53::-;24468:5;24453:12;24509:78;24516:9;;24509:78;;24542:8;;;;:::i;:::-;;-1:-1:-1;24565:10:0;;-1:-1:-1;24573:2:0;24565:10;;:::i;:::-;;;24509:78;;;24597:19;24629:6;-1:-1:-1;;;;;24619:17:0;;;;;-1:-1:-1;;;24619:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24619:17:0;;24597:39;;24647:154;24654:10;;24647:154;;24681:11;24691:1;24681:11;;:::i;:::-;;-1:-1:-1;24750:10:0;24758:2;24750:5;:10;:::i;:::-;24737:24;;:2;:24;:::i;:::-;24724:39;;24707:6;24714;24707:14;;;;;;-1:-1:-1;;;24707:14:0;;;;;;;;;;;;:56;-1:-1:-1;;;;;24707:56:0;;;;;;;;-1:-1:-1;24778:11:0;24787:2;24778:11;;:::i;:::-;;;24647:154;;105070:481;105173:11;:13;;105145:15;;;105173:13;;;:::i;:::-;;;;-1:-1:-1;;105207:11:0;;105285:25;;;;:16;:25;;;;;:41;;-1:-1:-1;;;;;;105285:41:0;105321:4;105285:41;;;105207:11;-1:-1:-1;105339:22:0;105349:2;105207:11;105339:9;:22::i;50297:211::-;50394:25;;;;:16;:25;;;;;;-1:-1:-1;;;;;50394:25:0;50423:10;50394:39;50386:78;;;;-1:-1:-1;;;50386:78:0;;34475:2:1;50386:78:0;;;34457:21:1;34514:2;34494:18;;;34487:30;34553:28;34533:18;;;34526:56;34599:18;;50386:78:0;34447:176:1;50087:129:0;50188:10;50168:31;;;;:19;:31;;;;;:40;;50202:6;;50168:40;:::i;11995:152::-;12065:4;12089:50;12094:3;-1:-1:-1;;;;;12114:23:0;;12089:4;:50::i;18021:173::-;18077:16;18096:6;;-1:-1:-1;;;;;18113:17:0;;;-1:-1:-1;;;;;;18113:17:0;;;;;;18146:40;;18096:6;;;;;;;18146:40;;18077:16;18146:40;18021:173;;:::o;50795:123::-;50895:4;50867:34;;;;:19;:34;;;;;:43;;50904:6;;50867:43;:::i;27179:277::-;27266:4;27375:23;27390:7;27375:14;:23::i;:::-;:73;;;;;27402:46;27427:7;27436:11;27402:24;:46::i;84336:315::-;84493:28;84503:4;84509:2;84513:7;84493:9;:28::i;:::-;84540:48;84563:4;84569:2;84573:7;84582:5;84540:22;:48::i;:::-;84532:111;;;;-1:-1:-1;;;84532:111:0;;;;;;;:::i;52995:458::-;53065:25;53107:31;;;:22;:31;;;;;:38;:42;53103:276;;-1:-1:-1;53173:31:0;;;;:22;:31;;;;;;52995:458::o;53103:276::-;53289:1;53253:25;;;:16;:25;;;;;;;;;-1:-1:-1;;;;;53253:25:0;53226:53;;:26;:53;;;;;:60;:64;53222:157;;-1:-1:-1;53314:53:0;53341:25;;;:16;:25;;;;;;;;;-1:-1:-1;;;;;53341:25:0;53314:53;;:26;:53;;;;;;52995:458::o;53222:157::-;-1:-1:-1;;53431:4:0;53396:41;;;;:26;:41;;;;;;52995:458::o;52726:191::-;52789:25;52816:17;52854:29;52875:7;52854:20;:29::i;:::-;52885:23;52900:7;52885:14;:23::i;:::-;52846:63;;;;52726:191;;;:::o;53956:510::-;54036:16;54054:14;54070:17;54099:35;54137:29;54158:7;54137:20;:29::i;:::-;54185:16;;54099:67;;-1:-1:-1;54205:1:0;-1:-1:-1;54185:21:0;54177:98;;;;;-1:-1:-1;;;54177:98:0;;32055:2:1;54177:98:0;;;32037:21:1;32074:18;;;32067:30;;;;32133:34;32113:18;;;32106:62;32204:34;32184:18;;;32177:62;32256:19;;54177:98:0;32027:254:1;54177:98:0;54300:16;;54296:85;;54354:4;54361:1;54338:31;;;;;;;54296:85;54399:9;54409:1;54399:12;;;;;;-1:-1:-1;;;54399:12:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54399:12:0;54446:5;54440;54413:23;54428:7;54413:14;:23::i;:::-;54437:1;54413:26;;;;;;-1:-1:-1;;;54413:26:0;;;;;;;;;;;;;;;;;:32;;;;:::i;:::-;:38;;;;:::i;:::-;54391:67;;;;;53956:510;;;;;;:::o;51270:975::-;51355:17;51375:25;;;:16;:25;;;;;;51329:13;;-1:-1:-1;;;;;51375:25:0;51420:42;:22;51375:25;51420:31;:42::i;:::-;51419:43;51411:90;;;;-1:-1:-1;;;51411:90:0;;;;;;;:::i;:::-;51524:19;;;;:10;:19;;;;;51518:33;;;;;:::i;:::-;:38;;-1:-1:-1;51514:284:0;;-1:-1:-1;;;;;51583:30:0;;;;;;:19;:30;;;;;51577:44;;;;;:::i;:::-;:49;;-1:-1:-1;51573:173:0;;-1:-1:-1;;;;;51678:30:0;;;;;;:19;:30;;;;;;;;51709:19;;;:10;:19;;;;;;51661:68;;;;51678:30;51661:68;;:::i;:::-;;;;;;;;;;;;;51647:83;;;51270:975;;;:::o;51573:173::-;51767:19;;;;:10;:19;;;;;51760:26;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51270:975;;;:::o;51514:284::-;51814:87;51846:9;-1:-1:-1;;;51814:31:0;:87::i;:::-;51810:196;;;51925:69;;-1:-1:-1;;;51925:69:0;;51979:4;51925:69;;;18730:51:1;18797:18;;;18790:34;;;-1:-1:-1;;;;;51925:45:0;;;;;18703:18:1;;51925:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;51925:69:0;;;;;;;;;;;;:::i;51810:196::-;-1:-1:-1;;;;;52023:37:0;;;;;;:26;:37;;;;;;;;52018:220;;-1:-1:-1;;;;;52108:28:0;;;;;;:17;:28;;;;;52138:18;:7;:16;:18::i;:::-;52091:66;;;;;;;;;:::i;52018:220::-;-1:-1:-1;;;;;52198:28:0;;;;;;:17;:28;;;;;52191:35;;;;;:::i;52018:220::-;51270:975;;;;:::o;48951:229::-;49023:31;:11;49044:9;49023:20;:31::i;:::-;49019:154;;;49075:44;;49108:10;;-1:-1:-1;;;;;49075:44:0;;;;;;;;49133:29;:11;49152:9;49133:18;:29::i;61000:567::-;61097:31;:11;61118:9;61097:20;:31::i;:::-;61089:74;;;;-1:-1:-1;;;61089:74:0;;24912:2:1;61089:74:0;;;24894:21:1;24951:2;24931:18;;;24924:30;24990:32;24970:18;;;24963:60;25040:18;;61089:74:0;24884:180:1;61089:74:0;-1:-1:-1;;;;;61182:27:0;;;;:124;;;61213:93;61245:11;-1:-1:-1;;;61213:31:0;:93::i;:::-;61174:171;;;;-1:-1:-1;;;61174:171:0;;31291:2:1;61174:171:0;;;31273:21:1;31330:2;31310:18;;;31303:30;31369:34;31349:18;;;31342:62;-1:-1:-1;;;31420:18:1;;;31413:32;31462:19;;61174:171:0;31263:224:1;61174:171:0;-1:-1:-1;;;;;61360:32:0;;;;;;;:21;:32;;;;;;;;:47;;;;61356:204;;-1:-1:-1;;;;;61424:32:0;;;;;;;:21;:32;;;;;;:46;;-1:-1:-1;;;;;;61424:46:0;;;;;;;;;61490:58;61537:10;;61424:46;:32;61490:58;;;61000:567;;:::o;47020:452::-;47122:4;-1:-1:-1;;;;;;47146:45:0;;-1:-1:-1;;;47146:45:0;;:85;;;47195:36;47219:11;47195:23;:36::i;:::-;47146:152;;;-1:-1:-1;;;;;;;47248:50:0;;-1:-1:-1;;;47248:50:0;47146:152;:202;;;-1:-1:-1;;;;;;;47302:46:0;;-1:-1:-1;;;47302:46:0;47146:202;:268;;;-1:-1:-1;;;;;;;47365:49:0;;-1:-1:-1;;;47365:49:0;47146:268;:318;;;-1:-1:-1;;;;;;;47418:46:0;;-1:-1:-1;;;47418:46:0;47139:325;47020:452;-1:-1:-1;;47020:452:0:o;99965:157::-;100075:35;100092:4;100098:2;100102:7;100075:16;:35::i;61632:270::-;61738:10;61761:3;61716:33;;;:21;:33;;;;;;-1:-1:-1;;;;;61716:33:0;:49;61712:183;;61834:10;61812:33;;;;:21;:33;;;;;;;;61782:101;;-1:-1:-1;;;61782:101:0;;;;;17923:34:1;;;;-1:-1:-1;;;;;17993:15:1;;;17973:18;;;17966:43;18025:18;;;18018:34;;;61812:33:0;;61782:76;;17858:18:1;;61782:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85948:110;86024:26;86034:2;86038:7;86024:26;;;;;;;;;;;;:9;:26::i;7837:1420::-;7903:4;8042:19;;;:12;;;:19;;;;;;8078:15;;8074:1176;;8453:21;8477:14;8490:1;8477:10;:14;:::i;:::-;8526:18;;8453:38;;-1:-1:-1;8506:17:0;;8526:22;;8547:1;;8526:22;:::i;:::-;8506:42;;8582:13;8569:9;:26;8565:405;;8616:17;8636:3;:11;;8648:9;8636:22;;;;;;-1:-1:-1;;;8636:22:0;;;;;;;;;;;;;;;;;8616:42;;8790:9;8761:3;:11;;8773:13;8761:26;;;;;;-1:-1:-1;;;8761:26:0;;;;;;;;;;;;;;;;;;;;:38;;;;8875:23;;;:12;;;:23;;;;;:36;;;8565:405;9051:17;;:3;;:17;;;-1:-1:-1;;;9051:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;9146:3;:12;;:19;9159:5;9146:19;;;;;;;;;;;9139:26;;;9189:4;9182:11;;;;;;;8074:1176;9233:5;9226:12;;;;;10021:120;10088:7;10115:3;:11;;10127:5;10115:18;;;;;;-1:-1:-1;;;10115:18:0;;;;;;;;;;;;;;;;;10108:25;;10021:120;;;;:::o;7247:414::-;7310:4;9440:19;;;:12;;;:19;;;;;;7327:327;;-1:-1:-1;7370:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;7553:18;;7531:19;;;:12;;;:19;;;;;;:40;;;;7586:11;;7327:327;-1:-1:-1;7637:5:0;7630:12;;26536:417;26600:4;26811:60;26836:7;-1:-1:-1;;;26811:24:0;:60::i;:::-;:134;;;;-1:-1:-1;26889:56:0;26914:7;-1:-1:-1;;;;;;26889:24:0;:56::i;:::-;26888:57;26791:154;26536:417;-1:-1:-1;;26536:417:0:o;30140:423::-;30279:80;;;-1:-1:-1;;;;;;22430:33:1;;30279:80:0;;;;22412:52:1;;;;30279:80:0;;;;;;;;;;22385:18:1;;;;30279:80:0;;;;;;;-1:-1:-1;;;;;30279:80:0;-1:-1:-1;;;30279:80:0;;;30408:45;;30233:4;;30279:80;30233:4;;;;-1:-1:-1;;;;;30408:18:0;;;30432:5;;30408:45;;30279:80;;30408:45;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30370:83;;;;30484:2;30468:6;:13;:18;30464:36;;;30495:5;30488:12;;;;;;;30464:36;30518:7;:37;;;;;30540:6;30529:26;;;;;;;;;;;;:::i;:::-;30511:44;30140:423;-1:-1:-1;;;;;;30140:423:0:o;89685:803::-;89840:4;-1:-1:-1;;;;;89861:13:0;;31701:20;31749:8;89857:624;;89897:72;;-1:-1:-1;;;89897:72:0;;-1:-1:-1;;;;;89897:36:0;;;;;:72;;15783:10;;89948:4;;89954:7;;89963:5;;89897:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89897:72:0;;;;;;;;-1:-1:-1;;89897:72:0;;;;;;;;;;;;:::i;:::-;;;89893:533;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90143:13:0;;90139:272;;90186:60;;-1:-1:-1;;;90186:60:0;;;;;;;:::i;90139:272::-;90361:6;90355:13;90346:6;90342:2;90338:15;90331:38;89893:533;-1:-1:-1;;;;;;90020:55:0;-1:-1:-1;;;90020:55:0;;-1:-1:-1;90013:62:0;;89857:624;-1:-1:-1;90465:4:0;89685:803;;;;;;:::o;93126:224::-;93228:4;-1:-1:-1;;;;;;93252:50:0;;-1:-1:-1;;;93252:50:0;;:90;;;93306:36;93330:11;93306:23;:36::i;62982:333::-;63074:53;63101:25;;;:16;:25;;;;;;;;;-1:-1:-1;;;;;63101:25:0;63074:53;;:26;:53;;;;;;;;63070:238;;;63190:25;;;;:16;:25;;;;;;;;63151:100;;-1:-1:-1;;;63151:100:0;;-1:-1:-1;;;;;17941:15:1;;;63151:100:0;;;17923:34:1;17993:15;;;17973:18;;;17966:43;18025:18;;;18018:34;;;63190:25:0;;;;63151:81;;17858:18:1;;63151:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63143:154;;;;-1:-1:-1;;;63143:154:0;;25271:2:1;63143:154:0;;;25253:21:1;25310:2;25290:18;;;25283:30;25349:34;25329:18;;;25322:62;-1:-1:-1;;;25400:18:1;;;25393:39;25449:19;;63143:154:0;25243:231:1;86285:321:0;86415:18;86421:2;86425:7;86415:5;:18::i;:::-;86466:54;86497:1;86501:2;86505:7;86514:5;86466:22;:54::i;:::-;86444:154;;;;-1:-1:-1;;;86444:154:0;;;;;;;:::i;86942:382::-;-1:-1:-1;;;;;87022:16:0;;87014:61;;;;-1:-1:-1;;;87014:61:0;;30111:2:1;87014:61:0;;;30093:21:1;;;30130:18;;;30123:30;30189:34;30169:18;;;30162:62;30241:18;;87014:61:0;30083:182:1;87014:61:0;87095:16;87103:7;87095;:16::i;:::-;87094:17;87086:58;;;;-1:-1:-1;;;87086:58:0;;24555:2:1;87086:58:0;;;24537:21:1;24594:2;24574:18;;;24567:30;24633;24613:18;;;24606:58;24681:18;;87086:58:0;24527:178:1;87086:58:0;87157:45;87186:1;87190:2;87194:7;87157:20;:45::i;:::-;-1:-1:-1;;;;;87215:13:0;;;;;;:9;:13;;;;;:18;;87232:1;;87215:13;:18;;87232:1;;87215:18;:::i;:::-;;;;-1:-1:-1;;87244:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;87244:21:0;-1:-1:-1;;;;;87244:21:0;;;;;;;;87283:33;;87244:16;;;87283:33;;87244:16;;87283:33;86942:382;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:403:1;85:8;95:6;149:3;142:4;134:6;130:17;126:27;116:2;;174:8;164;157:26;116:2;-1:-1:-1;204:20:1;;-1:-1:-1;;;;;236:30:1;;233:2;;;286:8;276;269:26;233:2;330:4;322:6;318:17;306:29;;390:3;383:4;373:6;370:1;366:14;358:6;354:27;350:38;347:47;344:2;;;407:1;404;397:12;344:2;106:311;;;;;:::o;422:375::-;473:8;483:6;537:3;530:4;522:6;518:17;514:27;504:2;;562:8;552;545:26;504:2;-1:-1:-1;592:20:1;;-1:-1:-1;;;;;624:30:1;;621:2;;;674:8;664;657:26;621:2;718:4;710:6;706:17;694:29;;770:3;763:4;754:6;746;742:19;738:30;735:39;732:2;;;787:1;784;777:12;802:257;861:6;914:2;902:9;893:7;889:23;885:32;882:2;;;935:6;927;920:22;882:2;979:9;966:23;998:31;1023:5;998:31;:::i;1064:261::-;1134:6;1187:2;1175:9;1166:7;1162:23;1158:32;1155:2;;;1208:6;1200;1193:22;1155:2;1245:9;1239:16;1264:31;1289:5;1264:31;:::i;1330:398::-;1398:6;1406;1459:2;1447:9;1438:7;1434:23;1430:32;1427:2;;;1480:6;1472;1465:22;1427:2;1524:9;1511:23;1543:31;1568:5;1543:31;:::i;:::-;1593:5;-1:-1:-1;1650:2:1;1635:18;;1622:32;1663:33;1622:32;1663:33;:::i;:::-;1715:7;1705:17;;;1417:311;;;;;:::o;1733:466::-;1810:6;1818;1826;1879:2;1867:9;1858:7;1854:23;1850:32;1847:2;;;1900:6;1892;1885:22;1847:2;1944:9;1931:23;1963:31;1988:5;1963:31;:::i;:::-;2013:5;-1:-1:-1;2070:2:1;2055:18;;2042:32;2083:33;2042:32;2083:33;:::i;:::-;1837:362;;2135:7;;-1:-1:-1;;;2189:2:1;2174:18;;;;2161:32;;1837:362::o;2204:1061::-;2299:6;2307;2315;2323;2376:3;2364:9;2355:7;2351:23;2347:33;2344:2;;;2398:6;2390;2383:22;2344:2;2442:9;2429:23;2461:31;2486:5;2461:31;:::i;:::-;2511:5;-1:-1:-1;2568:2:1;2553:18;;2540:32;2581:33;2540:32;2581:33;:::i;:::-;2633:7;-1:-1:-1;2687:2:1;2672:18;;2659:32;;-1:-1:-1;2742:2:1;2727:18;;2714:32;-1:-1:-1;;;;;2758:30:1;;2755:2;;;2806:6;2798;2791:22;2755:2;2834:22;;2887:4;2879:13;;2875:27;-1:-1:-1;2865:2:1;;2921:6;2913;2906:22;2865:2;2962;2949:16;2987:48;3003:31;3031:2;3003:31;:::i;:::-;2987:48;:::i;:::-;3058:2;3051:5;3044:17;3098:7;3093:2;3088;3084;3080:11;3076:20;3073:33;3070:2;;;3124:6;3116;3109:22;3070:2;3184;3179;3175;3171:11;3166:2;3159:5;3155:14;3142:45;3207:14;;;3223:2;3203:23;3196:39;;;;-1:-1:-1;2334:931:1;;;;-1:-1:-1;2334:931:1;-1:-1:-1;2334:931:1:o;3270:962::-;3409:6;3417;3425;3433;3441;3494:2;3482:9;3473:7;3469:23;3465:32;3462:2;;;3515:6;3507;3500:22;3462:2;3559:9;3546:23;3578:31;3603:5;3578:31;:::i;:::-;3628:5;-1:-1:-1;3684:2:1;3669:18;;3656:32;-1:-1:-1;;;;;3737:14:1;;;3734:2;;;3769:6;3761;3754:22;3734:2;3813:78;3883:7;3874:6;3863:9;3859:22;3813:78;:::i;:::-;3910:8;;-1:-1:-1;3787:104:1;-1:-1:-1;3998:2:1;3983:18;;3970:32;;-1:-1:-1;4014:16:1;;;4011:2;;;4048:6;4040;4033:22;4011:2;;4092:80;4164:7;4153:8;4142:9;4138:24;4092:80;:::i;:::-;3452:780;;;;-1:-1:-1;3452:780:1;;-1:-1:-1;4191:8:1;;4066:106;3452:780;-1:-1:-1;;;3452:780:1:o;4237:612::-;4344:6;4352;4360;4413:2;4401:9;4392:7;4388:23;4384:32;4381:2;;;4434:6;4426;4419:22;4381:2;4478:9;4465:23;4497:31;4522:5;4497:31;:::i;:::-;4547:5;-1:-1:-1;4603:2:1;4588:18;;4575:32;-1:-1:-1;;;;;4619:30:1;;4616:2;;;4667:6;4659;4652:22;4616:2;4711:78;4781:7;4772:6;4761:9;4757:22;4711:78;:::i;:::-;4371:478;;4808:8;;-1:-1:-1;4685:104:1;;-1:-1:-1;;;;4371:478:1:o;4854:392::-;4919:6;4927;4980:2;4968:9;4959:7;4955:23;4951:32;4948:2;;;5001:6;4993;4986:22;4948:2;5045:9;5032:23;5064:31;5089:5;5064:31;:::i;:::-;5114:5;-1:-1:-1;5171:2:1;5156:18;;5143:32;5184:30;5143:32;5184:30;:::i;5251:565::-;5331:6;5339;5347;5400:2;5388:9;5379:7;5375:23;5371:32;5368:2;;;5421:6;5413;5406:22;5368:2;5465:9;5452:23;5484:31;5509:5;5484:31;:::i;:::-;5534:5;-1:-1:-1;5590:2:1;5575:18;;5562:32;-1:-1:-1;;;;;5606:30:1;;5603:2;;;5654:6;5646;5639:22;5603:2;5698:58;5748:7;5739:6;5728:9;5724:22;5698:58;:::i;5821:700::-;5907:6;5915;5923;5931;5984:2;5972:9;5963:7;5959:23;5955:32;5952:2;;;6005:6;5997;5990:22;5952:2;6049:9;6036:23;6068:31;6093:5;6068:31;:::i;:::-;6118:5;-1:-1:-1;6174:2:1;6159:18;;6146:32;-1:-1:-1;;;;;6190:30:1;;6187:2;;;6238:6;6230;6223:22;6187:2;6282:58;6332:7;6323:6;6312:9;6308:22;6282:58;:::i;:::-;6359:8;;-1:-1:-1;6256:84:1;-1:-1:-1;;6446:2:1;6431:18;;6418:32;6459:30;6418:32;6459:30;:::i;:::-;5942:579;;;;-1:-1:-1;5942:579:1;;-1:-1:-1;;5942:579:1:o;6526:435::-;6593:6;6601;6654:2;6642:9;6633:7;6629:23;6625:32;6622:2;;;6675:6;6667;6660:22;6622:2;6719:9;6706:23;6738:31;6763:5;6738:31;:::i;:::-;6788:5;-1:-1:-1;6845:2:1;6830:18;;6817:32;6893:6;6880:20;;6868:33;;6858:2;;6920:6;6912;6905:22;6966:325;7034:6;7042;7095:2;7083:9;7074:7;7070:23;7066:32;7063:2;;;7116:6;7108;7101:22;7063:2;7160:9;7147:23;7179:31;7204:5;7179:31;:::i;:::-;7229:5;7281:2;7266:18;;;;7253:32;;-1:-1:-1;;;7053:238:1:o;7296:827::-;7426:6;7434;7442;7450;7503:2;7491:9;7482:7;7478:23;7474:32;7471:2;;;7524:6;7516;7509:22;7471:2;7569:9;7556:23;-1:-1:-1;;;;;7639:2:1;7631:6;7628:14;7625:2;;;7660:6;7652;7645:22;7625:2;7704:78;7774:7;7765:6;7754:9;7750:22;7704:78;:::i;:::-;7801:8;;-1:-1:-1;7678:104:1;-1:-1:-1;7889:2:1;7874:18;;7861:32;;-1:-1:-1;7905:16:1;;;7902:2;;;7939:6;7931;7924:22;7902:2;;7983:80;8055:7;8044:8;8033:9;8029:24;7983:80;:::i;:::-;7461:662;;;;-1:-1:-1;8082:8:1;-1:-1:-1;;;;7461:662:1:o;8128:1349::-;8260:6;8268;8276;8329:2;8317:9;8308:7;8304:23;8300:32;8297:2;;;8350:6;8342;8335:22;8297:2;8395:9;8382:23;-1:-1:-1;;;;;8465:2:1;8457:6;8454:14;8451:2;;;8486:6;8478;8471:22;8451:2;8529:6;8518:9;8514:22;8504:32;;8574:7;8567:4;8563:2;8559:13;8555:27;8545:2;;8601:6;8593;8586:22;8545:2;8642;8629:16;8664:4;8687:2;8683;8680:10;8677:2;;;8693:18;;:::i;:::-;8739:2;8736:1;8732:10;8762:28;8786:2;8782;8778:11;8762:28;:::i;:::-;8824:15;;;8855:12;;;;8887:11;;;8917;;;8913:20;;8910:33;-1:-1:-1;8907:2:1;;;8961:6;8953;8946:22;8907:2;8988:6;8979:15;;9003:163;9017:2;9014:1;9011:9;9003:163;;;9074:17;;9062:30;;9035:1;9028:9;;;;;9112:12;;;;9144;;9003:163;;;-1:-1:-1;9185:5:1;-1:-1:-1;;;9228:18:1;;9215:32;;-1:-1:-1;;9259:16:1;;;9256:2;;;9293:6;9285;9278:22;9256:2;;9337:80;9409:7;9398:8;9387:9;9383:24;9337:80;:::i;9482:251::-;9538:6;9591:2;9579:9;9570:7;9566:23;9562:32;9559:2;;;9612:6;9604;9597:22;9559:2;9656:9;9643:23;9675:28;9697:5;9675:28;:::i;9738:255::-;9805:6;9858:2;9846:9;9837:7;9833:23;9829:32;9826:2;;;9879:6;9871;9864:22;9826:2;9916:9;9910:16;9935:28;9957:5;9935:28;:::i;9998:255::-;10056:6;10109:2;10097:9;10088:7;10084:23;10080:32;10077:2;;;10130:6;10122;10115:22;10077:2;10174:9;10161:23;10193:30;10217:5;10193:30;:::i;10258:259::-;10327:6;10380:2;10368:9;10359:7;10355:23;10351:32;10348:2;;;10401:6;10393;10386:22;10348:2;10438:9;10432:16;10457:30;10481:5;10457:30;:::i;10522:430::-;10593:6;10601;10654:2;10642:9;10633:7;10629:23;10625:32;10622:2;;;10675:6;10667;10660:22;10622:2;10720:9;10707:23;-1:-1:-1;;;;;10745:6:1;10742:30;10739:2;;;10790:6;10782;10775:22;10739:2;10834:58;10884:7;10875:6;10864:9;10860:22;10834:58;:::i;:::-;10911:8;;10808:84;;-1:-1:-1;10612:340:1;-1:-1:-1;;;;10612:340:1:o;10957:559::-;11034:6;11042;11050;11103:2;11091:9;11082:7;11078:23;11074:32;11071:2;;;11124:6;11116;11109:22;11071:2;11169:9;11156:23;-1:-1:-1;;;;;11194:6:1;11191:30;11188:2;;;11239:6;11231;11224:22;11188:2;11283:58;11333:7;11324:6;11313:9;11309:22;11283:58;:::i;:::-;11360:8;;-1:-1:-1;11257:84:1;-1:-1:-1;;11445:2:1;11430:18;;11417:32;11458:28;11417:32;11458:28;:::i;:::-;11505:5;11495:15;;;11061:455;;;;;:::o;11521:675::-;11601:6;11654:2;11642:9;11633:7;11629:23;11625:32;11622:2;;;11675:6;11667;11660:22;11622:2;11713:9;11707:16;-1:-1:-1;;;;;11738:6:1;11735:30;11732:2;;;11783:6;11775;11768:22;11732:2;11811:22;;11864:4;11856:13;;11852:27;-1:-1:-1;11842:2:1;;11898:6;11890;11883:22;11842:2;11932;11926:9;11957:48;11973:31;12001:2;11973:31;:::i;11957:48::-;12028:2;12021:5;12014:17;12068:7;12063:2;12058;12054;12050:11;12046:20;12043:33;12040:2;;;12094:6;12086;12079:22;12040:2;12112:54;12163:2;12158;12151:5;12147:14;12142:2;12138;12134:11;12112:54;:::i;:::-;12185:5;11612:584;-1:-1:-1;;;;;11612:584:1:o;12201:190::-;12260:6;12313:2;12301:9;12292:7;12288:23;12284:32;12281:2;;;12334:6;12326;12319:22;12281:2;-1:-1:-1;12362:23:1;;12271:120;-1:-1:-1;12271:120:1:o;12396:895::-;12535:6;12543;12551;12559;12567;12620:2;12608:9;12599:7;12595:23;12591:32;12588:2;;;12641:6;12633;12626:22;12588:2;12682:9;12669:23;12659:33;;12743:2;12732:9;12728:18;12715:32;-1:-1:-1;;;;;12807:2:1;12799:6;12796:14;12793:2;;;12828:6;12820;12813:22;13296:498;13376:6;13384;13392;13445:2;13433:9;13424:7;13420:23;13416:32;13413:2;;;13466:6;13458;13451:22;13413:2;13507:9;13494:23;13484:33;;13568:2;13557:9;13553:18;13540:32;-1:-1:-1;;;;;13587:6:1;13584:30;13581:2;;;13632:6;13624;13617:22;13799:565;13887:6;13895;13903;13911;13964:2;13952:9;13943:7;13939:23;13935:32;13932:2;;;13985:6;13977;13970:22;13932:2;14026:9;14013:23;14003:33;;14083:2;14072:9;14068:18;14055:32;14045:42;;14138:2;14127:9;14123:18;14110:32;-1:-1:-1;;;;;14157:6:1;14154:30;14151:2;;;14202:6;14194;14187:22;14151:2;14246:58;14296:7;14287:6;14276:9;14272:22;14246:58;:::i;14369:471::-;14430:3;14468:5;14462:12;14495:6;14490:3;14483:19;14521:4;14550:2;14545:3;14541:12;14534:19;;14587:2;14580:5;14576:14;14608:3;14620:195;14634:6;14631:1;14628:13;14620:195;;;14699:13;;-1:-1:-1;;;;;14695:39:1;14683:52;;14755:12;;;;14790:15;;;;14731:1;14649:9;14620:195;;;-1:-1:-1;14831:3:1;;14438:402;-1:-1:-1;;;;;14438:402:1:o;14845:437::-;14898:3;14936:5;14930:12;14963:6;14958:3;14951:19;14989:4;15018:2;15013:3;15009:12;15002:19;;15055:2;15048:5;15044:14;15076:3;15088:169;15102:6;15099:1;15096:13;15088:169;;;15163:13;;15151:26;;15197:12;;;;15232:15;;;;15124:1;15117:9;15088:169;;15287:257;15328:3;15366:5;15360:12;15393:6;15388:3;15381:19;15409:63;15465:6;15458:4;15453:3;15449:14;15442:4;15435:5;15431:16;15409:63;:::i;:::-;15526:2;15505:15;-1:-1:-1;;15501:29:1;15492:39;;;;15533:4;15488:50;;15336:208;-1:-1:-1;;15336:208:1:o;15549:979::-;15634:12;;15599:3;;15691:1;15711:18;;;;15764;;;;15791:2;;15845:4;15837:6;15833:17;15823:27;;15791:2;15871;15919;15911:6;15908:14;15888:18;15885:38;15882:2;;;-1:-1:-1;;;15946:33:1;;16002:4;15999:1;15992:15;16032:4;15953:3;16020:17;15882:2;16063:18;16090:104;;;;16208:1;16203:319;;;;16056:466;;16090:104;-1:-1:-1;;16123:24:1;;16111:37;;16168:16;;;;-1:-1:-1;16090:104:1;;16203:319;38208:4;38227:17;;;38277:4;38261:21;;16297:1;16311:165;16325:6;16322:1;16319:13;16311:165;;;16403:14;;16390:11;;;16383:35;16446:16;;;;16340:10;;16311:165;;;16315:3;;16505:6;16500:3;16496:16;16489:23;;16056:466;;;;;;;15607:921;;;;:::o;16533:274::-;16662:3;16700:6;16694:13;16716:53;16762:6;16757:3;16750:4;16742:6;16738:17;16716:53;:::i;:::-;16785:16;;;;;16670:137;-1:-1:-1;;16670:137:1:o;16812:376::-;16988:3;17016:38;17050:3;17042:6;17016:38;:::i;:::-;17083:6;17077:13;17099:52;17144:6;17140:2;17133:4;17125:6;17121:17;17099:52;:::i;:::-;17167:15;;16996:192;-1:-1:-1;;;;16996:192:1:o;17193:277::-;17366:3;17391:73;17425:38;17459:3;17451:6;17425:38;:::i;:::-;17417:6;17391:73;:::i;18063:488::-;-1:-1:-1;;;;;18332:15:1;;;18314:34;;18384:15;;18379:2;18364:18;;18357:43;18431:2;18416:18;;18409:34;;;18479:3;18474:2;18459:18;;18452:31;;;18257:4;;18500:45;;18525:19;;18517:6;18500:45;:::i;18835:385::-;19067:1;19063;19058:3;19054:11;19050:19;19042:6;19038:32;19027:9;19020:51;19107:6;19102:2;19091:9;19087:18;19080:34;19150:2;19145;19134:9;19130:18;19123:30;19001:4;19170:44;19210:2;19199:9;19195:18;19187:6;19170:44;:::i;19225:661::-;19396:2;19448:21;;;19518:13;;19421:18;;;19540:22;;;19367:4;;19396:2;19619:15;;;;19593:2;19578:18;;;19367:4;19665:195;19679:6;19676:1;19673:13;19665:195;;;19744:13;;-1:-1:-1;;;;;19740:39:1;19728:52;;19835:15;;;;19800:12;;;;19776:1;19694:9;19665:195;;;-1:-1:-1;19877:3:1;;19376:510;-1:-1:-1;;;;;;19376:510:1:o;19891:1130::-;20195:2;20207:21;;;20180:18;;20263:22;;;20147:4;20342:6;20316:2;20301:18;;20147:4;20379:304;20393:6;20390:1;20387:13;20379:304;;;20468:6;20455:20;20488:31;20513:5;20488:31;:::i;:::-;-1:-1:-1;;;;;20544:31:1;20532:44;;20599:4;20658:15;;;;20623:12;;;;20572:1;20408:9;20379:304;;;-1:-1:-1;20721:19:1;;;20714:4;20699:20;;20692:49;20750:19;;;-1:-1:-1;;;;;20781:31:1;;20778:2;;;20828:4;20822;20815:18;20778:2;20865:6;20862:1;20858:14;20844:28;;20918:6;20910;20903:4;20898:3;20894:14;20881:44;20948:16;20966:4;20944:27;20980:16;;;20944:27;20156:865;-1:-1:-1;;;;;20156:865:1:o;21026:285::-;21221:2;21210:9;21203:21;21184:4;21241:64;21301:2;21290:9;21286:18;21278:6;21241:64;:::i;21316:489::-;21589:2;21578:9;21571:21;21552:4;21615:64;21675:2;21664:9;21660:18;21652:6;21615:64;:::i;:::-;21727:9;21719:6;21715:22;21710:2;21699:9;21695:18;21688:50;21755:44;21792:6;21784;21755:44;:::i;21810:261::-;21989:2;21978:9;21971:21;21952:4;22009:56;22061:2;22050:9;22046:18;22038:6;22009:56;:::i;22475:219::-;22624:2;22613:9;22606:21;22587:4;22644:44;22684:2;22673:9;22669:18;22661:6;22644:44;:::i;23111:414::-;23313:2;23295:21;;;23352:2;23332:18;;;23325:30;23391:34;23386:2;23371:18;;23364:62;-1:-1:-1;;;23457:2:1;23442:18;;23435:48;23515:3;23500:19;;23285:240::o;28742:341::-;28944:2;28926:21;;;28983:2;28963:18;;;28956:30;-1:-1:-1;;;29017:2:1;29002:18;;28995:47;29074:2;29059:18;;28916:167::o;31492:356::-;31694:2;31676:21;;;31713:18;;;31706:30;31772:34;31767:2;31752:18;;31745:62;31839:2;31824:18;;31666:182::o;33043:405::-;33245:2;33227:21;;;33284:2;33264:18;;;33257:30;33323:34;33318:2;33303:18;;33296:62;-1:-1:-1;;;33389:2:1;33374:18;;33367:39;33438:3;33423:19;;33217:231::o;33855:413::-;34057:2;34039:21;;;34096:2;34076:18;;;34069:30;34135:34;34130:2;34115:18;;34108:62;-1:-1:-1;;;34201:2:1;34186:18;;34179:47;34258:3;34243:19;;34029:239::o;34628:400::-;34830:2;34812:21;;;34869:2;34849:18;;;34842:30;34908:34;34903:2;34888:18;;34881:62;-1:-1:-1;;;34974:2:1;34959:18;;34952:34;35018:3;35003:19;;34802:226::o;35801:398::-;36003:2;35985:21;;;36042:2;36022:18;;;36015:30;36081:34;36076:2;36061:18;;36054:62;-1:-1:-1;;;36147:2:1;36132:18;;36125:32;36189:3;36174:19;;35975:224::o;36204:355::-;36406:2;36388:21;;;36445:2;36425:18;;;36418:30;36484:33;36479:2;36464:18;;36457:61;36550:2;36535:18;;36378:181::o;36564:400::-;36766:2;36748:21;;;36805:2;36785:18;;;36778:30;36844:34;36839:2;36824:18;;36817:62;-1:-1:-1;;;36910:2:1;36895:18;;36888:34;36954:3;36939:19;;36738:226::o;37151:534::-;37229:4;37235:6;37295:11;37282:25;37389:2;37385:7;37374:8;37358:14;37354:29;37350:43;37330:18;37326:68;37316:2;;37411:4;37405;37398:18;37316:2;37441:33;;37493:20;;;-1:-1:-1;;;;;;37525:30:1;;37522:2;;;37571:4;37565;37558:18;37522:2;37607:4;37595:17;;-1:-1:-1;37638:14:1;37634:27;;;37624:38;;37621:2;;;37675:1;37672;37665:12;37690:275;37761:2;37755:9;37826:2;37807:13;;-1:-1:-1;;37803:27:1;37791:40;;-1:-1:-1;;;;;37846:34:1;;37882:22;;;37843:62;37840:2;;;37908:18;;:::i;:::-;37944:2;37937:22;37735:230;;-1:-1:-1;37735:230:1:o;37970:186::-;38018:4;-1:-1:-1;;;;;38043:6:1;38040:30;38037:2;;;38073:18;;:::i;:::-;-1:-1:-1;38139:2:1;38118:15;-1:-1:-1;;38114:29:1;38145:4;38110:40;;38027:129::o;38293:128::-;38333:3;38364:1;38360:6;38357:1;38354:13;38351:2;;;38370:18;;:::i;:::-;-1:-1:-1;38406:9:1;;38341:80::o;38426:120::-;38466:1;38492;38482:2;;38497:18;;:::i;:::-;-1:-1:-1;38531:9:1;;38472:74::o;38551:168::-;38591:7;38657:1;38653;38649:6;38645:14;38642:1;38639:21;38634:1;38627:9;38620:17;38616:45;38613:2;;;38664:18;;:::i;:::-;-1:-1:-1;38704:9:1;;38603:116::o;38724:125::-;38764:4;38792:1;38789;38786:8;38783:2;;;38797:18;;:::i;:::-;-1:-1:-1;38834:9:1;;38773:76::o;38854:258::-;38926:1;38936:113;38950:6;38947:1;38944:13;38936:113;;;39026:11;;;39020:18;39007:11;;;39000:39;38972:2;38965:10;38936:113;;;39067:6;39064:1;39061:13;39058:2;;;-1:-1:-1;;39102:1:1;39084:16;;39077:27;38907:205::o;39117:380::-;39196:1;39192:12;;;;39239;;;39260:2;;39314:4;39306:6;39302:17;39292:27;;39260:2;39367;39359:6;39356:14;39336:18;39333:38;39330:2;;;39413:10;39408:3;39404:20;39401:1;39394:31;39448:4;39445:1;39438:15;39476:4;39473:1;39466:15;39502:197;39540:3;39568:6;39609:2;39602:5;39598:14;39636:2;39627:7;39624:15;39621:2;;;39642:18;;:::i;:::-;39691:1;39678:15;;39548:151;-1:-1:-1;;;39548:151:1:o;39704:135::-;39743:3;-1:-1:-1;;39764:17:1;;39761:2;;;39784:18;;:::i;:::-;-1:-1:-1;39831:1:1;39820:13;;39751:88::o;39844:112::-;39876:1;39902;39892:2;;39907:18;;:::i;:::-;-1:-1:-1;39941:9:1;;39882:74::o;39961:127::-;40022:10;40017:3;40013:20;40010:1;40003:31;40053:4;40050:1;40043:15;40077:4;40074:1;40067:15;40093:127;40154:10;40149:3;40145:20;40142:1;40135:31;40185:4;40182:1;40175:15;40209:4;40206:1;40199:15;40225:127;40286:10;40281:3;40277:20;40274:1;40267:31;40317:4;40314:1;40307:15;40341:4;40338:1;40331:15;40357:131;-1:-1:-1;;;;;40432:31:1;;40422:42;;40412:2;;40478:1;40475;40468:12;40493:118;40579:5;40572:13;40565:21;40558:5;40555:32;40545:2;;40601:1;40598;40591:12;40616:131;-1:-1:-1;;;;;;40690:32:1;;40680:43;;40670:2;;40737:1;40734;40727:12

Swarm Source

ipfs://7774ff44d2129ea986c9b42c450517cf528fb3ad6dd97428367437b9df8d7f66
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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