ETH Price: $2,678.32 (+0.36%)

Token

Mythic Pets (PETS)
 

Overview

Max Total Supply

2,001 PETS

Holders

320

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 PETS
0x098301e6208efb79161d4fd770918ff4fbb628aa
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Mythic Pets from [ApeLiquid.io](https://ApeLiquid.io) are a stand-alone NFT PFP collection of adorable and sometimes deadly pets. They are also the perfect companion on your Mythic Journey. They are packed with special abilities that also stack in a Mythic Journey. They will be able to eat [Mythic Pet Food](https://opensea.io/collection/mythic-pet-food) to enhance or replenish their abilities. Every single Mythic Pet is a 1:1 piece of beautiful art and handcrafted by the talented [Estebomb](https://twitter.com/_estebomb) ApeLiquid Ecosystem [Memberships](https://opensea.io/collection/apeliquid) | [Liquid Keys](https://opensea.io/collection/liquid-keys) | [Azuki Apes](https://opensea.io/collection/azukiapesocialclub) | [Liquid Invaders](https://opensea.io/collection/liquid-invaders) ... and much more at [ApeLiquid.io](https://apeliquid.io)

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MythicPets

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-02-25
*/

// SPDX-License-Identifier: MIT

/*
     _____                .____    .__             .__    .___   .__
    /  _  \ ______   ____ |    |   |__| ________ __|__| __| _/   |__| ____
   /  /_\  \\____ \_/ __ \|    |   |  |/ ____/  |  \  |/ __ |    |  |/  _ \
  /    |    \  |_> >  ___/|    |___|  < <_|  |  |  /  / /_/ |    |  (  <_> )
  \____|__  /   __/ \___  >_______ \__|\__   |____/|__\____ | /\ |__|\____/
          \/|__|        \/        \/      |__|             \/ \/
      __________        __
      \______   \ _____/  |_  ______
       |     ___// __ \   __\/  ___/
       |    |   \  ___/|  |  \___ \
       |____|    \___  >__| /____  >
                     \/          \/
*/

// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        external
        view
        returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

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

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable is IAccessControl {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index)
        external
        view
        returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set)
        internal
        view
        returns (bytes32[] memory)
    {
        return _values(set._inner);
    }

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set)
        internal
        view
        returns (address[] memory)
    {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly {
            result := store
        }

        return result;
    }

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set)
        internal
        view
        returns (uint256[] memory)
    {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly {
            result := store
        }

        return result;
    }
}

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

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

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

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

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

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

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

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

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

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
    {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        virtual
        returns (bool)
    {
        require(
            _exists(tokenId),
            "ERC721: operator query for nonexistent token"
        );
        address owner = 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 Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

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

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

pragma solidity ^0.8.0;

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role)
        public
        view
        virtual
        override
        returns (bytes32)
    {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account)
        public
        virtual
        override
    {
        require(
            account == _msgSender(),
            "AccessControl: can only renounce roles for self"
        );

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev 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 {
        _transferOwnership(address(0));
    }

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

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

pragma solidity ^0.8.0;

/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerable is
    IAccessControlEnumerable,
    AccessControl
{
    using EnumerableSet for EnumerableSet.AddressSet;

    mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;

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

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index)
        public
        view
        virtual
        override
        returns (address)
    {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role)
        public
        view
        virtual
        override
        returns (uint256)
    {
        return _roleMembers[role].length();
    }

    /**
     * @dev Overload {_grantRole} to track enumerable memberships
     */
    function _grantRole(bytes32 role, address account)
        internal
        virtual
        override
    {
        super._grantRole(role, account);
        _roleMembers[role].add(account);
    }

    /**
     * @dev Overload {_revokeRole} to track enumerable memberships
     */
    function _revokeRole(bytes32 role, address account)
        internal
        virtual
        override
    {
        super._revokeRole(role, account);
        _roleMembers[role].remove(account);
    }
}

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

pragma solidity ^0.8.4;

error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..).
 *
 * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 *
 * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Compiler will pack this into a single 256bit word.
    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    // Compiler will pack this into a single 256bit word.
    struct AddressData {
        // Realistically, 2**64-1 is more than enough.
        uint64 balance;
        // Keeps track of mint count with minimal overhead for tokenomics.
        uint64 numberMinted;
        // Keeps track of burn count with minimal overhead for tokenomics.
        uint64 numberBurned;
        // For miscellaneous variable(s) pertaining to the address
        // (e.g. number of whitelist mint slots used).
        // If there are multiple variables, please pack them into a uint64.
        uint64 aux;
    }

    // The tokenId of the next token to be minted.
    uint256 internal _currentIndex;

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

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

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

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

    /**
     * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.
     */
    function totalSupply() public view returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than _currentIndex - _startTokenId() times
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

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

    /**
     * @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 override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return uint256(_addressData[owner].balance);
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberMinted);
    }

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

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

    /**
     * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal {
        _addressData[owner].aux = aux;
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function _ownershipOf(uint256 tokenId)
        internal
        view
        returns (TokenOwnership memory)
    {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr && curr < _currentIndex) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (!ownership.burned) {
                    if (ownership.addr != address(0)) {
                        return ownership;
                    }
                    // Invariant:
                    // There will always be an ownership that has an address and is not burned
                    // before an ownership that does not have an address and is not burned.
                    // Hence, curr will not underflow.
                    while (true) {
                        curr--;
                        ownership = _ownerships[curr];
                        if (ownership.addr != address(0)) {
                            return ownership;
                        }
                    }
                }
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

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

    /**
     * @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)
    {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        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 = ERC721A.ownerOf(tokenId);
        if (to == owner) revert ApprovalToCurrentOwner();

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

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        override
        returns (address)
    {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

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

        _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 {
        _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 {
        _transfer(from, to, tokenId);
        if (
            to.isContract() &&
            !_checkContractOnERC721Received(from, to, tokenId, _data)
        ) {
            revert TransferToNonERC721ReceiverImplementer();
        }
    }

    /**
     * @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`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex &&
            !_ownerships[tokenId].burned;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, "");
    }

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

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

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

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            if (safe && to.isContract()) {
                do {
                    emit Transfer(address(0), to, updatedIndex);
                    if (
                        !_checkContractOnERC721Received(
                            address(0),
                            to,
                            updatedIndex++,
                            _data
                        )
                    ) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (updatedIndex != end);
                // Reentrancy protection
                if (_currentIndex != startTokenId) revert();
            } else {
                do {
                    emit Transfer(address(0), to, updatedIndex++);
                } while (updatedIndex != end);
            }
            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) private {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();

        bool isApprovedOrOwner = (_msgSender() == from ||
            isApprovedForAll(from, _msgSender()) ||
            getApproved(tokenId) == _msgSender());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

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

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

            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = to;
            currSlot.startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

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

    /**
     * @dev This is equivalent to _burn(tokenId, false)
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

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

        address from = prevOwnership.addr;

        if (approvalCheck) {
            bool isApprovedOrOwner = (_msgSender() == from ||
                isApprovedForAll(from, _msgSender()) ||
                getApproved(tokenId) == _msgSender());

            if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        }

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

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            AddressData storage addressData = _addressData[from];
            addressData.balance -= 1;
            addressData.numberBurned += 1;

            // Keep track of who burned the token, and the timestamp of burning.
            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = from;
            currSlot.startTimestamp = uint64(block.timestamp);
            currSlot.burned = true;

            // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

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

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

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

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        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 TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

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

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transfer.selector, to, value)
        );
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
        );
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, value)
        );
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(
                oldAllowance >= value,
                "SafeERC20: decreased allowance below zero"
            );
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(
                    token.approve.selector,
                    spender,
                    newAllowance
                )
            );
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(
            data,
            "SafeERC20: low-level call failed"
        );
        if (returndata.length > 0) {
            // Return data is optional
            require(
                abi.decode(returndata, (bool)),
                "SafeERC20: ERC20 operation did not succeed"
            );
        }
    }
}

pragma solidity ^0.8.0;

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 *
 * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
 * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
 * to run tests before sending real value to this contract.
 */
contract PaymentSplitter is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event ERC20PaymentReleased(
        IERC20 indexed token,
        address to,
        uint256 amount
    );
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    mapping(IERC20 => uint256) private _erc20TotalReleased;
    mapping(IERC20 => mapping(address => uint256)) private _erc20Released;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(
            payees.length == shares_.length,
            "PaymentSplitter: payees and shares length mismatch"
        );
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
     * contract.
     */
    function totalReleased(IERC20 token) public view returns (uint256) {
        return _erc20TotalReleased[token];
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
     * IERC20 contract.
     */
    function released(IERC20 token, address account)
        public
        view
        returns (uint256)
    {
        return _erc20Released[token][account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = address(this).balance + totalReleased();
        uint256 payment = _pendingPayment(
            account,
            totalReceived,
            released(account)
        );

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] += payment;
        _totalReleased += payment;

        Address.sendValue(account, payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
     * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
     * contract.
     */
    function release(IERC20 token, address account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = token.balanceOf(address(this)) +
            totalReleased(token);
        uint256 payment = _pendingPayment(
            account,
            totalReceived,
            released(token, account)
        );

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _erc20Released[token][account] += payment;
        _erc20TotalReleased[token] += payment;

        SafeERC20.safeTransfer(token, account, payment);
        emit ERC20PaymentReleased(token, account, payment);
    }

    /**
     * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
     * already released amounts.
     */
    function _pendingPayment(
        address account,
        uint256 totalReceived,
        uint256 alreadyReleased
    ) private view returns (uint256) {
        return
            (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(
            account != address(0),
            "PaymentSplitter: account is the zero address"
        );
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(
            _shares[account] == 0,
            "PaymentSplitter: account already has shares"
        );

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}
pragma solidity ^0.8.0;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator)
        external
        view
        returns (bool);

    function register(address registrant) external;

    function registerAndSubscribe(address registrant, address subscription)
        external;

    function registerAndCopyEntries(
        address registrant,
        address registrantToCopy
    ) external;

    function unregister(address addr) external;

    function updateOperator(
        address registrant,
        address operator,
        bool filtered
    ) external;

    function updateOperators(
        address registrant,
        address[] calldata operators,
        bool filtered
    ) external;

    function updateCodeHash(
        address registrant,
        bytes32 codehash,
        bool filtered
    ) external;

    function updateCodeHashes(
        address registrant,
        bytes32[] calldata codeHashes,
        bool filtered
    ) external;

    function subscribe(address registrant, address registrantToSubscribe)
        external;

    function unsubscribe(address registrant, bool copyExistingEntries) external;

    function subscriptionOf(address addr) external returns (address registrant);

    function subscribers(address registrant)
        external
        returns (address[] memory);

    function subscriberAt(address registrant, uint256 index)
        external
        returns (address);

    function copyEntriesOf(address registrant, address registrantToCopy)
        external;

    function isOperatorFiltered(address registrant, address operator)
        external
        returns (bool);

    function isCodeHashOfFiltered(address registrant, address operatorWithCode)
        external
        returns (bool);

    function isCodeHashFiltered(address registrant, bytes32 codeHash)
        external
        returns (bool);

    function filteredOperators(address addr)
        external
        returns (address[] memory);

    function filteredCodeHashes(address addr)
        external
        returns (bytes32[] memory);

    function filteredOperatorAt(address registrant, uint256 index)
        external
        returns (address);

    function filteredCodeHashAt(address registrant, uint256 index)
        external
        returns (bytes32);

    function isRegistered(address addr) external returns (bool);

    function codeHashOf(address addr) external returns (bytes32);
}

/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(
                    address(this),
                    subscriptionOrRegistrantToCopy
                );
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(
                        address(this),
                        subscriptionOrRegistrantToCopy
                    );
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (
                !OPERATOR_FILTER_REGISTRY.isOperatorAllowed(
                    address(this),
                    msg.sender
                )
            ) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (
                !OPERATOR_FILTER_REGISTRY.isOperatorAllowed(
                    address(this),
                    operator
                )
            ) {
                revert OperatorNotAllowed(operator);
            }
        }
        _;
    }
}

/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION =
        address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

contract OtherContract {
    mapping(uint256 => address) public _nftTokenForges;

    // Define function to get NFT token forge address from mapping
    function getNftTokenForgeAddress(uint256 key)
        public
        view
        returns (address)
    {
        return _nftTokenForges[key];
    }
}

contract MythicPets is
    ERC721A,
    ReentrancyGuard,
    Ownable,
    PaymentSplitter,
    DefaultOperatorFilterer
{
    // Minting Variables
    uint256 public mintPrice = 0.15 ether;
    uint256 public maxPurchase = 33;
    uint256 public maxSupply = 3333;

    // Sale Status
    bool public saleIsActive = false;
    bool public freeMintIsActive = true;
    bool public airdropIsActive = true;

    // the membership contract
    address public membership = 0xBA3B1b86ae330d2118e868b4906cc954a4207835;

    mapping(address => uint256) public addressesThatMinted;
    mapping(uint256 => bool) public memberFreeMinted; // by token id

    // Metadata
    string _baseTokenURI = "https://apeliquid.io/pets/json/";
    bool public locked;

    // Events
    event SaleActivation(bool isActive);
    event AirdropActivation(bool isActive);
    event FreeMintActivation(bool isActive);

    constructor()
        ERC721A("Mythic Pets", "PETS")
        PaymentSplitter(_payees, _shares)
    {}

    function flipMintStatus(uint256 tokenId) external onlyOwner {
        memberFreeMinted[tokenId] = !memberFreeMinted[tokenId];
    }

    // Holder status validation
    // Define function to get NFT token forge address from other contract
    function getNftTokenForgeAddress(address otherContract, uint256 key)
        public
        view
        returns (address)
    {
        return OtherContract(otherContract).getNftTokenForgeAddress(key);
    }

    function airdrop(uint256[] calldata _counts, address[] calldata _list)
        external
        onlyOwner
    {
        require(airdropIsActive, "AIRDROP NOT ACTIVE");

        for (uint256 i = 0; i < _list.length; i++) {
            require(totalSupply() + _counts[i] <= maxSupply, "SOLD OUT");
            _safeMint(_list[i], _counts[i]);
        }
    }

    function freeMint(uint256 memberTokenId) external nonReentrant {
        uint256 _count = 1; // one at a time for free

        require(freeMintIsActive, "FREE MINT INACTIVE");

        // Check to make sure we haven't already minted for this tokenid
        require(!memberFreeMinted[memberTokenId], "Already Minted!");

        require(totalSupply() + _count <= maxSupply, "SOLD OUT");
        //require(mintPrice * _count <= msg.value, "INCORRECT ETHER VALUE");

        require(
            getNftTokenForgeAddress(membership, memberTokenId) == msg.sender,
            "This membership is not forged!"
        );

        _safeMint(msg.sender, _count);
        // addressesThatMinted[msg.sender] += _count;
        memberFreeMinted[memberTokenId] = true;
    }

    function mint(uint256 _count) external payable nonReentrant {
        require(saleIsActive, "SALE INACTIVE");
        require(
            ((addressesThatMinted[msg.sender] + _count)) <= maxPurchase,
            "this would exceed mint max allowance"
        );

        require(totalSupply() + _count <= maxSupply, "SOLD OUT");
        require(mintPrice * _count <= msg.value, "INCORRECT ETHER VALUE");

        _safeMint(msg.sender, _count);
        addressesThatMinted[msg.sender] += _count;
    }

    function toggleSaleStatus() external onlyOwner {
        saleIsActive = !saleIsActive;
        emit SaleActivation(saleIsActive);
    }

    function freeMintStatus() external onlyOwner {
        freeMintIsActive = !freeMintIsActive;
        emit FreeMintActivation(freeMintIsActive);
    }

    function toggleAirdropStatus() external onlyOwner {
        airdropIsActive = !airdropIsActive;
        emit AirdropActivation(airdropIsActive);
    }

    function setMintPrice(uint256 _mintPrice) external onlyOwner {
        mintPrice = _mintPrice;
    }

    function setMaxPurchase(uint256 _maxPurchase) external onlyOwner {
        maxPurchase = _maxPurchase;
    }

    function lockMetadata() external onlyOwner {
        locked = true;
    }

    // Payments
    function claim() external {
        release(payable(msg.sender));
    }

    function getWalletOfOwner(address owner)
        external
        view
        returns (uint256[] memory)
    {
        unchecked {
            uint256[] memory a = new uint256[](balanceOf(owner));
            uint256 end = _currentIndex;
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            for (uint256 i; i < end; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    a[tokenIdsIdx++] = i;
                }
            }
            return a;
        }
    }

    function getTotalSupply() external view returns (uint256) {
        return totalSupply();
    }

    function setBaseURI(string memory baseURI) external onlyOwner {
        require(!locked, "METADATA_LOCKED");
        _baseTokenURI = baseURI;
    }

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

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        return string(abi.encodePacked(super.tokenURI(tokenId), ".json"));
    }

    function _startTokenId() internal view virtual override returns (uint256) {
        return 1;
    }

    address[] public _payees = [
        0xcd245Eb87Cce56756BBF4661A5a88999A48d8752,
        0xfebbB48C8f7A67Dc3DcEE19524A410E078e6A6a1,
        0x0C07747AB98EE84971C90Fbd353eda207B737c43,
        0x867Eb0804eACA9FEeda8a0E1d2B9a32eEF58AF8f
    ];
    uint256[] private _shares = [15, 10, 10, 65];

    // OpenSea's new bullshit requirements, which violate my moral code, but
    // are nonetheless necessary to make this all work properly.
    // They are also bloated as fuck and generally annoying, but if they do
    // not exist, OpenSea refuses to work properly. :middle_finger_emoji:
    function setApprovalForAll(address operator, bool approved)
        public
        override
        onlyAllowedOperatorApproval(operator)
    {
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId)
        public
        override
        onlyAllowedOperatorApproval(operator)
    {
        super.approve(operator, tokenId);
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"AirdropActivation","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":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"FreeMintActivation","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":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"PayeeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"SaleActivation","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":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_payees","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"addressesThatMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_counts","type":"uint256[]"},{"internalType":"address[]","name":"_list","type":"address[]"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"airdropIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"flipMintStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"memberTokenId","type":"uint256"}],"name":"freeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freeMintIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freeMintStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"otherContract","type":"address"},{"internalType":"uint256","name":"key","type":"uint256"}],"name":"getNftTokenForgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getWalletOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"memberFreeMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"membership","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"payee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"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":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPurchase","type":"uint256"}],"name":"setMaxPurchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleAirdropStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleSaleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"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"},{"stateMutability":"payable","type":"receive"}]

