ETH Price: $3,391.72 (+1.03%)

Token

Backpacks (PACK)
 

Overview

Max Total Supply

1,195 PACK

Holders

260

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
10 PACK
0xaad3ceabdb56c0d80710b21f9ebb27466d162229
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
JourneyPacks

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-01-12
*/

/**
 *Submitted for verification at Etherscan.io on 2022-08-04
 */

// 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 JourneyPacks is
    ERC721A,
    ReentrancyGuard,
    Ownable,
    PaymentSplitter,
    DefaultOperatorFilterer
{
    // Minting Variables
    uint256 public mintPrice = 0.1 ether;
    uint256 public maxPurchase = 10;
    uint256 public maxSupply = 3333;

    address[] public _payees = [
        0x7FDE663601A53A6953bbb98F1Ab87E86dEE81b35, // Liquid Payments
        0x867Eb0804eACA9FEeda8a0E1d2B9a32eEF58AF8f,
        0x0C07747AB98EE84971C90Fbd353eda207B737c43
    ];
    uint256[] private _shares = [25, 65, 10];

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

    mapping(address => uint256) public addressesThatMinted;

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

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

    constructor()
        ERC721A("Backpacks", "PACK")
        PaymentSplitter(_payees, _shares)
    {}

    //Holder status validation

    // Minting
    function ownerMint(address _to, uint256 _count) external onlyOwner {
        require(totalSupply() + _count <= maxSupply, "SOLD OUT");
        _safeMint(_to, _count);
    }

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

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

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

    // OpenSea's new bullshit requirements, which violate my moral code, but
    // are nonetheless necessary to make this all work properly.
    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);
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

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":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":"getApproved","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":"_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":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"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"}]

608060405267016345785d8a0000601155600a601255610d056013556040518060600160405280737fde663601a53a6953bbb98f1ab87e86dee81b3573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200173867eb0804eaca9feeda8a0e1d2b9a32eef58af8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001730c07747ab98ee84971c90fbd353eda207b737c4373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152506014906003620001089291906200099e565b506040518060600160405280601960ff168152602001604160ff168152602001600a60ff1681525060159060036200014292919062000a2d565b506000601660006101000a81548160ff0219169083151502179055506001601660016101000a81548160ff0219169083151502179055506040518060400160405280602081526020017f68747470733a2f2f6170656c69717569642e696f2f7061636b732f6a736f6e2f81525060189081620001bf919062000d1d565b50348015620001cd57600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb6600160148054806020026020016040519081016040528092919081815260200182805480156200026957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116200021e575b50505050506015805480602002602001604051908101604052809291908181526020018280548015620002bc57602002820191906000526020600020905b815481526020019060010190808311620002a7575b50505050506040518060400160405280600981526020017f4261636b7061636b7300000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f5041434b0000000000000000000000000000000000000000000000000000000081525081600290816200033e919062000d1d565b50806003908162000350919062000d1d565b50620003616200068e60201b60201c565b6000819055505050600160088190555062000391620003856200069760201b60201c565b6200069f60201b60201c565b8051825114620003d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003cf9062000e8b565b60405180910390fd5b60008251116200041f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004169062000efd565b60405180910390fd5b60005b82518110156200048e576200047883828151811062000446576200044562000f1f565b5b602002602001015183838151811062000464576200046362000f1f565b5b60200260200101516200076560201b60201c565b8080620004859062000f7d565b91505062000422565b50505060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620006865780156200054c576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401620005129291906200100f565b600060405180830381600087803b1580156200052d57600080fd5b505af115801562000542573d6000803e3d6000fd5b5050505062000685565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462000606576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b8152600401620005cc9291906200100f565b600060405180830381600087803b158015620005e757600080fd5b505af1158015620005fc573d6000803e3d6000fd5b5050505062000684565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016200064f91906200103c565b600060405180830381600087803b1580156200066a57600080fd5b505af11580156200067f573d6000803e3d6000fd5b505050505b5b5b505062001274565b60006001905090565b600033905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620007d7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007ce90620010cf565b60405180910390fd5b600081116200081d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008149062001141565b60405180910390fd5b6000600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414620008a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200089990620011d9565b60405180910390fd5b600e829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600a54620009599190620011fb565b600a819055507f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac82826040516200099292919062001247565b60405180910390a15050565b82805482825590600052602060002090810192821562000a1a579160200282015b8281111562000a195782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190620009bf565b5b50905062000a29919062000a84565b5090565b82805482825590600052602060002090810192821562000a71579160200282015b8281111562000a70578251829060ff1690559160200191906001019062000a4e565b5b50905062000a80919062000a84565b5090565b5b8082111562000a9f57600081600090555060010162000a85565b5090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062000b2557607f821691505b60208210810362000b3b5762000b3a62000add565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000ba57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000b66565b62000bb1868362000b66565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000bfe62000bf862000bf28462000bc9565b62000bd3565b62000bc9565b9050919050565b6000819050919050565b62000c1a8362000bdd565b62000c3262000c298262000c05565b84845462000b73565b825550505050565b600090565b62000c4962000c3a565b62000c5681848462000c0f565b505050565b5b8181101562000c7e5762000c7260008262000c3f565b60018101905062000c5c565b5050565b601f82111562000ccd5762000c978162000b41565b62000ca28462000b56565b8101602085101562000cb2578190505b62000cca62000cc18562000b56565b83018262000c5b565b50505b505050565b600082821c905092915050565b600062000cf26000198460080262000cd2565b1980831691505092915050565b600062000d0d838362000cdf565b9150826002028217905092915050565b62000d288262000aa3565b67ffffffffffffffff81111562000d445762000d4362000aae565b5b62000d50825462000b0c565b62000d5d82828562000c82565b600060209050601f83116001811462000d95576000841562000d80578287015190505b62000d8c858262000cff565b86555062000dfc565b601f19841662000da58662000b41565b60005b8281101562000dcf5784890151825560018201915060208501945060208101905062000da8565b8683101562000def578489015162000deb601f89168262000cdf565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b7f5061796d656e7453706c69747465723a2070617965657320616e64207368617260008201527f6573206c656e677468206d69736d617463680000000000000000000000000000602082015250565b600062000e7360328362000e04565b915062000e808262000e15565b604082019050919050565b6000602082019050818103600083015262000ea68162000e64565b9050919050565b7f5061796d656e7453706c69747465723a206e6f20706179656573000000000000600082015250565b600062000ee5601a8362000e04565b915062000ef28262000ead565b602082019050919050565b6000602082019050818103600083015262000f188162000ed6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f8a8262000bc9565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362000fbf5762000fbe62000f4e565b5b600182019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000ff78262000fca565b9050919050565b620010098162000fea565b82525050565b600060408201905062001026600083018562000ffe565b62001035602083018462000ffe565b9392505050565b600060208201905062001053600083018462000ffe565b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973207468652060008201527f7a65726f20616464726573730000000000000000000000000000000000000000602082015250565b6000620010b7602c8362000e04565b9150620010c48262001059565b604082019050919050565b60006020820190508181036000830152620010ea81620010a8565b9050919050565b7f5061796d656e7453706c69747465723a20736861726573206172652030000000600082015250565b600062001129601d8362000e04565b91506200113682620010f1565b602082019050919050565b600060208201905081810360008301526200115c816200111a565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e7420616c726561647960008201527f2068617320736861726573000000000000000000000000000000000000000000602082015250565b6000620011c1602b8362000e04565b9150620011ce8262001163565b604082019050919050565b60006020820190508181036000830152620011f481620011b2565b9050919050565b6000620012088262000bc9565b9150620012158362000bc9565b925082820190508082111562001230576200122f62000f4e565b5b92915050565b620012418162000bc9565b82525050565b60006040820190506200125e600083018562000ffe565b6200126d602083018462001236565b9392505050565b615cbc80620012846000396000f3fe60806040526004361061028c5760003560e01c8063715018a61161015a578063c4e41b22116100c1578063e33b7de31161007a578063e33b7de314610a30578063e985e9c514610a5b578063eb8d244414610a98578063ef6d492714610ac3578063f2fde38b14610ada578063f4a0a52814610b03576102d3565b8063c4e41b22146108f8578063c87b56dd14610923578063ce7c2ac214610960578063cf3090121461099d578063d5abeb01146109c8578063d79779b2146109f3576102d3565b8063989bdbb611610113578063989bdbb61461080b578063a0712d6814610822578063a22cb4651461083e578063aa3f395514610867578063ab2fdb0c14610892578063b88d4fde146108cf576102d3565b8063715018a6146106f95780638b83209b146107105780638da5cb5b1461074d57806395d89b4114610778578063977b055b146107a35780639852595c146107ce576102d3565b806341f43434116101fe578063627fdeab116101b7578063627fdeab146105c55780636352211e146106025780636673c4c21461063f5780636817c76c1461066857806370a082311461069357806371189742146106d0576102d3565b806341f43434146104df57806342842e0e1461050a578063484b973c1461053357806348b750441461055c5780634e71d92d1461058557806355f804b31461059c576102d3565b806318160ddd1161025057806318160ddd146103bd57806319165587146103e857806323b872dd14610411578063283248be1461043a5780633a98ef3914610477578063406072a9146104a2576102d3565b806301ffc9a7146102d8578063049c5c491461031557806306fdde031461032c578063081812fc14610357578063095ea7b314610394576102d3565b366102d3577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706102ba610b2c565b346040516102c99291906142b7565b60405180910390a1005b600080fd5b3480156102e457600080fd5b506102ff60048036038101906102fa919061434c565b610b34565b60405161030c9190614394565b60405180910390f35b34801561032157600080fd5b5061032a610c16565b005b34801561033857600080fd5b50610341610d04565b60405161034e919061443f565b60405180910390f35b34801561036357600080fd5b5061037e6004803603810190610379919061448d565b610d96565b60405161038b91906144ba565b60405180910390f35b3480156103a057600080fd5b506103bb60048036038101906103b69190614501565b610e12565b005b3480156103c957600080fd5b506103d2610f1c565b6040516103df9190614541565b60405180910390f35b3480156103f457600080fd5b5061040f600480360381019061040a919061459a565b610f33565b005b34801561041d57600080fd5b50610438600480360381019061043391906145c7565b6110dd565b005b34801561044657600080fd5b50610461600480360381019061045c919061448d565b61122d565b60405161046e91906144ba565b60405180910390f35b34801561048357600080fd5b5061048c61126c565b6040516104999190614541565b60405180910390f35b3480156104ae57600080fd5b506104c960048036038101906104c49190614658565b611276565b6040516104d69190614541565b60405180910390f35b3480156104eb57600080fd5b506104f46112fd565b60405161050191906146f7565b60405180910390f35b34801561051657600080fd5b50610531600480360381019061052c91906145c7565b61130f565b005b34801561053f57600080fd5b5061055a60048036038101906105559190614501565b61145f565b005b34801561056857600080fd5b50610583600480360381019061057e9190614658565b611540565b005b34801561059157600080fd5b5061059a6117f8565b005b3480156105a857600080fd5b506105c360048036038101906105be9190614847565b611803565b005b3480156105d157600080fd5b506105ec60048036038101906105e79190614890565b6118e2565b6040516105f9919061497b565b60405180910390f35b34801561060e57600080fd5b506106296004803603810190610624919061448d565b611ad8565b60405161063691906144ba565b60405180910390f35b34801561064b57600080fd5b5061066660048036038101906106619190614a53565b611aee565b005b34801561067457600080fd5b5061067d611c9b565b60405161068a9190614541565b60405180910390f35b34801561069f57600080fd5b506106ba60048036038101906106b59190614890565b611ca1565b6040516106c79190614541565b60405180910390f35b3480156106dc57600080fd5b506106f760048036038101906106f2919061448d565b611d70565b005b34801561070557600080fd5b5061070e611df6565b005b34801561071c57600080fd5b506107376004803603810190610732919061448d565b611e7e565b60405161074491906144ba565b60405180910390f35b34801561075957600080fd5b50610762611ec6565b60405161076f91906144ba565b60405180910390f35b34801561078457600080fd5b5061078d611ef0565b60405161079a919061443f565b60405180910390f35b3480156107af57600080fd5b506107b8611f82565b6040516107c59190614541565b60405180910390f35b3480156107da57600080fd5b506107f560048036038101906107f09190614890565b611f88565b6040516108029190614541565b60405180910390f35b34801561081757600080fd5b50610820611fd1565b005b61083c6004803603810190610837919061448d565b61206a565b005b34801561084a57600080fd5b5061086560048036038101906108609190614b00565b6122a7565b005b34801561087357600080fd5b5061087c6123b1565b6040516108899190614394565b60405180910390f35b34801561089e57600080fd5b506108b960048036038101906108b49190614890565b6123c4565b6040516108c69190614541565b60405180910390f35b3480156108db57600080fd5b506108f660048036038101906108f19190614be1565b6123dc565b005b34801561090457600080fd5b5061090d61252f565b60405161091a9190614541565b60405180910390f35b34801561092f57600080fd5b5061094a6004803603810190610945919061448d565b61253e565b604051610957919061443f565b60405180910390f35b34801561096c57600080fd5b5061098760048036038101906109829190614890565b61256f565b6040516109949190614541565b60405180910390f35b3480156109a957600080fd5b506109b26125b8565b6040516109bf9190614394565b60405180910390f35b3480156109d457600080fd5b506109dd6125cb565b6040516109ea9190614541565b60405180910390f35b3480156109ff57600080fd5b50610a1a6004803603810190610a159190614c64565b6125d1565b604051610a279190614541565b60405180910390f35b348015610a3c57600080fd5b50610a4561261a565b604051610a529190614541565b60405180910390f35b348015610a6757600080fd5b50610a826004803603810190610a7d9190614c91565b612624565b604051610a8f9190614394565b60405180910390f35b348015610aa457600080fd5b50610aad6126b8565b604051610aba9190614394565b60405180910390f35b348015610acf57600080fd5b50610ad86126cb565b005b348015610ae657600080fd5b50610b016004803603810190610afc9190614890565b6127b9565b005b348015610b0f57600080fd5b50610b2a6004803603810190610b25919061448d565b6128b0565b005b600033905090565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610bff57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610c0f5750610c0e82612936565b5b9050919050565b610c1e610b2c565b73ffffffffffffffffffffffffffffffffffffffff16610c3c611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614610c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8990614d1d565b60405180910390fd5b601660009054906101000a900460ff1615601660006101000a81548160ff0219169083151502179055507f58655b75d3df612fe99ead00dbf0812d415d35078fe06217a94c0818bb13967f601660009054906101000a900460ff16604051610cfa9190614394565b60405180910390a1565b606060028054610d1390614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3f90614d6c565b8015610d8c5780601f10610d6157610100808354040283529160200191610d8c565b820191906000526020600020905b815481529060010190602001808311610d6f57829003601f168201915b5050505050905090565b6000610da1826129a0565b610dd7576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610f0d576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610e8a929190614d9d565b602060405180830381865afa158015610ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecb9190614ddb565b610f0c57806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610f0391906144ba565b60405180910390fd5b5b610f1783836129ee565b505050565b6000610f26612af8565b6001546000540303905090565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610fb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fac90614e7a565b60405180910390fd5b6000610fbf61261a565b47610fca9190614ec9565b90506000610fe18383610fdc86611f88565b612b01565b905060008103611026576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161101d90614f6f565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546110759190614ec9565b9250508190555080600b600082825461108e9190614ec9565b9250508190555061109f8382612b6f565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b05683826040516110d0929190614fb0565b60405180910390a1505050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561121b573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361114f5761114a848484612c63565b611227565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611198929190614d9d565b602060405180830381865afa1580156111b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d99190614ddb565b61121a57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161121191906144ba565b60405180910390fd5b5b611226848484612c63565b5b50505050565b6014818154811061123d57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a54905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6daaeb6d7670e522a718067333cd4e81565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561144d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036113815761137c848484612c73565b611459565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016113ca929190614d9d565b602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190614ddb565b61144c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161144391906144ba565b60405180910390fd5b5b611458848484612c73565b5b50505050565b611467610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611485611ec6565b73ffffffffffffffffffffffffffffffffffffffff16146114db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d290614d1d565b60405180910390fd5b601354816114e7610f1c565b6114f19190614ec9565b1115611532576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152990615025565b60405180910390fd5b61153c8282612c93565b5050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054116115c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b990614e7a565b60405180910390fd5b60006115cd836125d1565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161160691906144ba565b602060405180830381865afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611647919061505a565b6116519190614ec9565b9050600061166983836116648787611276565b612b01565b9050600081036116ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116a590614f6f565b60405180910390fd5b80601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461173a9190614ec9565b9250508190555080600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117909190614ec9565b925050819055506117a2848483612cb1565b8373ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a84836040516117ea9291906142b7565b60405180910390a250505050565b61180133610f33565b565b61180b610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611829611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461187f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187690614d1d565b60405180910390fd5b601960009054906101000a900460ff16156118cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c6906150d3565b60405180910390fd5b80601890816118de9190615295565b5050565b606060006118ef83611ca1565b67ffffffffffffffff8111156119085761190761471c565b5b6040519080825280602002602001820160405280156119365781602001602082028036833780820191505090505b50905060008054905060008060005b83811015611acb576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015115611a225750611abe565b600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614611a6257806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abc5781868580600101965081518110611aaf57611aae615367565b5b6020026020010181815250505b505b8080600101915050611945565b5083945050505050919050565b6000611ae382612d37565b600001519050919050565b611af6610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611b14611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611b6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b6190614d1d565b60405180910390fd5b601660019054906101000a900460ff16611bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb0906153e2565b60405180910390fd5b60005b82829050811015611c9457601354858583818110611bdd57611bdc615367565b5b90506020020135611bec610f1c565b611bf69190614ec9565b1115611c37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c2e90615025565b60405180910390fd5b611c81838383818110611c4d57611c4c615367565b5b9050602002016020810190611c629190614890565b868684818110611c7557611c74615367565b5b90506020020135612c93565b8080611c8c90615402565b915050611bbc565b5050505050565b60115481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d08576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611d78610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611d96611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611dec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de390614d1d565b60405180910390fd5b8060128190555050565b611dfe610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611e1c611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6990614d1d565b60405180910390fd5b611e7c6000612fc6565b565b6000600e8281548110611e9457611e93615367565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060038054611eff90614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054611f2b90614d6c565b8015611f785780601f10611f4d57610100808354040283529160200191611f78565b820191906000526020600020905b815481529060010190602001808311611f5b57829003601f168201915b5050505050905090565b60125481565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611fd9610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611ff7611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461204d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161204490614d1d565b60405180910390fd5b6001601960006101000a81548160ff021916908315150217905550565b6002600854036120af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a690615496565b60405180910390fd5b6002600881905550601660009054906101000a900460ff16612106576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120fd90615502565b60405180910390fd5b60125481601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546121549190614ec9565b1115612195576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218c90615594565b60405180910390fd5b601354816121a1610f1c565b6121ab9190614ec9565b11156121ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e390615025565b60405180910390fd5b34816011546121fb91906155b4565b111561223c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223390615642565b60405180910390fd5b6122463382612c93565b80601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546122959190614ec9565b92505081905550600160088190555050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156123a2576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161231f929190614d9d565b602060405180830381865afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123609190614ddb565b6123a157806040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161239891906144ba565b60405180910390fd5b5b6123ac838361308c565b505050565b601660019054906101000a900460ff1681565b60176020528060005260406000206000915090505481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561251b573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361244f5761244a85858585613203565b612528565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612498929190614d9d565b602060405180830381865afa1580156124b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d99190614ddb565b61251a57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161251191906144ba565b60405180910390fd5b5b61252785858585613203565b5b5050505050565b6000612539610f1c565b905090565b60606125498261327f565b60405160200161255991906156ea565b6040516020818303038152906040529050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b601960009054906101000a900460ff1681565b60135481565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600b54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b601660009054906101000a900460ff1681565b6126d3610b2c565b73ffffffffffffffffffffffffffffffffffffffff166126f1611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614612747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273e90614d1d565b60405180910390fd5b601660019054906101000a900460ff1615601660016101000a81548160ff0219169083151502179055507f1727dc7b28fffc84b95ca0e64637ec1614ea28c6bc7e9efa20b6df6b2e65fe87601660019054906101000a900460ff166040516127af9190614394565b60405180910390a1565b6127c1610b2c565b73ffffffffffffffffffffffffffffffffffffffff166127df611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614612835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282c90614d1d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289b9061577e565b60405180910390fd5b6128ad81612fc6565b50565b6128b8610b2c565b73ffffffffffffffffffffffffffffffffffffffff166128d6611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614d1d565b60405180910390fd5b8060118190555050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000816129ab612af8565b111580156129ba575060005482105b80156129e7575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b60006129f982611ad8565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a60576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16612a7f610b2c565b73ffffffffffffffffffffffffffffffffffffffff1614158015612ab15750612aaf81612aaa610b2c565b612624565b155b15612ae8576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612af383838361331d565b505050565b60006001905090565b600081600a54600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205485612b5291906155b4565b612b5c91906157cd565b612b6691906157fe565b90509392505050565b80471015612bb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ba99061587e565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051612bd8906158cf565b60006040518083038185875af1925050503d8060008114612c15576040519150601f19603f3d011682016040523d82523d6000602084013e612c1a565b606091505b5050905080612c5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c5590615956565b60405180910390fd5b505050565b612c6e8383836133cf565b505050565b612c8e838383604051806020016040528060008152506123dc565b505050565b612cad828260405180602001604052806000815250613883565b5050565b612d328363a9059cbb60e01b8484604051602401612cd09291906142b7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613895565b505050565b612d3f61421a565b600082905080612d4d612af8565b11158015612d5c575060005481105b15612f8f576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff16151515158152505090508060400151612f8d57600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612e71578092505050612fc1565b5b600115612f8c57818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612f87578092505050612fc1565b612e72565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b613094610b2c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036130f8576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060076000613105610b2c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166131b2610b2c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516131f79190614394565b60405180910390a35050565b61320e8484846133cf565b61322d8373ffffffffffffffffffffffffffffffffffffffff1661395c565b801561324257506132408484848461396f565b155b15613279576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b606061328a826129a0565b6132c0576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006132ca613abf565b905060008151036132ea5760405180602001604052806000815250613315565b806132f484613b51565b604051602001613305929190615976565b6040516020818303038152906040525b915050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006133da82612d37565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613445576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613466610b2c565b73ffffffffffffffffffffffffffffffffffffffff16148061349557506134948561348f610b2c565b612624565b5b806134da57506134a3610b2c565b73ffffffffffffffffffffffffffffffffffffffff166134c284610d96565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613513576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613579576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6135868585856001613cb1565b6135926000848761331d565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361381157600054821461381057878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461387c8585856001613cb7565b5050505050565b6138908383836001613cbd565b505050565b60006138f7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166140879092919063ffffffff16565b905060008151111561395757808060200190518101906139179190614ddb565b613956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161394d90615a0c565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613995610b2c565b8786866040518563ffffffff1660e01b81526004016139b79493929190615a81565b6020604051808303816000875af19250505080156139f357506040513d601f19601f820116820180604052508101906139f09190615ae2565b60015b613a6c573d8060008114613a23576040519150601f19603f3d011682016040523d82523d6000602084013e613a28565b606091505b506000815103613a64576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b606060188054613ace90614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054613afa90614d6c565b8015613b475780601f10613b1c57610100808354040283529160200191613b47565b820191906000526020600020905b815481529060010190602001808311613b2a57829003601f168201915b5050505050905090565b606060008203613b98576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613cac565b600082905060005b60008214613bca578080613bb390615402565b915050600a82613bc391906157cd565b9150613ba0565b60008167ffffffffffffffff811115613be657613be561471c565b5b6040519080825280601f01601f191660200182016040528015613c185781602001600182028036833780820191505090505b5090505b60008514613ca557600182613c3191906157fe565b9150600a85613c409190615b0f565b6030613c4c9190614ec9565b60f81b818381518110613c6257613c61615367565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85613c9e91906157cd565b9450613c1c565b8093505050505b919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613d29576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613d63576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d706000868387613cb1565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008582019050838015613f3a5750613f398773ffffffffffffffffffffffffffffffffffffffff1661395c565b5b15613fff575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613faf600088848060010195508861396f565b613fe5576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808203613f40578260005414613ffa57600080fd5b61406a565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808203614000575b8160008190555050506140806000868387613cb7565b5050505050565b6060614096848460008561409f565b90509392505050565b6060824710156140e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140db90615bb2565b60405180910390fd5b6140ed8561395c565b61412c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161412390615c1e565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516141559190615c6f565b60006040518083038185875af1925050503d8060008114614192576040519150601f19603f3d011682016040523d82523d6000602084013e614197565b606091505b50915091506141a78282866141b3565b92505050949350505050565b606083156141c357829050614213565b6000835111156141d65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161420a919061443f565b60405180910390fd5b9392505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006142888261425d565b9050919050565b6142988161427d565b82525050565b6000819050919050565b6142b18161429e565b82525050565b60006040820190506142cc600083018561428f565b6142d960208301846142a8565b9392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614329816142f4565b811461433457600080fd5b50565b60008135905061434681614320565b92915050565b600060208284031215614362576143616142ea565b5b600061437084828501614337565b91505092915050565b60008115159050919050565b61438e81614379565b82525050565b60006020820190506143a96000830184614385565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143e95780820151818401526020810190506143ce565b60008484015250505050565b6000601f19601f8301169050919050565b6000614411826143af565b61441b81856143ba565b935061442b8185602086016143cb565b614434816143f5565b840191505092915050565b600060208201905081810360008301526144598184614406565b905092915050565b61446a8161429e565b811461447557600080fd5b50565b60008135905061448781614461565b92915050565b6000602082840312156144a3576144a26142ea565b5b60006144b184828501614478565b91505092915050565b60006020820190506144cf600083018461428f565b92915050565b6144de8161427d565b81146144e957600080fd5b50565b6000813590506144fb816144d5565b92915050565b60008060408385031215614518576145176142ea565b5b6000614526858286016144ec565b925050602061453785828601614478565b9150509250929050565b600060208201905061455660008301846142a8565b92915050565b60006145678261425d565b9050919050565b6145778161455c565b811461458257600080fd5b50565b6000813590506145948161456e565b92915050565b6000602082840312156145b0576145af6142ea565b5b60006145be84828501614585565b91505092915050565b6000806000606084860312156145e0576145df6142ea565b5b60006145ee868287016144ec565b93505060206145ff868287016144ec565b925050604061461086828701614478565b9150509250925092565b60006146258261427d565b9050919050565b6146358161461a565b811461464057600080fd5b50565b6000813590506146528161462c565b92915050565b6000806040838503121561466f5761466e6142ea565b5b600061467d85828601614643565b925050602061468e858286016144ec565b9150509250929050565b6000819050919050565b60006146bd6146b86146b38461425d565b614698565b61425d565b9050919050565b60006146cf826146a2565b9050919050565b60006146e1826146c4565b9050919050565b6146f1816146d6565b82525050565b600060208201905061470c60008301846146e8565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614754826143f5565b810181811067ffffffffffffffff821117156147735761477261471c565b5b80604052505050565b60006147866142e0565b9050614792828261474b565b919050565b600067ffffffffffffffff8211156147b2576147b161471c565b5b6147bb826143f5565b9050602081019050919050565b82818337600083830152505050565b60006147ea6147e584614797565b61477c565b90508281526020810184848401111561480657614805614717565b5b6148118482856147c8565b509392505050565b600082601f83011261482e5761482d614712565b5b813561483e8482602086016147d7565b91505092915050565b60006020828403121561485d5761485c6142ea565b5b600082013567ffffffffffffffff81111561487b5761487a6142ef565b5b61488784828501614819565b91505092915050565b6000602082840312156148a6576148a56142ea565b5b60006148b4848285016144ec565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6148f28161429e565b82525050565b600061490483836148e9565b60208301905092915050565b6000602082019050919050565b6000614928826148bd565b61493281856148c8565b935061493d836148d9565b8060005b8381101561496e57815161495588826148f8565b975061496083614910565b925050600181019050614941565b5085935050505092915050565b60006020820190508181036000830152614995818461491d565b905092915050565b600080fd5b600080fd5b60008083601f8401126149bd576149bc614712565b5b8235905067ffffffffffffffff8111156149da576149d961499d565b5b6020830191508360208202830111156149f6576149f56149a2565b5b9250929050565b60008083601f840112614a1357614a12614712565b5b8235905067ffffffffffffffff811115614a3057614a2f61499d565b5b602083019150836020820283011115614a4c57614a4b6149a2565b5b9250929050565b60008060008060408587031215614a6d57614a6c6142ea565b5b600085013567ffffffffffffffff811115614a8b57614a8a6142ef565b5b614a97878288016149a7565b9450945050602085013567ffffffffffffffff811115614aba57614ab96142ef565b5b614ac6878288016149fd565b925092505092959194509250565b614add81614379565b8114614ae857600080fd5b50565b600081359050614afa81614ad4565b92915050565b60008060408385031215614b1757614b166142ea565b5b6000614b25858286016144ec565b9250506020614b3685828601614aeb565b9150509250929050565b600067ffffffffffffffff821115614b5b57614b5a61471c565b5b614b64826143f5565b9050602081019050919050565b6000614b84614b7f84614b40565b61477c565b905082815260208101848484011115614ba057614b9f614717565b5b614bab8482856147c8565b509392505050565b600082601f830112614bc857614bc7614712565b5b8135614bd8848260208601614b71565b91505092915050565b60008060008060808587031215614bfb57614bfa6142ea565b5b6000614c09878288016144ec565b9450506020614c1a878288016144ec565b9350506040614c2b87828801614478565b925050606085013567ffffffffffffffff811115614c4c57614c4b6142ef565b5b614c5887828801614bb3565b91505092959194509250565b600060208284031215614c7a57614c796142ea565b5b6000614c8884828501614643565b91505092915050565b60008060408385031215614ca857614ca76142ea565b5b6000614cb6858286016144ec565b9250506020614cc7858286016144ec565b9150509250929050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614d076020836143ba565b9150614d1282614cd1565b602082019050919050565b60006020820190508181036000830152614d3681614cfa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614d8457607f821691505b602082108103614d9757614d96614d3d565b5b50919050565b6000604082019050614db2600083018561428f565b614dbf602083018461428f565b9392505050565b600081519050614dd581614ad4565b92915050565b600060208284031215614df157614df06142ea565b5b6000614dff84828501614dc6565b91505092915050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000614e646026836143ba565b9150614e6f82614e08565b604082019050919050565b60006020820190508181036000830152614e9381614e57565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614ed48261429e565b9150614edf8361429e565b9250828201905080821115614ef757614ef6614e9a565b5b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b6000614f59602b836143ba565b9150614f6482614efd565b604082019050919050565b60006020820190508181036000830152614f8881614f4c565b9050919050565b6000614f9a826146c4565b9050919050565b614faa81614f8f565b82525050565b6000604082019050614fc56000830185614fa1565b614fd260208301846142a8565b9392505050565b7f534f4c44204f5554000000000000000000000000000000000000000000000000600082015250565b600061500f6008836143ba565b915061501a82614fd9565b602082019050919050565b6000602082019050818103600083015261503e81615002565b9050919050565b60008151905061505481614461565b92915050565b6000602082840312156150705761506f6142ea565b5b600061507e84828501615045565b91505092915050565b7f4d455441444154415f4c4f434b45440000000000000000000000000000000000600082015250565b60006150bd600f836143ba565b91506150c882615087565b602082019050919050565b600060208201905081810360008301526150ec816150b0565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026151557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615118565b61515f8683615118565b95508019841693508086168417925050509392505050565b600061519261518d6151888461429e565b614698565b61429e565b9050919050565b6000819050919050565b6151ac83615177565b6151c06151b882615199565b848454615125565b825550505050565b600090565b6151d56151c8565b6151e08184846151a3565b505050565b5b81811015615204576151f96000826151cd565b6001810190506151e6565b5050565b601f8211156152495761521a816150f3565b61522384615108565b81016020851015615232578190505b61524661523e85615108565b8301826151e5565b50505b505050565b600082821c905092915050565b600061526c6000198460080261524e565b1980831691505092915050565b6000615285838361525b565b9150826002028217905092915050565b61529e826143af565b67ffffffffffffffff8111156152b7576152b661471c565b5b6152c18254614d6c565b6152cc828285615208565b600060209050601f8311600181146152ff57600084156152ed578287015190505b6152f78582615279565b86555061535f565b601f19841661530d866150f3565b60005b8281101561533557848901518255600182019150602085019450602081019050615310565b86831015615352578489015161534e601f89168261525b565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f41495244524f50204e4f54204143544956450000000000000000000000000000600082015250565b60006153cc6012836143ba565b91506153d782615396565b602082019050919050565b600060208201905081810360008301526153fb816153bf565b9050919050565b600061540d8261429e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361543f5761543e614e9a565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615480601f836143ba565b915061548b8261544a565b602082019050919050565b600060208201905081810360008301526154af81615473565b9050919050565b7f53414c4520494e41435449564500000000000000000000000000000000000000600082015250565b60006154ec600d836143ba565b91506154f7826154b6565b602082019050919050565b6000602082019050818103600083015261551b816154df565b9050919050565b7f7468697320776f756c6420657863656564206d696e74206d617820616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b600061557e6024836143ba565b915061558982615522565b604082019050919050565b600060208201905081810360008301526155ad81615571565b9050919050565b60006155bf8261429e565b91506155ca8361429e565b92508282026155d88161429e565b915082820484148315176155ef576155ee614e9a565b5b5092915050565b7f494e434f52524543542045544845522056414c55450000000000000000000000600082015250565b600061562c6015836143ba565b9150615637826155f6565b602082019050919050565b6000602082019050818103600083015261565b8161561f565b9050919050565b600081905092915050565b6000615678826143af565b6156828185615662565b93506156928185602086016143cb565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b60006156d4600583615662565b91506156df8261569e565b600582019050919050565b60006156f6828461566d565b9150615701826156c7565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157686026836143ba565b91506157738261570c565b604082019050919050565b600060208201905081810360008301526157978161575b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006157d88261429e565b91506157e38361429e565b9250826157f3576157f261579e565b5b828204905092915050565b60006158098261429e565b91506158148361429e565b925082820390508181111561582c5761582b614e9a565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000615868601d836143ba565b915061587382615832565b602082019050919050565b600060208201905081810360008301526158978161585b565b9050919050565b600081905092915050565b50565b60006158b960008361589e565b91506158c4826158a9565b600082019050919050565b60006158da826158ac565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b6000615940603a836143ba565b915061594b826158e4565b604082019050919050565b6000602082019050818103600083015261596f81615933565b9050919050565b6000615982828561566d565b915061598e828461566d565b91508190509392505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006159f6602a836143ba565b9150615a018261599a565b604082019050919050565b60006020820190508181036000830152615a25816159e9565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000615a5382615a2c565b615a5d8185615a37565b9350615a6d8185602086016143cb565b615a76816143f5565b840191505092915050565b6000608082019050615a96600083018761428f565b615aa3602083018661428f565b615ab060408301856142a8565b8181036060830152615ac28184615a48565b905095945050505050565b600081519050615adc81614320565b92915050565b600060208284031215615af857615af76142ea565b5b6000615b0684828501615acd565b91505092915050565b6000615b1a8261429e565b9150615b258361429e565b925082615b3557615b3461579e565b5b828206905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000615b9c6026836143ba565b9150615ba782615b40565b604082019050919050565b60006020820190508181036000830152615bcb81615b8f565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000615c08601d836143ba565b9150615c1382615bd2565b602082019050919050565b60006020820190508181036000830152615c3781615bfb565b9050919050565b6000615c4982615a2c565b615c53818561589e565b9350615c638185602086016143cb565b80840191505092915050565b6000615c7b8284615c3e565b91508190509291505056fea2646970667358221220a3bcfe60faa5bcbcf15a0272f22a02c028c3c8fd6eb7f914452fe91a2c07594d64736f6c63430008110033