6080604052670214e8348c4f00006011556021601255610d056013556000601460006101000a81548160ff0219169083151502179055506001601460016101000a81548160ff0219169083151502179055506001601460026101000a81548160ff02191690831515021790555073ba3b1b86ae330d2118e868b4906cc954a4207835601460036101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518060400160405280601f81526020017f68747470733a2f2f6170656c69717569642e696f2f706574732f6a736f6e2f008152506017908162000107919062000ddd565b50604051806080016040528073cd245eb87cce56756bbf4661a5a88999a48d875273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200173febbb48c8f7a67dc3dcee19524a410e078e6a6a173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001730c07747ab98ee84971c90fbd353eda207b737c4373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200173867eb0804eaca9feeda8a0e1d2b9a32eef58af8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525060199060046200023b92919062000a5e565b506040518060800160405280600f60ff168152602001600a60ff168152602001600a60ff168152602001604160ff16815250601a9060046200027f92919062000aed565b503480156200028d57600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb6600160198054806020026020016040519081016040528092919081815260200182805480156200032957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311620002de575b5050505050601a8054806020026020016040519081016040528092919081815260200182805480156200037c57602002820191906000526020600020905b81548152602001906001019080831162000367575b50505050506040518060400160405280600b81526020017f4d797468696320506574730000000000000000000000000000000000000000008152506040518060400160405280600481526020017f50455453000000000000000000000000000000000000000000000000000000008152508160029081620003fe919062000ddd565b50806003908162000410919062000ddd565b50620004216200074e60201b60201c565b6000819055505050600160088190555062000451620004456200075760201b60201c565b6200075f60201b60201c565b805182511462000498576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200048f9062000f4b565b60405180910390fd5b6000825111620004df576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004d69062000fbd565b60405180910390fd5b60005b82518110156200054e576200053883828151811062000506576200050562000fdf565b5b602002602001015183838151811062000524576200052362000fdf565b5b60200260200101516200082560201b60201c565b808062000545906200103d565b915050620004e2565b50505060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620007465780156200060c576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401620005d2929190620010cf565b600060405180830381600087803b158015620005ed57600080fd5b505af115801562000602573d6000803e3d6000fd5b5050505062000745565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614620006c6576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200068c929190620010cf565b600060405180830381600087803b158015620006a757600080fd5b505af1158015620006bc573d6000803e3d6000fd5b5050505062000744565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016200070f9190620010fc565b600060405180830381600087803b1580156200072a57600080fd5b505af11580156200073f573d6000803e3d6000fd5b505050505b5b5b505062001334565b60006001905090565b600033905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000897576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200088e906200118f565b60405180910390fd5b60008111620008dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008d49062001201565b60405180910390fd5b6000600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541462000962576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620009599062001299565b60405180910390fd5b600e829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600a5462000a199190620012bb565b600a819055507f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac828260405162000a5292919062001307565b60405180910390a15050565b82805482825590600052602060002090810192821562000ada579160200282015b8281111562000ad95782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000a7f565b5b50905062000ae9919062000b44565b5090565b82805482825590600052602060002090810192821562000b31579160200282015b8281111562000b30578251829060ff1690559160200191906001019062000b0e565b5b50905062000b40919062000b44565b5090565b5b8082111562000b5f57600081600090555060010162000b45565b5090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062000be557607f821691505b60208210810362000bfb5762000bfa62000b9d565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000c657fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000c26565b62000c71868362000c26565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000cbe62000cb862000cb28462000c89565b62000c93565b62000c89565b9050919050565b6000819050919050565b62000cda8362000c9d565b62000cf262000ce98262000cc5565b84845462000c33565b825550505050565b600090565b62000d0962000cfa565b62000d1681848462000ccf565b505050565b5b8181101562000d3e5762000d3260008262000cff565b60018101905062000d1c565b5050565b601f82111562000d8d5762000d578162000c01565b62000d628462000c16565b8101602085101562000d72578190505b62000d8a62000d818562000c16565b83018262000d1b565b50505b505050565b600082821c905092915050565b600062000db26000198460080262000d92565b1980831691505092915050565b600062000dcd838362000d9f565b9150826002028217905092915050565b62000de88262000b63565b67ffffffffffffffff81111562000e045762000e0362000b6e565b5b62000e10825462000bcc565b62000e1d82828562000d42565b600060209050601f83116001811462000e55576000841562000e40578287015190505b62000e4c858262000dbf565b86555062000ebc565b601f19841662000e658662000c01565b60005b8281101562000e8f5784890151825560018201915060208501945060208101905062000e68565b8683101562000eaf578489015162000eab601f89168262000d9f565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b7f5061796d656e7453706c69747465723a2070617965657320616e64207368617260008201527f6573206c656e677468206d69736d617463680000000000000000000000000000602082015250565b600062000f3360328362000ec4565b915062000f408262000ed5565b604082019050919050565b6000602082019050818103600083015262000f668162000f24565b9050919050565b7f5061796d656e7453706c69747465723a206e6f20706179656573000000000000600082015250565b600062000fa5601a8362000ec4565b915062000fb28262000f6d565b602082019050919050565b6000602082019050818103600083015262000fd88162000f96565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200104a8262000c89565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200107f576200107e6200100e565b5b600182019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620010b7826200108a565b9050919050565b620010c981620010aa565b82525050565b6000604082019050620010e66000830185620010be565b620010f56020830184620010be565b9392505050565b6000602082019050620011136000830184620010be565b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973207468652060008201527f7a65726f20616464726573730000000000000000000000000000000000000000602082015250565b600062001177602c8362000ec4565b9150620011848262001119565b604082019050919050565b60006020820190508181036000830152620011aa8162001168565b9050919050565b7f5061796d656e7453706c69747465723a20736861726573206172652030000000600082015250565b6000620011e9601d8362000ec4565b9150620011f682620011b1565b602082019050919050565b600060208201905081810360008301526200121c81620011da565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e7420616c726561647960008201527f2068617320736861726573000000000000000000000000000000000000000000602082015250565b600062001281602b8362000ec4565b91506200128e8262001223565b604082019050919050565b60006020820190508181036000830152620012b48162001272565b9050919050565b6000620012c88262000c89565b9150620012d58362000c89565b9250828201905080821115620012f057620012ef6200100e565b5b92915050565b620013018162000c89565b82525050565b60006040820190506200131e6000830185620010be565b6200132d6020830184620012f6565b9392505050565b615fdb80620013446000396000f3fe60806040526004361061031e5760003560e01c80637c928fe9116101ab578063b88d4fde116100f7578063e33b7de311610095578063ef6d49271161006f578063ef6d492714610c4e578063f2fde38b14610c65578063f4a0a52814610c8e578063fa6c6a5714610cb757610365565b8063e33b7de314610bbb578063e985e9c514610be6578063eb8d244414610c2357610365565b8063ce7c2ac2116100d1578063ce7c2ac214610aeb578063cf30901214610b28578063d5abeb0114610b53578063d79779b214610b7e57610365565b8063b88d4fde14610a5a578063c4e41b2214610a83578063c87b56dd14610aae57610365565b80639852595c11610164578063a22cb4651161013e578063a22cb4651461099e578063a2bf68b9146109c7578063aa3f3955146109f2578063ab2fdb0c14610a1d57610365565b80639852595c1461092e578063989bdbb61461096b578063a0712d681461098257610365565b80637c928fe91461081e57806387d0a657146108475780638b83209b146108705780638da5cb5b146108ad57806395d89b41146108d8578063977b055b1461090357610365565b806342842e0e1161026a578063627fdeab116102235780636817c76c116101fd5780636817c76c1461077657806370a08231146107a157806371189742146107de578063715018a61461080757610365565b8063627fdeab146106d35780636352211e146107105780636673c4c21461074d57610365565b806342842e0e146105c757806348b75044146105f05780634a9484e6146106195780634e71d92d14610656578063545dfaeb1461066d57806355f804b3146106aa57610365565b806319165587116102d757806335ee0fd2116102b157806335ee0fd2146105095780633a98ef3914610534578063406072a91461055f57806341f434341461059c57610365565b8063191655871461047a57806323b872dd146104a3578063283248be146104cc57610365565b806301ffc9a71461036a578063049c5c49146103a757806306fdde03146103be578063081812fc146103e9578063095ea7b31461042657806318160ddd1461044f57610365565b36610365577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77061034c610cce565b3460405161035b929190614450565b60405180910390a1005b600080fd5b34801561037657600080fd5b50610391600480360381019061038c91906144e5565b610cd6565b60405161039e919061452d565b60405180910390f35b3480156103b357600080fd5b506103bc610db8565b005b3480156103ca57600080fd5b506103d3610ea6565b6040516103e091906145d8565b60405180910390f35b3480156103f557600080fd5b50610410600480360381019061040b9190614626565b610f38565b60405161041d9190614653565b60405180910390f35b34801561043257600080fd5b5061044d6004803603810190610448919061469a565b610fb4565b005b34801561045b57600080fd5b506104646110be565b60405161047191906146da565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c9190614733565b6110d5565b005b3480156104af57600080fd5b506104ca60048036038101906104c59190614760565b61127f565b005b3480156104d857600080fd5b506104f360048036038101906104ee9190614626565b61128f565b6040516105009190614653565b60405180910390f35b34801561051557600080fd5b5061051e6112ce565b60405161052b919061452d565b60405180910390f35b34801561054057600080fd5b506105496112e1565b60405161055691906146da565b60405180910390f35b34801561056b57600080fd5b50610586600480360381019061058191906147f1565b6112eb565b60405161059391906146da565b60405180910390f35b3480156105a857600080fd5b506105b1611372565b6040516105be9190614890565b60405180910390f35b3480156105d357600080fd5b506105ee60048036038101906105e99190614760565b611384565b005b3480156105fc57600080fd5b50610617600480360381019061061291906147f1565b6113a4565b005b34801561062557600080fd5b50610640600480360381019061063b919061469a565b61165c565b60405161064d9190614653565b60405180910390f35b34801561066257600080fd5b5061066b6116e0565b005b34801561067957600080fd5b50610694600480360381019061068f9190614626565b6116eb565b6040516106a1919061452d565b60405180910390f35b3480156106b657600080fd5b506106d160048036038101906106cc91906149e0565b61170b565b005b3480156106df57600080fd5b506106fa60048036038101906106f59190614a29565b6117ea565b6040516107079190614b14565b60405180910390f35b34801561071c57600080fd5b5061073760048036038101906107329190614626565b6119e0565b6040516107449190614653565b60405180910390f35b34801561075957600080fd5b50610774600480360381019061076f9190614bec565b6119f6565b005b34801561078257600080fd5b5061078b611ba3565b60405161079891906146da565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190614a29565b611ba9565b6040516107d591906146da565b60405180910390f35b3480156107ea57600080fd5b5061080560048036038101906108009190614626565b611c78565b005b34801561081357600080fd5b5061081c611cfe565b005b34801561082a57600080fd5b5061084560048036038101906108409190614626565b611d86565b005b34801561085357600080fd5b5061086e60048036038101906108699190614626565b611fbb565b005b34801561087c57600080fd5b5061089760048036038101906108929190614626565b612086565b6040516108a49190614653565b60405180910390f35b3480156108b957600080fd5b506108c26120ce565b6040516108cf9190614653565b60405180910390f35b3480156108e457600080fd5b506108ed6120f8565b6040516108fa91906145d8565b60405180910390f35b34801561090f57600080fd5b5061091861218a565b60405161092591906146da565b60405180910390f35b34801561093a57600080fd5b5061095560048036038101906109509190614a29565b612190565b60405161096291906146da565b60405180910390f35b34801561097757600080fd5b506109806121d9565b005b61099c60048036038101906109979190614626565b612272565b005b3480156109aa57600080fd5b506109c560048036038101906109c09190614c99565b6124af565b005b3480156109d357600080fd5b506109dc6125b9565b6040516109e99190614653565b60405180910390f35b3480156109fe57600080fd5b50610a076125df565b604051610a14919061452d565b60405180910390f35b348015610a2957600080fd5b50610a446004803603810190610a3f9190614a29565b6125f2565b604051610a5191906146da565b60405180910390f35b348015610a6657600080fd5b50610a816004803603810190610a7c9190614d7a565b61260a565b005b348015610a8f57600080fd5b50610a98612686565b604051610aa591906146da565b60405180910390f35b348015610aba57600080fd5b50610ad56004803603810190610ad09190614626565b612695565b604051610ae291906145d8565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d9190614a29565b6126c6565b604051610b1f91906146da565b60405180910390f35b348015610b3457600080fd5b50610b3d61270f565b604051610b4a919061452d565b60405180910390f35b348015610b5f57600080fd5b50610b68612722565b604051610b7591906146da565b60405180910390f35b348015610b8a57600080fd5b50610ba56004803603810190610ba09190614dfd565b612728565b604051610bb291906146da565b60405180910390f35b348015610bc757600080fd5b50610bd0612771565b604051610bdd91906146da565b60405180910390f35b348015610bf257600080fd5b50610c0d6004803603810190610c089190614e2a565b61277b565b604051610c1a919061452d565b60405180910390f35b348015610c2f57600080fd5b50610c3861280f565b604051610c45919061452d565b60405180910390f35b348015610c5a57600080fd5b50610c63612822565b005b348015610c7157600080fd5b50610c8c6004803603810190610c879190614a29565b612910565b005b348015610c9a57600080fd5b50610cb56004803603810190610cb09190614626565b612a07565b005b348015610cc357600080fd5b50610ccc612a8d565b005b600033905090565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610da157507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610db15750610db082612b7b565b5b9050919050565b610dc0610cce565b73ffffffffffffffffffffffffffffffffffffffff16610dde6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b90614eb6565b60405180910390fd5b601460009054906101000a900460ff1615601460006101000a81548160ff0219169083151502179055507f58655b75d3df612fe99ead00dbf0812d415d35078fe06217a94c0818bb13967f601460009054906101000a900460ff16604051610e9c919061452d565b60405180910390a1565b606060028054610eb590614f05565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee190614f05565b8015610f2e5780601f10610f0357610100808354040283529160200191610f2e565b820191906000526020600020905b815481529060010190602001808311610f1157829003601f168201915b5050505050905090565b6000610f4382612be5565b610f79576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156110af576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161102c929190614f36565b602060405180830381865afa158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d9190614f74565b6110ae57806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016110a59190614653565b60405180910390fd5b5b6110b98383612c33565b505050565b60006110c8612d3d565b6001546000540303905090565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e90615013565b60405180910390fd5b6000611161612771565b4761116c9190615062565b90506000611183838361117e86612190565b612d46565b9050600081036111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90615108565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546112179190615062565b9250508190555080600b60008282546112309190615062565b925050819055506112418382612db4565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568382604051611272929190615149565b60405180910390a1505050565b61128a838383612ea8565b505050565b6019818154811061129f57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b601460019054906101000a900460ff1681565b6000600a54905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6daaeb6d7670e522a718067333cd4e81565b61139f8383836040518060200160405280600081525061260a565b505050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141d90615013565b60405180910390fd5b600061143183612728565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161146a9190614653565b602060405180830381865afa158015611487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ab9190615187565b6114b59190615062565b905060006114cd83836114c887876112eb565b612d46565b905060008103611512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161150990615108565b60405180910390fd5b80601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461159e9190615062565b9250508190555080600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f49190615062565b9250508190555061160684848361335c565b8373ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a848360405161164e929190614450565b60405180910390a250505050565b60008273ffffffffffffffffffffffffffffffffffffffff1663242772b8836040518263ffffffff1660e01b815260040161169791906146da565b602060405180830381865afa1580156116b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d891906151c9565b905092915050565b6116e9336110d5565b565b60166020528060005260406000206000915054906101000a900460ff1681565b611713610cce565b73ffffffffffffffffffffffffffffffffffffffff166117316120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611787576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177e90614eb6565b60405180910390fd5b601860009054906101000a900460ff16156117d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117ce90615242565b60405180910390fd5b80601790816117e69190615404565b5050565b606060006117f783611ba9565b67ffffffffffffffff8111156118105761180f6148b5565b5b60405190808252806020026020018201604052801561183e5781602001602082028036833780820191505090505b50905060008054905060008060005b838110156119d3576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff161515151581525050905080604001511561192a57506119c6565b600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461196a57806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036119c457818685806001019650815181106119b7576119b66154d6565b5b6020026020010181815250505b505b808060010191505061184d565b5083945050505050919050565b60006119eb826133e2565b600001519050919050565b6119fe610cce565b73ffffffffffffffffffffffffffffffffffffffff16611a1c6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6990614eb6565b60405180910390fd5b601460029054906101000a900460ff16611ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ab890615551565b60405180910390fd5b60005b82829050811015611b9c57601354858583818110611ae557611ae46154d6565b5b90506020020135611af46110be565b611afe9190615062565b1115611b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b36906155bd565b60405180910390fd5b611b89838383818110611b5557611b546154d6565b5b9050602002016020810190611b6a9190614a29565b868684818110611b7d57611b7c6154d6565b5b90506020020135613671565b8080611b94906155dd565b915050611ac4565b5050505050565b60115481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c10576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611c80610cce565b73ffffffffffffffffffffffffffffffffffffffff16611c9e6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611cf4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ceb90614eb6565b60405180910390fd5b8060128190555050565b611d06610cce565b73ffffffffffffffffffffffffffffffffffffffff16611d246120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611d7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7190614eb6565b60405180910390fd5b611d84600061368f565b565b600260085403611dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc290615671565b60405180910390fd5b6002600881905550600060019050601460019054906101000a900460ff16611e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1f906156dd565b60405180910390fd5b6016600083815260200190815260200160002060009054906101000a900460ff1615611e89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8090615749565b60405180910390fd5b60135481611e956110be565b611e9f9190615062565b1115611ee0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed7906155bd565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16611f23601460039054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461165c565b73ffffffffffffffffffffffffffffffffffffffff1614611f79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f70906157b5565b60405180910390fd5b611f833382613671565b60016016600084815260200190815260200160002060006101000a81548160ff02191690831515021790555050600160088190555050565b611fc3610cce565b73ffffffffffffffffffffffffffffffffffffffff16611fe16120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202e90614eb6565b60405180910390fd5b6016600082815260200190815260200160002060009054906101000a900460ff16156016600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000600e828154811061209c5761209b6154d6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461210790614f05565b80601f016020809104026020016040519081016040528092919081815260200182805461213390614f05565b80156121805780601f1061215557610100808354040283529160200191612180565b820191906000526020600020905b81548152906001019060200180831161216357829003601f168201915b5050505050905090565b60125481565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6121e1610cce565b73ffffffffffffffffffffffffffffffffffffffff166121ff6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224c90614eb6565b60405180910390fd5b6001601860006101000a81548160ff021916908315150217905550565b6002600854036122b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ae90615671565b60405180910390fd5b6002600881905550601460009054906101000a900460ff1661230e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230590615821565b60405180910390fd5b60125481601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461235c9190615062565b111561239d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612394906158b3565b60405180910390fd5b601354816123a96110be565b6123b39190615062565b11156123f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123eb906155bd565b60405180910390fd5b348160115461240391906158d3565b1115612444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243b90615961565b60405180910390fd5b61244e3382613671565b80601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461249d9190615062565b92505081905550600160088190555050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156125aa576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401612527929190614f36565b602060405180830381865afa158015612544573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125689190614f74565b6125a957806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016125a09190614653565b60405180910390fd5b5b6125b48383613755565b505050565b601460039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b601460029054906101000a900460ff1681565b60156020528060005260406000206000915090505481565b612615848484612ea8565b6126348373ffffffffffffffffffffffffffffffffffffffff166138cc565b80156126495750612647848484846138df565b155b15612680576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60006126906110be565b905090565b60606126a082613a2f565b6040516020016126b09190615a09565b6040516020818303038152906040529050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b601860009054906101000a900460ff1681565b60135481565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600b54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b601460009054906101000a900460ff1681565b61282a610cce565b73ffffffffffffffffffffffffffffffffffffffff166128486120ce565b73ffffffffffffffffffffffffffffffffffffffff161461289e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289590614eb6565b60405180910390fd5b601460029054906101000a900460ff1615601460026101000a81548160ff0219169083151502179055507f1727dc7b28fffc84b95ca0e64637ec1614ea28c6bc7e9efa20b6df6b2e65fe87601460029054906101000a900460ff16604051612906919061452d565b60405180910390a1565b612918610cce565b73ffffffffffffffffffffffffffffffffffffffff166129366120ce565b73ffffffffffffffffffffffffffffffffffffffff161461298c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161298390614eb6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129f290615a9d565b60405180910390fd5b612a048161368f565b50565b612a0f610cce565b73ffffffffffffffffffffffffffffffffffffffff16612a2d6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7a90614eb6565b60405180910390fd5b8060118190555050565b612a95610cce565b73ffffffffffffffffffffffffffffffffffffffff16612ab36120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612b09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0090614eb6565b60405180910390fd5b601460019054906101000a900460ff1615601460016101000a81548160ff0219169083151502179055507f8141ae84dbba32371aea19ef6ed4c40c1effede9613bc317cb583a6b8a6660dd601460019054906101000a900460ff16604051612b71919061452d565b60405180910390a1565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612bf0612d3d565b11158015612bff575060005482105b8015612c2c575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b6000612c3e826119e0565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ca5576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16612cc4610cce565b73ffffffffffffffffffffffffffffffffffffffff1614158015612cf65750612cf481612cef610cce565b61277b565b155b15612d2d576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d38838383613acd565b505050565b60006001905090565b600081600a54600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205485612d9791906158d3565b612da19190615aec565b612dab9190615b1d565b90509392505050565b80471015612df7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dee90615b9d565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051612e1d90615bee565b60006040518083038185875af1925050503d8060008114612e5a576040519150601f19603f3d011682016040523d82523d6000602084013e612e5f565b606091505b5050905080612ea3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9a90615c75565b60405180910390fd5b505050565b6000612eb3826133e2565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612f1e576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16612f3f610cce565b73ffffffffffffffffffffffffffffffffffffffff161480612f6e5750612f6d85612f68610cce565b61277b565b5b80612fb35750612f7c610cce565b73ffffffffffffffffffffffffffffffffffffffff16612f9b84610f38565b73ffffffffffffffffffffffffffffffffffffffff16145b905080612fec576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613052576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61305f8585856001613b7f565b61306b60008487613acd565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036132ea5760005482146132e957878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46133558585856001613b85565b5050505050565b6133dd8363a9059cbb60e01b848460405160240161337b929190614450565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613b8b565b505050565b6133ea6143b3565b6000829050806133f8612d3d565b11158015613407575060005481105b1561363a576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161363857600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461351c57809250505061366c565b5b60011561363757818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461363257809250505061366c565b61351d565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b61368b828260405180602001604052806000815250613c52565b5050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61375d610cce565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036137c1576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006137ce610cce565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661387b610cce565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516138c0919061452d565b60405180910390a35050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613905610cce565b8786866040518563ffffffff1660e01b81526004016139279493929190615cea565b6020604051808303816000875af192505050801561396357506040513d601f19601f820116820180604052508101906139609190615d4b565b60015b6139dc573d8060008114613993576040519150601f19603f3d011682016040523d82523d6000602084013e613998565b606091505b5060008151036139d4576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6060613a3a82612be5565b613a70576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613a7a613c64565b90506000815103613a9a5760405180602001604052806000815250613ac5565b80613aa484613cf6565b604051602001613ab5929190615d78565b6040516020818303038152906040525b915050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b50505050565b50505050565b6000613bed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613e569092919063ffffffff16565b9050600081511115613c4d5780806020019051810190613c0d9190614f74565b613c4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c4390615e0e565b60405180910390fd5b5b505050565b613c5f8383836001613e6e565b505050565b606060178054613c7390614f05565b80601f0160208091040260200160405190810160405280929190818152602001828054613c9f90614f05565b8015613cec5780601f10613cc157610100808354040283529160200191613cec565b820191906000526020600020905b815481529060010190602001808311613ccf57829003601f168201915b5050505050905090565b606060008203613d3d576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613e51565b600082905060005b60008214613d6f578080613d58906155dd565b915050600a82613d689190615aec565b9150613d45565b60008167ffffffffffffffff811115613d8b57613d8a6148b5565b5b6040519080825280601f01601f191660200182016040528015613dbd5781602001600182028036833780820191505090505b5090505b60008514613e4a57600182613dd69190615b1d565b9150600a85613de59190615e2e565b6030613df19190615062565b60f81b818381518110613e0757613e066154d6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85613e439190615aec565b9450613dc1565b8093505050505b919050565b6060613e658484600085614238565b90509392505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613eda576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613f14576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613f216000868387613b7f565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600085820190508380156140eb57506140ea8773ffffffffffffffffffffffffffffffffffffffff166138cc565b5b156141b0575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461416060008884806001019550886138df565b614196576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082036140f15782600054146141ab57600080fd5b61421b565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48082036141b1575b8160008190555050506142316000868387613b85565b5050505050565b60608247101561427d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161427490615ed1565b60405180910390fd5b614286856138cc565b6142c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142bc90615f3d565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516142ee9190615f8e565b60006040518083038185875af1925050503d806000811461432b576040519150601f19603f3d011682016040523d82523d6000602084013e614330565b606091505b509150915061434082828661434c565b92505050949350505050565b6060831561435c578290506143ac565b60008351111561436f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016143a391906145d8565b60405180910390fd5b9392505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614421826143f6565b9050919050565b61443181614416565b82525050565b6000819050919050565b61444a81614437565b82525050565b60006040820190506144656000830185614428565b6144726020830184614441565b9392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6144c28161448d565b81146144cd57600080fd5b50565b6000813590506144df816144b9565b92915050565b6000602082840312156144fb576144fa614483565b5b6000614509848285016144d0565b91505092915050565b60008115159050919050565b61452781614512565b82525050565b6000602082019050614542600083018461451e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015614582578082015181840152602081019050614567565b60008484015250505050565b6000601f19601f8301169050919050565b60006145aa82614548565b6145b48185614553565b93506145c4818560208601614564565b6145cd8161458e565b840191505092915050565b600060208201905081810360008301526145f2818461459f565b905092915050565b61460381614437565b811461460e57600080fd5b50565b600081359050614620816145fa565b92915050565b60006020828403121561463c5761463b614483565b5b600061464a84828501614611565b91505092915050565b60006020820190506146686000830184614428565b92915050565b61467781614416565b811461468257600080fd5b50565b6000813590506146948161466e565b92915050565b600080604083850312156146b1576146b0614483565b5b60006146bf85828601614685565b92505060206146d085828601614611565b9150509250929050565b60006020820190506146ef6000830184614441565b92915050565b6000614700826143f6565b9050919050565b614710816146f5565b811461471b57600080fd5b50565b60008135905061472d81614707565b92915050565b60006020828403121561474957614748614483565b5b60006147578482850161471e565b91505092915050565b60008060006060848603121561477957614778614483565b5b600061478786828701614685565b935050602061479886828701614685565b92505060406147a986828701614611565b9150509250925092565b60006147be82614416565b9050919050565b6147ce816147b3565b81146147d957600080fd5b50565b6000813590506147eb816147c5565b92915050565b6000806040838503121561480857614807614483565b5b6000614816858286016147dc565b925050602061482785828601614685565b9150509250929050565b6000819050919050565b600061485661485161484c846143f6565b614831565b6143f6565b9050919050565b60006148688261483b565b9050919050565b600061487a8261485d565b9050919050565b61488a8161486f565b82525050565b60006020820190506148a56000830184614881565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6148ed8261458e565b810181811067ffffffffffffffff8211171561490c5761490b6148b5565b5b80604052505050565b600061491f614479565b905061492b82826148e4565b919050565b600067ffffffffffffffff82111561494b5761494a6148b5565b5b6149548261458e565b9050602081019050919050565b82818337600083830152505050565b600061498361497e84614930565b614915565b90508281526020810184848401111561499f5761499e6148b0565b5b6149aa848285614961565b509392505050565b600082601f8301126149c7576149c66148ab565b5b81356149d7848260208601614970565b91505092915050565b6000602082840312156149f6576149f5614483565b5b600082013567ffffffffffffffff811115614a1457614a13614488565b5b614a20848285016149b2565b91505092915050565b600060208284031215614a3f57614a3e614483565b5b6000614a4d84828501614685565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614a8b81614437565b82525050565b6000614a9d8383614a82565b60208301905092915050565b6000602082019050919050565b6000614ac182614a56565b614acb8185614a61565b9350614ad683614a72565b8060005b83811015614b07578151614aee8882614a91565b9750614af983614aa9565b925050600181019050614ada565b5085935050505092915050565b60006020820190508181036000830152614b2e8184614ab6565b905092915050565b600080fd5b600080fd5b60008083601f840112614b5657614b556148ab565b5b8235905067ffffffffffffffff811115614b7357614b72614b36565b5b602083019150836020820283011115614b8f57614b8e614b3b565b5b9250929050565b60008083601f840112614bac57614bab6148ab565b5b8235905067ffffffffffffffff811115614bc957614bc8614b36565b5b602083019150836020820283011115614be557614be4614b3b565b5b9250929050565b60008060008060408587031215614c0657614c05614483565b5b600085013567ffffffffffffffff811115614c2457614c23614488565b5b614c3087828801614b40565b9450945050602085013567ffffffffffffffff811115614c5357614c52614488565b5b614c5f87828801614b96565b925092505092959194509250565b614c7681614512565b8114614c8157600080fd5b50565b600081359050614c9381614c6d565b92915050565b60008060408385031215614cb057614caf614483565b5b6000614cbe85828601614685565b9250506020614ccf85828601614c84565b9150509250929050565b600067ffffffffffffffff821115614cf457614cf36148b5565b5b614cfd8261458e565b9050602081019050919050565b6000614d1d614d1884614cd9565b614915565b905082815260208101848484011115614d3957614d386148b0565b5b614d44848285614961565b509392505050565b600082601f830112614d6157614d606148ab565b5b8135614d71848260208601614d0a565b91505092915050565b60008060008060808587031215614d9457614d93614483565b5b6000614da287828801614685565b9450506020614db387828801614685565b9350506040614dc487828801614611565b925050606085013567ffffffffffffffff811115614de557614de4614488565b5b614df187828801614d4c565b91505092959194509250565b600060208284031215614e1357614e12614483565b5b6000614e21848285016147dc565b91505092915050565b60008060408385031215614e4157614e40614483565b5b6000614e4f85828601614685565b9250506020614e6085828601614685565b9150509250929050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614ea0602083614553565b9150614eab82614e6a565b602082019050919050565b60006020820190508181036000830152614ecf81614e93565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614f1d57607f821691505b602082108103614f3057614f2f614ed6565b5b50919050565b6000604082019050614f4b6000830185614428565b614f586020830184614428565b9392505050565b600081519050614f6e81614c6d565b92915050565b600060208284031215614f8a57614f89614483565b5b6000614f9884828501614f5f565b91505092915050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000614ffd602683614553565b915061500882614fa1565b604082019050919050565b6000602082019050818103600083015261502c81614ff0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061506d82614437565b915061507883614437565b92508282019050808211156150905761508f615033565b5b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b60006150f2602b83614553565b91506150fd82615096565b604082019050919050565b60006020820190508181036000830152615121816150e5565b9050919050565b60006151338261485d565b9050919050565b61514381615128565b82525050565b600060408201905061515e600083018561513a565b61516b6020830184614441565b9392505050565b600081519050615181816145fa565b92915050565b60006020828403121561519d5761519c614483565b5b60006151ab84828501615172565b91505092915050565b6000815190506151c38161466e565b92915050565b6000602082840312156151df576151de614483565b5b60006151ed848285016151b4565b91505092915050565b7f4d455441444154415f4c4f434b45440000000000000000000000000000000000600082015250565b600061522c600f83614553565b9150615237826151f6565b602082019050919050565b6000602082019050818103600083015261525b8161521f565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026152c47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615287565b6152ce8683615287565b95508019841693508086168417925050509392505050565b60006153016152fc6152f784614437565b614831565b614437565b9050919050565b6000819050919050565b61531b836152e6565b61532f61532782615308565b848454615294565b825550505050565b600090565b615344615337565b61534f818484615312565b505050565b5b818110156153735761536860008261533c565b600181019050615355565b5050565b601f8211156153b85761538981615262565b61539284615277565b810160208510156153a1578190505b6153b56153ad85615277565b830182615354565b50505b505050565b600082821c905092915050565b60006153db600019846008026153bd565b1980831691505092915050565b60006153f483836153ca565b9150826002028217905092915050565b61540d82614548565b67ffffffffffffffff811115615426576154256148b5565b5b6154308254614f05565b61543b828285615377565b600060209050601f83116001811461546e576000841561545c578287015190505b61546685826153e8565b8655506154ce565b601f19841661547c86615262565b60005b828110156154a45784890151825560018201915060208501945060208101905061547f565b868310156154c157848901516154bd601f8916826153ca565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f41495244524f50204e4f54204143544956450000000000000000000000000000600082015250565b600061553b601283614553565b915061554682615505565b602082019050919050565b6000602082019050818103600083015261556a8161552e565b9050919050565b7f534f4c44204f5554000000000000000000000000000000000000000000000000600082015250565b60006155a7600883614553565b91506155b282615571565b602082019050919050565b600060208201905081810360008301526155d68161559a565b9050919050565b60006155e882614437565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361561a57615619615033565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061565b601f83614553565b915061566682615625565b602082019050919050565b6000602082019050818103600083015261568a8161564e565b9050919050565b7f46524545204d494e5420494e4143544956450000000000000000000000000000600082015250565b60006156c7601283614553565b91506156d282615691565b602082019050919050565b600060208201905081810360008301526156f6816156ba565b9050919050565b7f416c7265616479204d696e746564210000000000000000000000000000000000600082015250565b6000615733600f83614553565b915061573e826156fd565b602082019050919050565b6000602082019050818103600083015261576281615726565b9050919050565b7f54686973206d656d62657273686970206973206e6f7420666f72676564210000600082015250565b600061579f601e83614553565b91506157aa82615769565b602082019050919050565b600060208201905081810360008301526157ce81615792565b9050919050565b7f53414c4520494e41435449564500000000000000000000000000000000000000600082015250565b600061580b600d83614553565b9150615816826157d5565b602082019050919050565b6000602082019050818103600083015261583a816157fe565b9050919050565b7f7468697320776f756c6420657863656564206d696e74206d617820616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b600061589d602483614553565b91506158a882615841565b604082019050919050565b600060208201905081810360008301526158cc81615890565b9050919050565b60006158de82614437565b91506158e983614437565b92508282026158f781614437565b9150828204841483151761590e5761590d615033565b5b5092915050565b7f494e434f52524543542045544845522056414c55450000000000000000000000600082015250565b600061594b601583614553565b915061595682615915565b602082019050919050565b6000602082019050818103600083015261597a8161593e565b9050919050565b600081905092915050565b600061599782614548565b6159a18185615981565b93506159b1818560208601614564565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b60006159f3600583615981565b91506159fe826159bd565b600582019050919050565b6000615a15828461598c565b9150615a20826159e6565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615a87602683614553565b9150615a9282615a2b565b604082019050919050565b60006020820190508181036000830152615ab681615a7a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615af782614437565b9150615b0283614437565b925082615b1257615b11615abd565b5b828204905092915050565b6000615b2882614437565b9150615b3383614437565b9250828203905081811115615b4b57615b4a615033565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000615b87601d83614553565b9150615b9282615b51565b602082019050919050565b60006020820190508181036000830152615bb681615b7a565b9050919050565b600081905092915050565b50565b6000615bd8600083615bbd565b9150615be382615bc8565b600082019050919050565b6000615bf982615bcb565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b6000615c5f603a83614553565b9150615c6a82615c03565b604082019050919050565b60006020820190508181036000830152615c8e81615c52565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000615cbc82615c95565b615cc68185615ca0565b9350615cd6818560208601614564565b615cdf8161458e565b840191505092915050565b6000608082019050615cff6000830187614428565b615d0c6020830186614428565b615d196040830185614441565b8181036060830152615d2b8184615cb1565b905095945050505050565b600081519050615d45816144b9565b92915050565b600060208284031215615d6157615d60614483565b5b6000615d6f84828501615d36565b91505092915050565b6000615d84828561598c565b9150615d90828461598c565b91508190509392505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000615df8602a83614553565b9150615e0382615d9c565b604082019050919050565b60006020820190508181036000830152615e2781615deb565b9050919050565b6000615e3982614437565b9150615e4483614437565b925082615e5457615e53615abd565b5b828206905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000615ebb602683614553565b9150615ec682615e5f565b604082019050919050565b60006020820190508181036000830152615eea81615eae565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000615f27601d83614553565b9150615f3282615ef1565b602082019050919050565b60006020820190508181036000830152615f5681615f1a565b9050919050565b6000615f6882615c95565b615f728185615bbd565b9350615f82818560208601614564565b80840191505092915050565b6000615f9a8284615f5d565b91508190509291505056fea2646970667358221220215ad0174425e8b46642e22dd115f297cb220f26a08a40ef818b22f744e7292064736f6c63430008110033