Deployed Bytecode

0x60806040526004361061028c5760003560e01c8063715018a61161015a578063c4e41b22116100c1578063e33b7de31161007a578063e33b7de314610a30578063e985e9c514610a5b578063eb8d244414610a98578063ef6d492714610ac3578063f2fde38b14610ada578063f4a0a52814610b03576102d3565b8063c4e41b22146108f8578063c87b56dd14610923578063ce7c2ac214610960578063cf3090121461099d578063d5abeb01146109c8578063d79779b2146109f3576102d3565b8063989bdbb611610113578063989bdbb61461080b578063a0712d6814610822578063a22cb4651461083e578063aa3f395514610867578063ab2fdb0c14610892578063b88d4fde146108cf576102d3565b8063715018a6146106f95780638b83209b146107105780638da5cb5b1461074d57806395d89b4114610778578063977b055b146107a35780639852595c146107ce576102d3565b806341f43434116101fe578063627fdeab116101b7578063627fdeab146105c55780636352211e146106025780636673c4c21461063f5780636817c76c1461066857806370a082311461069357806371189742146106d0576102d3565b806341f43434146104df57806342842e0e1461050a578063484b973c1461053357806348b750441461055c5780634e71d92d1461058557806355f804b31461059c576102d3565b806318160ddd1161025057806318160ddd146103bd57806319165587146103e857806323b872dd14610411578063283248be1461043a5780633a98ef3914610477578063406072a9146104a2576102d3565b806301ffc9a7146102d8578063049c5c491461031557806306fdde031461032c578063081812fc14610357578063095ea7b314610394576102d3565b366102d3577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706102ba610b2c565b346040516102c99291906142b7565b60405180910390a1005b600080fd5b3480156102e457600080fd5b506102ff60048036038101906102fa919061434c565b610b34565b60405161030c9190614394565b60405180910390f35b34801561032157600080fd5b5061032a610c16565b005b34801561033857600080fd5b50610341610d04565b60405161034e919061443f565b60405180910390f35b34801561036357600080fd5b5061037e6004803603810190610379919061448d565b610d96565b60405161038b91906144ba565b60405180910390f35b3480156103a057600080fd5b506103bb60048036038101906103b69190614501565b610e12565b005b3480156103c957600080fd5b506103d2610f1c565b6040516103df9190614541565b60405180910390f35b3480156103f457600080fd5b5061040f600480360381019061040a919061459a565b610f33565b005b34801561041d57600080fd5b50610438600480360381019061043391906145c7565b6110dd565b005b34801561044657600080fd5b50610461600480360381019061045c919061448d565b61122d565b60405161046e91906144ba565b60405180910390f35b34801561048357600080fd5b5061048c61126c565b6040516104999190614541565b60405180910390f35b3480156104ae57600080fd5b506104c960048036038101906104c49190614658565b611276565b6040516104d69190614541565b60405180910390f35b3480156104eb57600080fd5b506104f46112fd565b60405161050191906146f7565b60405180910390f35b34801561051657600080fd5b50610531600480360381019061052c91906145c7565b61130f565b005b34801561053f57600080fd5b5061055a60048036038101906105559190614501565b61145f565b005b34801561056857600080fd5b50610583600480360381019061057e9190614658565b611540565b005b34801561059157600080fd5b5061059a6117f8565b005b3480156105a857600080fd5b506105c360048036038101906105be9190614847565b611803565b005b3480156105d157600080fd5b506105ec60048036038101906105e79190614890565b6118e2565b6040516105f9919061497b565b60405180910390f35b34801561060e57600080fd5b506106296004803603810190610624919061448d565b611ad8565b60405161063691906144ba565b60405180910390f35b34801561064b57600080fd5b5061066660048036038101906106619190614a53565b611aee565b005b34801561067457600080fd5b5061067d611c9b565b60405161068a9190614541565b60405180910390f35b34801561069f57600080fd5b506106ba60048036038101906106b59190614890565b611ca1565b6040516106c79190614541565b60405180910390f35b3480156106dc57600080fd5b506106f760048036038101906106f2919061448d565b611d70565b005b34801561070557600080fd5b5061070e611df6565b005b34801561071c57600080fd5b506107376004803603810190610732919061448d565b611e7e565b60405161074491906144ba565b60405180910390f35b34801561075957600080fd5b50610762611ec6565b60405161076f91906144ba565b60405180910390f35b34801561078457600080fd5b5061078d611ef0565b60405161079a919061443f565b60405180910390f35b3480156107af57600080fd5b506107b8611f82565b6040516107c59190614541565b60405180910390f35b3480156107da57600080fd5b506107f560048036038101906107f09190614890565b611f88565b6040516108029190614541565b60405180910390f35b34801561081757600080fd5b50610820611fd1565b005b61083c6004803603810190610837919061448d565b61206a565b005b34801561084a57600080fd5b5061086560048036038101906108609190614b00565b6122a7565b005b34801561087357600080fd5b5061087c6123b1565b6040516108899190614394565b60405180910390f35b34801561089e57600080fd5b506108b960048036038101906108b49190614890565b6123c4565b6040516108c69190614541565b60405180910390f35b3480156108db57600080fd5b506108f660048036038101906108f19190614be1565b6123dc565b005b34801561090457600080fd5b5061090d61252f565b60405161091a9190614541565b60405180910390f35b34801561092f57600080fd5b5061094a6004803603810190610945919061448d565b61253e565b604051610957919061443f565b60405180910390f35b34801561096c57600080fd5b5061098760048036038101906109829190614890565b61256f565b6040516109949190614541565b60405180910390f35b3480156109a957600080fd5b506109b26125b8565b6040516109bf9190614394565b60405180910390f35b3480156109d457600080fd5b506109dd6125cb565b6040516109ea9190614541565b60405180910390f35b3480156109ff57600080fd5b50610a1a6004803603810190610a159190614c64565b6125d1565b604051610a279190614541565b60405180910390f35b348015610a3c57600080fd5b50610a4561261a565b604051610a529190614541565b60405180910390f35b348015610a6757600080fd5b50610a826004803603810190610a7d9190614c91565b612624565b604051610a8f9190614394565b60405180910390f35b348015610aa457600080fd5b50610aad6126b8565b604051610aba9190614394565b60405180910390f35b348015610acf57600080fd5b50610ad86126cb565b005b348015610ae657600080fd5b50610b016004803603810190610afc9190614890565b6127b9565b005b348015610b0f57600080fd5b50610b2a6004803603810190610b25919061448d565b6128b0565b005b600033905090565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610bff57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610c0f5750610c0e82612936565b5b9050919050565b610c1e610b2c565b73ffffffffffffffffffffffffffffffffffffffff16610c3c611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614610c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8990614d1d565b60405180910390fd5b601660009054906101000a900460ff1615601660006101000a81548160ff0219169083151502179055507f58655b75d3df612fe99ead00dbf0812d415d35078fe06217a94c0818bb13967f601660009054906101000a900460ff16604051610cfa9190614394565b60405180910390a1565b606060028054610d1390614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3f90614d6c565b8015610d8c5780601f10610d6157610100808354040283529160200191610d8c565b820191906000526020600020905b815481529060010190602001808311610d6f57829003601f168201915b5050505050905090565b6000610da1826129a0565b610dd7576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610f0d576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610e8a929190614d9d565b602060405180830381865afa158015610ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecb9190614ddb565b610f0c57806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610f0391906144ba565b60405180910390fd5b5b610f1783836129ee565b505050565b6000610f26612af8565b6001546000540303905090565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610fb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fac90614e7a565b60405180910390fd5b6000610fbf61261a565b47610fca9190614ec9565b90506000610fe18383610fdc86611f88565b612b01565b905060008103611026576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161101d90614f6f565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546110759190614ec9565b9250508190555080600b600082825461108e9190614ec9565b9250508190555061109f8382612b6f565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b05683826040516110d0929190614fb0565b60405180910390a1505050565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561121b573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361114f5761114a848484612c63565b611227565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611198929190614d9d565b602060405180830381865afa1580156111b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d99190614ddb565b61121a57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161121191906144ba565b60405180910390fd5b5b611226848484612c63565b5b50505050565b6014818154811061123d57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a54905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6daaeb6d7670e522a718067333cd4e81565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561144d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036113815761137c848484612c73565b611459565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016113ca929190614d9d565b602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190614ddb565b61144c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161144391906144ba565b60405180910390fd5b5b611458848484612c73565b5b50505050565b611467610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611485611ec6565b73ffffffffffffffffffffffffffffffffffffffff16146114db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d290614d1d565b60405180910390fd5b601354816114e7610f1c565b6114f19190614ec9565b1115611532576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152990615025565b60405180910390fd5b61153c8282612c93565b5050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054116115c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b990614e7a565b60405180910390fd5b60006115cd836125d1565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161160691906144ba565b602060405180830381865afa158015611623573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611647919061505a565b6116519190614ec9565b9050600061166983836116648787611276565b612b01565b9050600081036116ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116a590614f6f565b60405180910390fd5b80601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461173a9190614ec9565b9250508190555080600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117909190614ec9565b925050819055506117a2848483612cb1565b8373ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a84836040516117ea9291906142b7565b60405180910390a250505050565b61180133610f33565b565b61180b610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611829611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461187f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187690614d1d565b60405180910390fd5b601960009054906101000a900460ff16156118cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c6906150d3565b60405180910390fd5b80601890816118de9190615295565b5050565b606060006118ef83611ca1565b67ffffffffffffffff8111156119085761190761471c565b5b6040519080825280602002602001820160405280156119365781602001602082028036833780820191505090505b50905060008054905060008060005b83811015611acb576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015115611a225750611abe565b600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614611a6257806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611abc5781868580600101965081518110611aaf57611aae615367565b5b6020026020010181815250505b505b8080600101915050611945565b5083945050505050919050565b6000611ae382612d37565b600001519050919050565b611af6610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611b14611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611b6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b6190614d1d565b60405180910390fd5b601660019054906101000a900460ff16611bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb0906153e2565b60405180910390fd5b60005b82829050811015611c9457601354858583818110611bdd57611bdc615367565b5b90506020020135611bec610f1c565b611bf69190614ec9565b1115611c37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c2e90615025565b60405180910390fd5b611c81838383818110611c4d57611c4c615367565b5b9050602002016020810190611c629190614890565b868684818110611c7557611c74615367565b5b90506020020135612c93565b8080611c8c90615402565b915050611bbc565b5050505050565b60115481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d08576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b611d78610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611d96611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611dec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de390614d1d565b60405180910390fd5b8060128190555050565b611dfe610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611e1c611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6990614d1d565b60405180910390fd5b611e7c6000612fc6565b565b6000600e8281548110611e9457611e93615367565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060038054611eff90614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054611f2b90614d6c565b8015611f785780601f10611f4d57610100808354040283529160200191611f78565b820191906000526020600020905b815481529060010190602001808311611f5b57829003601f168201915b5050505050905090565b60125481565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611fd9610b2c565b73ffffffffffffffffffffffffffffffffffffffff16611ff7611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461204d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161204490614d1d565b60405180910390fd5b6001601960006101000a81548160ff021916908315150217905550565b6002600854036120af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a690615496565b60405180910390fd5b6002600881905550601660009054906101000a900460ff16612106576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120fd90615502565b60405180910390fd5b60125481601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546121549190614ec9565b1115612195576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218c90615594565b60405180910390fd5b601354816121a1610f1c565b6121ab9190614ec9565b11156121ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e390615025565b60405180910390fd5b34816011546121fb91906155b4565b111561223c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223390615642565b60405180910390fd5b6122463382612c93565b80601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546122959190614ec9565b92505081905550600160088190555050565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156123a2576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161231f929190614d9d565b602060405180830381865afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123609190614ddb565b6123a157806040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161239891906144ba565b60405180910390fd5b5b6123ac838361308c565b505050565b601660019054906101000a900460ff1681565b60176020528060005260406000206000915090505481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561251b573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361244f5761244a85858585613203565b612528565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612498929190614d9d565b602060405180830381865afa1580156124b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d99190614ddb565b61251a57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161251191906144ba565b60405180910390fd5b5b61252785858585613203565b5b5050505050565b6000612539610f1c565b905090565b60606125498261327f565b60405160200161255991906156ea565b6040516020818303038152906040529050919050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b601960009054906101000a900460ff1681565b60135481565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600b54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b601660009054906101000a900460ff1681565b6126d3610b2c565b73ffffffffffffffffffffffffffffffffffffffff166126f1611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614612747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273e90614d1d565b60405180910390fd5b601660019054906101000a900460ff1615601660016101000a81548160ff0219169083151502179055507f1727dc7b28fffc84b95ca0e64637ec1614ea28c6bc7e9efa20b6df6b2e65fe87601660019054906101000a900460ff166040516127af9190614394565b60405180910390a1565b6127c1610b2c565b73ffffffffffffffffffffffffffffffffffffffff166127df611ec6565b73ffffffffffffffffffffffffffffffffffffffff1614612835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282c90614d1d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289b9061577e565b60405180910390fd5b6128ad81612fc6565b50565b6128b8610b2c565b73ffffffffffffffffffffffffffffffffffffffff166128d6611ec6565b73ffffffffffffffffffffffffffffffffffffffff161461292c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161292390614d1d565b60405180910390fd5b8060118190555050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000816129ab612af8565b111580156129ba575060005482105b80156129e7575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b60006129f982611ad8565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a60576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16612a7f610b2c565b73ffffffffffffffffffffffffffffffffffffffff1614158015612ab15750612aaf81612aaa610b2c565b612624565b155b15612ae8576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612af383838361331d565b505050565b60006001905090565b600081600a54600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205485612b5291906155b4565b612b5c91906157cd565b612b6691906157fe565b90509392505050565b80471015612bb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ba99061587e565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051612bd8906158cf565b60006040518083038185875af1925050503d8060008114612c15576040519150601f19603f3d011682016040523d82523d6000602084013e612c1a565b606091505b5050905080612c5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c5590615956565b60405180910390fd5b505050565b612c6e8383836133cf565b505050565b612c8e838383604051806020016040528060008152506123dc565b505050565b612cad828260405180602001604052806000815250613883565b5050565b612d328363a9059cbb60e01b8484604051602401612cd09291906142b7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613895565b505050565b612d3f61421a565b600082905080612d4d612af8565b11158015612d5c575060005481105b15612f8f576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff16151515158152505090508060400151612f8d57600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612e71578092505050612fc1565b5b600115612f8c57818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612f87578092505050612fc1565b612e72565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b613094610b2c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036130f8576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060076000613105610b2c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166131b2610b2c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516131f79190614394565b60405180910390a35050565b61320e8484846133cf565b61322d8373ffffffffffffffffffffffffffffffffffffffff1661395c565b801561324257506132408484848461396f565b155b15613279576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b606061328a826129a0565b6132c0576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006132ca613abf565b905060008151036132ea5760405180602001604052806000815250613315565b806132f484613b51565b604051602001613305929190615976565b6040516020818303038152906040525b915050919050565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006133da82612d37565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614613445576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16613466610b2c565b73ffffffffffffffffffffffffffffffffffffffff16148061349557506134948561348f610b2c565b612624565b5b806134da57506134a3610b2c565b73ffffffffffffffffffffffffffffffffffffffff166134c284610d96565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613513576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613579576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6135868585856001613cb1565b6135926000848761331d565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361381157600054821461381057878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461387c8585856001613cb7565b5050505050565b6138908383836001613cbd565b505050565b60006138f7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166140879092919063ffffffff16565b905060008151111561395757808060200190518101906139179190614ddb565b613956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161394d90615a0c565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613995610b2c565b8786866040518563ffffffff1660e01b81526004016139b79493929190615a81565b6020604051808303816000875af19250505080156139f357506040513d601f19601f820116820180604052508101906139f09190615ae2565b60015b613a6c573d8060008114613a23576040519150601f19603f3d011682016040523d82523d6000602084013e613a28565b606091505b506000815103613a64576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b606060188054613ace90614d6c565b80601f0160208091040260200160405190810160405280929190818152602001828054613afa90614d6c565b8015613b475780601f10613b1c57610100808354040283529160200191613b47565b820191906000526020600020905b815481529060010190602001808311613b2a57829003601f168201915b5050505050905090565b606060008203613b98576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613cac565b600082905060005b60008214613bca578080613bb390615402565b915050600a82613bc391906157cd565b9150613ba0565b60008167ffffffffffffffff811115613be657613be561471c565b5b6040519080825280601f01601f191660200182016040528015613c185781602001600182028036833780820191505090505b5090505b60008514613ca557600182613c3191906157fe565b9150600a85613c409190615b0f565b6030613c4c9190614ec9565b60f81b818381518110613c6257613c61615367565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85613c9e91906157cd565b9450613c1c565b8093505050505b919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613d29576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613d63576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d706000868387613cb1565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008582019050838015613f3a5750613f398773ffffffffffffffffffffffffffffffffffffffff1661395c565b5b15613fff575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613faf600088848060010195508861396f565b613fe5576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808203613f40578260005414613ffa57600080fd5b61406a565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808203614000575b8160008190555050506140806000868387613cb7565b5050505050565b6060614096848460008561409f565b90509392505050565b6060824710156140e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140db90615bb2565b60405180910390fd5b6140ed8561395c565b61412c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161412390615c1e565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516141559190615c6f565b60006040518083038185875af1925050503d8060008114614192576040519150601f19603f3d011682016040523d82523d6000602084013e614197565b606091505b50915091506141a78282866141b3565b92505050949350505050565b606083156141c357829050614213565b6000835111156141d65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161420a919061443f565b60405180910390fd5b9392505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006142888261425d565b9050919050565b6142988161427d565b82525050565b6000819050919050565b6142b18161429e565b82525050565b60006040820190506142cc600083018561428f565b6142d960208301846142a8565b9392505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614329816142f4565b811461433457600080fd5b50565b60008135905061434681614320565b92915050565b600060208284031215614362576143616142ea565b5b600061437084828501614337565b91505092915050565b60008115159050919050565b61438e81614379565b82525050565b60006020820190506143a96000830184614385565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143e95780820151818401526020810190506143ce565b60008484015250505050565b6000601f19601f8301169050919050565b6000614411826143af565b61441b81856143ba565b935061442b8185602086016143cb565b614434816143f5565b840191505092915050565b600060208201905081810360008301526144598184614406565b905092915050565b61446a8161429e565b811461447557600080fd5b50565b60008135905061448781614461565b92915050565b6000602082840312156144a3576144a26142ea565b5b60006144b184828501614478565b91505092915050565b60006020820190506144cf600083018461428f565b92915050565b6144de8161427d565b81146144e957600080fd5b50565b6000813590506144fb816144d5565b92915050565b60008060408385031215614518576145176142ea565b5b6000614526858286016144ec565b925050602061453785828601614478565b9150509250929050565b600060208201905061455660008301846142a8565b92915050565b60006145678261425d565b9050919050565b6145778161455c565b811461458257600080fd5b50565b6000813590506145948161456e565b92915050565b6000602082840312156145b0576145af6142ea565b5b60006145be84828501614585565b91505092915050565b6000806000606084860312156145e0576145df6142ea565b5b60006145ee868287016144ec565b93505060206145ff868287016144ec565b925050604061461086828701614478565b9150509250925092565b60006146258261427d565b9050919050565b6146358161461a565b811461464057600080fd5b50565b6000813590506146528161462c565b92915050565b6000806040838503121561466f5761466e6142ea565b5b600061467d85828601614643565b925050602061468e858286016144ec565b9150509250929050565b6000819050919050565b60006146bd6146b86146b38461425d565b614698565b61425d565b9050919050565b60006146cf826146a2565b9050919050565b60006146e1826146c4565b9050919050565b6146f1816146d6565b82525050565b600060208201905061470c60008301846146e8565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614754826143f5565b810181811067ffffffffffffffff821117156147735761477261471c565b5b80604052505050565b60006147866142e0565b9050614792828261474b565b919050565b600067ffffffffffffffff8211156147b2576147b161471c565b5b6147bb826143f5565b9050602081019050919050565b82818337600083830152505050565b60006147ea6147e584614797565b61477c565b90508281526020810184848401111561480657614805614717565b5b6148118482856147c8565b509392505050565b600082601f83011261482e5761482d614712565b5b813561483e8482602086016147d7565b91505092915050565b60006020828403121561485d5761485c6142ea565b5b600082013567ffffffffffffffff81111561487b5761487a6142ef565b5b61488784828501614819565b91505092915050565b6000602082840312156148a6576148a56142ea565b5b60006148b4848285016144ec565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6148f28161429e565b82525050565b600061490483836148e9565b60208301905092915050565b6000602082019050919050565b6000614928826148bd565b61493281856148c8565b935061493d836148d9565b8060005b8381101561496e57815161495588826148f8565b975061496083614910565b925050600181019050614941565b5085935050505092915050565b60006020820190508181036000830152614995818461491d565b905092915050565b600080fd5b600080fd5b60008083601f8401126149bd576149bc614712565b5b8235905067ffffffffffffffff8111156149da576149d961499d565b5b6020830191508360208202830111156149f6576149f56149a2565b5b9250929050565b60008083601f840112614a1357614a12614712565b5b8235905067ffffffffffffffff811115614a3057614a2f61499d565b5b602083019150836020820283011115614a4c57614a4b6149a2565b5b9250929050565b60008060008060408587031215614a6d57614a6c6142ea565b5b600085013567ffffffffffffffff811115614a8b57614a8a6142ef565b5b614a97878288016149a7565b9450945050602085013567ffffffffffffffff811115614aba57614ab96142ef565b5b614ac6878288016149fd565b925092505092959194509250565b614add81614379565b8114614ae857600080fd5b50565b600081359050614afa81614ad4565b92915050565b60008060408385031215614b1757614b166142ea565b5b6000614b25858286016144ec565b9250506020614b3685828601614aeb565b9150509250929050565b600067ffffffffffffffff821115614b5b57614b5a61471c565b5b614b64826143f5565b9050602081019050919050565b6000614b84614b7f84614b40565b61477c565b905082815260208101848484011115614ba057614b9f614717565b5b614bab8482856147c8565b509392505050565b600082601f830112614bc857614bc7614712565b5b8135614bd8848260208601614b71565b91505092915050565b60008060008060808587031215614bfb57614bfa6142ea565b5b6000614c09878288016144ec565b9450506020614c1a878288016144ec565b9350506040614c2b87828801614478565b925050606085013567ffffffffffffffff811115614c4c57614c4b6142ef565b5b614c5887828801614bb3565b91505092959194509250565b600060208284031215614c7a57614c796142ea565b5b6000614c8884828501614643565b91505092915050565b60008060408385031215614ca857614ca76142ea565b5b6000614cb6858286016144ec565b9250506020614cc7858286016144ec565b9150509250929050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000614d076020836143ba565b9150614d1282614cd1565b602082019050919050565b60006020820190508181036000830152614d3681614cfa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614d8457607f821691505b602082108103614d9757614d96614d3d565b5b50919050565b6000604082019050614db2600083018561428f565b614dbf602083018461428f565b9392505050565b600081519050614dd581614ad4565b92915050565b600060208284031215614df157614df06142ea565b5b6000614dff84828501614dc6565b91505092915050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000614e646026836143ba565b9150614e6f82614e08565b604082019050919050565b60006020820190508181036000830152614e9381614e57565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614ed48261429e565b9150614edf8361429e565b9250828201905080821115614ef757614ef6614e9a565b5b92915050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b6000614f59602b836143ba565b9150614f6482614efd565b604082019050919050565b60006020820190508181036000830152614f8881614f4c565b9050919050565b6000614f9a826146c4565b9050919050565b614faa81614f8f565b82525050565b6000604082019050614fc56000830185614fa1565b614fd260208301846142a8565b9392505050565b7f534f4c44204f5554000000000000000000000000000000000000000000000000600082015250565b600061500f6008836143ba565b915061501a82614fd9565b602082019050919050565b6000602082019050818103600083015261503e81615002565b9050919050565b60008151905061505481614461565b92915050565b6000602082840312156150705761506f6142ea565b5b600061507e84828501615045565b91505092915050565b7f4d455441444154415f4c4f434b45440000000000000000000000000000000000600082015250565b60006150bd600f836143ba565b91506150c882615087565b602082019050919050565b600060208201905081810360008301526150ec816150b0565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026151557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615118565b61515f8683615118565b95508019841693508086168417925050509392505050565b600061519261518d6151888461429e565b614698565b61429e565b9050919050565b6000819050919050565b6151ac83615177565b6151c06151b882615199565b848454615125565b825550505050565b600090565b6151d56151c8565b6151e08184846151a3565b505050565b5b81811015615204576151f96000826151cd565b6001810190506151e6565b5050565b601f8211156152495761521a816150f3565b61522384615108565b81016020851015615232578190505b61524661523e85615108565b8301826151e5565b50505b505050565b600082821c905092915050565b600061526c6000198460080261524e565b1980831691505092915050565b6000615285838361525b565b9150826002028217905092915050565b61529e826143af565b67ffffffffffffffff8111156152b7576152b661471c565b5b6152c18254614d6c565b6152cc828285615208565b600060209050601f8311600181146152ff57600084156152ed578287015190505b6152f78582615279565b86555061535f565b601f19841661530d866150f3565b60005b8281101561533557848901518255600182019150602085019450602081019050615310565b86831015615352578489015161534e601f89168261525b565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f41495244524f50204e4f54204143544956450000000000000000000000000000600082015250565b60006153cc6012836143ba565b91506153d782615396565b602082019050919050565b600060208201905081810360008301526153fb816153bf565b9050919050565b600061540d8261429e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361543f5761543e614e9a565b5b600182019050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000615480601f836143ba565b915061548b8261544a565b602082019050919050565b600060208201905081810360008301526154af81615473565b9050919050565b7f53414c4520494e41435449564500000000000000000000000000000000000000600082015250565b60006154ec600d836143ba565b91506154f7826154b6565b602082019050919050565b6000602082019050818103600083015261551b816154df565b9050919050565b7f7468697320776f756c6420657863656564206d696e74206d617820616c6c6f7760008201527f616e636500000000000000000000000000000000000000000000000000000000602082015250565b600061557e6024836143ba565b915061558982615522565b604082019050919050565b600060208201905081810360008301526155ad81615571565b9050919050565b60006155bf8261429e565b91506155ca8361429e565b92508282026155d88161429e565b915082820484148315176155ef576155ee614e9a565b5b5092915050565b7f494e434f52524543542045544845522056414c55450000000000000000000000600082015250565b600061562c6015836143ba565b9150615637826155f6565b602082019050919050565b6000602082019050818103600083015261565b8161561f565b9050919050565b600081905092915050565b6000615678826143af565b6156828185615662565b93506156928185602086016143cb565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b60006156d4600583615662565b91506156df8261569e565b600582019050919050565b60006156f6828461566d565b9150615701826156c7565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157686026836143ba565b91506157738261570c565b604082019050919050565b600060208201905081810360008301526157978161575b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006157d88261429e565b91506157e38361429e565b9250826157f3576157f261579e565b5b828204905092915050565b60006158098261429e565b91506158148361429e565b925082820390508181111561582c5761582b614e9a565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000615868601d836143ba565b915061587382615832565b602082019050919050565b600060208201905081810360008301526158978161585b565b9050919050565b600081905092915050565b50565b60006158b960008361589e565b91506158c4826158a9565b600082019050919050565b60006158da826158ac565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b6000615940603a836143ba565b915061594b826158e4565b604082019050919050565b6000602082019050818103600083015261596f81615933565b9050919050565b6000615982828561566d565b915061598e828461566d565b91508190509392505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006159f6602a836143ba565b9150615a018261599a565b604082019050919050565b60006020820190508181036000830152615a25816159e9565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000615a5382615a2c565b615a5d8185615a37565b9350615a6d8185602086016143cb565b615a76816143f5565b840191505092915050565b6000608082019050615a96600083018761428f565b615aa3602083018661428f565b615ab060408301856142a8565b8181036060830152615ac28184615a48565b905095945050505050565b600081519050615adc81614320565b92915050565b600060208284031215615af857615af76142ea565b5b6000615b0684828501615acd565b91505092915050565b6000615b1a8261429e565b9150615b258361429e565b925082615b3557615b3461579e565b5b828206905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000615b9c6026836143ba565b9150615ba782615b40565b604082019050919050565b60006020820190508181036000830152615bcb81615b8f565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000615c08601d836143ba565b9150615c1382615bd2565b602082019050919050565b60006020820190508181036000830152615c3781615bfb565b9050919050565b6000615c4982615a2c565b615c53818561589e565b9350615c638185602086016143cb565b80840191505092915050565b6000615c7b8284615c3e565b91508190509291505056fea2646970667358221220a3bcfe60faa5bcbcf15a0272f22a02c028c3c8fd6eb7f914452fe91a2c07594d64736f6c63430008110033

Deployed Bytecode Sourcemap

119403:5683:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108668:40;108684:12;:10;:12::i;:::-;108698:9;108668:40;;;;;;;:::i;:::-;;;;;;;;119403:5683;;;;;79932:355;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;121618:138;;;;;;;;;;;;;:::i;:::-;;83127:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84735:245;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124229:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79181:303;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110486:616;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124426:197;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119684:212;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108799:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109928:167;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116441:143;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124631:205;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;120489:175;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111370:704;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122253:73;;;;;;;;;;;;;:::i;:::-;;123267:150;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122334:820;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;82935:125;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120672:418;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119563:36;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80351:206;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122035:110;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;69785:103;;;;;;;;;;;;;:::i;:::-;;110186:100;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;69134:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83296:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119606:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109650:109;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122153:75;;;;;;;;;;;;;:::i;:::-;;121098:512;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124013:208;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;120011:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120054:54;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124844:239;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123162:97;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123547:205;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109446:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120198:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119644:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109236:119;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108984:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85442:214;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119972:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;121764:153;;;;;;;;;;;;;:::i;:::-;;70043:238;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;121925:102;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;35305:98;35358:7;35385:10;35378:17;;35305:98;:::o;79932:355::-;80079:4;80136:25;80121:40;;;:11;:40;;;;:105;;;;80193:33;80178:48;;;:11;:48;;;;80121:105;:158;;;;80243:36;80267:11;80243:23;:36::i;:::-;80121:158;80101:178;;79932:355;;;:::o;121618:138::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;121692:12:::1;;;;;;;;;;;121691:13;121676:12;;:28;;;;;;;;;;;;;;;;;;121720;121735:12;;;;;;;;;;;121720:28;;;;;;:::i;:::-;;;;;;;;121618:138::o:0;83127:100::-;83181:13;83214:5;83207:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83127:100;:::o;84735:245::-;84839:7;84869:16;84877:7;84869;:16::i;:::-;84864:64;;84894:34;;;;;;;;;;;;;;84864:64;84948:15;:24;84964:7;84948:24;;;;;;;;;;;;;;;;;;;;;84941:31;;84735:245;;;:::o;124229:189::-;124352:8;118710:1;116541:42;118662:45;;;:49;118658:318;;;116541:42;118751;;;118824:4;118852:8;118751:128;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118728:237;;118940:8;118921:28;;;;;;;;;;;:::i;:::-;;;;;;;;118728:237;118658:318;124378:32:::1;124392:8;124402:7;124378:13;:32::i;:::-;124229:189:::0;;;:::o;79181:303::-;79225:7;79450:15;:13;:15::i;:::-;79435:12;;79419:13;;:28;:46;79412:53;;79181:303;:::o;110486:616::-;110581:1;110562:7;:16;110570:7;110562:16;;;;;;;;;;;;;;;;:20;110554:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;110638:21;110686:15;:13;:15::i;:::-;110662:21;:39;;;;:::i;:::-;110638:63;;110712:15;110730:108;110760:7;110782:13;110810:17;110819:7;110810:8;:17::i;:::-;110730:15;:108::i;:::-;110712:126;;110870:1;110859:7;:12;110851:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;110954:7;110932:9;:18;110942:7;110932:18;;;;;;;;;;;;;;;;:29;;;;;;;:::i;:::-;;;;;;;;110990:7;110972:14;;:25;;;;;;;:::i;:::-;;;;;;;;111010:35;111028:7;111037;111010:17;:35::i;:::-;111061:33;111077:7;111086;111061:33;;;;;;;:::i;:::-;;;;;;;;110543:559;;110486:616;:::o;124426:197::-;124561:4;117871:1;116541:42;117823:45;;;:49;117819:632;;;118112:10;118104:18;;:4;:18;;;118100:85;;124578:37:::1;124597:4;124603:2;124607:7;124578:18;:37::i;:::-;118163:7:::0;;118100:85;116541:42;118222;;;118295:4;118323:10;118222:130;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118199:241;;118413:10;118394:30;;;;;;;;;;;:::i;:::-;;;;;;;;118199:241;117819:632;124578:37:::1;124597:4;124603:2;124607:7;124578:18;:37::i;:::-;124426:197:::0;;;;;:::o;119684:212::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;108799:91::-;108843:7;108870:12;;108863:19;;108799:91;:::o;109928:167::-;110025:7;110057:14;:21;110072:5;110057:21;;;;;;;;;;;;;;;:30;110079:7;110057:30;;;;;;;;;;;;;;;;110050:37;;109928:167;;;;:::o;116441:143::-;116541:42;116441:143;:::o;124631:205::-;124770:4;117871:1;116541:42;117823:45;;;:49;117819:632;;;118112:10;118104:18;;:4;:18;;;118100:85;;124787:41:::1;124810:4;124816:2;124820:7;124787:22;:41::i;:::-;118163:7:::0;;118100:85;116541:42;118222;;;118295:4;118323:10;118222:130;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118199:241;;118413:10;118394:30;;;;;;;;;;;:::i;:::-;;;;;;;;118199:241;117819:632;124787:41:::1;124810:4;124816:2;124820:7;124787:22;:41::i;:::-;124631:205:::0;;;;;:::o;120489:175::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;120601:9:::1;;120591:6;120575:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:35;;120567:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;120634:22;120644:3;120649:6;120634:9;:22::i;:::-;120489:175:::0;;:::o;111370:704::-;111471:1;111452:7;:16;111460:7;111452:16;;;;;;;;;;;;;;;;:20;111444:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;111528:21;111598:20;111612:5;111598:13;:20::i;:::-;111552:5;:15;;;111576:4;111552:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;;;;:::i;:::-;111528:90;;111629:15;111647:115;111677:7;111699:13;111727:24;111736:5;111743:7;111727:8;:24::i;:::-;111647:15;:115::i;:::-;111629:133;;111794:1;111783:7;:12;111775:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;111890:7;111856:14;:21;111871:5;111856:21;;;;;;;;;;;;;;;:30;111878:7;111856:30;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;111938:7;111908:19;:26;111928:5;111908:26;;;;;;;;;;;;;;;;:37;;;;;;;:::i;:::-;;;;;;;;111958:47;111981:5;111988:7;111997;111958:22;:47::i;:::-;112042:5;112021:45;;;112049:7;112058;112021:45;;;;;;;:::i;:::-;;;;;;;;111433:641;;111370:704;;:::o;122253:73::-;122290:28;122306:10;122290:7;:28::i;:::-;122253:73::o;123267:150::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;123349:6:::1;;;;;;;;;;;123348:7;123340:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;123402:7;123386:13;:23;;;;;;:::i;:::-;;123267:150:::0;:::o;122334:820::-;122425:16;122484:18;122519:16;122529:5;122519:9;:16::i;:::-;122505:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122484:52;;122551:11;122565:13;;122551:27;;122593:19;122627:25;122672:9;122667:446;122687:3;122683:1;:7;122667:446;;;122716:31;122750:11;:14;122762:1;122750:14;;;;;;;;;;;122716:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122787:9;:16;;;122783:73;;;122828:8;;;122783:73;122904:1;122878:28;;:9;:14;;;:28;;;122874:111;;122951:9;:14;;;122931:34;;122874:111;123028:5;123007:26;;:17;:26;;;123003:95;;123077:1;123058;123060:13;;;;;;123058:16;;;;;;;;:::i;:::-;;;;;;;:20;;;;;123003:95;122697:416;122667:446;122692:3;;;;;;;122667:446;;;;123134:1;123127:8;;;;;;122334:820;;;:::o;82935:125::-;82999:7;83026:21;83039:7;83026:12;:21::i;:::-;:26;;;83019:33;;82935:125;;;:::o;120672:418::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;120804:15:::1;;;;;;;;;;;120796:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;120860:9;120855:228;120879:5;;:12;;120875:1;:16;120855:228;;;121003:9;;120989:7;;120997:1;120989:10;;;;;;;:::i;:::-;;;;;;;;120973:13;:11;:13::i;:::-;:26;;;;:::i;:::-;:39;;120965:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;121040:31;121050:5;;121056:1;121050:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;121060:7;;121068:1;121060:10;;;;;;;:::i;:::-;;;;;;;;121040:9;:31::i;:::-;120893:3;;;;;:::i;:::-;;;;120855:228;;;;120672:418:::0;;;;:::o;119563:36::-;;;;:::o;80351:206::-;80415:7;80456:1;80439:19;;:5;:19;;;80435:60;;80467:28;;;;;;;;;;;;;;80435:60;80521:12;:19;80534:5;80521:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;80513:36;;80506:43;;80351:206;;;:::o;122035:110::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;122125:12:::1;122111:11;:26;;;;122035:110:::0;:::o;69785:103::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;69850:30:::1;69877:1;69850:18;:30::i;:::-;69785:103::o:0;110186:100::-;110237:7;110264;110272:5;110264:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;110257:21;;110186:100;;;:::o;69134:87::-;69180:7;69207:6;;;;;;;;;;;69200:13;;69134:87;:::o;83296:104::-;83352:13;83385:7;83378:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83296:104;:::o;119606:31::-;;;;:::o;109650:109::-;109706:7;109733:9;:18;109743:7;109733:18;;;;;;;;;;;;;;;;109726:25;;109650:109;;;:::o;122153:75::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;122216:4:::1;122207:6;;:13;;;;;;;;;;;;;;;;;;122153:75::o:0;121098:512::-;74799:1;75397:7;;:19;75389:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;74799:1;75530:7;:18;;;;121177:12:::1;;;;;;;;;;;121169:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;121288:11;;121276:6;121242:19;:31;121262:10;121242:31;;;;;;;;;;;;;;;;:40;;;;:::i;:::-;121240:59;;121218:145;;;;;;;;;;;;:::i;:::-;;;;;;;;;121410:9;;121400:6;121384:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:35;;121376:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;121473:9;121463:6;121451:9;;:18;;;;:::i;:::-;:31;;121443:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;121521:29;121531:10;121543:6;121521:9;:29::i;:::-;121596:6;121561:19;:31;121581:10;121561:31;;;;;;;;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;74755:1:::0;75709:7;:22;;;;121098:512;:::o;124013:208::-;124144:8;118710:1;116541:42;118662:45;;;:49;118658:318;;;116541:42;118751;;;118824:4;118852:8;118751:128;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118728:237;;118940:8;118921:28;;;;;;;;;;;:::i;:::-;;;;;;;;118728:237;118658:318;124170:43:::1;124194:8;124204;124170:23;:43::i;:::-;124013:208:::0;;;:::o;120011:34::-;;;;;;;;;;;;;:::o;120054:54::-;;;;;;;;;;;;;;;;;:::o;124844:239::-;125011:4;117871:1;116541:42;117823:45;;;:49;117819:632;;;118112:10;118104:18;;:4;:18;;;118100:85;;125028:47:::1;125051:4;125057:2;125061:7;125070:4;125028:22;:47::i;:::-;118163:7:::0;;118100:85;116541:42;118222;;;118295:4;118323:10;118222:130;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118199:241;;118413:10;118394:30;;;;;;;;;;;:::i;:::-;;;;;;;;118199:241;117819:632;125028:47:::1;125051:4;125057:2;125061:7;125070:4;125028:22;:47::i;:::-;124844:239:::0;;;;;;:::o;123162:97::-;123211:7;123238:13;:11;:13::i;:::-;123231:20;;123162:97;:::o;123547:205::-;123648:13;123710:23;123725:7;123710:14;:23::i;:::-;123693:50;;;;;;;;:::i;:::-;;;;;;;;;;;;;123679:65;;123547:205;;;:::o;109446:105::-;109500:7;109527;:16;109535:7;109527:16;;;;;;;;;;;;;;;;109520:23;;109446:105;;;:::o;120198:18::-;;;;;;;;;;;;;:::o;119644:31::-;;;;:::o;109236:119::-;109294:7;109321:19;:26;109341:5;109321:26;;;;;;;;;;;;;;;;109314:33;;109236:119;;;:::o;108984:95::-;109030:7;109057:14;;109050:21;;108984:95;:::o;85442:214::-;85584:4;85613:18;:25;85632:5;85613:25;;;;;;;;;;;;;;;:35;85639:8;85613:35;;;;;;;;;;;;;;;;;;;;;;;;;85606:42;;85442:214;;;;:::o;119972:32::-;;;;;;;;;;;;;:::o;121764:153::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;121844:15:::1;;;;;;;;;;;121843:16;121825:15;;:34;;;;;;;;;;;;;;;;;;121875;121893:15;;;;;;;;;;;121875:34;;;;;;:::i;:::-;;;;;;;;121764:153::o:0;70043:238::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;70166:1:::1;70146:22;;:8;:22;;::::0;70124:110:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;70245:28;70264:8;70245:18;:28::i;:::-;70043:238:::0;:::o;121925:102::-;69365:12;:10;:12::i;:::-;69354:23;;:7;:5;:7::i;:::-;:23;;;69346:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;122009:10:::1;121997:9;:22;;;;121925:102:::0;:::o;38288:207::-;38418:4;38462:25;38447:40;;;:11;:40;;;;38440:47;;38288:207;;;:::o;86881:213::-;86938:4;86994:7;86975:15;:13;:15::i;:::-;:26;;:66;;;;;87028:13;;87018:7;:23;86975:66;:111;;;;;87059:11;:20;87071:7;87059:20;;;;;;;;;;;:27;;;;;;;;;;;;87058:28;86975:111;86955:131;;86881:213;;;:::o;84290:379::-;84371:13;84387:24;84403:7;84387:15;:24::i;:::-;84371:40;;84432:5;84426:11;;:2;:11;;;84422:48;;84446:24;;;;;;;;;;;;;;84422:48;84503:5;84487:21;;:12;:10;:12::i;:::-;:21;;;;:63;;;;;84513:37;84530:5;84537:12;:10;:12::i;:::-;84513:16;:37::i;:::-;84512:38;84487:63;84483:138;;;84574:35;;;;;;;;;;;;;;84483:138;84633:28;84642:2;84646:7;84655:5;84633:8;:28::i;:::-;84360:309;84290:379;;:::o;123760:101::-;123825:7;123852:1;123845:8;;123760:101;:::o;112252:261::-;112398:7;112490:15;112475:12;;112455:7;:16;112463:7;112455:16;;;;;;;;;;;;;;;;112439:13;:32;;;;:::i;:::-;112438:49;;;;:::i;:::-;:67;;;;:::i;:::-;112418:87;;112252:261;;;;;:::o;28262:391::-;28391:6;28366:21;:31;;28344:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;28468:12;28486:9;:14;;28508:6;28486:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28467:52;;;28552:7;28530:115;;;;;;;;;;;;:::i;:::-;;;;;;;;;28333:320;28262:391;;:::o;85723:170::-;85857:28;85867:4;85873:2;85877:7;85857:9;:28::i;:::-;85723:170;;;:::o;85964:185::-;86102:39;86119:4;86125:2;86129:7;86102:39;;;;;;;;;;;;:16;:39::i;:::-;85964:185;;;:::o;87102:104::-;87171:27;87181:2;87185:8;87171:27;;;;;;;;;;;;:9;:27::i;:::-;87102:104;;:::o;101715:248::-;101832:123;101866:5;101909:23;;;101934:2;101938:5;101886:58;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101832:19;:123::i;:::-;101715:248;;;:::o;81732:1141::-;81821:21;;:::i;:::-;81860:12;81875:7;81860:22;;81943:4;81924:15;:13;:15::i;:::-;:23;;:47;;;;;81958:13;;81951:4;:20;81924:47;81920:886;;;81992:31;82026:11;:17;82038:4;82026:17;;;;;;;;;;;81992:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82067:9;:16;;;82062:729;;82138:1;82112:28;;:9;:14;;;:28;;;82108:101;;82176:9;82169:16;;;;;;82108:101;82511:261;82518:4;82511:261;;;82551:6;;;;;;;;82596:11;:17;82608:4;82596:17;;;;;;;;;;;82584:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82670:1;82644:28;;:9;:14;;;:28;;;82640:109;;82712:9;82705:16;;;;;;82640:109;82511:261;;;82062:729;81973:833;81920:886;82834:31;;;;;;;;;;;;;;81732:1141;;;;:::o;70441:191::-;70515:16;70534:6;;;;;;;;;;;70515:25;;70560:8;70551:6;;:17;;;;;;;;;;;;;;;;;;70615:8;70584:40;;70605:8;70584:40;;;;;;;;;;;;70504:128;70441:191;:::o;85052:319::-;85195:12;:10;:12::i;:::-;85183:24;;:8;:24;;;85179:54;;85216:17;;;;;;;;;;;;;;85179:54;85291:8;85246:18;:32;85265:12;:10;:12::i;:::-;85246:32;;;;;;;;;;;;;;;:42;85279:8;85246:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;85344:8;85315:48;;85330:12;:10;:12::i;:::-;85315:48;;;85354:8;85315:48;;;;;;:::i;:::-;;;;;;;;85052:319;;:::o;86220:406::-;86387:28;86397:4;86403:2;86407:7;86387:9;:28::i;:::-;86444:15;:2;:13;;;:15::i;:::-;:89;;;;;86477:56;86508:4;86514:2;86518:7;86527:5;86477:30;:56::i;:::-;86476:57;86444:89;86426:193;;;86567:40;;;;;;;;;;;;;;86426:193;86220:406;;;;:::o;83471:415::-;83589:13;83625:16;83633:7;83625;:16::i;:::-;83620:59;;83650:29;;;;;;;;;;;;;;83620:59;83692:21;83716:10;:8;:10::i;:::-;83692:34;;83782:1;83763:7;83757:21;:26;:121;;;;;;;;;;;;;;;;;83827:7;83836:18;:7;:16;:18::i;:::-;83810:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;83757:121;83737:141;;;83471:415;;;:::o;95268:196::-;95410:2;95383:15;:24;95399:7;95383:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;95448:7;95444:2;95428:28;;95437:5;95428:28;;;;;;;;;;;;95268:196;;;:::o;90211:2130::-;90326:35;90364:21;90377:7;90364:12;:21::i;:::-;90326:59;;90424:4;90402:26;;:13;:18;;;:26;;;90398:67;;90437:28;;;;;;;;;;;;;;90398:67;90478:22;90520:4;90504:20;;:12;:10;:12::i;:::-;:20;;;:73;;;;90541:36;90558:4;90564:12;:10;:12::i;:::-;90541:16;:36::i;:::-;90504:73;:126;;;;90618:12;:10;:12::i;:::-;90594:36;;:20;90606:7;90594:11;:20::i;:::-;:36;;;90504:126;90478:153;;90649:17;90644:66;;90675:35;;;;;;;;;;;;;;90644:66;90739:1;90725:16;;:2;:16;;;90721:52;;90750:23;;;;;;;;;;;;;;90721:52;90786:43;90808:4;90814:2;90818:7;90827:1;90786:21;:43::i;:::-;90894:35;90911:1;90915:7;90924:4;90894:8;:35::i;:::-;91255:1;91225:12;:18;91238:4;91225:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91299:1;91271:12;:16;91284:2;91271:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91317:31;91351:11;:20;91363:7;91351:20;;;;;;;;;;;91317:54;;91402:2;91386:8;:13;;;:18;;;;;;;;;;;;;;;;;;91452:15;91419:8;:23;;;:49;;;;;;;;;;;;;;;;;;91720:19;91752:1;91742:7;:11;91720:33;;91768:31;91802:11;:24;91814:11;91802:24;;;;;;;;;;;91768:58;;91870:1;91845:27;;:8;:13;;;;;;;;;;;;:27;;;91841:384;;92055:13;;92040:11;:28;92036:174;;92109:4;92093:8;:13;;;:20;;;;;;;;;;;;;;;;;;92162:13;:28;;;92136:8;:23;;;:54;;;;;;;;;;;;;;;;;;92036:174;91841:384;91200:1036;;;92272:7;92268:2;92253:27;;92262:4;92253:27;;;;;;;;;;;;92291:42;92312:4;92318:2;92322:7;92331:1;92291:20;:42::i;:::-;90315:2026;;90211:2130;;;:::o;87569:163::-;87692:32;87698:2;87702:8;87712:5;87719:4;87692:5;:32::i;:::-;87569:163;;;:::o;104682:802::-;105106:23;105132:106;105174:4;105132:106;;;;;;;;;;;;;;;;;105140:5;105132:27;;;;:106;;;;;:::i;:::-;105106:132;;105273:1;105253:10;:17;:21;105249:228;;;105368:10;105357:30;;;;;;;;;;;;:::i;:::-;105331:134;;;;;;;;;;;;:::i;:::-;;;;;;;;;105249:228;104752:732;104682:802;;:::o;26940:387::-;27000:4;27208:12;27275:7;27263:20;27255:28;;27318:1;27311:4;:8;27304:15;;;26940:387;;;:::o;95956:772::-;96119:4;96169:2;96153:36;;;96208:12;:10;:12::i;:::-;96239:4;96262:7;96288:5;96153:155;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;96136:585;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96496:1;96479:6;:13;:18;96475:235;;96525:40;;;;;;;;;;;;;;96475:235;96668:6;96662:13;96653:6;96649:2;96645:15;96638:38;96136:585;96374:45;;;96364:55;;;:6;:55;;;;96357:62;;;95956:772;;;;;;:::o;123425:114::-;123485:13;123518;123511:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123425:114;:::o;35772:723::-;35828:13;36058:1;36049:5;:10;36045:53;;36076:10;;;;;;;;;;;;;;;;;;;;;36045:53;36108:12;36123:5;36108:20;;36139:14;36164:78;36179:1;36171:4;:9;36164:78;;36197:8;;;;;:::i;:::-;;;;36228:2;36220:10;;;;;:::i;:::-;;;36164:78;;;36252:19;36284:6;36274:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36252:39;;36302:154;36318:1;36309:5;:10;36302:154;;36346:1;36336:11;;;;;:::i;:::-;;;36413:2;36405:5;:10;;;;:::i;:::-;36392:2;:24;;;;:::i;:::-;36379:39;;36362:6;36369;36362:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;36442:2;36433:11;;;;;:::i;:::-;;;36302:154;;;36480:6;36466:21;;;;;35772:723;;;;:::o;97376:159::-;;;;;:::o;98194:158::-;;;;;:::o;87991:1966::-;88130:20;88153:13;;88130:36;;88195:1;88181:16;;:2;:16;;;88177:48;;88206:19;;;;;;;;;;;;;;88177:48;88252:1;88240:8;:13;88236:44;;88262:18;;;;;;;;;;;;;;88236:44;88293:61;88323:1;88327:2;88331:12;88345:8;88293:21;:61::i;:::-;88666:8;88631:12;:16;88644:2;88631:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88730:8;88690:12;:16;88703:2;88690:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88789:2;88756:11;:25;88768:12;88756:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;88856:15;88806:11;:25;88818:12;88806:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;88889:20;88912:12;88889:35;;88939:11;88968:8;88953:12;:23;88939:37;;88997:4;:23;;;;;89005:15;:2;:13;;;:15::i;:::-;88997:23;88993:832;;;89041:505;89097:12;89093:2;89072:38;;89089:1;89072:38;;;;;;;;;;;;89164:212;89233:1;89266:2;89299:14;;;;;;89344:5;89164:30;:212::i;:::-;89133:365;;89434:40;;;;;;;;;;;;;;89133:365;89541:3;89525:12;:19;89041:505;;89627:12;89610:13;;:29;89606:43;;89641:8;;;89606:43;88993:832;;;89690:120;89746:14;;;;;;89742:2;89721:40;;89738:1;89721:40;;;;;;;;;;;;89805:3;89789:12;:19;89690:120;;88993:832;89855:12;89839:13;:28;;;;88606:1273;;89889:60;89918:1;89922:2;89926:12;89940:8;89889:20;:60::i;:::-;88119:1838;87991:1966;;;;:::o;29843:229::-;29980:12;30012:52;30034:6;30042:4;30048:1;30051:12;30012:21;:52::i;:::-;30005:59;;29843:229;;;;;:::o;31059:571::-;31229:12;31301:5;31276:21;:30;;31254:118;;;;;;;;;;;;:::i;:::-;;;;;;;;;31391:18;31402:6;31391:10;:18::i;:::-;31383:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;31457:12;31471:23;31498:6;:11;;31517:5;31538:4;31498:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31456:97;;;;31571:51;31588:7;31597:10;31609:12;31571:16;:51::i;:::-;31564:58;;;;31059:571;;;;;;:::o;34019:712::-;34169:12;34198:7;34194:530;;;34229:10;34222:17;;;;34194:530;34363:1;34343:10;:17;:21;34339:374;;;34541:10;34535:17;34602:15;34589:10;34585:2;34581:19;34574:44;34339:374;34684:12;34677:20;;;;;;;;;;;:::i;:::-;;;;;;;;34019: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:158::-;25464:10;25460:1;25452:6;25448:14;25441:34;25324:158;:::o;25488:365::-;25630:3;25651:66;25715:1;25710:3;25651:66;:::i;:::-;25644:73;;25726:93;25815:3;25726:93;:::i;:::-;25844:2;25839:3;25835:12;25828:19;;25488:365;;;:::o;25859:419::-;26025:4;26063:2;26052:9;26048:18;26040:26;;26112:9;26106:4;26102:20;26098:1;26087:9;26083:17;26076:47;26140:131;26266:4;26140:131;:::i;:::-;26132:139;;25859:419;;;:::o;26284:143::-;26341:5;26372:6;26366:13;26357:22;;26388:33;26415:5;26388:33;:::i;:::-;26284:143;;;;:::o;26433:351::-;26503:6;26552:2;26540:9;26531:7;26527:23;26523:32;26520:119;;;26558:79;;:::i;:::-;26520:119;26678:1;26703:64;26759:7;26750:6;26739:9;26735:22;26703:64;:::i;:::-;26693:74;;26649:128;26433:351;;;;:::o;26790:165::-;26930:17;26926:1;26918:6;26914:14;26907:41;26790:165;:::o;26961:366::-;27103:3;27124:67;27188:2;27183:3;27124:67;:::i;:::-;27117:74;;27200:93;27289:3;27200:93;:::i;:::-;27318:2;27313:3;27309:12;27302:19;;26961:366;;;:::o;27333:419::-;27499:4;27537:2;27526:9;27522:18;27514:26;;27586:9;27580:4;27576:20;27572:1;27561:9;27557:17;27550:47;27614:131;27740:4;27614:131;:::i;:::-;27606:139;;27333:419;;;:::o;27758:141::-;27807:4;27830:3;27822:11;;27853:3;27850:1;27843:14;27887:4;27884:1;27874:18;27866:26;;27758:141;;;:::o;27905:93::-;27942:6;27989:2;27984;27977:5;27973:14;27969:23;27959:33;;27905:93;;;:::o;28004:107::-;28048:8;28098:5;28092:4;28088:16;28067:37;;28004:107;;;;:::o;28117:393::-;28186:6;28236:1;28224:10;28220:18;28259:97;28289:66;28278:9;28259:97;:::i;:::-;28377:39;28407:8;28396:9;28377:39;:::i;:::-;28365:51;;28449:4;28445:9;28438:5;28434:21;28425:30;;28498:4;28488:8;28484:19;28477:5;28474:30;28464:40;;28193:317;;28117:393;;;;;:::o;28516:142::-;28566:9;28599:53;28617:34;28626:24;28644:5;28626:24;:::i;:::-;28617:34;:::i;:::-;28599:53;:::i;:::-;28586:66;;28516:142;;;:::o;28664:75::-;28707:3;28728:5;28721:12;;28664:75;;;:::o;28745:269::-;28855:39;28886:7;28855:39;:::i;:::-;28916:91;28965:41;28989:16;28965:41;:::i;:::-;28957:6;28950:4;28944:11;28916:91;:::i;:::-;28910:4;28903:105;28821:193;28745:269;;;:::o;29020:73::-;29065:3;29020:73;:::o;29099:189::-;29176:32;;:::i;:::-;29217:65;29275:6;29267;29261:4;29217:65;:::i;:::-;29152:136;29099:189;;:::o;29294:186::-;29354:120;29371:3;29364:5;29361:14;29354:120;;;29425:39;29462:1;29455:5;29425:39;:::i;:::-;29398:1;29391:5;29387:13;29378:22;;29354:120;;;29294:186;;:::o;29486:543::-;29587:2;29582:3;29579:11;29576:446;;;29621:38;29653:5;29621:38;:::i;:::-;29705:29;29723:10;29705:29;:::i;:::-;29695:8;29691:44;29888:2;29876:10;29873:18;29870:49;;;29909:8;29894:23;;29870:49;29932:80;29988:22;30006:3;29988:22;:::i;:::-;29978:8;29974:37;29961:11;29932:80;:::i;:::-;29591:431;;29576:446;29486:543;;;:::o;30035:117::-;30089:8;30139:5;30133:4;30129:16;30108:37;;30035:117;;;;:::o;30158:169::-;30202:6;30235:51;30283:1;30279:6;30271:5;30268:1;30264:13;30235:51;:::i;:::-;30231:56;30316:4;30310;30306:15;30296:25;;30209:118;30158:169;;;;:::o;30332:295::-;30408:4;30554:29;30579:3;30573:4;30554:29;:::i;:::-;30546:37;;30616:3;30613:1;30609:11;30603:4;30600:21;30592:29;;30332:295;;;;:::o;30632:1395::-;30749:37;30782:3;30749:37;:::i;:::-;30851:18;30843:6;30840:30;30837:56;;;30873:18;;:::i;:::-;30837:56;30917:38;30949:4;30943:11;30917:38;:::i;:::-;31002:67;31062:6;31054;31048:4;31002:67;:::i;:::-;31096:1;31120:4;31107:17;;31152:2;31144:6;31141:14;31169:1;31164:618;;;;31826:1;31843:6;31840:77;;;31892:9;31887:3;31883:19;31877:26;31868:35;;31840:77;31943:67;32003:6;31996:5;31943:67;:::i;:::-;31937:4;31930:81;31799:222;31134:887;;31164:618;31216:4;31212:9;31204:6;31200:22;31250:37;31282:4;31250:37;:::i;:::-;31309:1;31323:208;31337:7;31334:1;31331:14;31323:208;;;31416:9;31411:3;31407:19;31401:26;31393:6;31386:42;31467:1;31459:6;31455:14;31445:24;;31514:2;31503:9;31499:18;31486:31;;31360:4;31357:1;31353:12;31348:17;;31323:208;;;31559:6;31550:7;31547:19;31544:179;;;31617:9;31612:3;31608:19;31602:26;31660:48;31702:4;31694:6;31690:17;31679:9;31660:48;:::i;:::-;31652:6;31645:64;31567:156;31544:179;31769:1;31765;31757:6;31753:14;31749:22;31743:4;31736:36;31171:611;;;31134:887;;30724:1303;;;30632:1395;;:::o;32033:180::-;32081:77;32078:1;32071:88;32178:4;32175:1;32168:15;32202:4;32199:1;32192:15;32219:168;32359:20;32355:1;32347:6;32343:14;32336:44;32219:168;:::o;32393:366::-;32535:3;32556:67;32620:2;32615:3;32556:67;:::i;:::-;32549:74;;32632:93;32721:3;32632:93;:::i;:::-;32750:2;32745:3;32741:12;32734:19;;32393:366;;;:::o;32765:419::-;32931:4;32969:2;32958:9;32954:18;32946:26;;33018:9;33012:4;33008:20;33004:1;32993:9;32989:17;32982:47;33046:131;33172:4;33046:131;:::i;:::-;33038:139;;32765:419;;;:::o;33190:233::-;33229:3;33252:24;33270:5;33252:24;:::i;:::-;33243:33;;33298:66;33291:5;33288:77;33285:103;;33368:18;;:::i;:::-;33285:103;33415:1;33408:5;33404:13;33397:20;;33190:233;;;:::o;33429:181::-;33569:33;33565:1;33557:6;33553:14;33546:57;33429:181;:::o;33616:366::-;33758:3;33779:67;33843:2;33838:3;33779:67;:::i;:::-;33772:74;;33855:93;33944:3;33855:93;:::i;:::-;33973:2;33968:3;33964:12;33957:19;;33616:366;;;:::o;33988:419::-;34154:4;34192:2;34181:9;34177:18;34169:26;;34241:9;34235:4;34231:20;34227:1;34216:9;34212:17;34205:47;34269:131;34395:4;34269:131;:::i;:::-;34261:139;;33988:419;;;:::o;34413:163::-;34553:15;34549:1;34541:6;34537:14;34530:39;34413:163;:::o;34582:366::-;34724:3;34745:67;34809:2;34804:3;34745:67;:::i;:::-;34738:74;;34821:93;34910:3;34821:93;:::i;:::-;34939:2;34934:3;34930:12;34923:19;;34582:366;;;:::o;34954:419::-;35120:4;35158:2;35147:9;35143:18;35135:26;;35207:9;35201:4;35197:20;35193:1;35182:9;35178:17;35171:47;35235:131;35361:4;35235:131;:::i;:::-;35227:139;;34954:419;;;:::o;35379:223::-;35519:34;35515:1;35507:6;35503:14;35496:58;35588:6;35583:2;35575:6;35571:15;35564:31;35379:223;:::o;35608:366::-;35750:3;35771:67;35835:2;35830:3;35771:67;:::i;:::-;35764:74;;35847:93;35936:3;35847:93;:::i;:::-;35965:2;35960:3;35956:12;35949:19;;35608:366;;;:::o;35980:419::-;36146:4;36184:2;36173:9;36169:18;36161:26;;36233:9;36227:4;36223:20;36219:1;36208:9;36204:17;36197:47;36261:131;36387:4;36261:131;:::i;:::-;36253:139;;35980:419;;;:::o;36405:410::-;36445:7;36468:20;36486:1;36468:20;:::i;:::-;36463:25;;36502:20;36520:1;36502:20;:::i;:::-;36497:25;;36557:1;36554;36550:9;36579:30;36597:11;36579:30;:::i;:::-;36568:41;;36758:1;36749:7;36745:15;36742:1;36739:22;36719:1;36712:9;36692:83;36669:139;;36788:18;;:::i;:::-;36669:139;36453:362;36405:410;;;;:::o;36821:171::-;36961:23;36957:1;36949:6;36945:14;36938:47;36821:171;:::o;36998:366::-;37140:3;37161:67;37225:2;37220:3;37161:67;:::i;:::-;37154:74;;37237:93;37326:3;37237:93;:::i;:::-;37355:2;37350:3;37346:12;37339:19;;36998:366;;;:::o;37370:419::-;37536:4;37574:2;37563:9;37559:18;37551:26;;37623:9;37617:4;37613:20;37609:1;37598:9;37594:17;37587:47;37651:131;37777:4;37651:131;:::i;:::-;37643:139;;37370:419;;;:::o;37795:148::-;37897:11;37934:3;37919:18;;37795:148;;;;:::o;37949:390::-;38055:3;38083:39;38116:5;38083:39;:::i;:::-;38138:89;38220:6;38215:3;38138:89;:::i;:::-;38131:96;;38236:65;38294:6;38289:3;38282:4;38275:5;38271:16;38236:65;:::i;:::-;38326:6;38321:3;38317:16;38310:23;;38059:280;37949:390;;;;:::o;38345:155::-;38485:7;38481:1;38473:6;38469:14;38462:31;38345:155;:::o;38506:400::-;38666:3;38687:84;38769:1;38764:3;38687:84;:::i;:::-;38680:91;;38780:93;38869:3;38780:93;:::i;:::-;38898:1;38893:3;38889:11;38882:18;;38506:400;;;:::o;38912:541::-;39145:3;39167:95;39258:3;39249:6;39167:95;:::i;:::-;39160:102;;39279:148;39423:3;39279:148;:::i;:::-;39272:155;;39444:3;39437:10;;38912:541;;;;:::o;39459:225::-;39599:34;39595:1;39587:6;39583:14;39576:58;39668:8;39663:2;39655:6;39651:15;39644:33;39459:225;:::o;39690:366::-;39832:3;39853:67;39917:2;39912:3;39853:67;:::i;:::-;39846:74;;39929:93;40018:3;39929:93;:::i;:::-;40047:2;40042:3;40038:12;40031:19;;39690:366;;;:::o;40062:419::-;40228:4;40266:2;40255:9;40251:18;40243:26;;40315:9;40309:4;40305:20;40301:1;40290:9;40286:17;40279:47;40343:131;40469:4;40343:131;:::i;:::-;40335:139;;40062:419;;;:::o;40487:180::-;40535:77;40532:1;40525:88;40632:4;40629:1;40622:15;40656:4;40653:1;40646:15;40673:185;40713:1;40730:20;40748:1;40730:20;:::i;:::-;40725:25;;40764:20;40782:1;40764:20;:::i;:::-;40759:25;;40803:1;40793:35;;40808:18;;:::i;:::-;40793:35;40850:1;40847;40843:9;40838:14;;40673:185;;;;:::o;40864:194::-;40904:4;40924:20;40942:1;40924:20;:::i;:::-;40919:25;;40958:20;40976:1;40958:20;:::i;:::-;40953:25;;41002:1;40999;40995:9;40987:17;;41026:1;41020:4;41017:11;41014:37;;;41031:18;;:::i;:::-;41014:37;40864:194;;;;:::o;41064:179::-;41204:31;41200:1;41192:6;41188:14;41181:55;41064:179;:::o;41249:366::-;41391:3;41412:67;41476:2;41471:3;41412:67;:::i;:::-;41405:74;;41488:93;41577:3;41488:93;:::i;:::-;41606:2;41601:3;41597:12;41590:19;;41249:366;;;:::o;41621:419::-;41787:4;41825:2;41814:9;41810:18;41802:26;;41874:9;41868:4;41864:20;41860:1;41849:9;41845:17;41838:47;41902:131;42028:4;41902:131;:::i;:::-;41894:139;;41621:419;;;:::o;42046:147::-;42147:11;42184:3;42169:18;;42046:147;;;;:::o;42199:114::-;;:::o;42319:398::-;42478:3;42499:83;42580:1;42575:3;42499:83;:::i;:::-;42492:90;;42591:93;42680:3;42591:93;:::i;:::-;42709:1;42704:3;42700:11;42693:18;;42319:398;;;:::o;42723:379::-;42907:3;42929:147;43072:3;42929:147;:::i;:::-;42922:154;;43093:3;43086:10;;42723:379;;;:::o;43108:245::-;43248:34;43244:1;43236:6;43232:14;43225:58;43317:28;43312:2;43304:6;43300:15;43293:53;43108:245;:::o;43359:366::-;43501:3;43522:67;43586:2;43581:3;43522:67;:::i;:::-;43515:74;;43598:93;43687:3;43598:93;:::i;:::-;43716:2;43711:3;43707:12;43700:19;;43359:366;;;:::o;43731:419::-;43897:4;43935:2;43924:9;43920:18;43912:26;;43984:9;43978:4;43974:20;43970:1;43959:9;43955:17;43948:47;44012:131;44138:4;44012:131;:::i;:::-;44004:139;;43731:419;;;:::o;44156:435::-;44336:3;44358:95;44449:3;44440:6;44358:95;:::i;:::-;44351:102;;44470:95;44561:3;44552:6;44470:95;:::i;:::-;44463:102;;44582:3;44575:10;;44156:435;;;;;:::o;44597:229::-;44737:34;44733:1;44725:6;44721:14;44714:58;44806:12;44801:2;44793:6;44789:15;44782:37;44597:229;:::o;44832:366::-;44974:3;44995:67;45059:2;45054:3;44995:67;:::i;:::-;44988:74;;45071:93;45160:3;45071:93;:::i;:::-;45189:2;45184:3;45180:12;45173:19;;44832:366;;;:::o;45204:419::-;45370:4;45408:2;45397:9;45393:18;45385:26;;45457:9;45451:4;45447:20;45443:1;45432:9;45428:17;45421:47;45485:131;45611:4;45485:131;:::i;:::-;45477:139;;45204:419;;;:::o;45629:98::-;45680:6;45714:5;45708:12;45698:22;;45629:98;;;:::o;45733:168::-;45816:11;45850:6;45845:3;45838:19;45890:4;45885:3;45881:14;45866:29;;45733:168;;;;:::o;45907:373::-;45993:3;46021:38;46053:5;46021:38;:::i;:::-;46075:70;46138:6;46133:3;46075:70;:::i;:::-;46068:77;;46154:65;46212:6;46207:3;46200:4;46193:5;46189:16;46154:65;:::i;:::-;46244:29;46266:6;46244:29;:::i;:::-;46239:3;46235:39;46228:46;;45997:283;45907:373;;;;:::o;46286:640::-;46481:4;46519:3;46508:9;46504:19;46496:27;;46533:71;46601:1;46590:9;46586:17;46577:6;46533:71;:::i;:::-;46614:72;46682:2;46671:9;46667:18;46658:6;46614:72;:::i;:::-;46696;46764:2;46753:9;46749:18;46740:6;46696:72;:::i;:::-;46815:9;46809:4;46805:20;46800:2;46789:9;46785:18;46778:48;46843:76;46914:4;46905:6;46843:76;:::i;:::-;46835:84;;46286:640;;;;;;;:::o;46932:141::-;46988:5;47019:6;47013:13;47004:22;;47035:32;47061:5;47035:32;:::i;:::-;46932:141;;;;:::o;47079:349::-;47148:6;47197:2;47185:9;47176:7;47172:23;47168:32;47165:119;;;47203:79;;:::i;:::-;47165:119;47323:1;47348:63;47403:7;47394:6;47383:9;47379:22;47348:63;:::i;:::-;47338:73;;47294:127;47079:349;;;;:::o;47434:176::-;47466:1;47483:20;47501:1;47483:20;:::i;:::-;47478:25;;47517:20;47535:1;47517:20;:::i;:::-;47512:25;;47556:1;47546:35;;47561:18;;:::i;:::-;47546:35;47602:1;47599;47595:9;47590:14;;47434:176;;;;:::o;47616:225::-;47756:34;47752:1;47744:6;47740:14;47733:58;47825:8;47820:2;47812:6;47808:15;47801:33;47616:225;:::o;47847:366::-;47989:3;48010:67;48074:2;48069:3;48010:67;:::i;:::-;48003:74;;48086:93;48175:3;48086:93;:::i;:::-;48204:2;48199:3;48195:12;48188:19;;47847:366;;;:::o;48219:419::-;48385:4;48423:2;48412:9;48408:18;48400:26;;48472:9;48466:4;48462:20;48458:1;48447:9;48443:17;48436:47;48500:131;48626:4;48500:131;:::i;:::-;48492:139;;48219:419;;;:::o;48644:179::-;48784:31;48780:1;48772:6;48768:14;48761:55;48644:179;:::o;48829:366::-;48971:3;48992:67;49056:2;49051:3;48992:67;:::i;:::-;48985:74;;49068:93;49157:3;49068:93;:::i;:::-;49186:2;49181:3;49177:12;49170:19;;48829:366;;;:::o;49201:419::-;49367:4;49405:2;49394:9;49390:18;49382:26;;49454:9;49448:4;49444:20;49440:1;49429:9;49425:17;49418:47;49482:131;49608:4;49482:131;:::i;:::-;49474:139;;49201:419;;;:::o;49626:386::-;49730:3;49758:38;49790:5;49758:38;:::i;:::-;49812:88;49893:6;49888:3;49812:88;:::i;:::-;49805:95;;49909:65;49967:6;49962:3;49955:4;49948:5;49944:16;49909:65;:::i;:::-;49999:6;49994:3;49990:16;49983:23;;49734:278;49626:386;;;;:::o;50018:271::-;50148:3;50170:93;50259:3;50250:6;50170:93;:::i;:::-;50163:100;;50280:3;50273:10;;50018:271;;;;:::o

Swarm Source

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