Deployed Bytecode

0x60806040526004361061031e5760003560e01c80637c928fe9116101ab578063b88d4fde116100f7578063e33b7de311610095578063ef6d49271161006f578063ef6d492714610c4e578063f2fde38b14610c65578063f4a0a52814610c8e578063fa6c6a5714610cb757610365565b8063e33b7de314610bbb578063e985e9c514610be6578063eb8d244414610c2357610365565b8063ce7c2ac2116100d1578063ce7c2ac214610aeb578063cf30901214610b28578063d5abeb0114610b53578063d79779b214610b7e57610365565b8063b88d4fde14610a5a578063c4e41b2214610a83578063c87b56dd14610aae57610365565b80639852595c11610164578063a22cb4651161013e578063a22cb4651461099e578063a2bf68b9146109c7578063aa3f3955146109f2578063ab2fdb0c14610a1d57610365565b80639852595c1461092e578063989bdbb61461096b578063a0712d681461098257610365565b80637c928fe91461081e57806387d0a657146108475780638b83209b146108705780638da5cb5b146108ad57806395d89b41146108d8578063977b055b1461090357610365565b806342842e0e1161026a578063627fdeab116102235780636817c76c116101fd5780636817c76c1461077657806370a08231146107a157806371189742146107de578063715018a61461080757610365565b8063627fdeab146106d35780636352211e146107105780636673c4c21461074d57610365565b806342842e0e146105c757806348b75044146105f05780634a9484e6146106195780634e71d92d14610656578063545dfaeb1461066d57806355f804b3146106aa57610365565b806319165587116102d757806335ee0fd2116102b157806335ee0fd2146105095780633a98ef3914610534578063406072a91461055f57806341f434341461059c57610365565b8063191655871461047a57806323b872dd146104a3578063283248be146104cc57610365565b806301ffc9a71461036a578063049c5c49146103a757806306fdde03146103be578063081812fc146103e9578063095ea7b31461042657806318160ddd1461044f57610365565b36610365577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77061034c610cce565b3460405161035b929190614450565b60405180910390a1005b600080fd5b34801561037657600080fd5b50610391600480360381019061038c91906144e5565b610cd6565b60405161039e919061452d565b60405180910390f35b3480156103b357600080fd5b506103bc610db8565b005b3480156103ca57600080fd5b506103d3610ea6565b6040516103e091906145d8565b60405180910390f35b3480156103f557600080fd5b50610410600480360381019061040b9190614626565b610f38565b60405161041d9190614653565b60405180910390f35b34801561043257600080fd5b5061044d6004803603810190610448919061469a565b610fb4565b005b34801561045b57600080fd5b506104646110be565b60405161047191906146da565b60405180910390f35b34801561048657600080fd5b506104a1600480360381019061049c9190614733565b6110d5565b005b3480156104af57600080fd5b506104ca60048036038101906104c59190614760565b61127f565b005b3480156104d857600080fd5b506104f360048036038101906104ee9190614626565b61128f565b6040516105009190614653565b60405180910390f35b34801561051557600080fd5b5061051e6112ce565b60405161052b919061452d565b60405180910390f35b34801561054057600080fd5b506105496112e1565b60405161055691906146da565b60405180910390f35b34801561056b57600080fd5b50610586600480360381019061058191906147f1565b6112eb565b60405161059391906146da565b60405180910390f35b3480156105a857600080fd5b506105b1611372565b6040516105be9190614890565b60405180910390f35b3480156105d357600080fd5b506105ee60048036038101906105e99190614760565b611384565b005b3480156105fc57600080fd5b50610617600480360381019061061291906147f1565b6113a4565b005b34801561062557600080fd5b50610640600480360381019061063b919061469a565b61165c565b60405161064d9190614653565b60405180910390f35b34801561066257600080fd5b5061066b6116e0565b005b34801561067957600080fd5b50610694600480360381019061068f9190614626565b6116eb565b6040516106a1919061452d565b60405180910390f35b3480156106b657600080fd5b506106d160048036038101906106cc91906149e0565b61170b565b005b3480156106df57600080fd5b506106fa60048036038101906106f59190614a29565b6117ea565b6040516107079190614b14565b60405180910390f35b34801561071c57600080fd5b5061073760048036038101906107329190614626565b6119e0565b6040516107449190614653565b60405180910390f35b34801561075957600080fd5b50610774600480360381019061076f9190614bec565b6119f6565b005b34801561078257600080fd5b5061078b611ba3565b60405161079891906146da565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190614a29565b611ba9565b6040516107d591906146da565b60405180910390f35b3480156107ea57600080fd5b5061080560048036038101906108009190614626565b611c78565b005b34801561081357600080fd5b5061081c611cfe565b005b34801561082a57600080fd5b5061084560048036038101906108409190614626565b611d86565b005b34801561085357600080fd5b5061086e60048036038101906108699190614626565b611fbb565b005b34801561087c57600080fd5b5061089760048036038101906108929190614626565b612086565b6040516108a49190614653565b60405180910390f35b3480156108b957600080fd5b506108c26120ce565b6040516108cf9190614653565b60405180910390f35b3480156108e457600080fd5b506108ed6120f8565b6040516108fa91906145d8565b60405180910390f35b34801561090f57600080fd5b5061091861218a565b60405161092591906146da565b60405180910390f35b34801561093a57600080fd5b5061095560048036038101906109509190614a29565b612190565b60405161096291906146da565b60405180910390f35b34801561097757600080fd5b506109806121d9565b005b61099c60048036038101906109979190614626565b612272565b005b3480156109aa57600080fd5b506109c560048036038101906109c09190614c99565b6124af565b005b3480156109d357600080fd5b506109dc6125b9565b6040516109e99190614653565b60405180910390f35b3480156109fe57600080fd5b50610a076125df565b604051610a14919061452d565b60405180910390f35b348015610a2957600080fd5b50610a446004803603810190610a3f9190614a29565b6125f2565b604051610a5191906146da565b60405180910390f35b348015610a6657600080fd5b50610a816004803603810190610a7c9190614d7a565b61260a565b005b348015610a8f57600080fd5b50610a98612686565b604051610aa591906146da565b60405180910390f35b348015610aba57600080fd5b50610ad56004803603810190610ad09190614626565b612695565b604051610ae291906145d8565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d9190614a29565b6126c6565b604051610b1f91906146da565b60405180910390f35b348015610b3457600080fd5b50610b3d61270f565b604051610b4a919061452d565b60405180910390f35b348015610b5f57600080fd5b50610b68612722565b604051610b7591906146da565b60405180910390f35b348015610b8a57600080fd5b50610ba56004803603810190610ba09190614dfd565b612728565b604051610bb291906146da565b60405180910390f35b348015610bc757600080fd5b50610bd0612771565b604051610bdd91906146da565b60405180910390f35b348015610bf257600080fd5b50610c0d6004803603810190610c089190614e2a565b61277b565b604051610c1a919061452d565b60405180910390f35b348015610c2f57600080fd5b50610c3861280f565b604051610c45919061452d565b60405180910390f35b348015610c5a57600080fd5b50610c63612822565b005b348015610c7157600080fd5b50610c8c6004803603810190610c879190614a29565b612910565b005b348015610c9a57600080fd5b50610cb56004803603810190610cb09190614626565b612a07565b005b348015610cc357600080fd5b50610ccc612a8d565b005b600033905090565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610da157507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610db15750610db082612b7b565b5b9050919050565b610dc0610cce565b73ffffffffffffffffffffffffffffffffffffffff16610dde6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b90614eb6565b60405180910390fd5b601460009054906101000a900460ff1615601460006101000a81548160ff0219169083151502179055507f58655b75d3df612fe99ead00dbf0812d415d35078fe06217a94c0818bb13967f601460009054906101000a900460ff16604051610e9c919061452d565b60405180910390a1565b606060028054610eb590614f05565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee190614f05565b8015610f2e5780601f10610f0357610100808354040283529160200191610f2e565b820191906000526020600020905b815481529060010190602001808311610f1157829003601f168201915b5050505050905090565b6000610f4382612be5565b610f79576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156110af576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161102c929190614f36565b602060405180830381865afa158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d9190614f74565b6110ae57806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016110a59190614653565b60405180910390fd5b5b6110b98383612c33565b505050565b60006110c8612d3d565b6001546000540303905090565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e90615013565b60405180910390fd5b6000611161612771565b4761116c9190615062565b90506000611183838361117e86612190565b612d46565b9050600081036111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90615108565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546112179190615062565b9250508190555080600b60008282546112309190615062565b925050819055506112418382612db4565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568382604051611272929190615149565b60405180910390a1505050565b61128a838383612ea8565b505050565b6019818154811061129f57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b601460019054906101000a900460ff1681565b6000600a54905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6daaeb6d7670e522a718067333cd4e81565b61139f8383836040518060200160405280600081525061260a565b505050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141d90615013565b60405180910390fd5b600061143183612728565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161146a9190614653565b602060405180830381865afa158015611487573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ab9190615187565b6114b59190615062565b905060006114cd83836114c887876112eb565b612d46565b905060008103611512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161150990615108565b60405180910390fd5b80601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461159e9190615062565b9250508190555080600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f49190615062565b9250508190555061160684848361335c565b8373ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a848360405161164e929190614450565b60405180910390a250505050565b60008273ffffffffffffffffffffffffffffffffffffffff1663242772b8836040518263ffffffff1660e01b815260040161169791906146da565b602060405180830381865afa1580156116b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d891906151c9565b905092915050565b6116e9336110d5565b565b60166020528060005260406000206000915054906101000a900460ff1681565b611713610cce565b73ffffffffffffffffffffffffffffffffffffffff166117316120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611787576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177e90614eb6565b60405180910390fd5b601860009054906101000a900460ff16156117d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117ce90615242565b60405180910390fd5b80601790816117e69190615404565b5050565b606060006117f783611ba9565b67ffffffffffffffff8111156118105761180f6148b5565b5b60405190808252806020026020018201604052801561183e5781602001602082028036833780820191505090505b50905060008054905060008060005b838110156119d3576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff161515151581525050905080604001511561192a57506119c6565b600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461196a57806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036119c457818685806001019650815181106119b7576119b66154d6565b5b6020026020010181815250505b505b808060010191505061184d565b5083945050505050919050565b60006119eb826133e2565b600001519050919050565b6119fe610cce565b73ffffffffffffffffffffffffffffffffffffffff16611a1c6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6990614eb6565b60405180910390fd5b601460029054906101000a900460ff16611ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ab890615551565b60405180910390fd5b60005b82829050811015611b9c57601354858583818110611ae557611ae46154d6565b5b90506020020135611af46110be565b611afe9190615062565b1115611b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b36906155bd565b60405180910390fd5b611b89838383818110611b5557611b546154d6565b5b9050602002016020810190611b6a9190614a29565b868684818110611b7d57611b7c6154d6565b5b90506020020135613671565b8080611b94906155dd565b915050611ac4565b5050505050565b60115481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c10576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611c80610cce565b73ffffffffffffffffffffffffffffffffffffffff16611c9e6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611cf4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ceb90614eb6565b60405180910390fd5b8060128190555050565b611d06610cce565b73ffffffffffffffffffffffffffffffffffffffff16611d246120ce565b73ffffffffffffffffffffffffffffffffffffffff1614611d7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d7190614eb6565b60405180910390fd5b611d84600061368f565b565b600260085403611dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc290615671565b60405180910390fd5b6002600881905550600060019050601460019054906101000a900460ff16611e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1f906156dd565b60405180910390fd5b6016600083815260200190815260200160002060009054906101000a900460ff1615611e89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8090615749565b60405180910390fd5b60135481611e956110be565b611e9f9190615062565b1115611ee0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed7906155bd565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16611f23601460039054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461165c565b73ffffffffffffffffffffffffffffffffffffffff1614611f79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f70906157b5565b60405180910390fd5b611f833382613671565b60016016600084815260200190815260200160002060006101000a81548160ff02191690831515021790555050600160088190555050565b611fc3610cce565b73ffffffffffffffffffffffffffffffffffffffff16611fe16120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202e90614eb6565b60405180910390fd5b6016600082815260200190815260200160002060009054906101000a900460ff16156016600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000600e828154811061209c5761209b6154d6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461210790614f05565b80601f016020809104026020016040519081016040528092919081815260200182805461213390614f05565b80156121805780601f1061215557610100808354040283529160200191612180565b820191906000526020600020905b81548152906001019060200180831161216357829003601f168201915b5050505050905090565b60125481565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6121e1610cce565b73ffffffffffffffffffffffffffffffffffffffff166121ff6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224c90614eb6565b60405180910390fd5b6001601860006101000a81548160ff021916908315150217905550565b6002600854036122b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ae90615671565b60405180910390fd5b6002600881905550601460009054906101000a900460ff1661230e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230590615821565b60405180910390fd5b60125481601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461235c9190615062565b111561239d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612394906158b3565b60405180910390fd5b601354816123a96110be565b6123b39190615062565b11156123f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123eb906155bd565b60405180910390fd5b348160115461240391906158d3565b1115612444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161243b90615961565b60405180910390fd5b61244e3382613671565b80601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461249d9190615062565b92505081905550600160088190555050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156125aa576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401612527929190614f36565b602060405180830381865afa158015612544573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125689190614f74565b6125a957806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016125a09190614653565b60405180910390fd5b5b6125b48383613755565b505050565b601460039054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b601460029054906101000a900460ff1681565b60156020528060005260406000206000915090505481565b612615848484612ea8565b6126348373ffffffffffffffffffffffffffffffffffffffff166138cc565b80156126495750612647848484846138df565b155b15612680576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b60006126906110be565b905090565b60606126a082613a2f565b6040516020016126b09190615a09565b6040516020818303038152906040529050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b601860009054906101000a900460ff1681565b60135481565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600b54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b601460009054906101000a900460ff1681565b61282a610cce565b73ffffffffffffffffffffffffffffffffffffffff166128486120ce565b73ffffffffffffffffffffffffffffffffffffffff161461289e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289590614eb6565b60405180910390fd5b601460029054906101000a900460ff1615601460026101000a81548160ff0219169083151502179055507f1727dc7b28fffc84b95ca0e64637ec1614ea28c6bc7e9efa20b6df6b2e65fe87601460029054906101000a900460ff16604051612906919061452d565b60405180910390a1565b612918610cce565b73ffffffffffffffffffffffffffffffffffffffff166129366120ce565b73ffffffffffffffffffffffffffffffffffffffff161461298c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161298390614eb6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129f290615a9d565b60405180910390fd5b612a048161368f565b50565b612a0f610cce565b73ffffffffffffffffffffffffffffffffffffffff16612a2d6120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7a90614eb6565b60405180910390fd5b8060118190555050565b612a95610cce565b73ffffffffffffffffffffffffffffffffffffffff16612ab36120ce565b73ffffffffffffffffffffffffffffffffffffffff1614612b09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0090614eb6565b60405180910390fd5b601460019054906101000a900460ff1615601460016101000a81548160ff0219169083151502179055507f8141ae84dbba32371aea19ef6ed4c40c1effede9613bc317cb583a6b8a6660dd601460019054906101000a900460ff16604051612b71919061452d565b60405180910390a1565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081612bf0612d3d565b11158015612bff575060005482105b8015612c2c575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b6000612c3e826119e0565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ca5576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16612cc4610cce565b73ffffffffffffffffffffffffffffffffffffffff1614158015612cf65750612cf481612cef610cce565b61277b565b155b15612d2d576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d38838383613acd565b505050565b60006001905090565b600081600a54600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205485612d9791906158d3565b612da19190615aec565b612dab9190615b1d565b90509392505050565b80471015612df7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dee90615b9d565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051612e1d90615bee565b60006040518083038185875af1925050503d8060008114612e5a576040519150601f19603f3d011682016040523d82523d6000602084013e612e5f565b606091505b5050905080612ea3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9a90615c75565b60405180910390fd5b505050565b6000612eb3826133e2565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612f1e576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16612f3f610cce565b73ffffffffffffffffffffffffffffffffffffffff161480612f6e5750612f6d85612f68610cce565b61277b565b5b80612fb35750612f7c610cce565b73ffffffffffffffffffffffffffffffffffffffff16612f9b84610f38565b73ffffffffffffffffffffffffffffffffffffffff16145b905080612fec576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613052576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61305f8585856001613b7f565b61306b60008487613acd565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036132ea5760005482146132e957878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46133558585856001613b85565b5050505050565b6133dd8363a9059cbb60e01b848460405160240161337b929190614450565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613b8b565b505050565b6133ea6143b3565b6000829050806133f8612d3d565b11158015613407575060005481105b1561363a576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161363857600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461351c57809250505061366c565b5b60011561363757818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461363257809250505061366c565b61351d565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b61368b828260405180602001604052806000815250613c52565b5050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61375d610cce565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036137c1576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006137ce610cce565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661387b610cce565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516138c0919061452d565b60405180910390a35050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613905610cce565b8786866040518563ffffffff1660e01b81526004016139279493929190615cea565b6020604051808303816000875af192505050801561396357506040513d601f19601f820116820180604052508101906139609190615d4b565b60015b6139dc573d8060008114613993576040519150601f19603f3d011682016040523d82523d6000602084013e613998565b606091505b5060008151036139d4576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6060613a3a82612be5565b613a70576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613a7a613c64565b90506000815103613a9a5760405180602001604052806000815250613ac5565b80613aa484613cf6565b604051602001613ab5929190615d78565b6040516020818303038152906040525b915050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b50505050565b50505050565b6000613bed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613e569092919063ffffffff16565b9050600081511115613c4d5780806020019051810190613c0d9190614f74565b613c4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c4390615e0e565b60405180910390fd5b5b505050565b613c5f8383836001613e6e565b505050565b606060178054613c7390614f05565b80601f0160208091040260200160405190810160405280929190818152602001828054613c9f90614f05565b8015613cec5780601f10613cc157610100808354040283529160200191613cec565b820191906000526020600020905b815481529060010190602001808311613ccf57829003601f168201915b5050505050905090565b606060008203613d3d576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613e51565b600082905060005b60008214613d6f578080613d58906155dd565b915050600a82613d689190615aec565b9150613d45565b60008167ffffffffffffffff811115613d8b57613d8a6148b5565b5b6040519080825280601f01601f191660200182016040528015613dbd5781602001600182028036833780820191505090505b5090505b60008514613e4a57600182613dd69190615b1d565b9150600a85613de59190615e2e565b6030613df19190615062565b60f81b818381518110613e0757613e066154d6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85613e439190615aec565b9450613dc1565b8093505050505b919050565b6060613e658484600085614238565b90509392505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613eda576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613f14576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613f216000868387613b7f565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600085820190508380156140eb57506140ea8773ffffffffffffffffffffffffffffffffffffffff166138cc565b5b156141b0575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461416060008884806001019550886138df565b614196576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082036140f15782600054146141ab57600080fd5b61421b565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48082036141b1575b8160008190555050506142316000868387613b85565b5050505050565b60608247101561427d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161427490615ed1565b60405180910390fd5b614286856138cc565b6142c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142bc90615f3d565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516142ee9190615f8e565b60006040518083038185875af1925050503d806000811461432b576040519150601f19603f3d011682016040523d82523d6000602084013e614330565b606091505b509150915061434082828661434c565b92505050949350505050565b6060831561435c578290506143ac565b60008351111561436f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016143a391906145d8565b60405180910390fd5b9392505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000614421826143f6565b9050919050565b61443181614416565b82525050565b6000819050919050565b61444a81614437565b82525050565b60006040820190506144656000830185614428565b6144726020830184614441565b9392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6144c28161448d565b81146144cd57600080fd5b50565b6000813590506144df816144b9565b92915050565b6000602082840312156144fb576144fa614483565b5b6000614509848285016144d0565b91505092915050565b60008115159050919050565b61452781614512565b82525050565b6000602082019050614542600083018461451e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015614582578082015181840152602081019050614567565b60008484015250505050565b6000601f19601f8301169050919050565b60006145aa82614548565b6145b48185614553565b93506145c4818560208601614564565b6145cd8161458e565b840191505092915050565b600060208201905081810360008301526145f2818461459f565b905092915050565b61460381614437565b811461460e57600080fd5b50565b600081359050614620816145fa565b92915050565b60006020828403121561463c5761463b614483565b5b600061464a84828501614611565b91505092915050565b60006020820190506146686000830184614428565b92915050565b61467781614416565b811461468257600080fd5b50565b6000813590506146948161466e565b92915050565b600080604083850312156146b1576146b0614483565b5b60006146bf85828601614685565b92505060206146d085828601614611565b9150509250929050565b60006020820190506146ef6000830184614441565b92915050565b6000614700826143f6565b9050919050565b614710816146f5565b811461471b57600080fd5b50565b60008135905061472d81614707565b92915050565b60006020828403121561474957614748614483565b5b60006147578482850161471e565b91505092915050565b60008060006060848603121561477957614778614483565b5b600061478786828701614685565b935050602061479886828701614685565b92505060406147a986828701614611565b9150509250925092565b60006147be82614416565b9050919050565b6147ce816147b3565b81146147d957600080fd5b50565b6000813590506147eb816147c5565b92915050565b6000806040838503121561480857614807614483565b5b6000614816858286016147dc565b925050602061482785828601614685565b9150509250929050565b6000819050919050565b600061485661485161484c846143f6565b614831565b6143f6565b9050919050565b60006148688261483b565b9050919050565b600061487a8261485d565b9050919050565b61488a8161486f565b82525050565b60006020820190506148a56000830184614881565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6148ed8261458e565b810181811067ffffffffffffffff8211171561490c5761490b6148b5565b5b80604052505050565b600061491f614479565b905061492b82826148e4565b919050565b600067ffffffffffffffff82111561494b5761494a6148b5565b5b6149548261458e565b9050602081019050919050565b82818337600083830152505050565b600061498361497e84614930565b614915565b90508281526020810184848401111561499f5761499e6148b0565b5b6149aa848285614961565b509392505050565b600082601f8301126149c7576149c66148ab565b5b81356149d7848260208601614970565b91505092915050565b6000602082840312156149f6576149f5614483565b5b600082013567ffffffffffffffff811115614a1457614a13614488565b5b614a20848285016149b2565b91505092915050565b600060208284031215614a3f57614a3e614483565b5b6000614a4d84828501614685565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614a8b81614437565b82525050565b6000614a9d8383614a82565b60208301905092915050565b6000602082019050919050565b6000614ac182614a56565b614acb8185614a61565b9350614ad683614a72565b8060005b83811015614b07578151614aee8882614a91565b9750614af983614aa9565b925050600181019050614ada565b5085935050505092915050565b60006020820190508181036000830152614b2e8184614ab6565b905092915050565b600080fd5b600080fd5b60008083601f840112614b5657614b556148ab565b5b8235905067ffffffffffffffff811115614b7357614b72614b36565b5b602083019150836020820283011115614b8f57614b8e614b3b565b5b9250929050565b60008083601f840112614bac57614bab6148ab565b5b8235905067ffffffffffffffff811115614bc957614bc8614b36565b5b602083019150836020820283011115614be557614be4614b3b565b5b9250929050565b60008060008060408587031215614c0657614c05614483565b5b600085013567ffffffffffffffff811115614c2457614c23614488565b5b614c3087828801614b40565b9450945050602085013567ffffffffffffffff811115614c5357614c52614488565b5b614c5f87828801614b96565b925092505092959194509250565b614c7681614512565b8114614c8157600080fd5b50565b600081359050614c9381614c6d565b92915050565b60008060408385031215614cb057614caf614483565b5b6000614cbe85828601614685565b9250506020614ccf85828601614c84565b9150509250929050565b600067ffffffffffffffff821115614cf457614cf36148b5565b5b614cfd8261458e565b9050602081019050919050565b6000614d1d614d1884614cd9565b614915565b905082815260208101848484011115614d3957614d386148b0565b5b614d44848285614961565b509392505050565b600082601f830112614d6157614d606148ab565b5b8135614d71848260208601614d0a565b91505092915050565b60008060008060808587031215614d9457614d93614483565b5b6000614da287828801614685565b9450506020614db387828801614685565b9350506040614dc487828801614611565b925050606085013567ffffffffffffffff811115614de557614de4614488565b5b614df187828801614d4c565b91505092959194509250565b600060208284031215614e1357614e12614483565b5b6000614e21848285016147dc565b91505092915050565b60008060408385031215614e4157614e40614483565b5b6000614e4f85828601614685565b9250506020614e6085828601614685565b9150509250929050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614ea0602083614553565b9150614eab82614e6a565b602082019050919050565b60006020820190508181036000830152614ecf81614e93565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614f1d57607f821691505b602082108103614f3057614f2f614ed6565b5b50919050565b6000604082019050614f4b6000830185614428565b614f586020830184614428565b9392505050565b600081519050614f6e81614c6d565b92915050565b600060208284031215614f8a57614f89614483565b5b6000614f9884828501614f5f565b91505092915050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000614ffd602683614553565b915061500882614fa1565b604082019050919050565b6000602082019050818103600083015261502c81614ff0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061506d82614437565b915061507883614437565b92508282019050808211156150905761508f615033565b5b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b60006150f2602b83614553565b91506150fd82615096565b604082019050919050565b60006020820190508181036000830152615121816150e5565b9050919050565b60006151338261485d565b9050919050565b61514381615128565b82525050565b600060408201905061515e600083018561513a565b61516b6020830184614441565b9392505050565b600081519050615181816145fa565b92915050565b60006020828403121561519d5761519c614483565b5b60006151ab84828501615172565b91505092915050565b6000815190506151c38161466e565b92915050565b6000602082840312156151df576151de614483565b5b60006151ed848285016151b4565b91505092915050565b7f4d455441444154415f4c4f434b45440000000000000000000000000000000000600082015250565b600061522c600f83614553565b9150615237826151f6565b602082019050919050565b6000602082019050818103600083015261525b8161521f565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026152c47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615287565b6152ce8683615287565b95508019841693508086168417925050509392505050565b60006153016152fc6152f784614437565b614831565b614437565b9050919050565b6000819050919050565b61531b836152e6565b61532f61532782615308565b848454615294565b825550505050565b600090565b615344615337565b61534f818484615312565b505050565b5b818110156153735761536860008261533c565b600181019050615355565b5050565b601f8211156153b85761538981615262565b61539284615277565b810160208510156153a1578190505b6153b56153ad85615277565b830182615354565b50505b505050565b600082821c905092915050565b60006153db600019846008026153bd565b1980831691505092915050565b60006153f483836153ca565b9150826002028217905092915050565b61540d82614548565b67ffffffffffffffff811115615426576154256148b5565b5b6154308254614f05565b61543b828285615377565b600060209050601f83116001811461546e576000841561545c578287015190505b61546685826153e8565b8655506154ce565b601f19841661547c86615262565b60005b828110156154a45784890151825560018201915060208501945060208101905061547f565b868310156154c157848901516154bd601f8916826153ca565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f41495244524f50204e4f54204143544956450000000000000000000000000000600082015250565b600061553b601283614553565b915061554682615505565b602082019050919050565b6000602082019050818103600083015261556a8161552e565b9050919050565b7f534f4c44204f5554000000000000000000000000000000000000000000000000600082015250565b60006155a7600883614553565b91506155b282615571565b602082019050919050565b600060208201905081810360008301526155d68161559a565b9050919050565b60006155e882614437565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361561a57615619615033565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061565b601f83614553565b915061566682615625565b602082019050919050565b6000602082019050818103600083015261568a8161564e565b9050919050565b7f46524545204d494e5420494e4143544956450000000000000000000000000000600082015250565b60006156c7601283614553565b91506156d282615691565b602082019050919050565b600060208201905081810360008301526156f6816156ba565b9050919050565b7f416c7265616479204d696e746564210000000000000000000000000000000000600082015250565b6000615733600f83614553565b915061573e826156fd565b602082019050919050565b6000602082019050818103600083015261576281615726565b9050919050565b7f54686973206d656d62657273686970206973206e6f7420666f72676564210000600082015250565b600061579f601e83614553565b91506157aa82615769565b602082019050919050565b600060208201905081810360008301526157ce81615792565b9050919050565b7f53414c4520494e41435449564500000000000000000000000000000000000000600082015250565b600061580b600d83614553565b9150615816826157d5565b602082019050919050565b6000602082019050818103600083015261583a816157fe565b9050919050565b7f7468697320776f756c6420657863656564206d696e74206d617820616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b600061589d602483614553565b91506158a882615841565b604082019050919050565b600060208201905081810360008301526158cc81615890565b9050919050565b60006158de82614437565b91506158e983614437565b92508282026158f781614437565b9150828204841483151761590e5761590d615033565b5b5092915050565b7f494e434f52524543542045544845522056414c55450000000000000000000000600082015250565b600061594b601583614553565b915061595682615915565b602082019050919050565b6000602082019050818103600083015261597a8161593e565b9050919050565b600081905092915050565b600061599782614548565b6159a18185615981565b93506159b1818560208601614564565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b60006159f3600583615981565b91506159fe826159bd565b600582019050919050565b6000615a15828461598c565b9150615a20826159e6565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615a87602683614553565b9150615a9282615a2b565b604082019050919050565b60006020820190508181036000830152615ab681615a7a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615af782614437565b9150615b0283614437565b925082615b1257615b11615abd565b5b828204905092915050565b6000615b2882614437565b9150615b3383614437565b9250828203905081811115615b4b57615b4a615033565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000615b87601d83614553565b9150615b9282615b51565b602082019050919050565b60006020820190508181036000830152615bb681615b7a565b9050919050565b600081905092915050565b50565b6000615bd8600083615bbd565b9150615be382615bc8565b600082019050919050565b6000615bf982615bcb565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b6000615c5f603a83614553565b9150615c6a82615c03565b604082019050919050565b60006020820190508181036000830152615c8e81615c52565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000615cbc82615c95565b615cc68185615ca0565b9350615cd6818560208601614564565b615cdf8161458e565b840191505092915050565b6000608082019050615cff6000830187614428565b615d0c6020830186614428565b615d196040830185614441565b8181036060830152615d2b8184615cb1565b905095945050505050565b600081519050615d45816144b9565b92915050565b600060208284031215615d6157615d60614483565b5b6000615d6f84828501615d36565b91505092915050565b6000615d84828561598c565b9150615d90828461598c565b91508190509392505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000615df8602a83614553565b9150615e0382615d9c565b604082019050919050565b60006020820190508181036000830152615e2781615deb565b9050919050565b6000615e3982614437565b9150615e4483614437565b925082615e5457615e53615abd565b5b828206905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000615ebb602683614553565b9150615ec682615e5f565b604082019050919050565b60006020820190508181036000830152615eea81615eae565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000615f27601d83614553565b9150615f3282615ef1565b602082019050919050565b60006020820190508181036000830152615f5681615f1a565b9050919050565b6000615f6882615c95565b615f728185615bbd565b9350615f82818560208601614564565b80840191505092915050565b6000615f9a8284615f5d565b91508190509291505056fea2646970667358221220215ad0174425e8b46642e22dd115f297cb220f26a08a40ef818b22f744e7292064736f6c63430008110033

Deployed Bytecode Sourcemap

119484:6616:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108431:40;108447:12;:10;:12::i;:::-;108461:9;108431:40;;;;;;;:::i;:::-;;;;;;;;119484:6616;;;;;79695:355;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122677:138;;;;;;;;;;;;;:::i;:::-;;82890:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84498:245;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125906:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;78944:303;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110249:616;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;85486:170;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125088:246;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119823:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108562:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109691:167;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116204:143;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85727:185;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111133:704;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;120770:214;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123472:73;;;;;;;;;;;;;:::i;:::-;;120080:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124486:150;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123553:820;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;82698:125;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120992:366;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119642:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80114:206;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123254:110;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;69548:103;;;;;;;;;;;;;:::i;:::-;;121366:783;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;120521:133;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;109949:100;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68897:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83059:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119686:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109413:109;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123372:75;;;;;;;;;;;;;:::i;:::-;;122157:512;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125690:208;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119940:70;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119865:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120019:54;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85983:406;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124381:97;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124766:205;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109209:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120232:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119724:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108999:119;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108747:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85205:214;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119784:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122983:153;;;;;;;;;;;;;:::i;:::-;;69806:238;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123144:102;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122823:152;;;;;;;;;;;;;:::i;:::-;;35068:98;35121:7;35148:10;35141:17;;35068:98;:::o;79695:355::-;79842:4;79899:25;79884:40;;;:11;:40;;;;:105;;;;79956:33;79941:48;;;:11;:48;;;;79884:105;:158;;;;80006:36;80030:11;80006:23;:36::i;:::-;79884:158;79864:178;;79695:355;;;:::o;122677:138::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;122751:12:::1;;;;;;;;;;;122750:13;122735:12;;:28;;;;;;;;;;;;;;;;;;122779;122794:12;;;;;;;;;;;122779:28;;;;;;:::i;:::-;;;;;;;;122677:138::o:0;82890:100::-;82944:13;82977:5;82970:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82890:100;:::o;84498:245::-;84602:7;84632:16;84640:7;84632;:16::i;:::-;84627:64;;84657:34;;;;;;;;;;;;;;84627:64;84711:15;:24;84727:7;84711:24;;;;;;;;;;;;;;;;;;;;;84704:31;;84498:245;;;:::o;125906:189::-;126029:8;118473:1;116304:42;118425:45;;;:49;118421:318;;;116304:42;118514;;;118587:4;118615:8;118514:128;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118491:237;;118703:8;118684:28;;;;;;;;;;;:::i;:::-;;;;;;;;118491:237;118421:318;126055:32:::1;126069:8;126079:7;126055:13;:32::i;:::-;125906:189:::0;;;:::o;78944:303::-;78988:7;79213:15;:13;:15::i;:::-;79198:12;;79182:13;;:28;:46;79175:53;;78944:303;:::o;110249:616::-;110344:1;110325:7;:16;110333:7;110325:16;;;;;;;;;;;;;;;;:20;110317:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;110401:21;110449:15;:13;:15::i;:::-;110425:21;:39;;;;:::i;:::-;110401:63;;110475:15;110493:108;110523:7;110545:13;110573:17;110582:7;110573:8;:17::i;:::-;110493:15;:108::i;:::-;110475:126;;110633:1;110622:7;:12;110614:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;110717:7;110695:9;:18;110705:7;110695:18;;;;;;;;;;;;;;;;:29;;;;;;;:::i;:::-;;;;;;;;110753:7;110735:14;;:25;;;;;;;:::i;:::-;;;;;;;;110773:35;110791:7;110800;110773:17;:35::i;:::-;110824:33;110840:7;110849;110824:33;;;;;;;:::i;:::-;;;;;;;;110306:559;;110249:616;:::o;85486:170::-;85620:28;85630:4;85636:2;85640:7;85620:9;:28::i;:::-;85486:170;;;:::o;125088:246::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;119823:35::-;;;;;;;;;;;;;:::o;108562:91::-;108606:7;108633:12;;108626:19;;108562:91;:::o;109691:167::-;109788:7;109820:14;:21;109835:5;109820:21;;;;;;;;;;;;;;;:30;109842:7;109820:30;;;;;;;;;;;;;;;;109813:37;;109691:167;;;;:::o;116204:143::-;116304:42;116204:143;:::o;85727:185::-;85865:39;85882:4;85888:2;85892:7;85865:39;;;;;;;;;;;;:16;:39::i;:::-;85727:185;;;:::o;111133:704::-;111234:1;111215:7;:16;111223:7;111215:16;;;;;;;;;;;;;;;;:20;111207:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;111291:21;111361:20;111375:5;111361:13;:20::i;:::-;111315:5;:15;;;111339:4;111315:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;;;;:::i;:::-;111291:90;;111392:15;111410:115;111440:7;111462:13;111490:24;111499:5;111506:7;111490:8;:24::i;:::-;111410:15;:115::i;:::-;111392:133;;111557:1;111546:7;:12;111538:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;111653:7;111619:14;:21;111634:5;111619:21;;;;;;;;;;;;;;;:30;111641:7;111619:30;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;111701:7;111671:19;:26;111691:5;111671:26;;;;;;;;;;;;;;;;:37;;;;;;;:::i;:::-;;;;;;;;111721:47;111744:5;111751:7;111760;111721:22;:47::i;:::-;111805:5;111784:45;;;111812:7;111821;111784:45;;;;;;;:::i;:::-;;;;;;;;111196:641;;111133:704;;:::o;120770:214::-;120887:7;120933:13;120919:52;;;120972:3;120919:57;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;120912:64;;120770:214;;;;:::o;123472:73::-;123509:28;123525:10;123509:7;:28::i;:::-;123472:73::o;120080:48::-;;;;;;;;;;;;;;;;;;;;;;:::o;124486:150::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;124568:6:::1;;;;;;;;;;;124567:7;124559:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;124621:7;124605:13;:23;;;;;;:::i;:::-;;124486:150:::0;:::o;123553:820::-;123644:16;123703:18;123738:16;123748:5;123738:9;:16::i;:::-;123724:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123703:52;;123770:11;123784:13;;123770:27;;123812:19;123846:25;123891:9;123886:446;123906:3;123902:1;:7;123886:446;;;123935:31;123969:11;:14;123981:1;123969:14;;;;;;;;;;;123935:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124006:9;:16;;;124002:73;;;124047:8;;;124002:73;124123:1;124097:28;;:9;:14;;;:28;;;124093:111;;124170:9;:14;;;124150:34;;124093:111;124247:5;124226:26;;:17;:26;;;124222:95;;124296:1;124277;124279:13;;;;;;124277:16;;;;;;;;:::i;:::-;;;;;;;:20;;;;;124222:95;123916:416;123886:446;123911:3;;;;;;;123886:446;;;;124353:1;124346:8;;;;;;123553:820;;;:::o;82698:125::-;82762:7;82789:21;82802:7;82789:12;:21::i;:::-;:26;;;82782:33;;82698:125;;;:::o;120992:366::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;121124:15:::1;;;;;;;;;;;121116:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;121180:9;121175:176;121199:5;;:12;;121195:1;:16;121175:176;;;121271:9;;121257:7;;121265:1;121257:10;;;;;;;:::i;:::-;;;;;;;;121241:13;:11;:13::i;:::-;:26;;;;:::i;:::-;:39;;121233:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;121308:31;121318:5;;121324:1;121318:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;121328:7;;121336:1;121328:10;;;;;;;:::i;:::-;;;;;;;;121308:9;:31::i;:::-;121213:3;;;;;:::i;:::-;;;;121175:176;;;;120992:366:::0;;;;:::o;119642:37::-;;;;:::o;80114:206::-;80178:7;80219:1;80202:19;;:5;:19;;;80198:60;;80230:28;;;;;;;;;;;;;;80198:60;80284:12;:19;80297:5;80284:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;80276:36;;80269:43;;80114:206;;;:::o;123254:110::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;123344:12:::1;123330:11;:26;;;;123254:110:::0;:::o;69548:103::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;69613:30:::1;69640:1;69613:18;:30::i;:::-;69548:103::o:0;121366:783::-;74562:1;75160:7;;:19;75152:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;74562:1;75293:7;:18;;;;121440:14:::1;121457:1;121440:18;;121505:16;;;;;;;;;;;121497:47;;;;;;;;;;;;:::i;:::-;;;;;;;;;121640:16;:31;121657:13;121640:31;;;;;;;;;;;;;;;;;;;;;121639:32;121631:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;121738:9;;121728:6;121712:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:35;;121704:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;121927:10;121873:64;;:50;121897:10;;;;;;;;;;;121909:13;121873:23;:50::i;:::-;:64;;;121851:144;;;;;;;;;;;;:::i;:::-;;;;;;;;;122008:29;122018:10;122030:6;122008:9;:29::i;:::-;122137:4;122103:16;:31;122120:13;122103:31;;;;;;;;;;;;:38;;;;;;;;;;;;;;;;;;121429:720;74518:1:::0;75472:7;:22;;;;121366:783;:::o;120521:133::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;120621:16:::1;:25;120638:7;120621:25;;;;;;;;;;;;;;;;;;;;;120620:26;120592:16;:25;120609:7;120592:25;;;;;;;;;;;;:54;;;;;;;;;;;;;;;;;;120521:133:::0;:::o;109949:100::-;110000:7;110027;110035:5;110027:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;110020:21;;109949:100;;;:::o;68897:87::-;68943:7;68970:6;;;;;;;;;;;68963:13;;68897:87;:::o;83059:104::-;83115:13;83148:7;83141:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83059:104;:::o;119686:31::-;;;;:::o;109413:109::-;109469:7;109496:9;:18;109506:7;109496:18;;;;;;;;;;;;;;;;109489:25;;109413:109;;;:::o;123372:75::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;123435:4:::1;123426:6;;:13;;;;;;;;;;;;;;;;;;123372:75::o:0;122157:512::-;74562:1;75160:7;;:19;75152:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;74562:1;75293:7;:18;;;;122236:12:::1;;;;;;;;;;;122228:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;122347:11;;122335:6;122301:19;:31;122321:10;122301:31;;;;;;;;;;;;;;;;:40;;;;:::i;:::-;122299:59;;122277:145;;;;;;;;;;;;:::i;:::-;;;;;;;;;122469:9;;122459:6;122443:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:35;;122435:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;122532:9;122522:6;122510:9;;:18;;;;:::i;:::-;:31;;122502:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;122580:29;122590:10;122602:6;122580:9;:29::i;:::-;122655:6;122620:19;:31;122640:10;122620:31;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;74518:1:::0;75472:7;:22;;;;122157:512;:::o;125690:208::-;125821:8;118473:1;116304:42;118425:45;;;:49;118421:318;;;116304:42;118514;;;118587:4;118615:8;118514:128;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118491:237;;118703:8;118684:28;;;;;;;;;;;:::i;:::-;;;;;;;;118491:237;118421:318;125847:43:::1;125871:8;125881;125847:23;:43::i;:::-;125690:208:::0;;;:::o;119940:70::-;;;;;;;;;;;;;:::o;119865:34::-;;;;;;;;;;;;;:::o;120019:54::-;;;;;;;;;;;;;;;;;:::o;85983:406::-;86150:28;86160:4;86166:2;86170:7;86150:9;:28::i;:::-;86207:15;:2;:13;;;:15::i;:::-;:89;;;;;86240:56;86271:4;86277:2;86281:7;86290:5;86240:30;:56::i;:::-;86239:57;86207:89;86189:193;;;86330:40;;;;;;;;;;;;;;86189:193;85983:406;;;;:::o;124381:97::-;124430:7;124457:13;:11;:13::i;:::-;124450:20;;124381:97;:::o;124766:205::-;124867:13;124929:23;124944:7;124929:14;:23::i;:::-;124912:50;;;;;;;;:::i;:::-;;;;;;;;;;;;;124898:65;;124766:205;;;:::o;109209:105::-;109263:7;109290;:16;109298:7;109290:16;;;;;;;;;;;;;;;;109283:23;;109209:105;;;:::o;120232:18::-;;;;;;;;;;;;;:::o;119724:31::-;;;;:::o;108999:119::-;109057:7;109084:19;:26;109104:5;109084:26;;;;;;;;;;;;;;;;109077:33;;108999:119;;;:::o;108747:95::-;108793:7;108820:14;;108813:21;;108747:95;:::o;85205:214::-;85347:4;85376:18;:25;85395:5;85376:25;;;;;;;;;;;;;;;:35;85402:8;85376:35;;;;;;;;;;;;;;;;;;;;;;;;;85369:42;;85205:214;;;;:::o;119784:32::-;;;;;;;;;;;;;:::o;122983:153::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;123063:15:::1;;;;;;;;;;;123062:16;123044:15;;:34;;;;;;;;;;;;;;;;;;123094;123112:15;;;;;;;;;;;123094:34;;;;;;:::i;:::-;;;;;;;;122983:153::o:0;69806:238::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;69929:1:::1;69909:22;;:8;:22;;::::0;69887:110:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;70008:28;70027:8;70008:18;:28::i;:::-;69806:238:::0;:::o;123144:102::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;123228:10:::1;123216:9;:22;;;;123144:102:::0;:::o;122823:152::-;69128:12;:10;:12::i;:::-;69117:23;;:7;:5;:7::i;:::-;:23;;;69109:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;122899:16:::1;;;;;;;;;;;122898:17;122879:16;;:36;;;;;;;;;;;;;;;;;;122931;122950:16;;;;;;;;;;;122931:36;;;;;;:::i;:::-;;;;;;;;122823:152::o:0;38051:207::-;38181:4;38225:25;38210:40;;;:11;:40;;;;38203:47;;38051:207;;;:::o;86644:213::-;86701:4;86757:7;86738:15;:13;:15::i;:::-;:26;;:66;;;;;86791:13;;86781:7;:23;86738:66;:111;;;;;86822:11;:20;86834:7;86822:20;;;;;;;;;;;:27;;;;;;;;;;;;86821:28;86738:111;86718:131;;86644:213;;;:::o;84053:379::-;84134:13;84150:24;84166:7;84150:15;:24::i;:::-;84134:40;;84195:5;84189:11;;:2;:11;;;84185:48;;84209:24;;;;;;;;;;;;;;84185:48;84266:5;84250:21;;:12;:10;:12::i;:::-;:21;;;;:63;;;;;84276:37;84293:5;84300:12;:10;:12::i;:::-;84276:16;:37::i;:::-;84275:38;84250:63;84246:138;;;84337:35;;;;;;;;;;;;;;84246:138;84396:28;84405:2;84409:7;84418:5;84396:8;:28::i;:::-;84123:309;84053:379;;:::o;124979:101::-;125044:7;125071:1;125064:8;;124979:101;:::o;112015:261::-;112161:7;112253:15;112238:12;;112218:7;:16;112226:7;112218:16;;;;;;;;;;;;;;;;112202:13;:32;;;;:::i;:::-;112201:49;;;;:::i;:::-;:67;;;;:::i;:::-;112181:87;;112015:261;;;;;:::o;28025:391::-;28154:6;28129:21;:31;;28107:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;28231:12;28249:9;:14;;28271:6;28249:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28230:52;;;28315:7;28293:115;;;;;;;;;;;;:::i;:::-;;;;;;;;;28096:320;28025:391;;:::o;89974:2130::-;90089:35;90127:21;90140:7;90127:12;:21::i;:::-;90089:59;;90187:4;90165:26;;:13;:18;;;:26;;;90161:67;;90200:28;;;;;;;;;;;;;;90161:67;90241:22;90283:4;90267:20;;:12;:10;:12::i;:::-;:20;;;:73;;;;90304:36;90321:4;90327:12;:10;:12::i;:::-;90304:16;:36::i;:::-;90267:73;:126;;;;90381:12;:10;:12::i;:::-;90357:36;;:20;90369:7;90357:11;:20::i;:::-;:36;;;90267:126;90241:153;;90412:17;90407:66;;90438:35;;;;;;;;;;;;;;90407:66;90502:1;90488:16;;:2;:16;;;90484:52;;90513:23;;;;;;;;;;;;;;90484:52;90549:43;90571:4;90577:2;90581:7;90590:1;90549:21;:43::i;:::-;90657:35;90674:1;90678:7;90687:4;90657:8;:35::i;:::-;91018:1;90988:12;:18;91001:4;90988:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91062:1;91034:12;:16;91047:2;91034:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91080:31;91114:11;:20;91126:7;91114:20;;;;;;;;;;;91080:54;;91165:2;91149:8;:13;;;:18;;;;;;;;;;;;;;;;;;91215:15;91182:8;:23;;;:49;;;;;;;;;;;;;;;;;;91483:19;91515:1;91505:7;:11;91483:33;;91531:31;91565:11;:24;91577:11;91565:24;;;;;;;;;;;91531:58;;91633:1;91608:27;;:8;:13;;;;;;;;;;;;:27;;;91604:384;;91818:13;;91803:11;:28;91799:174;;91872:4;91856:8;:13;;;:20;;;;;;;;;;;;;;;;;;91925:13;:28;;;91899:8;:23;;;:54;;;;;;;;;;;;;;;;;;91799:174;91604:384;90963:1036;;;92035:7;92031:2;92016:27;;92025:4;92016:27;;;;;;;;;;;;92054:42;92075:4;92081:2;92085:7;92094:1;92054:20;:42::i;:::-;90078:2026;;89974:2130;;;:::o;101478:248::-;101595:123;101629:5;101672:23;;;101697:2;101701:5;101649:58;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101595:19;:123::i;:::-;101478:248;;;:::o;81495:1141::-;81584:21;;:::i;:::-;81623:12;81638:7;81623:22;;81706:4;81687:15;:13;:15::i;:::-;:23;;:47;;;;;81721:13;;81714:4;:20;81687:47;81683:886;;;81755:31;81789:11;:17;81801:4;81789:17;;;;;;;;;;;81755:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81830:9;:16;;;81825:729;;81901:1;81875:28;;:9;:14;;;:28;;;81871:101;;81939:9;81932:16;;;;;;81871:101;82274:261;82281:4;82274:261;;;82314:6;;;;;;;;82359:11;:17;82371:4;82359:17;;;;;;;;;;;82347:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82433:1;82407:28;;:9;:14;;;:28;;;82403:109;;82475:9;82468:16;;;;;;82403:109;82274:261;;;81825:729;81736:833;81683:886;82597:31;;;;;;;;;;;;;;81495:1141;;;;:::o;86865:104::-;86934:27;86944:2;86948:8;86934:27;;;;;;;;;;;;:9;:27::i;:::-;86865:104;;:::o;70204:191::-;70278:16;70297:6;;;;;;;;;;;70278:25;;70323:8;70314:6;;:17;;;;;;;;;;;;;;;;;;70378:8;70347:40;;70368:8;70347:40;;;;;;;;;;;;70267:128;70204:191;:::o;84815:319::-;84958:12;:10;:12::i;:::-;84946:24;;:8;:24;;;84942:54;;84979:17;;;;;;;;;;;;;;84942:54;85054:8;85009:18;:32;85028:12;:10;:12::i;:::-;85009:32;;;;;;;;;;;;;;;:42;85042:8;85009:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;85107:8;85078:48;;85093:12;:10;:12::i;:::-;85078:48;;;85117:8;85078:48;;;;;;:::i;:::-;;;;;;;;84815:319;;:::o;26703:387::-;26763:4;26971:12;27038:7;27026:20;27018:28;;27081:1;27074:4;:8;27067:15;;;26703:387;;;:::o;95719:772::-;95882:4;95932:2;95916:36;;;95971:12;:10;:12::i;:::-;96002:4;96025:7;96051:5;95916:155;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;95899:585;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96259:1;96242:6;:13;:18;96238:235;;96288:40;;;;;;;;;;;;;;96238:235;96431:6;96425:13;96416:6;96412:2;96408:15;96401:38;95899:585;96137:45;;;96127:55;;;:6;:55;;;;96120:62;;;95719:772;;;;;;:::o;83234:415::-;83352:13;83388:16;83396:7;83388;:16::i;:::-;83383:59;;83413:29;;;;;;;;;;;;;;83383:59;83455:21;83479:10;:8;:10::i;:::-;83455:34;;83545:1;83526:7;83520:21;:26;:121;;;;;;;;;;;;;;;;;83590:7;83599:18;:7;:16;:18::i;:::-;83573:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;83520:121;83500:141;;;83234:415;;;:::o;95031:196::-;95173:2;95146:15;:24;95162:7;95146:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;95211:7;95207:2;95191:28;;95200:5;95191:28;;;;;;;;;;;;95031:196;;;:::o;97139:159::-;;;;;:::o;97957:158::-;;;;;:::o;104445:802::-;104869:23;104895:106;104937:4;104895:106;;;;;;;;;;;;;;;;;104903:5;104895:27;;;;:106;;;;;:::i;:::-;104869:132;;105036:1;105016:10;:17;:21;105012:228;;;105131:10;105120:30;;;;;;;;;;;;:::i;:::-;105094:134;;;;;;;;;;;;:::i;:::-;;;;;;;;;105012:228;104515:732;104445:802;;:::o;87332:163::-;87455:32;87461:2;87465:8;87475:5;87482:4;87455:5;:32::i;:::-;87332:163;;;:::o;124644:114::-;124704:13;124737;124730:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124644:114;:::o;35535:723::-;35591:13;35821:1;35812:5;:10;35808:53;;35839:10;;;;;;;;;;;;;;;;;;;;;35808:53;35871:12;35886:5;35871:20;;35902:14;35927:78;35942:1;35934:4;:9;35927:78;;35960:8;;;;;:::i;:::-;;;;35991:2;35983:10;;;;;:::i;:::-;;;35927:78;;;36015:19;36047:6;36037:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36015:39;;36065:154;36081:1;36072:5;:10;36065:154;;36109:1;36099:11;;;;;:::i;:::-;;;36176:2;36168:5;:10;;;;:::i;:::-;36155:2;:24;;;;:::i;:::-;36142:39;;36125:6;36132;36125:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;36205:2;36196:11;;;;;:::i;:::-;;;36065:154;;;36243:6;36229:21;;;;;35535:723;;;;:::o;29606:229::-;29743:12;29775:52;29797:6;29805:4;29811:1;29814:12;29775:21;:52::i;:::-;29768:59;;29606:229;;;;;:::o;87754:1966::-;87893:20;87916:13;;87893:36;;87958:1;87944:16;;:2;:16;;;87940:48;;87969:19;;;;;;;;;;;;;;87940:48;88015:1;88003:8;:13;87999:44;;88025:18;;;;;;;;;;;;;;87999:44;88056:61;88086:1;88090:2;88094:12;88108:8;88056:21;:61::i;:::-;88429:8;88394:12;:16;88407:2;88394:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88493:8;88453:12;:16;88466:2;88453:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88552:2;88519:11;:25;88531:12;88519:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;88619:15;88569:11;:25;88581:12;88569:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;88652:20;88675:12;88652:35;;88702:11;88731:8;88716:12;:23;88702:37;;88760:4;:23;;;;;88768:15;:2;:13;;;:15::i;:::-;88760:23;88756:832;;;88804:505;88860:12;88856:2;88835:38;;88852:1;88835:38;;;;;;;;;;;;88927:212;88996:1;89029:2;89062:14;;;;;;89107:5;88927:30;:212::i;:::-;88896:365;;89197:40;;;;;;;;;;;;;;88896:365;89304:3;89288:12;:19;88804:505;;89390:12;89373:13;;:29;89369:43;;89404:8;;;89369:43;88756:832;;;89453:120;89509:14;;;;;;89505:2;89484:40;;89501:1;89484:40;;;;;;;;;;;;89568:3;89552:12;:19;89453:120;;88756:832;89618:12;89602:13;:28;;;;88369:1273;;89652:60;89681:1;89685:2;89689:12;89703:8;89652:20;:60::i;:::-;87882:1838;87754:1966;;;;:::o;30822:571::-;30992:12;31064:5;31039:21;:30;;31017:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;31154:18;31165:6;31154:10;:18::i;:::-;31146:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;31220:12;31234:23;31261:6;:11;;31280:5;31301:4;31261:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31219:97;;;;31334:51;31351:7;31360:10;31372:12;31334:16;:51::i;:::-;31327:58;;;;30822:571;;;;;;:::o;33782:712::-;33932:12;33961:7;33957:530;;;33992:10;33985:17;;;;33957:530;34126:1;34106:10;:17;:21;34102:374;;;34304:10;34298:17;34365:15;34352:10;34348:2;34344:19;34337:44;34102:374;34447:12;34440:20;;;;;;;;;;;:::i;:::-;;;;;;;;33782:712;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:126:1:-;44:7;84:42;77:5;73:54;62:65;;7:126;;;:::o;139:96::-;176:7;205:24;223:5;205:24;:::i;:::-;194:35;;139:96;;;:::o;241:118::-;328:24;346:5;328:24;:::i;:::-;323:3;316:37;241:118;;:::o;365:77::-;402:7;431:5;420:16;;365:77;;;:::o;448:118::-;535:24;553:5;535:24;:::i;:::-;530:3;523:37;448:118;;:::o;572:332::-;693:4;731:2;720:9;716:18;708:26;;744:71;812:1;801:9;797:17;788:6;744:71;:::i;:::-;825:72;893:2;882:9;878:18;869:6;825:72;:::i;:::-;572:332;;;;;:::o;910:75::-;943:6;976:2;970:9;960:19;;910:75;:::o;991:117::-;1100:1;1097;1090:12;1114:117;1223:1;1220;1213:12;1237:149;1273:7;1313:66;1306:5;1302:78;1291:89;;1237:149;;;:::o;1392:120::-;1464:23;1481:5;1464:23;:::i;:::-;1457:5;1454:34;1444:62;;1502:1;1499;1492:12;1444:62;1392:120;:::o;1518:137::-;1563:5;1601:6;1588:20;1579:29;;1617:32;1643:5;1617:32;:::i;:::-;1518:137;;;;:::o;1661:327::-;1719:6;1768:2;1756:9;1747:7;1743:23;1739:32;1736:119;;;1774:79;;:::i;:::-;1736:119;1894:1;1919:52;1963:7;1954:6;1943:9;1939:22;1919:52;:::i;:::-;1909:62;;1865:116;1661:327;;;;:::o;1994:90::-;2028:7;2071:5;2064:13;2057:21;2046:32;;1994:90;;;:::o;2090:109::-;2171:21;2186:5;2171:21;:::i;:::-;2166:3;2159:34;2090:109;;:::o;2205:210::-;2292:4;2330:2;2319:9;2315:18;2307:26;;2343:65;2405:1;2394:9;2390:17;2381:6;2343:65;:::i;:::-;2205:210;;;;:::o;2421:99::-;2473:6;2507:5;2501:12;2491:22;;2421:99;;;:::o;2526:169::-;2610:11;2644:6;2639:3;2632:19;2684:4;2679:3;2675:14;2660:29;;2526:169;;;;:::o;2701:246::-;2782:1;2792:113;2806:6;2803:1;2800:13;2792:113;;;2891:1;2886:3;2882:11;2876:18;2872:1;2867:3;2863:11;2856:39;2828:2;2825:1;2821:10;2816:15;;2792:113;;;2939:1;2930:6;2925:3;2921:16;2914:27;2763:184;2701:246;;;:::o;2953:102::-;2994:6;3045:2;3041:7;3036:2;3029:5;3025:14;3021:28;3011:38;;2953:102;;;:::o;3061:377::-;3149:3;3177:39;3210:5;3177:39;:::i;:::-;3232:71;3296:6;3291:3;3232:71;:::i;:::-;3225:78;;3312:65;3370:6;3365:3;3358:4;3351:5;3347:16;3312:65;:::i;:::-;3402:29;3424:6;3402:29;:::i;:::-;3397:3;3393:39;3386:46;;3153:285;3061:377;;;;:::o;3444:313::-;3557:4;3595:2;3584:9;3580:18;3572:26;;3644:9;3638:4;3634:20;3630:1;3619:9;3615:17;3608:47;3672:78;3745:4;3736:6;3672:78;:::i;:::-;3664:86;;3444:313;;;;:::o;3763:122::-;3836:24;3854:5;3836:24;:::i;:::-;3829:5;3826:35;3816:63;;3875:1;3872;3865:12;3816:63;3763:122;:::o;3891:139::-;3937:5;3975:6;3962:20;3953:29;;3991:33;4018:5;3991:33;:::i;:::-;3891:139;;;;:::o;4036:329::-;4095:6;4144:2;4132:9;4123:7;4119:23;4115:32;4112:119;;;4150:79;;:::i;:::-;4112:119;4270:1;4295:53;4340:7;4331:6;4320:9;4316:22;4295:53;:::i;:::-;4285:63;;4241:117;4036:329;;;;:::o;4371:222::-;4464:4;4502:2;4491:9;4487:18;4479:26;;4515:71;4583:1;4572:9;4568:17;4559:6;4515:71;:::i;:::-;4371:222;;;;:::o;4599:122::-;4672:24;4690:5;4672:24;:::i;:::-;4665:5;4662:35;4652:63;;4711:1;4708;4701:12;4652:63;4599:122;:::o;4727:139::-;4773:5;4811:6;4798:20;4789:29;;4827:33;4854:5;4827:33;:::i;:::-;4727:139;;;;:::o;4872:474::-;4940:6;4948;4997:2;4985:9;4976:7;4972:23;4968:32;4965:119;;;5003:79;;:::i;:::-;4965:119;5123:1;5148:53;5193:7;5184:6;5173:9;5169:22;5148:53;:::i;:::-;5138:63;;5094:117;5250:2;5276:53;5321:7;5312:6;5301:9;5297:22;5276:53;:::i;:::-;5266:63;;5221:118;4872:474;;;;;:::o;5352:222::-;5445:4;5483:2;5472:9;5468:18;5460:26;;5496:71;5564:1;5553:9;5549:17;5540:6;5496:71;:::i;:::-;5352:222;;;;:::o;5580:104::-;5625:7;5654:24;5672:5;5654:24;:::i;:::-;5643:35;;5580:104;;;:::o;5690:138::-;5771:32;5797:5;5771:32;:::i;:::-;5764:5;5761:43;5751:71;;5818:1;5815;5808:12;5751:71;5690:138;:::o;5834:155::-;5888:5;5926:6;5913:20;5904:29;;5942:41;5977:5;5942:41;:::i;:::-;5834:155;;;;:::o;5995:345::-;6062:6;6111:2;6099:9;6090:7;6086:23;6082:32;6079:119;;;6117:79;;:::i;:::-;6079:119;6237:1;6262:61;6315:7;6306:6;6295:9;6291:22;6262:61;:::i;:::-;6252:71;;6208:125;5995:345;;;;:::o;6346:619::-;6423:6;6431;6439;6488:2;6476:9;6467:7;6463:23;6459:32;6456:119;;;6494:79;;:::i;:::-;6456:119;6614:1;6639:53;6684:7;6675:6;6664:9;6660:22;6639:53;:::i;:::-;6629:63;;6585:117;6741:2;6767:53;6812:7;6803:6;6792:9;6788:22;6767:53;:::i;:::-;6757:63;;6712:118;6869:2;6895:53;6940:7;6931:6;6920:9;6916:22;6895:53;:::i;:::-;6885:63;;6840:118;6346:619;;;;;:::o;6971:111::-;7023:7;7052:24;7070:5;7052:24;:::i;:::-;7041:35;;6971:111;;;:::o;7088:152::-;7176:39;7209:5;7176:39;:::i;:::-;7169:5;7166:50;7156:78;;7230:1;7227;7220:12;7156:78;7088:152;:::o;7246:169::-;7307:5;7345:6;7332:20;7323:29;;7361:48;7403:5;7361:48;:::i;:::-;7246:169;;;;:::o;7421:504::-;7504:6;7512;7561:2;7549:9;7540:7;7536:23;7532:32;7529:119;;;7567:79;;:::i;:::-;7529:119;7687:1;7712:68;7772:7;7763:6;7752:9;7748:22;7712:68;:::i;:::-;7702:78;;7658:132;7829:2;7855:53;7900:7;7891:6;7880:9;7876:22;7855:53;:::i;:::-;7845:63;;7800:118;7421:504;;;;;:::o;7931:60::-;7959:3;7980:5;7973:12;;7931:60;;;:::o;7997:142::-;8047:9;8080:53;8098:34;8107:24;8125:5;8107:24;:::i;:::-;8098:34;:::i;:::-;8080:53;:::i;:::-;8067:66;;7997:142;;;:::o;8145:126::-;8195:9;8228:37;8259:5;8228:37;:::i;:::-;8215:50;;8145:126;;;:::o;8277:158::-;8359:9;8392:37;8423:5;8392:37;:::i;:::-;8379:50;;8277:158;;;:::o;8441:195::-;8560:69;8623:5;8560:69;:::i;:::-;8555:3;8548:82;8441:195;;:::o;8642:286::-;8767:4;8805:2;8794:9;8790:18;8782:26;;8818:103;8918:1;8907:9;8903:17;8894:6;8818:103;:::i;:::-;8642:286;;;;:::o;8934:117::-;9043:1;9040;9033:12;9057:117;9166:1;9163;9156:12;9180:180;9228:77;9225:1;9218:88;9325:4;9322:1;9315:15;9349:4;9346:1;9339:15;9366:281;9449:27;9471:4;9449:27;:::i;:::-;9441:6;9437:40;9579:6;9567:10;9564:22;9543:18;9531:10;9528:34;9525:62;9522:88;;;9590:18;;:::i;:::-;9522:88;9630:10;9626:2;9619:22;9409:238;9366:281;;:::o;9653:129::-;9687:6;9714:20;;:::i;:::-;9704:30;;9743:33;9771:4;9763:6;9743:33;:::i;:::-;9653:129;;;:::o;9788:308::-;9850:4;9940:18;9932:6;9929:30;9926:56;;;9962:18;;:::i;:::-;9926:56;10000:29;10022:6;10000:29;:::i;:::-;9992:37;;10084:4;10078;10074:15;10066:23;;9788:308;;;:::o;10102:146::-;10199:6;10194:3;10189;10176:30;10240:1;10231:6;10226:3;10222:16;10215:27;10102:146;;;:::o;10254:425::-;10332:5;10357:66;10373:49;10415:6;10373:49;:::i;:::-;10357:66;:::i;:::-;10348:75;;10446:6;10439:5;10432:21;10484:4;10477:5;10473:16;10522:3;10513:6;10508:3;10504:16;10501:25;10498:112;;;10529:79;;:::i;:::-;10498:112;10619:54;10666:6;10661:3;10656;10619:54;:::i;:::-;10338:341;10254:425;;;;;:::o;10699:340::-;10755:5;10804:3;10797:4;10789:6;10785:17;10781:27;10771:122;;10812:79;;:::i;:::-;10771:122;10929:6;10916:20;10954:79;11029:3;11021:6;11014:4;11006:6;11002:17;10954:79;:::i;:::-;10945:88;;10761:278;10699:340;;;;:::o;11045:509::-;11114:6;11163:2;11151:9;11142:7;11138:23;11134:32;11131:119;;;11169:79;;:::i;:::-;11131:119;11317:1;11306:9;11302:17;11289:31;11347:18;11339:6;11336:30;11333:117;;;11369:79;;:::i;:::-;11333:117;11474:63;11529:7;11520:6;11509:9;11505:22;11474:63;:::i;:::-;11464:73;;11260:287;11045:509;;;;:::o;11560:329::-;11619:6;11668:2;11656:9;11647:7;11643:23;11639:32;11636:119;;;11674:79;;:::i;:::-;11636:119;11794:1;11819:53;11864:7;11855:6;11844:9;11840:22;11819:53;:::i;:::-;11809:63;;11765:117;11560:329;;;;:::o;11895:114::-;11962:6;11996:5;11990:12;11980:22;;11895:114;;;:::o;12015:184::-;12114:11;12148:6;12143:3;12136:19;12188:4;12183:3;12179:14;12164:29;;12015:184;;;;:::o;12205:132::-;12272:4;12295:3;12287:11;;12325:4;12320:3;12316:14;12308:22;;12205:132;;;:::o;12343:108::-;12420:24;12438:5;12420:24;:::i;:::-;12415:3;12408:37;12343:108;;:::o;12457:179::-;12526:10;12547:46;12589:3;12581:6;12547:46;:::i;:::-;12625:4;12620:3;12616:14;12602:28;;12457:179;;;;:::o;12642:113::-;12712:4;12744;12739:3;12735:14;12727:22;;12642:113;;;:::o;12791:732::-;12910:3;12939:54;12987:5;12939:54;:::i;:::-;13009:86;13088:6;13083:3;13009:86;:::i;:::-;13002:93;;13119:56;13169:5;13119:56;:::i;:::-;13198:7;13229:1;13214:284;13239:6;13236:1;13233:13;13214:284;;;13315:6;13309:13;13342:63;13401:3;13386:13;13342:63;:::i;:::-;13335:70;;13428:60;13481:6;13428:60;:::i;:::-;13418:70;;13274:224;13261:1;13258;13254:9;13249:14;;13214:284;;;13218:14;13514:3;13507:10;;12915:608;;;12791:732;;;;:::o;13529:373::-;13672:4;13710:2;13699:9;13695:18;13687:26;;13759:9;13753:4;13749:20;13745:1;13734:9;13730:17;13723:47;13787:108;13890:4;13881:6;13787:108;:::i;:::-;13779:116;;13529:373;;;;:::o;13908:117::-;14017:1;14014;14007:12;14031:117;14140:1;14137;14130:12;14171:568;14244:8;14254:6;14304:3;14297:4;14289:6;14285:17;14281:27;14271:122;;14312:79;;:::i;:::-;14271:122;14425:6;14412:20;14402:30;;14455:18;14447:6;14444:30;14441:117;;;14477:79;;:::i;:::-;14441:117;14591:4;14583:6;14579:17;14567:29;;14645:3;14637:4;14629:6;14625:17;14615:8;14611:32;14608:41;14605:128;;;14652:79;;:::i;:::-;14605:128;14171:568;;;;;:::o;14762:::-;14835:8;14845:6;14895:3;14888:4;14880:6;14876:17;14872:27;14862:122;;14903:79;;:::i;:::-;14862:122;15016:6;15003:20;14993:30;;15046:18;15038:6;15035:30;15032:117;;;15068:79;;:::i;:::-;15032:117;15182:4;15174:6;15170:17;15158:29;;15236:3;15228:4;15220:6;15216:17;15206:8;15202:32;15199:41;15196:128;;;15243:79;;:::i;:::-;15196:128;14762:568;;;;;:::o;15336:934::-;15458:6;15466;15474;15482;15531:2;15519:9;15510:7;15506:23;15502:32;15499:119;;;15537:79;;:::i;:::-;15499:119;15685:1;15674:9;15670:17;15657:31;15715:18;15707:6;15704:30;15701:117;;;15737:79;;:::i;:::-;15701:117;15850:80;15922:7;15913:6;15902:9;15898:22;15850:80;:::i;:::-;15832:98;;;;15628:312;16007:2;15996:9;15992:18;15979:32;16038:18;16030:6;16027:30;16024:117;;;16060:79;;:::i;:::-;16024:117;16173:80;16245:7;16236:6;16225:9;16221:22;16173:80;:::i;:::-;16155:98;;;;15950:313;15336:934;;;;;;;:::o;16276:116::-;16346:21;16361:5;16346:21;:::i;:::-;16339:5;16336:32;16326:60;;16382:1;16379;16372:12;16326:60;16276:116;:::o;16398:133::-;16441:5;16479:6;16466:20;16457:29;;16495:30;16519:5;16495:30;:::i;:::-;16398:133;;;;:::o;16537:468::-;16602:6;16610;16659:2;16647:9;16638:7;16634:23;16630:32;16627:119;;;16665:79;;:::i;:::-;16627:119;16785:1;16810:53;16855:7;16846:6;16835:9;16831:22;16810:53;:::i;:::-;16800:63;;16756:117;16912:2;16938:50;16980:7;16971:6;16960:9;16956:22;16938:50;:::i;:::-;16928:60;;16883:115;16537:468;;;;;:::o;17011:307::-;17072:4;17162:18;17154:6;17151:30;17148:56;;;17184:18;;:::i;:::-;17148:56;17222:29;17244:6;17222:29;:::i;:::-;17214:37;;17306:4;17300;17296:15;17288:23;;17011:307;;;:::o;17324:423::-;17401:5;17426:65;17442:48;17483:6;17442:48;:::i;:::-;17426:65;:::i;:::-;17417:74;;17514:6;17507:5;17500:21;17552:4;17545:5;17541:16;17590:3;17581:6;17576:3;17572:16;17569:25;17566:112;;;17597:79;;:::i;:::-;17566:112;17687:54;17734:6;17729:3;17724;17687:54;:::i;:::-;17407:340;17324:423;;;;;:::o;17766:338::-;17821:5;17870:3;17863:4;17855:6;17851:17;17847:27;17837:122;;17878:79;;:::i;:::-;17837:122;17995:6;17982:20;18020:78;18094:3;18086:6;18079:4;18071:6;18067:17;18020:78;:::i;:::-;18011:87;;17827:277;17766:338;;;;:::o;18110:943::-;18205:6;18213;18221;18229;18278:3;18266:9;18257:7;18253:23;18249:33;18246:120;;;18285:79;;:::i;:::-;18246:120;18405:1;18430:53;18475:7;18466:6;18455:9;18451:22;18430:53;:::i;:::-;18420:63;;18376:117;18532:2;18558:53;18603:7;18594:6;18583:9;18579:22;18558:53;:::i;:::-;18548:63;;18503:118;18660:2;18686:53;18731:7;18722:6;18711:9;18707:22;18686:53;:::i;:::-;18676:63;;18631:118;18816:2;18805:9;18801:18;18788:32;18847:18;18839:6;18836:30;18833:117;;;18869:79;;:::i;:::-;18833:117;18974:62;19028:7;19019:6;19008:9;19004:22;18974:62;:::i;:::-;18964:72;;18759:287;18110:943;;;;;;;:::o;19059:359::-;19133:6;19182:2;19170:9;19161:7;19157:23;19153:32;19150:119;;;19188:79;;:::i;:::-;19150:119;19308:1;19333:68;19393:7;19384:6;19373:9;19369:22;19333:68;:::i;:::-;19323:78;;19279:132;19059:359;;;;:::o;19424:474::-;19492:6;19500;19549:2;19537:9;19528:7;19524:23;19520:32;19517:119;;;19555:79;;:::i;:::-;19517:119;19675:1;19700:53;19745:7;19736:6;19725:9;19721:22;19700:53;:::i;:::-;19690:63;;19646:117;19802:2;19828:53;19873:7;19864:6;19853:9;19849:22;19828:53;:::i;:::-;19818:63;;19773:118;19424:474;;;;;:::o;19904:182::-;20044:34;20040:1;20032:6;20028:14;20021:58;19904:182;:::o;20092:366::-;20234:3;20255:67;20319:2;20314:3;20255:67;:::i;:::-;20248:74;;20331:93;20420:3;20331:93;:::i;:::-;20449:2;20444:3;20440:12;20433:19;;20092:366;;;:::o;20464:419::-;20630:4;20668:2;20657:9;20653:18;20645:26;;20717:9;20711:4;20707:20;20703:1;20692:9;20688:17;20681:47;20745:131;20871:4;20745:131;:::i;:::-;20737:139;;20464:419;;;:::o;20889:180::-;20937:77;20934:1;20927:88;21034:4;21031:1;21024:15;21058:4;21055:1;21048:15;21075:320;21119:6;21156:1;21150:4;21146:12;21136:22;;21203:1;21197:4;21193:12;21224:18;21214:81;;21280:4;21272:6;21268:17;21258:27;;21214:81;21342:2;21334:6;21331:14;21311:18;21308:38;21305:84;;21361:18;;:::i;:::-;21305:84;21126:269;21075:320;;;:::o;21401:332::-;21522:4;21560:2;21549:9;21545:18;21537:26;;21573:71;21641:1;21630:9;21626:17;21617:6;21573:71;:::i;:::-;21654:72;21722:2;21711:9;21707:18;21698:6;21654:72;:::i;:::-;21401:332;;;;;:::o;21739:137::-;21793:5;21824:6;21818:13;21809:22;;21840:30;21864:5;21840:30;:::i;:::-;21739:137;;;;:::o;21882:345::-;21949:6;21998:2;21986:9;21977:7;21973:23;21969:32;21966:119;;;22004:79;;:::i;:::-;21966:119;22124:1;22149:61;22202:7;22193:6;22182:9;22178:22;22149:61;:::i;:::-;22139:71;;22095:125;21882:345;;;;:::o;22233:225::-;22373:34;22369:1;22361:6;22357:14;22350:58;22442:8;22437:2;22429:6;22425:15;22418:33;22233:225;:::o;22464:366::-;22606:3;22627:67;22691:2;22686:3;22627:67;:::i;:::-;22620:74;;22703:93;22792:3;22703:93;:::i;:::-;22821:2;22816:3;22812:12;22805:19;;22464:366;;;:::o;22836:419::-;23002:4;23040:2;23029:9;23025:18;23017:26;;23089:9;23083:4;23079:20;23075:1;23064:9;23060:17;23053:47;23117:131;23243:4;23117:131;:::i;:::-;23109:139;;22836:419;;;:::o;23261:180::-;23309:77;23306:1;23299:88;23406:4;23403:1;23396:15;23430:4;23427:1;23420:15;23447:191;23487:3;23506:20;23524:1;23506:20;:::i;:::-;23501:25;;23540:20;23558:1;23540:20;:::i;:::-;23535:25;;23583:1;23580;23576:9;23569:16;;23604:3;23601:1;23598:10;23595:36;;;23611:18;;:::i;:::-;23595:36;23447:191;;;;:::o;23644:230::-;23784:34;23780:1;23772:6;23768:14;23761:58;23853:13;23848:2;23840:6;23836:15;23829:38;23644:230;:::o;23880:366::-;24022:3;24043:67;24107:2;24102:3;24043:67;:::i;:::-;24036:74;;24119:93;24208:3;24119:93;:::i;:::-;24237:2;24232:3;24228:12;24221:19;;23880:366;;;:::o;24252:419::-;24418:4;24456:2;24445:9;24441:18;24433:26;;24505:9;24499:4;24495:20;24491:1;24480:9;24476:17;24469:47;24533:131;24659:4;24533:131;:::i;:::-;24525:139;;24252:419;;;:::o;24677:134::-;24735:9;24768:37;24799:5;24768:37;:::i;:::-;24755:50;;24677:134;;;:::o;24817:147::-;24912:45;24951:5;24912:45;:::i;:::-;24907:3;24900:58;24817:147;;:::o;24970:348::-;25099:4;25137:2;25126:9;25122:18;25114:26;;25150:79;25226:1;25215:9;25211:17;25202:6;25150:79;:::i;:::-;25239:72;25307:2;25296:9;25292:18;25283:6;25239:72;:::i;:::-;24970:348;;;;;:::o;25324:143::-;25381:5;25412:6;25406:13;25397:22;;25428:33;25455:5;25428:33;:::i;:::-;25324:143;;;;:::o;25473:351::-;25543:6;25592:2;25580:9;25571:7;25567:23;25563:32;25560:119;;;25598:79;;:::i;:::-;25560:119;25718:1;25743:64;25799:7;25790:6;25779:9;25775:22;25743:64;:::i;:::-;25733:74;;25689:128;25473:351;;;;:::o;25830:143::-;25887:5;25918:6;25912:13;25903:22;;25934:33;25961:5;25934:33;:::i;:::-;25830:143;;;;:::o;25979:351::-;26049:6;26098:2;26086:9;26077:7;26073:23;26069:32;26066:119;;;26104:79;;:::i;:::-;26066:119;26224:1;26249:64;26305:7;26296:6;26285:9;26281:22;26249:64;:::i;:::-;26239:74;;26195:128;25979:351;;;;:::o;26336:165::-;26476:17;26472:1;26464:6;26460:14;26453:41;26336:165;:::o;26507:366::-;26649:3;26670:67;26734:2;26729:3;26670:67;:::i;:::-;26663:74;;26746:93;26835:3;26746:93;:::i;:::-;26864:2;26859:3;26855:12;26848:19;;26507:366;;;:::o;26879:419::-;27045:4;27083:2;27072:9;27068:18;27060:26;;27132:9;27126:4;27122:20;27118:1;27107:9;27103:17;27096:47;27160:131;27286:4;27160:131;:::i;:::-;27152:139;;26879:419;;;:::o;27304:141::-;27353:4;27376:3;27368:11;;27399:3;27396:1;27389:14;27433:4;27430:1;27420:18;27412:26;;27304:141;;;:::o;27451:93::-;27488:6;27535:2;27530;27523:5;27519:14;27515:23;27505:33;;27451:93;;;:::o;27550:107::-;27594:8;27644:5;27638:4;27634:16;27613:37;;27550:107;;;;:::o;27663:393::-;27732:6;27782:1;27770:10;27766:18;27805:97;27835:66;27824:9;27805:97;:::i;:::-;27923:39;27953:8;27942:9;27923:39;:::i;:::-;27911:51;;27995:4;27991:9;27984:5;27980:21;27971:30;;28044:4;28034:8;28030:19;28023:5;28020:30;28010:40;;27739:317;;27663:393;;;;;:::o;28062:142::-;28112:9;28145:53;28163:34;28172:24;28190:5;28172:24;:::i;:::-;28163:34;:::i;:::-;28145:53;:::i;:::-;28132:66;;28062:142;;;:::o;28210:75::-;28253:3;28274:5;28267:12;;28210:75;;;:::o;28291:269::-;28401:39;28432:7;28401:39;:::i;:::-;28462:91;28511:41;28535:16;28511:41;:::i;:::-;28503:6;28496:4;28490:11;28462:91;:::i;:::-;28456:4;28449:105;28367:193;28291:269;;;:::o;28566:73::-;28611:3;28566:73;:::o;28645:189::-;28722:32;;:::i;:::-;28763:65;28821:6;28813;28807:4;28763:65;:::i;:::-;28698:136;28645:189;;:::o;28840:186::-;28900:120;28917:3;28910:5;28907:14;28900:120;;;28971:39;29008:1;29001:5;28971:39;:::i;:::-;28944:1;28937:5;28933:13;28924:22;;28900:120;;;28840:186;;:::o;29032:543::-;29133:2;29128:3;29125:11;29122:446;;;29167:38;29199:5;29167:38;:::i;:::-;29251:29;29269:10;29251:29;:::i;:::-;29241:8;29237:44;29434:2;29422:10;29419:18;29416:49;;;29455:8;29440:23;;29416:49;29478:80;29534:22;29552:3;29534:22;:::i;:::-;29524:8;29520:37;29507:11;29478:80;:::i;:::-;29137:431;;29122:446;29032:543;;;:::o;29581:117::-;29635:8;29685:5;29679:4;29675:16;29654:37;;29581:117;;;;:::o;29704:169::-;29748:6;29781:51;29829:1;29825:6;29817:5;29814:1;29810:13;29781:51;:::i;:::-;29777:56;29862:4;29856;29852:15;29842:25;;29755:118;29704:169;;;;:::o;29878:295::-;29954:4;30100:29;30125:3;30119:4;30100:29;:::i;:::-;30092:37;;30162:3;30159:1;30155:11;30149:4;30146:21;30138:29;;29878:295;;;;:::o;30178:1395::-;30295:37;30328:3;30295:37;:::i;:::-;30397:18;30389:6;30386:30;30383:56;;;30419:18;;:::i;:::-;30383:56;30463:38;30495:4;30489:11;30463:38;:::i;:::-;30548:67;30608:6;30600;30594:4;30548:67;:::i;:::-;30642:1;30666:4;30653:17;;30698:2;30690:6;30687:14;30715:1;30710:618;;;;31372:1;31389:6;31386:77;;;31438:9;31433:3;31429:19;31423:26;31414:35;;31386:77;31489:67;31549:6;31542:5;31489:67;:::i;:::-;31483:4;31476:81;31345:222;30680:887;;30710:618;30762:4;30758:9;30750:6;30746:22;30796:37;30828:4;30796:37;:::i;:::-;30855:1;30869:208;30883:7;30880:1;30877:14;30869:208;;;30962:9;30957:3;30953:19;30947:26;30939:6;30932:42;31013:1;31005:6;31001:14;30991:24;;31060:2;31049:9;31045:18;31032:31;;30906:4;30903:1;30899:12;30894:17;;30869:208;;;31105:6;31096:7;31093:19;31090:179;;;31163:9;31158:3;31154:19;31148:26;31206:48;31248:4;31240:6;31236:17;31225:9;31206:48;:::i;:::-;31198:6;31191:64;31113:156;31090:179;31315:1;31311;31303:6;31299:14;31295:22;31289:4;31282:36;30717:611;;;30680:887;;30270:1303;;;30178:1395;;:::o;31579:180::-;31627:77;31624:1;31617:88;31724:4;31721:1;31714:15;31748:4;31745:1;31738:15;31765:168;31905:20;31901:1;31893:6;31889:14;31882:44;31765:168;:::o;31939:366::-;32081:3;32102:67;32166:2;32161:3;32102:67;:::i;:::-;32095:74;;32178:93;32267:3;32178:93;:::i;:::-;32296:2;32291:3;32287:12;32280:19;;31939:366;;;:::o;32311:419::-;32477:4;32515:2;32504:9;32500:18;32492:26;;32564:9;32558:4;32554:20;32550:1;32539:9;32535:17;32528:47;32592:131;32718:4;32592:131;:::i;:::-;32584:139;;32311:419;;;:::o;32736:158::-;32876:10;32872:1;32864:6;32860:14;32853:34;32736:158;:::o;32900:365::-;33042:3;33063:66;33127:1;33122:3;33063:66;:::i;:::-;33056:73;;33138:93;33227:3;33138:93;:::i;:::-;33256:2;33251:3;33247:12;33240:19;;32900:365;;;:::o;33271:419::-;33437:4;33475:2;33464:9;33460:18;33452:26;;33524:9;33518:4;33514:20;33510:1;33499:9;33495:17;33488:47;33552:131;33678:4;33552:131;:::i;:::-;33544:139;;33271:419;;;:::o;33696:233::-;33735:3;33758:24;33776:5;33758:24;:::i;:::-;33749:33;;33804:66;33797:5;33794:77;33791:103;;33874:18;;:::i;:::-;33791:103;33921:1;33914:5;33910:13;33903:20;;33696:233;;;:::o;33935:181::-;34075:33;34071:1;34063:6;34059:14;34052:57;33935:181;:::o;34122:366::-;34264:3;34285:67;34349:2;34344:3;34285:67;:::i;:::-;34278:74;;34361:93;34450:3;34361:93;:::i;:::-;34479:2;34474:3;34470:12;34463:19;;34122:366;;;:::o;34494:419::-;34660:4;34698:2;34687:9;34683:18;34675:26;;34747:9;34741:4;34737:20;34733:1;34722:9;34718:17;34711:47;34775:131;34901:4;34775:131;:::i;:::-;34767:139;;34494:419;;;:::o;34919:168::-;35059:20;35055:1;35047:6;35043:14;35036:44;34919:168;:::o;35093:366::-;35235:3;35256:67;35320:2;35315:3;35256:67;:::i;:::-;35249:74;;35332:93;35421:3;35332:93;:::i;:::-;35450:2;35445:3;35441:12;35434:19;;35093:366;;;:::o;35465:419::-;35631:4;35669:2;35658:9;35654:18;35646:26;;35718:9;35712:4;35708:20;35704:1;35693:9;35689:17;35682:47;35746:131;35872:4;35746:131;:::i;:::-;35738:139;;35465:419;;;:::o;35890:165::-;36030:17;36026:1;36018:6;36014:14;36007:41;35890:165;:::o;36061:366::-;36203:3;36224:67;36288:2;36283:3;36224:67;:::i;:::-;36217:74;;36300:93;36389:3;36300:93;:::i;:::-;36418:2;36413:3;36409:12;36402:19;;36061:366;;;:::o;36433:419::-;36599:4;36637:2;36626:9;36622:18;36614:26;;36686:9;36680:4;36676:20;36672:1;36661:9;36657:17;36650:47;36714:131;36840:4;36714:131;:::i;:::-;36706:139;;36433:419;;;:::o;36858:180::-;36998:32;36994:1;36986:6;36982:14;36975:56;36858:180;:::o;37044:366::-;37186:3;37207:67;37271:2;37266:3;37207:67;:::i;:::-;37200:74;;37283:93;37372:3;37283:93;:::i;:::-;37401:2;37396:3;37392:12;37385:19;;37044:366;;;:::o;37416:419::-;37582:4;37620:2;37609:9;37605:18;37597:26;;37669:9;37663:4;37659:20;37655:1;37644:9;37640:17;37633:47;37697:131;37823:4;37697:131;:::i;:::-;37689:139;;37416:419;;;:::o;37841:163::-;37981:15;37977:1;37969:6;37965:14;37958:39;37841:163;:::o;38010:366::-;38152:3;38173:67;38237:2;38232:3;38173:67;:::i;:::-;38166:74;;38249:93;38338:3;38249:93;:::i;:::-;38367:2;38362:3;38358:12;38351:19;;38010:366;;;:::o;38382:419::-;38548:4;38586:2;38575:9;38571:18;38563:26;;38635:9;38629:4;38625:20;38621:1;38610:9;38606:17;38599:47;38663:131;38789:4;38663:131;:::i;:::-;38655:139;;38382:419;;;:::o;38807:223::-;38947:34;38943:1;38935:6;38931:14;38924:58;39016:6;39011:2;39003:6;38999:15;38992:31;38807:223;:::o;39036:366::-;39178:3;39199:67;39263:2;39258:3;39199:67;:::i;:::-;39192:74;;39275:93;39364:3;39275:93;:::i;:::-;39393:2;39388:3;39384:12;39377:19;;39036:366;;;:::o;39408:419::-;39574:4;39612:2;39601:9;39597:18;39589:26;;39661:9;39655:4;39651:20;39647:1;39636:9;39632:17;39625:47;39689:131;39815:4;39689:131;:::i;:::-;39681:139;;39408:419;;;:::o;39833:410::-;39873:7;39896:20;39914:1;39896:20;:::i;:::-;39891:25;;39930:20;39948:1;39930:20;:::i;:::-;39925:25;;39985:1;39982;39978:9;40007:30;40025:11;40007:30;:::i;:::-;39996:41;;40186:1;40177:7;40173:15;40170:1;40167:22;40147:1;40140:9;40120:83;40097:139;;40216:18;;:::i;:::-;40097:139;39881:362;39833:410;;;;:::o;40249:171::-;40389:23;40385:1;40377:6;40373:14;40366:47;40249:171;:::o;40426:366::-;40568:3;40589:67;40653:2;40648:3;40589:67;:::i;:::-;40582:74;;40665:93;40754:3;40665:93;:::i;:::-;40783:2;40778:3;40774:12;40767:19;;40426:366;;;:::o;40798:419::-;40964:4;41002:2;40991:9;40987:18;40979:26;;41051:9;41045:4;41041:20;41037:1;41026:9;41022:17;41015:47;41079:131;41205:4;41079:131;:::i;:::-;41071:139;;40798:419;;;:::o;41223:148::-;41325:11;41362:3;41347:18;;41223:148;;;;:::o;41377:390::-;41483:3;41511:39;41544:5;41511:39;:::i;:::-;41566:89;41648:6;41643:3;41566:89;:::i;:::-;41559:96;;41664:65;41722:6;41717:3;41710:4;41703:5;41699:16;41664:65;:::i;:::-;41754:6;41749:3;41745:16;41738:23;;41487:280;41377:390;;;;:::o;41773:155::-;41913:7;41909:1;41901:6;41897:14;41890:31;41773:155;:::o;41934:400::-;42094:3;42115:84;42197:1;42192:3;42115:84;:::i;:::-;42108:91;;42208:93;42297:3;42208:93;:::i;:::-;42326:1;42321:3;42317:11;42310:18;;41934:400;;;:::o;42340:541::-;42573:3;42595:95;42686:3;42677:6;42595:95;:::i;:::-;42588:102;;42707:148;42851:3;42707:148;:::i;:::-;42700:155;;42872:3;42865:10;;42340:541;;;;:::o;42887:225::-;43027:34;43023:1;43015:6;43011:14;43004:58;43096:8;43091:2;43083:6;43079:15;43072:33;42887:225;:::o;43118:366::-;43260:3;43281:67;43345:2;43340:3;43281:67;:::i;:::-;43274:74;;43357:93;43446:3;43357:93;:::i;:::-;43475:2;43470:3;43466:12;43459:19;;43118:366;;;:::o;43490:419::-;43656:4;43694:2;43683:9;43679:18;43671:26;;43743:9;43737:4;43733:20;43729:1;43718:9;43714:17;43707:47;43771:131;43897:4;43771:131;:::i;:::-;43763:139;;43490:419;;;:::o;43915:180::-;43963:77;43960:1;43953:88;44060:4;44057:1;44050:15;44084:4;44081:1;44074:15;44101:185;44141:1;44158:20;44176:1;44158:20;:::i;:::-;44153:25;;44192:20;44210:1;44192:20;:::i;:::-;44187:25;;44231:1;44221:35;;44236:18;;:::i;:::-;44221:35;44278:1;44275;44271:9;44266:14;;44101:185;;;;:::o;44292:194::-;44332:4;44352:20;44370:1;44352:20;:::i;:::-;44347:25;;44386:20;44404:1;44386:20;:::i;:::-;44381:25;;44430:1;44427;44423:9;44415:17;;44454:1;44448:4;44445:11;44442:37;;;44459:18;;:::i;:::-;44442:37;44292:194;;;;:::o;44492:179::-;44632:31;44628:1;44620:6;44616:14;44609:55;44492:179;:::o;44677:366::-;44819:3;44840:67;44904:2;44899:3;44840:67;:::i;:::-;44833:74;;44916:93;45005:3;44916:93;:::i;:::-;45034:2;45029:3;45025:12;45018:19;;44677:366;;;:::o;45049:419::-;45215:4;45253:2;45242:9;45238:18;45230:26;;45302:9;45296:4;45292:20;45288:1;45277:9;45273:17;45266:47;45330:131;45456:4;45330:131;:::i;:::-;45322:139;;45049:419;;;:::o;45474:147::-;45575:11;45612:3;45597:18;;45474:147;;;;:::o;45627:114::-;;:::o;45747:398::-;45906:3;45927:83;46008:1;46003:3;45927:83;:::i;:::-;45920:90;;46019:93;46108:3;46019:93;:::i;:::-;46137:1;46132:3;46128:11;46121:18;;45747:398;;;:::o;46151:379::-;46335:3;46357:147;46500:3;46357:147;:::i;:::-;46350:154;;46521:3;46514:10;;46151:379;;;:::o;46536:245::-;46676:34;46672:1;46664:6;46660:14;46653:58;46745:28;46740:2;46732:6;46728:15;46721:53;46536:245;:::o;46787:366::-;46929:3;46950:67;47014:2;47009:3;46950:67;:::i;:::-;46943:74;;47026:93;47115:3;47026:93;:::i;:::-;47144:2;47139:3;47135:12;47128:19;;46787:366;;;:::o;47159:419::-;47325:4;47363:2;47352:9;47348:18;47340:26;;47412:9;47406:4;47402:20;47398:1;47387:9;47383:17;47376:47;47440:131;47566:4;47440:131;:::i;:::-;47432:139;;47159:419;;;:::o;47584:98::-;47635:6;47669:5;47663:12;47653:22;;47584:98;;;:::o;47688:168::-;47771:11;47805:6;47800:3;47793:19;47845:4;47840:3;47836:14;47821:29;;47688:168;;;;:::o;47862:373::-;47948:3;47976:38;48008:5;47976:38;:::i;:::-;48030:70;48093:6;48088:3;48030:70;:::i;:::-;48023:77;;48109:65;48167:6;48162:3;48155:4;48148:5;48144:16;48109:65;:::i;:::-;48199:29;48221:6;48199:29;:::i;:::-;48194:3;48190:39;48183:46;;47952:283;47862:373;;;;:::o;48241:640::-;48436:4;48474:3;48463:9;48459:19;48451:27;;48488:71;48556:1;48545:9;48541:17;48532:6;48488:71;:::i;:::-;48569:72;48637:2;48626:9;48622:18;48613:6;48569:72;:::i;:::-;48651;48719:2;48708:9;48704:18;48695:6;48651:72;:::i;:::-;48770:9;48764:4;48760:20;48755:2;48744:9;48740:18;48733:48;48798:76;48869:4;48860:6;48798:76;:::i;:::-;48790:84;;48241:640;;;;;;;:::o;48887:141::-;48943:5;48974:6;48968:13;48959:22;;48990:32;49016:5;48990:32;:::i;:::-;48887:141;;;;:::o;49034:349::-;49103:6;49152:2;49140:9;49131:7;49127:23;49123:32;49120:119;;;49158:79;;:::i;:::-;49120:119;49278:1;49303:63;49358:7;49349:6;49338:9;49334:22;49303:63;:::i;:::-;49293:73;;49249:127;49034:349;;;;:::o;49389:435::-;49569:3;49591:95;49682:3;49673:6;49591:95;:::i;:::-;49584:102;;49703:95;49794:3;49785:6;49703:95;:::i;:::-;49696:102;;49815:3;49808:10;;49389:435;;;;;:::o;49830:229::-;49970:34;49966:1;49958:6;49954:14;49947:58;50039:12;50034:2;50026:6;50022:15;50015:37;49830:229;:::o;50065:366::-;50207:3;50228:67;50292:2;50287:3;50228:67;:::i;:::-;50221:74;;50304:93;50393:3;50304:93;:::i;:::-;50422:2;50417:3;50413:12;50406:19;;50065:366;;;:::o;50437:419::-;50603:4;50641:2;50630:9;50626:18;50618:26;;50690:9;50684:4;50680:20;50676:1;50665:9;50661:17;50654:47;50718:131;50844:4;50718:131;:::i;:::-;50710:139;;50437:419;;;:::o;50862:176::-;50894:1;50911:20;50929:1;50911:20;:::i;:::-;50906:25;;50945:20;50963:1;50945:20;:::i;:::-;50940:25;;50984:1;50974:35;;50989:18;;:::i;:::-;50974:35;51030:1;51027;51023:9;51018:14;;50862:176;;;;:::o;51044:225::-;51184:34;51180:1;51172:6;51168:14;51161:58;51253:8;51248:2;51240:6;51236:15;51229:33;51044:225;:::o;51275:366::-;51417:3;51438:67;51502:2;51497:3;51438:67;:::i;:::-;51431:74;;51514:93;51603:3;51514:93;:::i;:::-;51632:2;51627:3;51623:12;51616:19;;51275:366;;;:::o;51647:419::-;51813:4;51851:2;51840:9;51836:18;51828:26;;51900:9;51894:4;51890:20;51886:1;51875:9;51871:17;51864:47;51928:131;52054:4;51928:131;:::i;:::-;51920:139;;51647:419;;;:::o;52072:179::-;52212:31;52208:1;52200:6;52196:14;52189:55;52072:179;:::o;52257:366::-;52399:3;52420:67;52484:2;52479:3;52420:67;:::i;:::-;52413:74;;52496:93;52585:3;52496:93;:::i;:::-;52614:2;52609:3;52605:12;52598:19;;52257:366;;;:::o;52629:419::-;52795:4;52833:2;52822:9;52818:18;52810:26;;52882:9;52876:4;52872:20;52868:1;52857:9;52853:17;52846:47;52910:131;53036:4;52910:131;:::i;:::-;52902:139;;52629:419;;;:::o;53054:386::-;53158:3;53186:38;53218:5;53186:38;:::i;:::-;53240:88;53321:6;53316:3;53240:88;:::i;:::-;53233:95;;53337:65;53395:6;53390:3;53383:4;53376:5;53372:16;53337:65;:::i;:::-;53427:6;53422:3;53418:16;53411:23;;53162:278;53054:386;;;;:::o;53446:271::-;53576:3;53598:93;53687:3;53678:6;53598:93;:::i;:::-;53591:100;;53708:3;53701:10;;53446:271;;;;:::o

Swarm Source

ipfs://215ad0174425e8b46642e22dd115f297cb220f26a08a40ef818b22f744e72920
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.