ETH Price: $3,606.96 (+6.09%)

Token

Bitcoin Ape Punks (BAP)
 

Overview

Max Total Supply

10,000 BAP

Holders

3,493

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
2 BAP
0xacf122bc7a1a7be6aeceea2081d2a0098c60779b
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:
BitcoinApePunks

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-03-15
*/

/**
 *Submitted for verification at Etherscan.io on 2022-12-28
*/

// SPDX-License-Identifier: MIT
// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

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.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
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) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

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

        /// @solidity memory-safe-assembly
        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 in 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;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

// File: contracts/IOperatorFilterRegistry.sol


pragma solidity ^0.8.13;

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);
}
// File: contracts/OperatorFilterer.sol


// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module which provides 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} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */



pragma solidity ^0.8.13;

/**
 * @title  OwnedRegistrant
 * @notice Ownable contract that registers itself with the OperatorFilterRegistry and administers its own entries,
 *         to facilitate a subscription whose ownership can be transferred.
 */

pragma solidity ^0.8.13;

contract OperatorFilterRegistryErrorsAndEvents {
    error CannotFilterEOAs();
    error AddressAlreadyFiltered(address operator);
    error AddressNotFiltered(address operator);
    error CodeHashAlreadyFiltered(bytes32 codeHash);
    error CodeHashNotFiltered(bytes32 codeHash);
    error OnlyAddressOrOwner();
    error NotRegistered(address registrant);
    error AlreadyRegistered();
    error AlreadySubscribed(address subscription);
    error NotSubscribed();
    error CannotUpdateWhileSubscribed(address subscription);
    error CannotSubscribeToSelf();
    error CannotSubscribeToZeroAddress();
    error NotOwnable();
    error AddressFiltered(address filtered);
    error CodeHashFiltered(address account, bytes32 codeHash);
    error CannotSubscribeToRegistrantWithSubscription(address registrant);
    error CannotCopyFromSelf();

    event RegistrationUpdated(address indexed registrant, bool indexed registered);
    event OperatorUpdated(address indexed registrant, address indexed operator, bool indexed filtered);
    event OperatorsUpdated(address indexed registrant, address[] operators, bool indexed filtered);
    event CodeHashUpdated(address indexed registrant, bytes32 indexed codeHash, bool indexed filtered);
    event CodeHashesUpdated(address indexed registrant, bytes32[] codeHashes, bool indexed filtered);
    event SubscriptionUpdated(address indexed registrant, address indexed subscription, bool indexed subscribed);
}

pragma solidity ^0.8.13;

/**
 * @title  OperatorFilterRegistry
 * @notice Borrows heavily from the QQL BlacklistOperatorFilter contract:
 *         https://github.com/qql-art/contracts/blob/main/contracts/BlacklistOperatorFilter.sol
 * @notice This contracts allows tokens or token owners to register specific addresses or codeHashes that may be
 * *       restricted according to the isOperatorAllowed function.
 */
contract OperatorFilterRegistry is IOperatorFilterRegistry, OperatorFilterRegistryErrorsAndEvents {
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.Bytes32Set;

    /// @dev initialized accounts have a nonzero codehash (see https://eips.ethereum.org/EIPS/eip-1052)
    /// Note that this will also be a smart contract's codehash when making calls from its constructor.
    bytes32 constant EOA_CODEHASH = keccak256("");

    mapping(address => EnumerableSet.AddressSet) private _filteredOperators;
    mapping(address => EnumerableSet.Bytes32Set) private _filteredCodeHashes;
    mapping(address => address) private _registrations;
    mapping(address => EnumerableSet.AddressSet) private _subscribers;

    /**
     * @notice restricts method caller to the address or EIP-173 "owner()"
     */
    modifier onlyAddressOrOwner(address addr) {
        if (msg.sender != addr) {
            try Ownable(addr).owner() returns (address owner) {
                if (msg.sender != owner) {
                    revert OnlyAddressOrOwner();
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert NotOwnable();
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
        _;
    }

    /**
     * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns
     *         true if supplied registrant address is not registered.
     */
    function isOperatorAllowed(address registrant, address operator) external view returns (bool) {
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            EnumerableSet.AddressSet storage filteredOperatorsRef;
            EnumerableSet.Bytes32Set storage filteredCodeHashesRef;

            filteredOperatorsRef = _filteredOperators[registration];
            filteredCodeHashesRef = _filteredCodeHashes[registration];

            if (filteredOperatorsRef.contains(operator)) {
                revert AddressFiltered(operator);
            }
            if (operator.code.length > 0) {
                bytes32 codeHash = operator.codehash;
                if (filteredCodeHashesRef.contains(codeHash)) {
                    revert CodeHashFiltered(operator, codeHash);
                }
            }
        }
        return true;
    }

    //////////////////
    // AUTH METHODS //
    //////////////////

    /**
     * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.
     */
    function register(address registrant) external onlyAddressOrOwner(registrant) {
        if (_registrations[registrant] != address(0)) {
            revert AlreadyRegistered();
        }
        _registrations[registrant] = registrant;
        emit RegistrationUpdated(registrant, true);
    }

    /**
     * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner.
     *         Note that this does not remove any filtered addresses or codeHashes.
     *         Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes.
     */
    function unregister(address registrant) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            _subscribers[registration].remove(registrant);
            emit SubscriptionUpdated(registrant, registration, false);
        }
        _registrations[registrant] = address(0);
        emit RegistrationUpdated(registrant, false);
    }

    /**
     * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes.
     */
    function registerAndSubscribe(address registrant, address subscription) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            revert AlreadyRegistered();
        }
        if (registrant == subscription) {
            revert CannotSubscribeToSelf();
        }
        address subscriptionRegistration = _registrations[subscription];
        if (subscriptionRegistration == address(0)) {
            revert NotRegistered(subscription);
        }
        if (subscriptionRegistration != subscription) {
            revert CannotSubscribeToRegistrantWithSubscription(subscription);
        }

        _registrations[registrant] = subscription;
        _subscribers[subscription].add(registrant);
        emit RegistrationUpdated(registrant, true);
        emit SubscriptionUpdated(registrant, subscription, true);
    }

    /**
     * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another
     *         address without subscribing.
     */
    function registerAndCopyEntries(address registrant, address registrantToCopy)
        external
        onlyAddressOrOwner(registrant)
    {
        if (registrantToCopy == registrant) {
            revert CannotCopyFromSelf();
        }
        address registration = _registrations[registrant];
        if (registration != address(0)) {
            revert AlreadyRegistered();
        }
        address registrantRegistration = _registrations[registrantToCopy];
        if (registrantRegistration == address(0)) {
            revert NotRegistered(registrantToCopy);
        }
        _registrations[registrant] = registrant;
        emit RegistrationUpdated(registrant, true);
        _copyEntries(registrant, registrantToCopy);
    }

    /**
     * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.
     */
    function updateOperator(address registrant, address operator, bool filtered)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant];

        if (!filtered) {
            bool removed = filteredOperatorsRef.remove(operator);
            if (!removed) {
                revert AddressNotFiltered(operator);
            }
        } else {
            bool added = filteredOperatorsRef.add(operator);
            if (!added) {
                revert AddressAlreadyFiltered(operator);
            }
        }
        emit OperatorUpdated(registrant, operator, filtered);
    }

    /**
     * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.
     */
    function updateCodeHash(address registrant, bytes32 codeHash, bool filtered)
        external
        onlyAddressOrOwner(registrant)
    {
        if (codeHash == EOA_CODEHASH) {
            revert CannotFilterEOAs();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant];

        if (!filtered) {
            bool removed = filteredCodeHashesRef.remove(codeHash);
            if (!removed) {
                revert CodeHashNotFiltered(codeHash);
            }
        } else {
            bool added = filteredCodeHashesRef.add(codeHash);
            if (!added) {
                revert CodeHashAlreadyFiltered(codeHash);
            }
        }
        emit CodeHashUpdated(registrant, codeHash, filtered);
    }

    /**
     * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates.
     */
    function updateOperators(address registrant, address[] calldata operators, bool filtered)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrant];
        uint256 operatorsLength = operators.length;
        unchecked {
            if (!filtered) {
                for (uint256 i = 0; i < operatorsLength; ++i) {
                    address operator = operators[i];
                    bool removed = filteredOperatorsRef.remove(operator);
                    if (!removed) {
                        revert AddressNotFiltered(operator);
                    }
                }
            } else {
                for (uint256 i = 0; i < operatorsLength; ++i) {
                    address operator = operators[i];
                    bool added = filteredOperatorsRef.add(operator);
                    if (!added) {
                        revert AddressAlreadyFiltered(operator);
                    }
                }
            }
        }
        emit OperatorsUpdated(registrant, operators, filtered);
    }

    /**
     * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates.
     */
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered)
        external
        onlyAddressOrOwner(registrant)
    {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrant];
        uint256 codeHashesLength = codeHashes.length;
        unchecked {
            if (!filtered) {
                for (uint256 i = 0; i < codeHashesLength; ++i) {
                    bytes32 codeHash = codeHashes[i];
                    bool removed = filteredCodeHashesRef.remove(codeHash);
                    if (!removed) {
                        revert CodeHashNotFiltered(codeHash);
                    }
                }
            } else {
                for (uint256 i = 0; i < codeHashesLength; ++i) {
                    bytes32 codeHash = codeHashes[i];
                    if (codeHash == EOA_CODEHASH) {
                        revert CannotFilterEOAs();
                    }
                    bool added = filteredCodeHashesRef.add(codeHash);
                    if (!added) {
                        revert CodeHashAlreadyFiltered(codeHash);
                    }
                }
            }
        }
        emit CodeHashesUpdated(registrant, codeHashes, filtered);
    }

    /**
     * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous
     *         subscription if present.
     *         Note that accounts with subscriptions may go on to subscribe to other accounts - in this case,
     *         subscriptions will not be forwarded. Instead the former subscription's existing entries will still be
     *         used.
     */
    function subscribe(address registrant, address newSubscription) external onlyAddressOrOwner(registrant) {
        if (registrant == newSubscription) {
            revert CannotSubscribeToSelf();
        }
        if (newSubscription == address(0)) {
            revert CannotSubscribeToZeroAddress();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration == newSubscription) {
            revert AlreadySubscribed(newSubscription);
        }
        address newSubscriptionRegistration = _registrations[newSubscription];
        if (newSubscriptionRegistration == address(0)) {
            revert NotRegistered(newSubscription);
        }
        if (newSubscriptionRegistration != newSubscription) {
            revert CannotSubscribeToRegistrantWithSubscription(newSubscription);
        }

        if (registration != registrant) {
            _subscribers[registration].remove(registrant);
            emit SubscriptionUpdated(registrant, registration, false);
        }
        _registrations[registrant] = newSubscription;
        _subscribers[newSubscription].add(registrant);
        emit SubscriptionUpdated(registrant, newSubscription, true);
    }

    /**
     * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.
     */
    function unsubscribe(address registrant, bool copyExistingEntries) external onlyAddressOrOwner(registrant) {
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration == registrant) {
            revert NotSubscribed();
        }
        _subscribers[registration].remove(registrant);
        _registrations[registrant] = registrant;
        emit SubscriptionUpdated(registrant, registration, false);
        if (copyExistingEntries) {
            _copyEntries(registrant, registration);
        }
    }

    /**
     * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.
     */
    function copyEntriesOf(address registrant, address registrantToCopy) external onlyAddressOrOwner(registrant) {
        if (registrant == registrantToCopy) {
            revert CannotCopyFromSelf();
        }
        address registration = _registrations[registrant];
        if (registration == address(0)) {
            revert NotRegistered(registrant);
        }
        if (registration != registrant) {
            revert CannotUpdateWhileSubscribed(registration);
        }
        address registrantRegistration = _registrations[registrantToCopy];
        if (registrantRegistration == address(0)) {
            revert NotRegistered(registrantToCopy);
        }
        _copyEntries(registrant, registrantToCopy);
    }

    /// @dev helper to copy entries from registrantToCopy to registrant and emit events
    function _copyEntries(address registrant, address registrantToCopy) private {
        EnumerableSet.AddressSet storage filteredOperatorsRef = _filteredOperators[registrantToCopy];
        EnumerableSet.Bytes32Set storage filteredCodeHashesRef = _filteredCodeHashes[registrantToCopy];
        uint256 filteredOperatorsLength = filteredOperatorsRef.length();
        uint256 filteredCodeHashesLength = filteredCodeHashesRef.length();
        unchecked {
            for (uint256 i = 0; i < filteredOperatorsLength; ++i) {
                address operator = filteredOperatorsRef.at(i);
                bool added = _filteredOperators[registrant].add(operator);
                if (added) {
                    emit OperatorUpdated(registrant, operator, true);
                }
            }
            for (uint256 i = 0; i < filteredCodeHashesLength; ++i) {
                bytes32 codehash = filteredCodeHashesRef.at(i);
                bool added = _filteredCodeHashes[registrant].add(codehash);
                if (added) {
                    emit CodeHashUpdated(registrant, codehash, true);
                }
            }
        }
    }

    //////////////////
    // VIEW METHODS //
    //////////////////

    /**
     * @notice Get the subscription address of a given registrant, if any.
     */
    function subscriptionOf(address registrant) external view returns (address subscription) {
        subscription = _registrations[registrant];
        if (subscription == address(0)) {
            revert NotRegistered(registrant);
        } else if (subscription == registrant) {
            subscription = address(0);
        }
    }

    /**
     * @notice Get the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscribers(address registrant) external view returns (address[] memory) {
        return _subscribers[registrant].values();
    }

    /**
     * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant.
     *         Note that order is not guaranteed as updates are made.
     */
    function subscriberAt(address registrant, uint256 index) external view returns (address) {
        return _subscribers[registrant].at(index);
    }

    /**
     * @notice Returns true if operator is filtered by a given address or its subscription.
     */
    function isOperatorFiltered(address registrant, address operator) external view returns (bool) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].contains(operator);
        }
        return _filteredOperators[registrant].contains(operator);
    }

    /**
     * @notice Returns true if a codeHash is filtered by a given address or its subscription.
     */
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external view returns (bool) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].contains(codeHash);
        }
        return _filteredCodeHashes[registrant].contains(codeHash);
    }

    /**
     * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.
     */
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external view returns (bool) {
        bytes32 codeHash = operatorWithCode.codehash;
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].contains(codeHash);
        }
        return _filteredCodeHashes[registrant].contains(codeHash);
    }

    /**
     * @notice Returns true if an address has registered
     */
    function isRegistered(address registrant) external view returns (bool) {
        return _registrations[registrant] != address(0);
    }

    /**
     * @notice Returns a list of filtered operators for a given address or its subscription.
     */
    function filteredOperators(address registrant) external view returns (address[] memory) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].values();
        }
        return _filteredOperators[registrant].values();
    }

    /**
     * @notice Returns the set of filtered codeHashes for a given address or its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashes(address registrant) external view returns (bytes32[] memory) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].values();
        }
        return _filteredCodeHashes[registrant].values();
    }

    /**
     * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredOperatorAt(address registrant, uint256 index) external view returns (address) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredOperators[registration].at(index);
        }
        return _filteredOperators[registrant].at(index);
    }

    /**
     * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or
     *         its subscription.
     *         Note that order is not guaranteed as updates are made.
     */
    function filteredCodeHashAt(address registrant, uint256 index) external view returns (bytes32) {
        address registration = _registrations[registrant];
        if (registration != registrant) {
            return _filteredCodeHashes[registration].at(index);
        }
        return _filteredCodeHashes[registrant].at(index);
    }

    /// @dev Convenience method to compute the code hash of an arbitrary contract
    function codeHashOf(address a) external view returns (bytes32) {
        return a.codehash;
    }
}


pragma solidity ^0.8.13;


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 {
        // 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) {
            _checkFilterOperator(msg.sender);
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        _checkFilterOperator(operator);
        _;
    }

    function _checkFilterOperator(address operator) internal view 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);
            }
        }
    }
}


// File: contracts/DefaultOperatorFilterer.sol


pragma solidity ^0.8.13;


/**
 * @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) {}
}
// File: @openzeppelin/contracts/utils/math/Math.sol


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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


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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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


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



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


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


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

pragma solidity ^0.8.0;

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



pragma solidity ^0.8.0;


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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

pragma solidity ^0.8.0;



interface IERC721Enumerable is IERC721 {
  
    function totalSupply() external view returns (uint256);


    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);


    function tokenByIndex(uint256 index) external view returns (uint256);
}

pragma solidity ^0.8.0;

abstract contract ReentrancyGuard {

    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }


    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        _status = _ENTERED;

        _;

        _status = _NOT_ENTERED;
    }
}


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;




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


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

pragma solidity ^0.8.0;


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, IERC721Enumerable, DefaultOperatorFilterer {
    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();
        }
    }

    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        require(index < balanceOf(owner), "ERC721A: owner index out of bounds");
        uint256 numMintedSoFar = totalSupply();
        uint256 tokenIdsIdx;
        address currOwnershipAddr;

        unchecked {
            for (uint256 i; i < numMintedSoFar; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    if (tokenIdsIdx == index) {
                        return i;
                    }
                    tokenIdsIdx++;
                }
            }
        }

        revert("ERC721A: unable to get token of owner by index");
    }

    function tokenByIndex(uint256 index) public view override returns (uint256) {
        require(index < totalSupply(), "ERC721A: global index out of bounds");
        return index;
    }

    /**
     * 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 ||
            interfaceId == type(IERC721Enumerable).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 onlyAllowedOperator(to) {
        address owner = ERC721A.ownerOf(tokenId);
        require(to != owner, "ERC721A: approval to current owner");

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

        _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 onlyAllowedOperator(operator) {
        require(operator != _msgSender(), "ERC721A: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override onlyAllowedOperator(from){
        _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 {}
}


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

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

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

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

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

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

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

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

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

abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

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

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

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() external {
        address sender = _msgSender();
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        _transferOwnership(sender);
    }
}

contract OwnedRegistrant is Ownable2Step {
    address constant registry = 0x000000000000AAeB6D7670E522A718067333cd4E;

    constructor(address _owner) {
        IOperatorFilterRegistry(registry).register(address(this));
        transferOwnership(_owner);
    }
}


pragma solidity ^0.8.13;

/**
 * @title  UpdatableOperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry. This contract allows the Owner to update the
 *         OperatorFilterRegistry address via updateOperatorFilterRegistryAddress, including to the zero address,
 *         which will bypass registry checks.
 *         Note that OpenSea will still disable creator fee enforcement if filtered operators begin fulfilling orders
 *         on-chain, eg, if the registry is revoked or bypassed.
 * @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 UpdatableOperatorFilterer {
    error OperatorNotAllowed(address operator);
    error OnlyOwner();

    IOperatorFilterRegistry public operatorFilterRegistry;

    constructor(address _registry, address subscriptionOrRegistrantToCopy, bool subscribe) {
        IOperatorFilterRegistry registry = IOperatorFilterRegistry(_registry);
        operatorFilterRegistry = registry;
        // 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(registry).code.length > 0) {
            if (subscribe) {
                registry.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    registry.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    registry.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // 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) {
            _checkFilterOperator(msg.sender);
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        _checkFilterOperator(operator);
        _;
    }

    /**
     * @notice Update the address that the contract will make OperatorFilter checks against. When set to the zero
     *         address, checks will be bypassed. OnlyOwner.
     */
    function updateOperatorFilterRegistryAddress(address newRegistry) public virtual {
        if (msg.sender != owner()) {
            revert OnlyOwner();
        }
        operatorFilterRegistry = IOperatorFilterRegistry(newRegistry);
    }

    /**
     * @dev assume the contract has an owner, but leave specific Ownable implementation up to inheriting contract
     */
    function owner() public view virtual returns (address);

    function _checkFilterOperator(address operator) internal view virtual {
        IOperatorFilterRegistry registry = operatorFilterRegistry;
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(registry) != address(0) && address(registry).code.length > 0) {
            if (!registry.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
    }
}


pragma solidity ^0.8.13;

/**
 * @title  RevokableOperatorFilterer
 * @notice This contract is meant to allow contracts to permanently skip OperatorFilterRegistry checks if desired. The
 *         Registry itself has an "unregister" function, but if the contract is ownable, the owner can re-register at
 *         any point. As implemented, this abstract contract allows the contract owner to permanently skip the
 *         OperatorFilterRegistry checks by calling revokeOperatorFilterRegistry. Once done, the registry
 *         address cannot be further updated.
 *         Note that OpenSea will still disable creator fee enforcement if filtered operators begin fulfilling orders
 *         on-chain, eg, if the registry is revoked or bypassed.
 */
abstract contract RevokableOperatorFilterer is UpdatableOperatorFilterer {
    error RegistryHasBeenRevoked();
    error InitialRegistryAddressCannotBeZeroAddress();

    bool public isOperatorFilterRegistryRevoked;

    constructor(address _registry, address subscriptionOrRegistrantToCopy, bool subscribe)
        UpdatableOperatorFilterer(_registry, subscriptionOrRegistrantToCopy, subscribe)
    {
        // don't allow creating a contract with a permanently revoked registry
        if (_registry == address(0)) {
            revert InitialRegistryAddressCannotBeZeroAddress();
        }
    }

    function _checkFilterOperator(address operator) internal view virtual override {
        if (address(operatorFilterRegistry) != address(0)) {
            super._checkFilterOperator(operator);
        }
    }

    /**
     * @notice Update the address that the contract will make OperatorFilter checks against. When set to the zero
     *         address, checks will be permanently bypassed, and the address cannot be updated again. OnlyOwner.
     */
    function updateOperatorFilterRegistryAddress(address newRegistry) public override {
        if (msg.sender != owner()) {
            revert OnlyOwner();
        }
        // if registry has been revoked, do not allow further updates
        if (isOperatorFilterRegistryRevoked) {
            revert RegistryHasBeenRevoked();
        }

        operatorFilterRegistry = IOperatorFilterRegistry(newRegistry);
    }

    /**
     * @notice Revoke the OperatorFilterRegistry address, permanently bypassing checks. OnlyOwner.
     */
    function revokeOperatorFilterRegistry() public {
        if (msg.sender != owner()) {
            revert OnlyOwner();
        }
        // if registry has been revoked, do not allow further updates
        if (isOperatorFilterRegistryRevoked) {
            revert RegistryHasBeenRevoked();
        }

        // set to zero address to bypass checks
        operatorFilterRegistry = IOperatorFilterRegistry(address(0));
        isOperatorFilterRegistryRevoked = true;
    }
}

pragma solidity ^0.8.13;

/**
 * @title  RevokableDefaultOperatorFilterer
 * @notice Inherits from RevokableOperatorFilterer and automatically subscribes to the default OpenSea subscription.
 *         Note that OpenSea will disable creator fee enforcement if filtered operators begin fulfilling orders
 *         on-chain, eg, if the registry is revoked or bypassed.
 */
abstract contract RevokableDefaultOperatorFilterer is RevokableOperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() RevokableOperatorFilterer(0x000000000000AAeB6D7670E522A718067333cd4E, DEFAULT_SUBSCRIPTION, true) {}
}


pragma solidity ^0.8.9;

contract BitcoinApePunks is ERC721A, Ownable, ReentrancyGuard {
    using Strings for uint256;
    
    uint   public price             = 0.0069 ether;
    uint   public maxTx          = 20;
    uint   public maxSupply          = 10000;
    uint256 public reservedSupply = 100;
    string private baseURI;
    bool   public mintEnabled;  
    uint   public maxPerFree        = 1;
    uint   public totalFreeMinted = 0;
    uint   public totalFree         = 10000;
    uint256 public bridgeFee;
    bool public inscriptionPhaseActive = false;
    
    mapping(address => uint256) public _FreeMinted;

    constructor() ERC721A("Bitcoin Ape Punks", "BAP") {}

    function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
        require(_exists(_tokenId),"ERC721Metadata: URI query for nonexistent token");
        string memory currentBaseURI = _baseURI();
        return bytes(currentBaseURI).length > 0
            ? string(abi.encodePacked(currentBaseURI,Strings.toString(_tokenId),".json"))
            : "";
    }

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

    function mint(uint256 count) external payable {
        
        bool MintForFree = ((totalFreeMinted < totalFree) &&
            (_FreeMinted[msg.sender] < maxPerFree));

        if (MintForFree) { 
            require(mintEnabled, "Mint is not live yet");
            require(totalSupply() + count <= maxSupply, "No more");
            require(count <= maxTx, "Max per TX reached.");
            if(count >= (maxPerFree - _FreeMinted[msg.sender]))
            {
             require(msg.value >= (count * price) - ((maxPerFree - _FreeMinted[msg.sender]) * price), "Please send the exact ETH amount");
             _FreeMinted[msg.sender] = maxPerFree;
             totalFreeMinted += maxPerFree;
            }
            else if(count < (maxPerFree - _FreeMinted[msg.sender]))
            {
             require(msg.value >= 0, "Please send the exact ETH amount");
             _FreeMinted[msg.sender] += count;
             totalFreeMinted += count;
            }
        }
        else{
            require(mintEnabled, "Mint is not live yet");
            require(msg.value >= count * price, "Please send the exact ETH amount");
            require(totalSupply() + count <= maxSupply, "No more");
            require(count <= maxTx, "Max per TX reached.");
        }

        _safeMint(msg.sender, count);
    }

    function reservedMint(uint256 Amount) external onlyOwner
    {
        uint256 Remaining = reservedSupply;

        require(totalSupply() + Amount <= maxSupply, "No more supply to be minted");
        require(Remaining >= Amount, "Reserved Supply Minted");
    
        reservedSupply = Remaining - Amount;
        _safeMint(msg.sender, Amount);
       // totalSupply() += Amount;
    }

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

    function setBridgeFee(uint256 _fee) public onlyOwner {
        bridgeFee = _fee;
    }
    
    function toggleInscriptionsActive() public onlyOwner {
        inscriptionPhaseActive = !inscriptionPhaseActive;
    }
    
    function bridge(uint256 _tokenId) public payable {
        
        require(ownerOf(_tokenId) == msg.sender, "You do not own this token.");
        require(msg.value >= bridgeFee, "Insufficient fee to inscribe this token to ordinal BTC.");

        _burn(_tokenId);     
    }

    function bridgeMultiple(uint256[] calldata tokenIds) public payable {
    
     require(msg.value >= (tokenIds.length * bridgeFee), "Insufficient fee to inscribe this token to ordinal BTC.");

     for (uint i = 0; i < tokenIds.length; i++) {
      require(ownerOf(tokenIds[i]) == msg.sender, "You do not own this token.");
        _burn(tokenIds[i]);
       }
    }

    function burnUnbridgedTokens(uint256[] calldata tokenIds) public onlyOwner {
    for (uint i = 0; i < tokenIds.length; i++) {
      require(_exists(tokenIds[i]), "Token does not exist");
      _burn(tokenIds[i]);
      }
    }
   
   function setBaseUri(string memory baseuri_) public onlyOwner {
        baseURI = baseuri_;
    }

    function setCost(uint256 price_) external onlyOwner {
        price = price_;
    }

    function costInspect() public view returns (uint256) {
        return price;
    }

     function setmaxTx(uint256 _MaxTx) external onlyOwner {
        maxTx = _MaxTx;
    }

    function setMaxTotalFree(uint256 MaxTotalFree_) external onlyOwner {
        totalFree = MaxTotalFree_;
    }

    function setMaxPerFree(uint256 MaxPerFree_) external onlyOwner {
        maxPerFree = MaxPerFree_;
    }

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_FreeMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"bridgeMultiple","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"burnUnbridgedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"costInspect","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inscriptionPhaseActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerFree","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"reservedMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reservedSupply","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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseuri_","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setBridgeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"name":"setCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"MaxPerFree_","type":"uint256"}],"name":"setMaxPerFree","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"MaxTotalFree_","type":"uint256"}],"name":"setMaxTotalFree","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_MaxTx","type":"uint256"}],"name":"setmaxTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleInscriptionsActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFree","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFreeMinted","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"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526618838370f34000600a556014600b55612710600c556064600d55600160105560006011556127106012556000601460006101000a81548160ff0219169083151502179055503480156200005757600080fd5b506040518060400160405280601181526020017f426974636f696e204170652050756e6b730000000000000000000000000000008152506040518060400160405280600381526020017f4241500000000000000000000000000000000000000000000000000000000000815250733cc6cdda760b79bafa08df41ecfa224f810dceb6600160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620002d057801562000196576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200015c92919062000454565b600060405180830381600087803b1580156200017757600080fd5b505af11580156200018c573d6000803e3d6000fd5b50505050620002cf565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462000250576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200021692919062000454565b600060405180830381600087803b1580156200023157600080fd5b505af115801562000246573d6000803e3d6000fd5b50505050620002ce565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000299919062000481565b600060405180830381600087803b158015620002b457600080fd5b505af1158015620002c9573d6000803e3d6000fd5b505050505b5b5b50508160029081620002e3919062000718565b508060039081620002f5919062000718565b50620003066200033c60201b60201c565b60008190555050506200032e620003226200034160201b60201c565b6200034960201b60201c565b6001600981905550620007ff565b600090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200043c826200040f565b9050919050565b6200044e816200042f565b82525050565b60006040820190506200046b600083018562000443565b6200047a602083018462000443565b9392505050565b600060208201905062000498600083018462000443565b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200052057607f821691505b602082108103620005365762000535620004d8565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620005a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000561565b620005ac868362000561565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620005f9620005f3620005ed84620005c4565b620005ce565b620005c4565b9050919050565b6000819050919050565b6200061583620005d8565b6200062d620006248262000600565b8484546200056e565b825550505050565b600090565b6200064462000635565b620006518184846200060a565b505050565b5b8181101562000679576200066d6000826200063a565b60018101905062000657565b5050565b601f821115620006c85762000692816200053c565b6200069d8462000551565b81016020851015620006ad578190505b620006c5620006bc8562000551565b83018262000656565b50505b505050565b600082821c905092915050565b6000620006ed60001984600802620006cd565b1980831691505092915050565b6000620007088383620006da565b9150826002028217905092915050565b62000723826200049e565b67ffffffffffffffff8111156200073f576200073e620004a9565b5b6200074b825462000507565b620007588282856200067d565b600060209050601f8311600181146200079057600084156200077b578287015190505b620007878582620006fa565b865550620007f7565b601f198416620007a0866200053c565b60005b82811015620007ca57848901518255600182019150602085019450602081019050620007a3565b86831015620007ea5784890151620007e6601f891682620006da565b8355505b6001600288020188555050505b505050505050565b6152b6806200080f6000396000f3fe60806040526004361061027d5760003560e01c806382b12dd71161014f578063b0c2b561116100c1578063d5abeb011161007a578063d5abeb0114610944578063dad7b5c91461096f578063e945971c1461099a578063e985e9c5146109c3578063f2f0e5c914610a00578063f2fde38b14610a1c5761027d565b8063b0c2b56114610834578063b88d4fde1461085d578063b941160114610886578063c7c39ffc146108b1578063c87b56dd146108dc578063d1239730146109195761027d565b806395d89b411161011357806395d89b4114610747578063998cdf8314610772578063a035b1fe1461079b578063a0712d68146107c6578063a0bcfc7f146107e2578063a22cb4651461080b5761027d565b806382b12dd7146106835780638c74bf0e146106ae5780638da5cb5b146106d757806390fd50b3146107025780639495152d1461071e5761027d565b806341f43434116101f35780636352211e116101ac5780636352211e1461057357806370a08231146105b0578063715018a6146105ed5780637437681e146106045780637c3293db1461062f5780637d55094d1461066c5761027d565b806341f434341461046557806342842e0e1461049057806344a0d68a146104b957806344d19d2b146104e25780634f6ccce71461050d5780635a963f1b1461054a5761027d565b80632029ba95116102455780632029ba951461037b57806323b872dd146103a65780632f745c59146103cf578063333e44e61461040c5780633ccfd60b146104375780634005c0161461044e5761027d565b806301ffc9a71461028257806306fdde03146102bf578063081812fc146102ea578063095ea7b31461032757806318160ddd14610350575b600080fd5b34801561028e57600080fd5b506102a960048036038101906102a49190613ae3565b610a45565b6040516102b69190613b2b565b60405180910390f35b3480156102cb57600080fd5b506102d4610b8f565b6040516102e19190613bd6565b60405180910390f35b3480156102f657600080fd5b50610311600480360381019061030c9190613c2e565b610c21565b60405161031e9190613c9c565b60405180910390f35b34801561033357600080fd5b5061034e60048036038101906103499190613ce3565b610c9d565b005b34801561035c57600080fd5b50610365610cb6565b6040516103729190613d32565b60405180910390f35b34801561038757600080fd5b50610390610ccd565b60405161039d9190613b2b565b60405180910390f35b3480156103b257600080fd5b506103cd60048036038101906103c89190613d4d565b610ce0565b005b3480156103db57600080fd5b506103f660048036038101906103f19190613ce3565b610d2f565b6040516104039190613d32565b60405180910390f35b34801561041857600080fd5b50610421610f3a565b60405161042e9190613d32565b60405180910390f35b34801561044357600080fd5b5061044c610f40565b005b34801561045a57600080fd5b5061046361104c565b005b34801561047157600080fd5b5061047a611080565b6040516104879190613dff565b60405180910390f35b34801561049c57600080fd5b506104b760048036038101906104b29190613d4d565b611092565b005b3480156104c557600080fd5b506104e060048036038101906104db9190613c2e565b6110e1565b005b3480156104ee57600080fd5b506104f76110f3565b6040516105049190613d32565b60405180910390f35b34801561051957600080fd5b50610534600480360381019061052f9190613c2e565b6110f9565b6040516105419190613d32565b60405180910390f35b34801561055657600080fd5b50610571600480360381019061056c9190613c2e565b61114c565b005b34801561057f57600080fd5b5061059a60048036038101906105959190613c2e565b61115e565b6040516105a79190613c9c565b60405180910390f35b3480156105bc57600080fd5b506105d760048036038101906105d29190613e1a565b611174565b6040516105e49190613d32565b60405180910390f35b3480156105f957600080fd5b50610602611243565b005b34801561061057600080fd5b50610619611257565b6040516106269190613d32565b60405180910390f35b34801561063b57600080fd5b5061065660048036038101906106519190613e1a565b61125d565b6040516106639190613d32565b60405180910390f35b34801561067857600080fd5b50610681611275565b005b34801561068f57600080fd5b506106986112a9565b6040516106a59190613d32565b60405180910390f35b3480156106ba57600080fd5b506106d560048036038101906106d09190613c2e565b6112af565b005b3480156106e357600080fd5b506106ec611378565b6040516106f99190613c9c565b60405180910390f35b61071c60048036038101906107179190613c2e565b6113a2565b005b34801561072a57600080fd5b5061074560048036038101906107409190613eac565b611469565b005b34801561075357600080fd5b5061075c61151a565b6040516107699190613bd6565b60405180910390f35b34801561077e57600080fd5b5061079960048036038101906107949190613c2e565b6115ac565b005b3480156107a757600080fd5b506107b06115be565b6040516107bd9190613d32565b60405180910390f35b6107e060048036038101906107db9190613c2e565b6115c4565b005b3480156107ee57600080fd5b5061080960048036038101906108049190614029565b611ad1565b005b34801561081757600080fd5b50610832600480360381019061082d919061409e565b611aec565b005b34801561084057600080fd5b5061085b60048036038101906108569190613c2e565b611b05565b005b34801561086957600080fd5b50610884600480360381019061087f919061417f565b611b17565b005b34801561089257600080fd5b5061089b611b68565b6040516108a89190613d32565b60405180910390f35b3480156108bd57600080fd5b506108c6611b72565b6040516108d39190613d32565b60405180910390f35b3480156108e857600080fd5b5061090360048036038101906108fe9190613c2e565b611b78565b6040516109109190613bd6565b60405180910390f35b34801561092557600080fd5b5061092e611c1f565b60405161093b9190613b2b565b60405180910390f35b34801561095057600080fd5b50610959611c32565b6040516109669190613d32565b60405180910390f35b34801561097b57600080fd5b50610984611c38565b6040516109919190613d32565b60405180910390f35b3480156109a657600080fd5b506109c160048036038101906109bc9190613c2e565b611c3e565b005b3480156109cf57600080fd5b506109ea60048036038101906109e59190614202565b611c50565b6040516109f79190613b2b565b60405180910390f35b610a1a6004803603810190610a159190613eac565b611ce4565b005b348015610a2857600080fd5b50610a436004803603810190610a3e9190613e1a565b611e0e565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610b1057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610b7857507f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610b885750610b8782611e91565b5b9050919050565b606060028054610b9e90614271565b80601f0160208091040260200160405190810160405280929190818152602001828054610bca90614271565b8015610c175780601f10610bec57610100808354040283529160200191610c17565b820191906000526020600020905b815481529060010190602001808311610bfa57829003601f168201915b5050505050905090565b6000610c2c82611efb565b610c62576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b81610ca781611f49565b610cb18383612046565b505050565b6000610cc061219d565b6001546000540303905090565b601460009054906101000a900460ff1681565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d1e57610d1d33611f49565b5b610d298484846121a2565b50505050565b6000610d3a83611174565b8210610d7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7290614314565b60405180910390fd5b6000610d85610cb6565b905060008060005b83811015610ef8576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614610e9a57806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610eea57868403610ee1578195505050505050610f34565b83806001019450505b508080600101915050610d8d565b506040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2b906143a6565b60405180910390fd5b92915050565b60125481565b610f486121f1565b600260095403610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490614412565b60405180910390fd5b600260098190555060003373ffffffffffffffffffffffffffffffffffffffff1647604051610fbb90614463565b60006040518083038185875af1925050503d8060008114610ff8576040519150601f19603f3d011682016040523d82523d6000602084013e610ffd565b606091505b5050905080611041576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611038906144c4565b60405180910390fd5b506001600981905550565b6110546121f1565b601460009054906101000a900460ff1615601460006101000a81548160ff021916908315150217905550565b6daaeb6d7670e522a718067333cd4e81565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146110d0576110cf33611f49565b5b6110db84848461226f565b50505050565b6110e96121f1565b80600a8190555050565b600d5481565b6000611103610cb6565b8210611144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113b90614556565b60405180910390fd5b819050919050565b6111546121f1565b8060128190555050565b6000611169826122ce565b600001519050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111db576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b61124b6121f1565b611255600061255d565b565b600b5481565b60156020528060005260406000206000915090505481565b61127d6121f1565b600f60009054906101000a900460ff1615600f60006101000a81548160ff021916908315150217905550565b60135481565b6112b76121f1565b6000600d549050600c54826112ca610cb6565b6112d491906145a5565b1115611315576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130c90614625565b60405180910390fd5b81811015611358576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134f90614691565b60405180910390fd5b818161136491906146b1565b600d819055506113743383612623565b5050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b3373ffffffffffffffffffffffffffffffffffffffff166113c28261115e565b73ffffffffffffffffffffffffffffffffffffffff1614611418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140f90614731565b60405180910390fd5b60135434101561145d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611454906147c3565b60405180910390fd5b61146681612641565b50565b6114716121f1565b60005b82829050811015611515576114a1838383818110611495576114946147e3565b5b90506020020135611efb565b6114e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d79061485e565b60405180910390fd5b6115028383838181106114f6576114f56147e3565b5b90506020020135612641565b808061150d9061487e565b915050611474565b505050565b60606003805461152990614271565b80601f016020809104026020016040519081016040528092919081815260200182805461155590614271565b80156115a25780601f10611577576101008083540402835291602001916115a2565b820191906000526020600020905b81548152906001019060200180831161158557829003601f168201915b5050505050905090565b6115b46121f1565b8060138190555050565b600a5481565b60006012546011541080156116195750601054601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b9050801561198757600f60009054906101000a900460ff16611670576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166790614912565b60405180910390fd5b600c548261167c610cb6565b61168691906145a5565b11156116c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116be9061497e565b60405180910390fd5b600b5482111561170c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611703906149ea565b60405180910390fd5b601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460105461175991906146b1565b821061187957600a54601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546010546117af91906146b1565b6117b99190614a0a565b600a54836117c79190614a0a565b6117d191906146b1565b341015611813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180a90614a98565b60405180910390fd5b601054601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506010546011600082825461186d91906145a5565b92505081905550611982565b601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546010546118c691906146b1565b821015611981576000341015611911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190890614a98565b60405180910390fd5b81601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461196091906145a5565b92505081905550816011600082825461197991906145a5565b925050819055505b5b611ac3565b600f60009054906101000a900460ff166119d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119cd90614912565b60405180910390fd5b600a54826119e49190614a0a565b341015611a26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1d90614a98565b60405180910390fd5b600c5482611a32610cb6565b611a3c91906145a5565b1115611a7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a749061497e565b60405180910390fd5b600b54821115611ac2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ab9906149ea565b60405180910390fd5b5b611acd3383612623565b5050565b611ad96121f1565b80600e9081611ae89190614c5a565b5050565b81611af681611f49565b611b00838361264f565b505050565b611b0d6121f1565b80600b8190555050565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b5557611b5433611f49565b5b611b618585858561280e565b5050505050565b6000600a54905090565b60105481565b6060611b8382611efb565b611bc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb990614d9e565b60405180910390fd5b6000611bcc6128c9565b90506000815111611bec5760405180602001604052806000815250611c17565b80611bf68461295b565b604051602001611c07929190614e46565b6040516020818303038152906040525b915050919050565b600f60009054906101000a900460ff1681565b600c5481565b60115481565b611c466121f1565b8060108190555050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60135482829050611cf59190614a0a565b341015611d37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2e906147c3565b60405180910390fd5b60005b82829050811015611e09573373ffffffffffffffffffffffffffffffffffffffff16611d7e848484818110611d7257611d716147e3565b5b9050602002013561115e565b73ffffffffffffffffffffffffffffffffffffffff1614611dd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcb90614731565b60405180910390fd5b611df6838383818110611dea57611de96147e3565b5b90506020020135612641565b8080611e019061487e565b915050611d3a565b505050565b611e166121f1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7c90614ee7565b60405180910390fd5b611e8e8161255d565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081611f0661219d565b11158015611f15575060005482105b8015611f42575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115612043576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611fc0929190614f07565b602060405180830381865afa158015611fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120019190614f45565b61204257806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016120399190613c9c565b60405180910390fd5b5b50565b813373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146120845761208333611f49565b5b600061208f8361115e565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036120ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f690614fe4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661211e612a29565b73ffffffffffffffffffffffffffffffffffffffff16148061214d575061214c81612147612a29565b611c50565b5b61218c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218390615076565b60405180910390fd5b612197848483612a31565b50505050565b600090565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146121e0576121df33611f49565b5b6121eb848484612ae3565b50505050565b6121f9612a29565b73ffffffffffffffffffffffffffffffffffffffff16612217611378565b73ffffffffffffffffffffffffffffffffffffffff161461226d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612264906150e2565b60405180910390fd5b565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146122ad576122ac33611f49565b5b6122c884848460405180602001604052806000815250611b17565b50505050565b6122d6613a34565b6000829050806122e461219d565b111580156122f3575060005481105b15612526576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161252457600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612408578092505050612558565b5b60011561252357818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461251e578092505050612558565b612409565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61263d828260405180602001604052806000815250612f97565b5050565b61264c816000612fa9565b50565b813373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461268d5761268c33611f49565b5b612695612a29565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612702576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f99061514e565b60405180910390fd5b816007600061270f612a29565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff166127bc612a29565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31846040516128019190613b2b565b60405180910390a3505050565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461284c5761284b33611f49565b5b612857858585612ae3565b6128768473ffffffffffffffffffffffffffffffffffffffff16613398565b801561288b5750612889858585856133bb565b155b156128c2576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6060600e80546128d890614271565b80601f016020809104026020016040519081016040528092919081815260200182805461290490614271565b80156129515780601f1061292657610100808354040283529160200191612951565b820191906000526020600020905b81548152906001019060200180831161293457829003601f168201915b5050505050905090565b60606000600161296a8461350b565b01905060008167ffffffffffffffff81111561298957612988613efe565b5b6040519080825280601f01601f1916602001820160405280156129bb5781602001600182028036833780820191505090505b509050600082602001820190505b600115612a1e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612a1257612a1161516e565b5b049450600085036129c9575b819350505050919050565b600033905090565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000612aee826122ce565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612b59576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16612b7a612a29565b73ffffffffffffffffffffffffffffffffffffffff161480612ba95750612ba885612ba3612a29565b611c50565b5b80612bee5750612bb7612a29565b73ffffffffffffffffffffffffffffffffffffffff16612bd684610c21565b73ffffffffffffffffffffffffffffffffffffffff16145b905080612c27576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c8d576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c9a858585600161365e565b612ca660008487612a31565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612f25576000548214612f2457878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612f908585856001613664565b5050505050565b612fa4838383600161366a565b505050565b6000612fb4836122ce565b905060008160000151905082156130955760008173ffffffffffffffffffffffffffffffffffffffff16612fe6612a29565b73ffffffffffffffffffffffffffffffffffffffff16148061301557506130148261300f612a29565b611c50565b5b8061305a5750613023612a29565b73ffffffffffffffffffffffffffffffffffffffff1661304286610c21565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613093576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6130a381600086600161365e565b6130af60008583612a31565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060018160000160108282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008781526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600181600001601c6101000a81548160ff02191690831515021790555060006001870190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361331257600054821461331157848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b5050505083600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613380816000866001613664565b60016000815480929190600101919050555050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026133e1612a29565b8786866040518563ffffffff1660e01b815260040161340394939291906151f2565b6020604051808303816000875af192505050801561343f57506040513d601f19601f8201168201806040525081019061343c9190615253565b60015b6134b8573d806000811461346f576040519150601f19603f3d011682016040523d82523d6000602084013e613474565b606091505b5060008151036134b0576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613569577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161355f5761355e61516e565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106135a6576d04ee2d6d415b85acef8100000000838161359c5761359b61516e565b5b0492506020810190505b662386f26fc1000083106135d557662386f26fc1000083816135cb576135ca61516e565b5b0492506010810190505b6305f5e10083106135fe576305f5e10083816135f4576135f361516e565b5b0492506008810190505b61271083106136235761271083816136195761361861516e565b5b0492506004810190505b60648310613646576064838161363c5761363b61516e565b5b0492506002810190505b600a8310613655576001810190505b80915050919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036136d6576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613710576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61371d600086838761365e565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600085820190508380156138e757506138e68773ffffffffffffffffffffffffffffffffffffffff16613398565b5b156139ac575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461395c60008884806001019550886133bb565b613992576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082036138ed5782600054146139a757600080fd5b613a17565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48082036139ad575b816000819055505050613a2d6000868387613664565b5050505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ac081613a8b565b8114613acb57600080fd5b50565b600081359050613add81613ab7565b92915050565b600060208284031215613af957613af8613a81565b5b6000613b0784828501613ace565b91505092915050565b60008115159050919050565b613b2581613b10565b82525050565b6000602082019050613b406000830184613b1c565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613b80578082015181840152602081019050613b65565b60008484015250505050565b6000601f19601f8301169050919050565b6000613ba882613b46565b613bb28185613b51565b9350613bc2818560208601613b62565b613bcb81613b8c565b840191505092915050565b60006020820190508181036000830152613bf08184613b9d565b905092915050565b6000819050919050565b613c0b81613bf8565b8114613c1657600080fd5b50565b600081359050613c2881613c02565b92915050565b600060208284031215613c4457613c43613a81565b5b6000613c5284828501613c19565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613c8682613c5b565b9050919050565b613c9681613c7b565b82525050565b6000602082019050613cb16000830184613c8d565b92915050565b613cc081613c7b565b8114613ccb57600080fd5b50565b600081359050613cdd81613cb7565b92915050565b60008060408385031215613cfa57613cf9613a81565b5b6000613d0885828601613cce565b9250506020613d1985828601613c19565b9150509250929050565b613d2c81613bf8565b82525050565b6000602082019050613d476000830184613d23565b92915050565b600080600060608486031215613d6657613d65613a81565b5b6000613d7486828701613cce565b9350506020613d8586828701613cce565b9250506040613d9686828701613c19565b9150509250925092565b6000819050919050565b6000613dc5613dc0613dbb84613c5b565b613da0565b613c5b565b9050919050565b6000613dd782613daa565b9050919050565b6000613de982613dcc565b9050919050565b613df981613dde565b82525050565b6000602082019050613e146000830184613df0565b92915050565b600060208284031215613e3057613e2f613a81565b5b6000613e3e84828501613cce565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613e6c57613e6b613e47565b5b8235905067ffffffffffffffff811115613e8957613e88613e4c565b5b602083019150836020820283011115613ea557613ea4613e51565b5b9250929050565b60008060208385031215613ec357613ec2613a81565b5b600083013567ffffffffffffffff811115613ee157613ee0613a86565b5b613eed85828601613e56565b92509250509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613f3682613b8c565b810181811067ffffffffffffffff82111715613f5557613f54613efe565b5b80604052505050565b6000613f68613a77565b9050613f748282613f2d565b919050565b600067ffffffffffffffff821115613f9457613f93613efe565b5b613f9d82613b8c565b9050602081019050919050565b82818337600083830152505050565b6000613fcc613fc784613f79565b613f5e565b905082815260208101848484011115613fe857613fe7613ef9565b5b613ff3848285613faa565b509392505050565b600082601f8301126140105761400f613e47565b5b8135614020848260208601613fb9565b91505092915050565b60006020828403121561403f5761403e613a81565b5b600082013567ffffffffffffffff81111561405d5761405c613a86565b5b61406984828501613ffb565b91505092915050565b61407b81613b10565b811461408657600080fd5b50565b60008135905061409881614072565b92915050565b600080604083850312156140b5576140b4613a81565b5b60006140c385828601613cce565b92505060206140d485828601614089565b9150509250929050565b600067ffffffffffffffff8211156140f9576140f8613efe565b5b61410282613b8c565b9050602081019050919050565b600061412261411d846140de565b613f5e565b90508281526020810184848401111561413e5761413d613ef9565b5b614149848285613faa565b509392505050565b600082601f83011261416657614165613e47565b5b813561417684826020860161410f565b91505092915050565b6000806000806080858703121561419957614198613a81565b5b60006141a787828801613cce565b94505060206141b887828801613cce565b93505060406141c987828801613c19565b925050606085013567ffffffffffffffff8111156141ea576141e9613a86565b5b6141f687828801614151565b91505092959194509250565b6000806040838503121561421957614218613a81565b5b600061422785828601613cce565b925050602061423885828601613cce565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061428957607f821691505b60208210810361429c5761429b614242565b5b50919050565b7f455243373231413a206f776e657220696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b60006142fe602283613b51565b9150614309826142a2565b604082019050919050565b6000602082019050818103600083015261432d816142f1565b9050919050565b7f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060008201527f6f776e657220627920696e646578000000000000000000000000000000000000602082015250565b6000614390602e83613b51565b915061439b82614334565b604082019050919050565b600060208201905081810360008301526143bf81614383565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b60006143fc601f83613b51565b9150614407826143c6565b602082019050919050565b6000602082019050818103600083015261442b816143ef565b9050919050565b600081905092915050565b50565b600061444d600083614432565b91506144588261443d565b600082019050919050565b600061446e82614440565b9150819050919050565b7f5472616e73666572206661696c65642e00000000000000000000000000000000600082015250565b60006144ae601083613b51565b91506144b982614478565b602082019050919050565b600060208201905081810360008301526144dd816144a1565b9050919050565b7f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f7560008201527f6e64730000000000000000000000000000000000000000000000000000000000602082015250565b6000614540602383613b51565b915061454b826144e4565b604082019050919050565b6000602082019050818103600083015261456f81614533565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006145b082613bf8565b91506145bb83613bf8565b92508282019050808211156145d3576145d2614576565b5b92915050565b7f4e6f206d6f726520737570706c7920746f206265206d696e7465640000000000600082015250565b600061460f601b83613b51565b915061461a826145d9565b602082019050919050565b6000602082019050818103600083015261463e81614602565b9050919050565b7f526573657276656420537570706c79204d696e74656400000000000000000000600082015250565b600061467b601683613b51565b915061468682614645565b602082019050919050565b600060208201905081810360008301526146aa8161466e565b9050919050565b60006146bc82613bf8565b91506146c783613bf8565b92508282039050818111156146df576146de614576565b5b92915050565b7f596f7520646f206e6f74206f776e207468697320746f6b656e2e000000000000600082015250565b600061471b601a83613b51565b9150614726826146e5565b602082019050919050565b6000602082019050818103600083015261474a8161470e565b9050919050565b7f496e73756666696369656e742066656520746f20696e7363726962652074686960008201527f7320746f6b656e20746f206f7264696e616c204254432e000000000000000000602082015250565b60006147ad603783613b51565b91506147b882614751565b604082019050919050565b600060208201905081810360008301526147dc816147a0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f546f6b656e20646f6573206e6f74206578697374000000000000000000000000600082015250565b6000614848601483613b51565b915061485382614812565b602082019050919050565b600060208201905081810360008301526148778161483b565b9050919050565b600061488982613bf8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036148bb576148ba614576565b5b600182019050919050565b7f4d696e74206973206e6f74206c69766520796574000000000000000000000000600082015250565b60006148fc601483613b51565b9150614907826148c6565b602082019050919050565b6000602082019050818103600083015261492b816148ef565b9050919050565b7f4e6f206d6f726500000000000000000000000000000000000000000000000000600082015250565b6000614968600783613b51565b915061497382614932565b602082019050919050565b600060208201905081810360008301526149978161495b565b9050919050565b7f4d61782070657220545820726561636865642e00000000000000000000000000600082015250565b60006149d4601383613b51565b91506149df8261499e565b602082019050919050565b60006020820190508181036000830152614a03816149c7565b9050919050565b6000614a1582613bf8565b9150614a2083613bf8565b9250828202614a2e81613bf8565b91508282048414831517614a4557614a44614576565b5b5092915050565b7f506c656173652073656e64207468652065786163742045544820616d6f756e74600082015250565b6000614a82602083613b51565b9150614a8d82614a4c565b602082019050919050565b60006020820190508181036000830152614ab181614a75565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b1a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614add565b614b248683614add565b95508019841693508086168417925050509392505050565b6000614b57614b52614b4d84613bf8565b613da0565b613bf8565b9050919050565b6000819050919050565b614b7183614b3c565b614b85614b7d82614b5e565b848454614aea565b825550505050565b600090565b614b9a614b8d565b614ba5818484614b68565b505050565b5b81811015614bc957614bbe600082614b92565b600181019050614bab565b5050565b601f821115614c0e57614bdf81614ab8565b614be884614acd565b81016020851015614bf7578190505b614c0b614c0385614acd565b830182614baa565b50505b505050565b600082821c905092915050565b6000614c3160001984600802614c13565b1980831691505092915050565b6000614c4a8383614c20565b9150826002028217905092915050565b614c6382613b46565b67ffffffffffffffff811115614c7c57614c7b613efe565b5b614c868254614271565b614c91828285614bcd565b600060209050601f831160018114614cc45760008415614cb2578287015190505b614cbc8582614c3e565b865550614d24565b601f198416614cd286614ab8565b60005b82811015614cfa57848901518255600182019150602085019450602081019050614cd5565b86831015614d175784890151614d13601f891682614c20565b8355505b6001600288020188555050505b505050505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614d88602f83613b51565b9150614d9382614d2c565b604082019050919050565b60006020820190508181036000830152614db781614d7b565b9050919050565b600081905092915050565b6000614dd482613b46565b614dde8185614dbe565b9350614dee818560208601613b62565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000614e30600583614dbe565b9150614e3b82614dfa565b600582019050919050565b6000614e528285614dc9565b9150614e5e8284614dc9565b9150614e6982614e23565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614ed1602683613b51565b9150614edc82614e75565b604082019050919050565b60006020820190508181036000830152614f0081614ec4565b9050919050565b6000604082019050614f1c6000830185613c8d565b614f296020830184613c8d565b9392505050565b600081519050614f3f81614072565b92915050565b600060208284031215614f5b57614f5a613a81565b5b6000614f6984828501614f30565b91505092915050565b7f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000614fce602283613b51565b9150614fd982614f72565b604082019050919050565b60006020820190508181036000830152614ffd81614fc1565b9050919050565b7f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000602082015250565b6000615060603983613b51565b915061506b82615004565b604082019050919050565b6000602082019050818103600083015261508f81615053565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006150cc602083613b51565b91506150d782615096565b602082019050919050565b600060208201905081810360008301526150fb816150bf565b9050919050565b7f455243373231413a20617070726f766520746f2063616c6c6572000000000000600082015250565b6000615138601a83613b51565b915061514382615102565b602082019050919050565b600060208201905081810360008301526151678161512b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006151c48261519d565b6151ce81856151a8565b93506151de818560208601613b62565b6151e781613b8c565b840191505092915050565b60006080820190506152076000830187613c8d565b6152146020830186613c8d565b6152216040830185613d23565b818103606083015261523381846151b9565b905095945050505050565b60008151905061524d81613ab7565b92915050565b60006020828403121561526957615268613a81565b5b60006152778482850161523e565b9150509291505056fea264697066735822122088a2040ffbac4cbf7c04cb5e67b8f5bed4d7e46ac6874c233249ab047377890664736f6c63430008130033

Deployed Bytecode

0x60806040526004361061027d5760003560e01c806382b12dd71161014f578063b0c2b561116100c1578063d5abeb011161007a578063d5abeb0114610944578063dad7b5c91461096f578063e945971c1461099a578063e985e9c5146109c3578063f2f0e5c914610a00578063f2fde38b14610a1c5761027d565b8063b0c2b56114610834578063b88d4fde1461085d578063b941160114610886578063c7c39ffc146108b1578063c87b56dd146108dc578063d1239730146109195761027d565b806395d89b411161011357806395d89b4114610747578063998cdf8314610772578063a035b1fe1461079b578063a0712d68146107c6578063a0bcfc7f146107e2578063a22cb4651461080b5761027d565b806382b12dd7146106835780638c74bf0e146106ae5780638da5cb5b146106d757806390fd50b3146107025780639495152d1461071e5761027d565b806341f43434116101f35780636352211e116101ac5780636352211e1461057357806370a08231146105b0578063715018a6146105ed5780637437681e146106045780637c3293db1461062f5780637d55094d1461066c5761027d565b806341f434341461046557806342842e0e1461049057806344a0d68a146104b957806344d19d2b146104e25780634f6ccce71461050d5780635a963f1b1461054a5761027d565b80632029ba95116102455780632029ba951461037b57806323b872dd146103a65780632f745c59146103cf578063333e44e61461040c5780633ccfd60b146104375780634005c0161461044e5761027d565b806301ffc9a71461028257806306fdde03146102bf578063081812fc146102ea578063095ea7b31461032757806318160ddd14610350575b600080fd5b34801561028e57600080fd5b506102a960048036038101906102a49190613ae3565b610a45565b6040516102b69190613b2b565b60405180910390f35b3480156102cb57600080fd5b506102d4610b8f565b6040516102e19190613bd6565b60405180910390f35b3480156102f657600080fd5b50610311600480360381019061030c9190613c2e565b610c21565b60405161031e9190613c9c565b60405180910390f35b34801561033357600080fd5b5061034e60048036038101906103499190613ce3565b610c9d565b005b34801561035c57600080fd5b50610365610cb6565b6040516103729190613d32565b60405180910390f35b34801561038757600080fd5b50610390610ccd565b60405161039d9190613b2b565b60405180910390f35b3480156103b257600080fd5b506103cd60048036038101906103c89190613d4d565b610ce0565b005b3480156103db57600080fd5b506103f660048036038101906103f19190613ce3565b610d2f565b6040516104039190613d32565b60405180910390f35b34801561041857600080fd5b50610421610f3a565b60405161042e9190613d32565b60405180910390f35b34801561044357600080fd5b5061044c610f40565b005b34801561045a57600080fd5b5061046361104c565b005b34801561047157600080fd5b5061047a611080565b6040516104879190613dff565b60405180910390f35b34801561049c57600080fd5b506104b760048036038101906104b29190613d4d565b611092565b005b3480156104c557600080fd5b506104e060048036038101906104db9190613c2e565b6110e1565b005b3480156104ee57600080fd5b506104f76110f3565b6040516105049190613d32565b60405180910390f35b34801561051957600080fd5b50610534600480360381019061052f9190613c2e565b6110f9565b6040516105419190613d32565b60405180910390f35b34801561055657600080fd5b50610571600480360381019061056c9190613c2e565b61114c565b005b34801561057f57600080fd5b5061059a60048036038101906105959190613c2e565b61115e565b6040516105a79190613c9c565b60405180910390f35b3480156105bc57600080fd5b506105d760048036038101906105d29190613e1a565b611174565b6040516105e49190613d32565b60405180910390f35b3480156105f957600080fd5b50610602611243565b005b34801561061057600080fd5b50610619611257565b6040516106269190613d32565b60405180910390f35b34801561063b57600080fd5b5061065660048036038101906106519190613e1a565b61125d565b6040516106639190613d32565b60405180910390f35b34801561067857600080fd5b50610681611275565b005b34801561068f57600080fd5b506106986112a9565b6040516106a59190613d32565b60405180910390f35b3480156106ba57600080fd5b506106d560048036038101906106d09190613c2e565b6112af565b005b3480156106e357600080fd5b506106ec611378565b6040516106f99190613c9c565b60405180910390f35b61071c60048036038101906107179190613c2e565b6113a2565b005b34801561072a57600080fd5b5061074560048036038101906107409190613eac565b611469565b005b34801561075357600080fd5b5061075c61151a565b6040516107699190613bd6565b60405180910390f35b34801561077e57600080fd5b5061079960048036038101906107949190613c2e565b6115ac565b005b3480156107a757600080fd5b506107b06115be565b6040516107bd9190613d32565b60405180910390f35b6107e060048036038101906107db9190613c2e565b6115c4565b005b3480156107ee57600080fd5b5061080960048036038101906108049190614029565b611ad1565b005b34801561081757600080fd5b50610832600480360381019061082d919061409e565b611aec565b005b34801561084057600080fd5b5061085b60048036038101906108569190613c2e565b611b05565b005b34801561086957600080fd5b50610884600480360381019061087f919061417f565b611b17565b005b34801561089257600080fd5b5061089b611b68565b6040516108a89190613d32565b60405180910390f35b3480156108bd57600080fd5b506108c6611b72565b6040516108d39190613d32565b60405180910390f35b3480156108e857600080fd5b5061090360048036038101906108fe9190613c2e565b611b78565b6040516109109190613bd6565b60405180910390f35b34801561092557600080fd5b5061092e611c1f565b60405161093b9190613b2b565b60405180910390f35b34801561095057600080fd5b50610959611c32565b6040516109669190613d32565b60405180910390f35b34801561097b57600080fd5b50610984611c38565b6040516109919190613d32565b60405180910390f35b3480156109a657600080fd5b506109c160048036038101906109bc9190613c2e565b611c3e565b005b3480156109cf57600080fd5b506109ea60048036038101906109e59190614202565b611c50565b6040516109f79190613b2b565b60405180910390f35b610a1a6004803603810190610a159190613eac565b611ce4565b005b348015610a2857600080fd5b50610a436004803603810190610a3e9190613e1a565b611e0e565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610b1057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610b7857507f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610b885750610b8782611e91565b5b9050919050565b606060028054610b9e90614271565b80601f0160208091040260200160405190810160405280929190818152602001828054610bca90614271565b8015610c175780601f10610bec57610100808354040283529160200191610c17565b820191906000526020600020905b815481529060010190602001808311610bfa57829003601f168201915b5050505050905090565b6000610c2c82611efb565b610c62576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b81610ca781611f49565b610cb18383612046565b505050565b6000610cc061219d565b6001546000540303905090565b601460009054906101000a900460ff1681565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d1e57610d1d33611f49565b5b610d298484846121a2565b50505050565b6000610d3a83611174565b8210610d7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7290614314565b60405180910390fd5b6000610d85610cb6565b905060008060005b83811015610ef8576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614610e9a57806000015192505b8773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610eea57868403610ee1578195505050505050610f34565b83806001019450505b508080600101915050610d8d565b506040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2b906143a6565b60405180910390fd5b92915050565b60125481565b610f486121f1565b600260095403610f8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8490614412565b60405180910390fd5b600260098190555060003373ffffffffffffffffffffffffffffffffffffffff1647604051610fbb90614463565b60006040518083038185875af1925050503d8060008114610ff8576040519150601f19603f3d011682016040523d82523d6000602084013e610ffd565b606091505b5050905080611041576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611038906144c4565b60405180910390fd5b506001600981905550565b6110546121f1565b601460009054906101000a900460ff1615601460006101000a81548160ff021916908315150217905550565b6daaeb6d7670e522a718067333cd4e81565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146110d0576110cf33611f49565b5b6110db84848461226f565b50505050565b6110e96121f1565b80600a8190555050565b600d5481565b6000611103610cb6565b8210611144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113b90614556565b60405180910390fd5b819050919050565b6111546121f1565b8060128190555050565b6000611169826122ce565b600001519050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111db576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b61124b6121f1565b611255600061255d565b565b600b5481565b60156020528060005260406000206000915090505481565b61127d6121f1565b600f60009054906101000a900460ff1615600f60006101000a81548160ff021916908315150217905550565b60135481565b6112b76121f1565b6000600d549050600c54826112ca610cb6565b6112d491906145a5565b1115611315576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130c90614625565b60405180910390fd5b81811015611358576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134f90614691565b60405180910390fd5b818161136491906146b1565b600d819055506113743383612623565b5050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b3373ffffffffffffffffffffffffffffffffffffffff166113c28261115e565b73ffffffffffffffffffffffffffffffffffffffff1614611418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140f90614731565b60405180910390fd5b60135434101561145d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611454906147c3565b60405180910390fd5b61146681612641565b50565b6114716121f1565b60005b82829050811015611515576114a1838383818110611495576114946147e3565b5b90506020020135611efb565b6114e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d79061485e565b60405180910390fd5b6115028383838181106114f6576114f56147e3565b5b90506020020135612641565b808061150d9061487e565b915050611474565b505050565b60606003805461152990614271565b80601f016020809104026020016040519081016040528092919081815260200182805461155590614271565b80156115a25780601f10611577576101008083540402835291602001916115a2565b820191906000526020600020905b81548152906001019060200180831161158557829003601f168201915b5050505050905090565b6115b46121f1565b8060138190555050565b600a5481565b60006012546011541080156116195750601054601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b9050801561198757600f60009054906101000a900460ff16611670576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166790614912565b60405180910390fd5b600c548261167c610cb6565b61168691906145a5565b11156116c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116be9061497e565b60405180910390fd5b600b5482111561170c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611703906149ea565b60405180910390fd5b601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460105461175991906146b1565b821061187957600a54601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546010546117af91906146b1565b6117b99190614a0a565b600a54836117c79190614a0a565b6117d191906146b1565b341015611813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180a90614a98565b60405180910390fd5b601054601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506010546011600082825461186d91906145a5565b92505081905550611982565b601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546010546118c691906146b1565b821015611981576000341015611911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190890614a98565b60405180910390fd5b81601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461196091906145a5565b92505081905550816011600082825461197991906145a5565b925050819055505b5b611ac3565b600f60009054906101000a900460ff166119d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119cd90614912565b60405180910390fd5b600a54826119e49190614a0a565b341015611a26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a1d90614a98565b60405180910390fd5b600c5482611a32610cb6565b611a3c91906145a5565b1115611a7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a749061497e565b60405180910390fd5b600b54821115611ac2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ab9906149ea565b60405180910390fd5b5b611acd3383612623565b5050565b611ad96121f1565b80600e9081611ae89190614c5a565b5050565b81611af681611f49565b611b00838361264f565b505050565b611b0d6121f1565b80600b8190555050565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b5557611b5433611f49565b5b611b618585858561280e565b5050505050565b6000600a54905090565b60105481565b6060611b8382611efb565b611bc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bb990614d9e565b60405180910390fd5b6000611bcc6128c9565b90506000815111611bec5760405180602001604052806000815250611c17565b80611bf68461295b565b604051602001611c07929190614e46565b6040516020818303038152906040525b915050919050565b600f60009054906101000a900460ff1681565b600c5481565b60115481565b611c466121f1565b8060108190555050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60135482829050611cf59190614a0a565b341015611d37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2e906147c3565b60405180910390fd5b60005b82829050811015611e09573373ffffffffffffffffffffffffffffffffffffffff16611d7e848484818110611d7257611d716147e3565b5b9050602002013561115e565b73ffffffffffffffffffffffffffffffffffffffff1614611dd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcb90614731565b60405180910390fd5b611df6838383818110611dea57611de96147e3565b5b90506020020135612641565b8080611e019061487e565b915050611d3a565b505050565b611e166121f1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7c90614ee7565b60405180910390fd5b611e8e8161255d565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600081611f0661219d565b11158015611f15575060005482105b8015611f42575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115612043576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611fc0929190614f07565b602060405180830381865afa158015611fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120019190614f45565b61204257806040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016120399190613c9c565b60405180910390fd5b5b50565b813373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146120845761208333611f49565b5b600061208f8361115e565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036120ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f690614fe4565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661211e612a29565b73ffffffffffffffffffffffffffffffffffffffff16148061214d575061214c81612147612a29565b611c50565b5b61218c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161218390615076565b60405180910390fd5b612197848483612a31565b50505050565b600090565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146121e0576121df33611f49565b5b6121eb848484612ae3565b50505050565b6121f9612a29565b73ffffffffffffffffffffffffffffffffffffffff16612217611378565b73ffffffffffffffffffffffffffffffffffffffff161461226d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612264906150e2565b60405180910390fd5b565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146122ad576122ac33611f49565b5b6122c884848460405180602001604052806000815250611b17565b50505050565b6122d6613a34565b6000829050806122e461219d565b111580156122f3575060005481105b15612526576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161252457600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612408578092505050612558565b5b60011561252357818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461251e578092505050612558565b612409565b5b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61263d828260405180602001604052806000815250612f97565b5050565b61264c816000612fa9565b50565b813373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461268d5761268c33611f49565b5b612695612a29565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612702576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f99061514e565b60405180910390fd5b816007600061270f612a29565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff166127bc612a29565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31846040516128019190613b2b565b60405180910390a3505050565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461284c5761284b33611f49565b5b612857858585612ae3565b6128768473ffffffffffffffffffffffffffffffffffffffff16613398565b801561288b5750612889858585856133bb565b155b156128c2576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6060600e80546128d890614271565b80601f016020809104026020016040519081016040528092919081815260200182805461290490614271565b80156129515780601f1061292657610100808354040283529160200191612951565b820191906000526020600020905b81548152906001019060200180831161293457829003601f168201915b5050505050905090565b60606000600161296a8461350b565b01905060008167ffffffffffffffff81111561298957612988613efe565b5b6040519080825280601f01601f1916602001820160405280156129bb5781602001600182028036833780820191505090505b509050600082602001820190505b600115612a1e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612a1257612a1161516e565b5b049450600085036129c9575b819350505050919050565b600033905090565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6000612aee826122ce565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614612b59576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16612b7a612a29565b73ffffffffffffffffffffffffffffffffffffffff161480612ba95750612ba885612ba3612a29565b611c50565b5b80612bee5750612bb7612a29565b73ffffffffffffffffffffffffffffffffffffffff16612bd684610c21565b73ffffffffffffffffffffffffffffffffffffffff16145b905080612c27576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c8d576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c9a858585600161365e565b612ca660008487612a31565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612f25576000548214612f2457878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612f908585856001613664565b5050505050565b612fa4838383600161366a565b505050565b6000612fb4836122ce565b905060008160000151905082156130955760008173ffffffffffffffffffffffffffffffffffffffff16612fe6612a29565b73ffffffffffffffffffffffffffffffffffffffff16148061301557506130148261300f612a29565b611c50565b5b8061305a5750613023612a29565b73ffffffffffffffffffffffffffffffffffffffff1661304286610c21565b73ffffffffffffffffffffffffffffffffffffffff16145b905080613093576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6130a381600086600161365e565b6130af60008583612a31565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060018160000160108282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008781526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600181600001601c6101000a81548160ff02191690831515021790555060006001870190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361331257600054821461331157848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b5050505083600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613380816000866001613664565b60016000815480929190600101919050555050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026133e1612a29565b8786866040518563ffffffff1660e01b815260040161340394939291906151f2565b6020604051808303816000875af192505050801561343f57506040513d601f19601f8201168201806040525081019061343c9190615253565b60015b6134b8573d806000811461346f576040519150601f19603f3d011682016040523d82523d6000602084013e613474565b606091505b5060008151036134b0576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613569577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161355f5761355e61516e565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106135a6576d04ee2d6d415b85acef8100000000838161359c5761359b61516e565b5b0492506020810190505b662386f26fc1000083106135d557662386f26fc1000083816135cb576135ca61516e565b5b0492506010810190505b6305f5e10083106135fe576305f5e10083816135f4576135f361516e565b5b0492506008810190505b61271083106136235761271083816136195761361861516e565b5b0492506004810190505b60648310613646576064838161363c5761363b61516e565b5b0492506002810190505b600a8310613655576001810190505b80915050919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036136d6576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008403613710576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61371d600086838761365e565b83600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550846004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000819050600085820190508380156138e757506138e68773ffffffffffffffffffffffffffffffffffffffff16613398565b5b156139ac575b818773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461395c60008884806001019550886133bb565b613992576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082036138ed5782600054146139a757600080fd5b613a17565b5b818060010192508773ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48082036139ad575b816000819055505050613a2d6000868387613664565b5050505050565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ac081613a8b565b8114613acb57600080fd5b50565b600081359050613add81613ab7565b92915050565b600060208284031215613af957613af8613a81565b5b6000613b0784828501613ace565b91505092915050565b60008115159050919050565b613b2581613b10565b82525050565b6000602082019050613b406000830184613b1c565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613b80578082015181840152602081019050613b65565b60008484015250505050565b6000601f19601f8301169050919050565b6000613ba882613b46565b613bb28185613b51565b9350613bc2818560208601613b62565b613bcb81613b8c565b840191505092915050565b60006020820190508181036000830152613bf08184613b9d565b905092915050565b6000819050919050565b613c0b81613bf8565b8114613c1657600080fd5b50565b600081359050613c2881613c02565b92915050565b600060208284031215613c4457613c43613a81565b5b6000613c5284828501613c19565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613c8682613c5b565b9050919050565b613c9681613c7b565b82525050565b6000602082019050613cb16000830184613c8d565b92915050565b613cc081613c7b565b8114613ccb57600080fd5b50565b600081359050613cdd81613cb7565b92915050565b60008060408385031215613cfa57613cf9613a81565b5b6000613d0885828601613cce565b9250506020613d1985828601613c19565b9150509250929050565b613d2c81613bf8565b82525050565b6000602082019050613d476000830184613d23565b92915050565b600080600060608486031215613d6657613d65613a81565b5b6000613d7486828701613cce565b9350506020613d8586828701613cce565b9250506040613d9686828701613c19565b9150509250925092565b6000819050919050565b6000613dc5613dc0613dbb84613c5b565b613da0565b613c5b565b9050919050565b6000613dd782613daa565b9050919050565b6000613de982613dcc565b9050919050565b613df981613dde565b82525050565b6000602082019050613e146000830184613df0565b92915050565b600060208284031215613e3057613e2f613a81565b5b6000613e3e84828501613cce565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112613e6c57613e6b613e47565b5b8235905067ffffffffffffffff811115613e8957613e88613e4c565b5b602083019150836020820283011115613ea557613ea4613e51565b5b9250929050565b60008060208385031215613ec357613ec2613a81565b5b600083013567ffffffffffffffff811115613ee157613ee0613a86565b5b613eed85828601613e56565b92509250509250929050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613f3682613b8c565b810181811067ffffffffffffffff82111715613f5557613f54613efe565b5b80604052505050565b6000613f68613a77565b9050613f748282613f2d565b919050565b600067ffffffffffffffff821115613f9457613f93613efe565b5b613f9d82613b8c565b9050602081019050919050565b82818337600083830152505050565b6000613fcc613fc784613f79565b613f5e565b905082815260208101848484011115613fe857613fe7613ef9565b5b613ff3848285613faa565b509392505050565b600082601f8301126140105761400f613e47565b5b8135614020848260208601613fb9565b91505092915050565b60006020828403121561403f5761403e613a81565b5b600082013567ffffffffffffffff81111561405d5761405c613a86565b5b61406984828501613ffb565b91505092915050565b61407b81613b10565b811461408657600080fd5b50565b60008135905061409881614072565b92915050565b600080604083850312156140b5576140b4613a81565b5b60006140c385828601613cce565b92505060206140d485828601614089565b9150509250929050565b600067ffffffffffffffff8211156140f9576140f8613efe565b5b61410282613b8c565b9050602081019050919050565b600061412261411d846140de565b613f5e565b90508281526020810184848401111561413e5761413d613ef9565b5b614149848285613faa565b509392505050565b600082601f83011261416657614165613e47565b5b813561417684826020860161410f565b91505092915050565b6000806000806080858703121561419957614198613a81565b5b60006141a787828801613cce565b94505060206141b887828801613cce565b93505060406141c987828801613c19565b925050606085013567ffffffffffffffff8111156141ea576141e9613a86565b5b6141f687828801614151565b91505092959194509250565b6000806040838503121561421957614218613a81565b5b600061422785828601613cce565b925050602061423885828601613cce565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061428957607f821691505b60208210810361429c5761429b614242565b5b50919050565b7f455243373231413a206f776e657220696e646578206f7574206f6620626f756e60008201527f6473000000000000000000000000000000000000000000000000000000000000602082015250565b60006142fe602283613b51565b9150614309826142a2565b604082019050919050565b6000602082019050818103600083015261432d816142f1565b9050919050565b7f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060008201527f6f776e657220627920696e646578000000000000000000000000000000000000602082015250565b6000614390602e83613b51565b915061439b82614334565b604082019050919050565b600060208201905081810360008301526143bf81614383565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b60006143fc601f83613b51565b9150614407826143c6565b602082019050919050565b6000602082019050818103600083015261442b816143ef565b9050919050565b600081905092915050565b50565b600061444d600083614432565b91506144588261443d565b600082019050919050565b600061446e82614440565b9150819050919050565b7f5472616e73666572206661696c65642e00000000000000000000000000000000600082015250565b60006144ae601083613b51565b91506144b982614478565b602082019050919050565b600060208201905081810360008301526144dd816144a1565b9050919050565b7f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f7560008201527f6e64730000000000000000000000000000000000000000000000000000000000602082015250565b6000614540602383613b51565b915061454b826144e4565b604082019050919050565b6000602082019050818103600083015261456f81614533565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006145b082613bf8565b91506145bb83613bf8565b92508282019050808211156145d3576145d2614576565b5b92915050565b7f4e6f206d6f726520737570706c7920746f206265206d696e7465640000000000600082015250565b600061460f601b83613b51565b915061461a826145d9565b602082019050919050565b6000602082019050818103600083015261463e81614602565b9050919050565b7f526573657276656420537570706c79204d696e74656400000000000000000000600082015250565b600061467b601683613b51565b915061468682614645565b602082019050919050565b600060208201905081810360008301526146aa8161466e565b9050919050565b60006146bc82613bf8565b91506146c783613bf8565b92508282039050818111156146df576146de614576565b5b92915050565b7f596f7520646f206e6f74206f776e207468697320746f6b656e2e000000000000600082015250565b600061471b601a83613b51565b9150614726826146e5565b602082019050919050565b6000602082019050818103600083015261474a8161470e565b9050919050565b7f496e73756666696369656e742066656520746f20696e7363726962652074686960008201527f7320746f6b656e20746f206f7264696e616c204254432e000000000000000000602082015250565b60006147ad603783613b51565b91506147b882614751565b604082019050919050565b600060208201905081810360008301526147dc816147a0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f546f6b656e20646f6573206e6f74206578697374000000000000000000000000600082015250565b6000614848601483613b51565b915061485382614812565b602082019050919050565b600060208201905081810360008301526148778161483b565b9050919050565b600061488982613bf8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036148bb576148ba614576565b5b600182019050919050565b7f4d696e74206973206e6f74206c69766520796574000000000000000000000000600082015250565b60006148fc601483613b51565b9150614907826148c6565b602082019050919050565b6000602082019050818103600083015261492b816148ef565b9050919050565b7f4e6f206d6f726500000000000000000000000000000000000000000000000000600082015250565b6000614968600783613b51565b915061497382614932565b602082019050919050565b600060208201905081810360008301526149978161495b565b9050919050565b7f4d61782070657220545820726561636865642e00000000000000000000000000600082015250565b60006149d4601383613b51565b91506149df8261499e565b602082019050919050565b60006020820190508181036000830152614a03816149c7565b9050919050565b6000614a1582613bf8565b9150614a2083613bf8565b9250828202614a2e81613bf8565b91508282048414831517614a4557614a44614576565b5b5092915050565b7f506c656173652073656e64207468652065786163742045544820616d6f756e74600082015250565b6000614a82602083613b51565b9150614a8d82614a4c565b602082019050919050565b60006020820190508181036000830152614ab181614a75565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b1a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614add565b614b248683614add565b95508019841693508086168417925050509392505050565b6000614b57614b52614b4d84613bf8565b613da0565b613bf8565b9050919050565b6000819050919050565b614b7183614b3c565b614b85614b7d82614b5e565b848454614aea565b825550505050565b600090565b614b9a614b8d565b614ba5818484614b68565b505050565b5b81811015614bc957614bbe600082614b92565b600181019050614bab565b5050565b601f821115614c0e57614bdf81614ab8565b614be884614acd565b81016020851015614bf7578190505b614c0b614c0385614acd565b830182614baa565b50505b505050565b600082821c905092915050565b6000614c3160001984600802614c13565b1980831691505092915050565b6000614c4a8383614c20565b9150826002028217905092915050565b614c6382613b46565b67ffffffffffffffff811115614c7c57614c7b613efe565b5b614c868254614271565b614c91828285614bcd565b600060209050601f831160018114614cc45760008415614cb2578287015190505b614cbc8582614c3e565b865550614d24565b601f198416614cd286614ab8565b60005b82811015614cfa57848901518255600182019150602085019450602081019050614cd5565b86831015614d175784890151614d13601f891682614c20565b8355505b6001600288020188555050505b505050505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000614d88602f83613b51565b9150614d9382614d2c565b604082019050919050565b60006020820190508181036000830152614db781614d7b565b9050919050565b600081905092915050565b6000614dd482613b46565b614dde8185614dbe565b9350614dee818560208601613b62565b80840191505092915050565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000600082015250565b6000614e30600583614dbe565b9150614e3b82614dfa565b600582019050919050565b6000614e528285614dc9565b9150614e5e8284614dc9565b9150614e6982614e23565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614ed1602683613b51565b9150614edc82614e75565b604082019050919050565b60006020820190508181036000830152614f0081614ec4565b9050919050565b6000604082019050614f1c6000830185613c8d565b614f296020830184613c8d565b9392505050565b600081519050614f3f81614072565b92915050565b600060208284031215614f5b57614f5a613a81565b5b6000614f6984828501614f30565b91505092915050565b7f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000614fce602283613b51565b9150614fd982614f72565b604082019050919050565b60006020820190508181036000830152614ffd81614fc1565b9050919050565b7f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000602082015250565b6000615060603983613b51565b915061506b82615004565b604082019050919050565b6000602082019050818103600083015261508f81615053565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006150cc602083613b51565b91506150d782615096565b602082019050919050565b600060208201905081810360008301526150fb816150bf565b9050919050565b7f455243373231413a20617070726f766520746f2063616c6c6572000000000000600082015250565b6000615138601a83613b51565b915061514382615102565b602082019050919050565b600060208201905081810360008301526151678161512b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600081519050919050565b600082825260208201905092915050565b60006151c48261519d565b6151ce81856151a8565b93506151de818560208601613b62565b6151e781613b8c565b840191505092915050565b60006080820190506152076000830187613c8d565b6152146020830186613c8d565b6152216040830185613d23565b818103606083015261523381846151b9565b905095945050505050565b60008151905061524d81613ab7565b92915050565b60006020828403121561526957615268613a81565b5b60006152778482850161523e565b9150509291505056fea264697066735822122088a2040ffbac4cbf7c04cb5e67b8f5bed4d7e46ac6874c233249ab047377890664736f6c63430008130033

Deployed Bytecode Sourcemap

113347:5942:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83744:372;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;86926:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;88503:204;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118349:157;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;81904:303;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113858:42;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118514:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;82215:886;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113781:39;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119100:186;;;;;;;;;;;;;:::i;:::-;;116501:120;;;;;;;;;;;;;:::i;:::-;;40348:143;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118685:171;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117652:85;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;113594:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83109:187;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117932:111;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;86734:125;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;84182:206;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103473:103;;;;;;;;;;;;;:::i;:::-;;113507:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113913:46;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116306:87;;;;;;;;;;;;;:::i;:::-;;113827:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;115902:396;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102825:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116633:282;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117305:231;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;87095:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116401:88;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;113454:46;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114547:1347;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117546:98;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;118165:176;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117838:86;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;118864:228;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;117745:84;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113699:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114028:395;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113665:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113547:40;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113741:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118051:106;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;89176:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116923:374;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;103731:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;83744:372;83846:4;83898:25;83883:40;;;:11;:40;;;;:105;;;;83955:33;83940:48;;;:11;:48;;;;83883:105;:172;;;;84020:35;84005:50;;;:11;:50;;;;83883:172;:225;;;;84072:36;84096:11;84072:23;:36::i;:::-;83883:225;83863:245;;83744:372;;;:::o;86926:100::-;86980:13;87013:5;87006:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86926:100;:::o;88503:204::-;88571:7;88596:16;88604:7;88596;:16::i;:::-;88591:64;;88621:34;;;;;;;;;;;;;;88591:64;88675:15;:24;88691:7;88675:24;;;;;;;;;;;;;;;;;;;;;88668:31;;88503:204;;;:::o;118349:157::-;118445:8;41869:30;41890:8;41869:20;:30::i;:::-;118466:32:::1;118480:8;118490:7;118466:13;:32::i;:::-;118349:157:::0;;;:::o;81904:303::-;81948:7;82173:15;:13;:15::i;:::-;82158:12;;82142:13;;:28;:46;82135:53;;81904:303;:::o;113858:42::-;;;;;;;;;;;;;:::o;118514:163::-;118615:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;118632:37:::1;118651:4;118657:2;118661:7;118632:18;:37::i;:::-;118514:163:::0;;;;:::o;82215:886::-;82304:7;82340:16;82350:5;82340:9;:16::i;:::-;82332:5;:24;82324:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;82406:22;82431:13;:11;:13::i;:::-;82406:38;;82455:19;82485:25;82553:9;82548:466;82568:14;82564:1;:18;82548:466;;;82608:31;82642:11;:14;82654:1;82642:14;;;;;;;;;;;82608:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82705:1;82679:28;;:9;:14;;;:28;;;82675:111;;82752:9;:14;;;82732:34;;82675:111;82829:5;82808:26;;:17;:26;;;82804:195;;82878:5;82863:11;:20;82859:85;;82919:1;82912:8;;;;;;;;;82859:85;82966:13;;;;;;;82804:195;82589:425;82584:3;;;;;;;82548:466;;;;83037:56;;;;;;;;;;:::i;:::-;;;;;;;;82215:886;;;;;:::o;113781:39::-;;;;:::o;119100:186::-;102711:13;:11;:13::i;:::-;76983:1:::1;77133:7;;:19:::0;77125:63:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;76983:1;77201:7;:18;;;;119164:12:::2;119182:10;:15;;119205:21;119182:49;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119163:68;;;119250:7;119242:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;119152:134;76939:1:::1;77246:7;:22;;;;119100:186::o:0;116501:120::-;102711:13;:11;:13::i;:::-;116591:22:::1;;;;;;;;;;;116590:23;116565:22;;:48;;;;;;;;;;;;;;;;;;116501:120::o:0;40348:143::-;40448:42;40348:143;:::o;118685:171::-;118790:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;118807:41:::1;118830:4;118836:2;118840:7;118807:22;:41::i;:::-;118685:171:::0;;;;:::o;117652:85::-;102711:13;:11;:13::i;:::-;117723:6:::1;117715:5;:14;;;;117652:85:::0;:::o;113594:35::-;;;;:::o;83109:187::-;83176:7;83212:13;:11;:13::i;:::-;83204:5;:21;83196:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;83283:5;83276:12;;83109:187;;;:::o;117932:111::-;102711:13;:11;:13::i;:::-;118022::::1;118010:9;:25;;;;117932:111:::0;:::o;86734:125::-;86798:7;86825:21;86838:7;86825:12;:21::i;:::-;:26;;;86818:33;;86734:125;;;:::o;84182:206::-;84246:7;84287:1;84270:19;;:5;:19;;;84266:60;;84298:28;;;;;;;;;;;;;;84266:60;84352:12;:19;84365:5;84352:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;84344:36;;84337:43;;84182:206;;;:::o;103473:103::-;102711:13;:11;:13::i;:::-;103538:30:::1;103565:1;103538:18;:30::i;:::-;103473:103::o:0;113507:33::-;;;;:::o;113913:46::-;;;;;;;;;;;;;;;;;:::o;116306:87::-;102711:13;:11;:13::i;:::-;116374:11:::1;;;;;;;;;;;116373:12;116359:11;;:26;;;;;;;;;;;;;;;;;;116306:87::o:0;113827:24::-;;;;:::o;115902:396::-;102711:13;:11;:13::i;:::-;115975:17:::1;115995:14;;115975:34;;116056:9;;116046:6;116030:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:35;;116022:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;116129:6;116116:9;:19;;116108:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;116208:6;116196:9;:18;;;;:::i;:::-;116179:14;:35;;;;116225:29;116235:10;116247:6;116225:9;:29::i;:::-;115964:334;115902:396:::0;:::o;102825:87::-;102871:7;102898:6;;;;;;;;;;;102891:13;;102825:87;:::o;116633:282::-;116732:10;116711:31;;:17;116719:8;116711:7;:17::i;:::-;:31;;;116703:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;116805:9;;116792;:22;;116784:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;116887:15;116893:8;116887:5;:15::i;:::-;116633:282;:::o;117305:231::-;102711:13;:11;:13::i;:::-;117392:6:::1;117387:142;117408:8;;:15;;117404:1;:19;117387:142;;;117447:20;117455:8;;117464:1;117455:11;;;;;;;:::i;:::-;;;;;;;;117447:7;:20::i;:::-;117439:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;117501:18;117507:8;;117516:1;117507:11;;;;;;;:::i;:::-;;;;;;;;117501:5;:18::i;:::-;117425:3;;;;;:::i;:::-;;;;117387:142;;;;117305:231:::0;;:::o;87095:104::-;87151:13;87184:7;87177:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87095:104;:::o;116401:88::-;102711:13;:11;:13::i;:::-;116477:4:::1;116465:9;:16;;;;116401:88:::0;:::o;113454:46::-;;;;:::o;114547:1347::-;114614:16;114653:9;;114635:15;;:27;114634:84;;;;;114707:10;;114681:11;:23;114693:10;114681:23;;;;;;;;;;;;;;;;:36;114634:84;114614:105;;114736:11;114732:1114;;;114773:11;;;;;;;;;;;114765:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;114857:9;;114848:5;114832:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:34;;114824:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;114910:5;;114901;:14;;114893:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;114980:11;:23;114992:10;114980:23;;;;;;;;;;;;;;;;114967:10;;:36;;;;:::i;:::-;114957:5;:47;114954:580;;115116:5;;115089:11;:23;115101:10;115089:23;;;;;;;;;;;;;;;;115076:10;;:36;;;;:::i;:::-;115075:46;;;;:::i;:::-;115065:5;;115057;:13;;;;:::i;:::-;115056:66;;;;:::i;:::-;115043:9;:79;;115035:124;;;;;;;;;;;;:::i;:::-;;;;;;;;;115201:10;;115175:11;:23;115187:10;115175:23;;;;;;;;;;;;;;;:36;;;;115246:10;;115227:15;;:29;;;;;;;:::i;:::-;;;;;;;;114954:580;;;115316:11;:23;115328:10;115316:23;;;;;;;;;;;;;;;;115303:10;;:36;;;;:::i;:::-;115294:5;:46;115291:243;;;115392:1;115379:9;:14;;115371:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;115473:5;115446:11;:23;115458:10;115446:23;;;;;;;;;;;;;;;;:32;;;;;;;:::i;:::-;;;;;;;;115513:5;115494:15;;:24;;;;;;;:::i;:::-;;;;;;;;115291:243;114954:580;114732:1114;;;115582:11;;;;;;;;;;;115574:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;115662:5;;115654;:13;;;;:::i;:::-;115641:9;:26;;115633:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;115752:9;;115743:5;115727:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:34;;115719:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;115805:5;;115796;:14;;115788:46;;;;;;;;;;;;:::i;:::-;;;;;;;;;114732:1114;115858:28;115868:10;115880:5;115858:9;:28::i;:::-;114593:1301;114547:1347;:::o;117546:98::-;102711:13;:11;:13::i;:::-;117628:8:::1;117618:7;:18;;;;;;:::i;:::-;;117546:98:::0;:::o;118165:176::-;118269:8;41869:30;41890:8;41869:20;:30::i;:::-;118290:43:::1;118314:8;118324;118290:23;:43::i;:::-;118165:176:::0;;;:::o;117838:86::-;102711:13;:11;:13::i;:::-;117910:6:::1;117902:5;:14;;;;117838:86:::0;:::o;118864:228::-;119015:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;119037:47:::1;119060:4;119066:2;119070:7;119079:4;119037:22;:47::i;:::-;118864:228:::0;;;;;:::o;117745:84::-;117789:7;117816:5;;117809:12;;117745:84;:::o;113699:35::-;;;;:::o;114028:395::-;114102:13;114136:17;114144:8;114136:7;:17::i;:::-;114128:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;114215:28;114246:10;:8;:10::i;:::-;114215:41;;114305:1;114280:14;114274:28;:32;:141;;;;;;;;;;;;;;;;;114346:14;114361:26;114378:8;114361:16;:26::i;:::-;114329:67;;;;;;;;;:::i;:::-;;;;;;;;;;;;;114274:141;114267:148;;;114028:395;;;:::o;113665:25::-;;;;;;;;;;;;;:::o;113547:40::-;;;;:::o;113741:33::-;;;;:::o;118051:106::-;102711:13;:11;:13::i;:::-;118138:11:::1;118125:10;:24;;;;118051:106:::0;:::o;89176:164::-;89273:4;89297:18;:25;89316:5;89297:25;;;;;;;;;;;;;;;:35;89323:8;89297:35;;;;;;;;;;;;;;;;;;;;;;;;;89290:42;;89176:164;;;;:::o;116923:374::-;117045:9;;117027:8;;:15;;:27;;;;:::i;:::-;117013:9;:42;;117005:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;117130:6;117125:165;117146:8;;:15;;117142:1;:19;117125:165;;;117209:10;117185:34;;:20;117193:8;;117202:1;117193:11;;;;;;;:::i;:::-;;;;;;;;117185:7;:20::i;:::-;:34;;;117177:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;117261:18;117267:8;;117276:1;117267:11;;;;;;;:::i;:::-;;;;;;;;117261:5;:18::i;:::-;117163:3;;;;;:::i;:::-;;;;117125:165;;;;116923:374;;:::o;103731:201::-;102711:13;:11;:13::i;:::-;103840:1:::1;103820:22;;:8;:22;;::::0;103812:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;103896:28;103915:8;103896:18;:28::i;:::-;103731:201:::0;:::o;70370:157::-;70455:4;70494:25;70479:40;;;:11;:40;;;;70472:47;;70370:157;;;:::o;90603:174::-;90660:4;90703:7;90684:15;:13;:15::i;:::-;:26;;:53;;;;;90724:13;;90714:7;:23;90684:53;:85;;;;;90742:11;:20;90754:7;90742:20;;;;;;;;;;;:27;;;;;;;;;;;;90741:28;90684:85;90677:92;;90603:174;;;:::o;41927:419::-;42166:1;40448:42;42118:45;;;:49;42114:225;;;40448:42;42189;;;42240:4;42247:8;42189:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42184:144;;42303:8;42284:28;;;;;;;;;;;:::i;:::-;;;;;;;;42184:144;42114:225;41927:419;:::o;87992:445::-;88082:2;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;88097:13:::1;88113:24;88129:7;88113:15;:24::i;:::-;88097:40;;88162:5;88156:11;;:2;:11;;::::0;88148:58:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;88257:5;88241:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;88266:37;88283:5;88290:12;:10;:12::i;:::-;88266:16;:37::i;:::-;88241:62;88219:169;;;;;;;;;;;;:::i;:::-;;;;;;;;;88401:28;88410:2;88414:7;88423:5;88401:8;:28::i;:::-;88086:351;87992:445:::0;;;:::o;81678:92::-;81734:7;81678:92;:::o;89406:195::-;89549:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;89565:28:::1;89575:4;89581:2;89585:7;89565:9;:28::i;:::-;89406:195:::0;;;;:::o;102990:132::-;103065:12;:10;:12::i;:::-;103054:23;;:7;:5;:7::i;:::-;:23;;;103046:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;102990:132::o;89672:211::-;89819:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;89836:39:::1;89853:4;89859:2;89863:7;89836:39;;;;;;;;;;;::::0;:16:::1;:39::i;:::-;89672:211:::0;;;;:::o;85563:1109::-;85625:21;;:::i;:::-;85659:12;85674:7;85659:22;;85742:4;85723:15;:13;:15::i;:::-;:23;;:47;;;;;85757:13;;85750:4;:20;85723:47;85719:886;;;85791:31;85825:11;:17;85837:4;85825:17;;;;;;;;;;;85791:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85866:9;:16;;;85861:729;;85937:1;85911:28;;:9;:14;;;:28;;;85907:101;;85975:9;85968:16;;;;;;85907:101;86310:261;86317:4;86310:261;;;86350:6;;;;;;;;86395:11;:17;86407:4;86395:17;;;;;;;;;;;86383:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86469:1;86443:28;;:9;:14;;;:28;;;86439:109;;86511:9;86504:16;;;;;;86439:109;86310:261;;;85861:729;85772:833;85719:886;86633:31;;;;;;;;;;;;;;85563:1109;;;;:::o;104092:191::-;104166:16;104185:6;;;;;;;;;;;104166:25;;104211:8;104202:6;;:17;;;;;;;;;;;;;;;;;;104266:8;104235:40;;104256:8;104235:40;;;;;;;;;;;;104155:128;104092:191;:::o;90785:104::-;90854:27;90864:2;90868:8;90854:27;;;;;;;;;;;;:9;:27::i;:::-;90785:104;;:::o;95916:89::-;95976:21;95982:7;95991:5;95976;:21::i;:::-;95916:89;:::o;88779:326::-;88883:8;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;88924:12:::1;:10;:12::i;:::-;88912:24;;:8;:24;;::::0;88904:63:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;89025:8;88980:18;:32;88999:12;:10;:12::i;:::-;88980:32;;;;;;;;;;;;;;;:42;89013:8;88980:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;89078:8;89049:48;;89064:12;:10;:12::i;:::-;89049:48;;;89088:8;89049:48;;;;;;:::i;:::-;;;;;;;;88779:326:::0;;;:::o;89954:394::-;90130:4;41697:10;41689:18;;:4;:18;;;41685:83;;41724:32;41745:10;41724:20;:32::i;:::-;41685:83;90146:28:::1;90156:4;90162:2;90166:7;90146:9;:28::i;:::-;90189:15;:2;:13;;;:15::i;:::-;:76;;;;;90209:56;90240:4;90246:2;90250:7;90259:5;90209:30;:56::i;:::-;90208:57;90189:76;90185:156;;;90289:40;;;;;;;;;;;;;;90185:156;89954:394:::0;;;;;:::o;114431:108::-;114491:13;114524:7;114517:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114431:108;:::o;56132:716::-;56188:13;56239:14;56276:1;56256:17;56267:5;56256:10;:17::i;:::-;:21;56239:38;;56292:20;56326:6;56315:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56292:41;;56348:11;56477:6;56473:2;56469:15;56461:6;56457:28;56450:35;;56514:288;56521:4;56514:288;;;56546:5;;;;;;;;56688:8;56683:2;56676:5;56672:14;56667:30;56662:3;56654:44;56744:2;56735:11;;;;;;:::i;:::-;;;;;56778:1;56769:5;:10;56514:288;56765:21;56514:288;56823:6;56816:13;;;;;56132:716;;;:::o;77908:98::-;77961:7;77988:10;77981:17;;77908:98;:::o;98760:196::-;98902:2;98875:15;:24;98891:7;98875:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;98940:7;98936:2;98920:28;;98929:5;98920:28;;;;;;;;;;;;98760:196;;;:::o;93703:2130::-;93818:35;93856:21;93869:7;93856:12;:21::i;:::-;93818:59;;93916:4;93894:26;;:13;:18;;;:26;;;93890:67;;93929:28;;;;;;;;;;;;;;93890:67;93970:22;94012:4;93996:20;;:12;:10;:12::i;:::-;:20;;;:73;;;;94033:36;94050:4;94056:12;:10;:12::i;:::-;94033:16;:36::i;:::-;93996:73;:126;;;;94110:12;:10;:12::i;:::-;94086:36;;:20;94098:7;94086:11;:20::i;:::-;:36;;;93996:126;93970:153;;94141:17;94136:66;;94167:35;;;;;;;;;;;;;;94136:66;94231:1;94217:16;;:2;:16;;;94213:52;;94242:23;;;;;;;;;;;;;;94213:52;94278:43;94300:4;94306:2;94310:7;94319:1;94278:21;:43::i;:::-;94386:35;94403:1;94407:7;94416:4;94386:8;:35::i;:::-;94747:1;94717:12;:18;94730:4;94717:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94791:1;94763:12;:16;94776:2;94763:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94809:31;94843:11;:20;94855:7;94843:20;;;;;;;;;;;94809:54;;94894:2;94878:8;:13;;;:18;;;;;;;;;;;;;;;;;;94944:15;94911:8;:23;;;:49;;;;;;;;;;;;;;;;;;95212:19;95244:1;95234:7;:11;95212:33;;95260:31;95294:11;:24;95306:11;95294:24;;;;;;;;;;;95260:58;;95362:1;95337:27;;:8;:13;;;;;;;;;;;;:27;;;95333:384;;95547:13;;95532:11;:28;95528:174;;95601:4;95585:8;:13;;;:20;;;;;;;;;;;;;;;;;;95654:13;:28;;;95628:8;:23;;;:54;;;;;;;;;;;;;;;;;;95528:174;95333:384;94692:1036;;;95764:7;95760:2;95745:27;;95754:4;95745:27;;;;;;;;;;;;95783:42;95804:4;95810:2;95814:7;95823:1;95783:20;:42::i;:::-;93807:2026;;93703:2130;;;:::o;91252:163::-;91375:32;91381:2;91385:8;91395:5;91402:4;91375:5;:32::i;:::-;91252:163;;;:::o;96234:2408::-;96314:35;96352:21;96365:7;96352:12;:21::i;:::-;96314:59;;96386:12;96401:13;:18;;;96386:33;;96436:13;96432:290;;;96466:22;96508:4;96492:20;;:12;:10;:12::i;:::-;:20;;;:77;;;;96533:36;96550:4;96556:12;:10;:12::i;:::-;96533:16;:36::i;:::-;96492:77;:134;;;;96614:12;:10;:12::i;:::-;96590:36;;:20;96602:7;96590:11;:20::i;:::-;:36;;;96492:134;96466:161;;96649:17;96644:66;;96675:35;;;;;;;;;;;;;;96644:66;96451:271;96432:290;96734:51;96756:4;96770:1;96774:7;96783:1;96734:21;:51::i;:::-;96850:35;96867:1;96871:7;96880:4;96850:8;:35::i;:::-;97181:31;97215:12;:18;97228:4;97215:18;;;;;;;;;;;;;;;97181:52;;97271:1;97248:11;:19;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97315:1;97287:11;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97415:31;97449:11;:20;97461:7;97449:20;;;;;;;;;;;97415:54;;97500:4;97484:8;:13;;;:20;;;;;;;;;;;;;;;;;;97552:15;97519:8;:23;;;:49;;;;;;;;;;;;;;;;;;97601:4;97583:8;:15;;;:22;;;;;;;;;;;;;;;;;;97853:19;97885:1;97875:7;:11;97853:33;;97901:31;97935:11;:24;97947:11;97935:24;;;;;;;;;;;97901:58;;98003:1;97978:27;;:8;:13;;;;;;;;;;;;:27;;;97974:384;;98188:13;;98173:11;:28;98169:174;;98242:4;98226:8;:13;;;:20;;;;;;;;;;;;;;;;;;98295:13;:28;;;98269:8;:23;;;:54;;;;;;;;;;;;;;;;;;98169:174;97974:384;97156:1213;;;;98413:7;98409:1;98386:35;;98395:4;98386:35;;;;;;;;;;;;98432:50;98453:4;98467:1;98471:7;98480:1;98432:20;:50::i;:::-;98609:12;;:14;;;;;;;;;;;;;96303:2339;;96234:2408;;:::o;59259:326::-;59319:4;59576:1;59554:7;:19;;;:23;59547:30;;59259:326;;;:::o;99448:667::-;99611:4;99648:2;99632:36;;;99669:12;:10;:12::i;:::-;99683:4;99689:7;99698:5;99632:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;99628:480;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99883:1;99866:6;:13;:18;99862:235;;99912:40;;;;;;;;;;;;;;99862:235;100055:6;100049:13;100040:6;100036:2;100032:15;100025:38;99628:480;99761:45;;;99751:55;;;:6;:55;;;;99744:62;;;99448:667;;;;;;:::o;52998:922::-;53051:7;53071:14;53088:1;53071:18;;53138:6;53129:5;:15;53125:102;;53174:6;53165:15;;;;;;:::i;:::-;;;;;53209:2;53199:12;;;;53125:102;53254:6;53245:5;:15;53241:102;;53290:6;53281:15;;;;;;:::i;:::-;;;;;53325:2;53315:12;;;;53241:102;53370:6;53361:5;:15;53357:102;;53406:6;53397:15;;;;;;:::i;:::-;;;;;53441:2;53431:12;;;;53357:102;53486:5;53477;:14;53473:99;;53521:5;53512:14;;;;;;:::i;:::-;;;;;53555:1;53545:11;;;;53473:99;53599:5;53590;:14;53586:99;;53634:5;53625:14;;;;;;:::i;:::-;;;;;53668:1;53658:11;;;;53586:99;53712:5;53703;:14;53699:99;;53747:5;53738:14;;;;;;:::i;:::-;;;;;53781:1;53771:11;;;;53699:99;53825:5;53816;:14;53812:66;;53861:1;53851:11;;;;53812:66;53906:6;53899:13;;;52998:922;;;:::o;100763:159::-;;;;;:::o;101581:158::-;;;;;:::o;91674:1775::-;91813:20;91836:13;;91813:36;;91878:1;91864:16;;:2;:16;;;91860:48;;91889:19;;;;;;;;;;;;;;91860:48;91935:1;91923:8;:13;91919:44;;91945:18;;;;;;;;;;;;;;91919:44;91976:61;92006:1;92010:2;92014:12;92028:8;91976:21;:61::i;:::-;92349:8;92314:12;:16;92327:2;92314:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92413:8;92373:12;:16;92386:2;92373:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92472:2;92439:11;:25;92451:12;92439:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;92539:15;92489:11;:25;92501:12;92489:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;92572:20;92595:12;92572:35;;92622:11;92651:8;92636:12;:23;92622:37;;92680:4;:23;;;;;92688:15;:2;:13;;;:15::i;:::-;92680:23;92676:641;;;92724:314;92780:12;92776:2;92755:38;;92772:1;92755:38;;;;;;;;;;;;92821:69;92860:1;92864:2;92868:14;;;;;;92884:5;92821:30;:69::i;:::-;92816:174;;92926:40;;;;;;;;;;;;;;92816:174;93033:3;93017:12;:19;92724:314;;93119:12;93102:13;;:29;93098:43;;93133:8;;;93098:43;92676:641;;;93182:120;93238:14;;;;;;93234:2;93213:40;;93230:1;93213:40;;;;;;;;;;;;93297:3;93281:12;:19;93182:120;;92676:641;93347:12;93331:13;:28;;;;92289:1082;;93381:60;93410:1;93414:2;93418:12;93432:8;93381:20;:60::i;:::-;91802:1647;91674:1775;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:60::-;5895:3;5916:5;5909:12;;5867:60;;;:::o;5933:142::-;5983:9;6016:53;6034:34;6043:24;6061:5;6043:24;:::i;:::-;6034:34;:::i;:::-;6016:53;:::i;:::-;6003:66;;5933:142;;;:::o;6081:126::-;6131:9;6164:37;6195:5;6164:37;:::i;:::-;6151:50;;6081:126;;;:::o;6213:157::-;6294:9;6327:37;6358:5;6327:37;:::i;:::-;6314:50;;6213:157;;;:::o;6376:193::-;6494:68;6556:5;6494:68;:::i;:::-;6489:3;6482:81;6376:193;;:::o;6575:284::-;6699:4;6737:2;6726:9;6722:18;6714:26;;6750:102;6849:1;6838:9;6834:17;6825:6;6750:102;:::i;:::-;6575:284;;;;:::o;6865:329::-;6924:6;6973:2;6961:9;6952:7;6948:23;6944:32;6941:119;;;6979:79;;:::i;:::-;6941:119;7099:1;7124:53;7169:7;7160:6;7149:9;7145:22;7124:53;:::i;:::-;7114:63;;7070:117;6865:329;;;;:::o;7200:117::-;7309:1;7306;7299:12;7323:117;7432:1;7429;7422:12;7446:117;7555:1;7552;7545:12;7586:568;7659:8;7669:6;7719:3;7712:4;7704:6;7700:17;7696:27;7686:122;;7727:79;;:::i;:::-;7686:122;7840:6;7827:20;7817:30;;7870:18;7862:6;7859:30;7856:117;;;7892:79;;:::i;:::-;7856:117;8006:4;7998:6;7994:17;7982:29;;8060:3;8052:4;8044:6;8040:17;8030:8;8026:32;8023:41;8020:128;;;8067:79;;:::i;:::-;8020:128;7586:568;;;;;:::o;8160:559::-;8246:6;8254;8303:2;8291:9;8282:7;8278:23;8274:32;8271:119;;;8309:79;;:::i;:::-;8271:119;8457:1;8446:9;8442:17;8429:31;8487:18;8479:6;8476:30;8473:117;;;8509:79;;:::i;:::-;8473:117;8622:80;8694:7;8685:6;8674:9;8670:22;8622:80;:::i;:::-;8604:98;;;;8400:312;8160:559;;;;;:::o;8725:117::-;8834:1;8831;8824:12;8848:180;8896:77;8893:1;8886:88;8993:4;8990:1;8983:15;9017:4;9014:1;9007:15;9034:281;9117:27;9139:4;9117:27;:::i;:::-;9109:6;9105:40;9247:6;9235:10;9232:22;9211:18;9199:10;9196:34;9193:62;9190:88;;;9258:18;;:::i;:::-;9190:88;9298:10;9294:2;9287:22;9077:238;9034:281;;:::o;9321:129::-;9355:6;9382:20;;:::i;:::-;9372:30;;9411:33;9439:4;9431:6;9411:33;:::i;:::-;9321:129;;;:::o;9456:308::-;9518:4;9608:18;9600:6;9597:30;9594:56;;;9630:18;;:::i;:::-;9594:56;9668:29;9690:6;9668:29;:::i;:::-;9660:37;;9752:4;9746;9742:15;9734:23;;9456:308;;;:::o;9770:146::-;9867:6;9862:3;9857;9844:30;9908:1;9899:6;9894:3;9890:16;9883:27;9770:146;;;:::o;9922:425::-;10000:5;10025:66;10041:49;10083:6;10041:49;:::i;:::-;10025:66;:::i;:::-;10016:75;;10114:6;10107:5;10100:21;10152:4;10145:5;10141:16;10190:3;10181:6;10176:3;10172:16;10169:25;10166:112;;;10197:79;;:::i;:::-;10166:112;10287:54;10334:6;10329:3;10324;10287:54;:::i;:::-;10006:341;9922:425;;;;;:::o;10367:340::-;10423:5;10472:3;10465:4;10457:6;10453:17;10449:27;10439:122;;10480:79;;:::i;:::-;10439:122;10597:6;10584:20;10622:79;10697:3;10689:6;10682:4;10674:6;10670:17;10622:79;:::i;:::-;10613:88;;10429:278;10367:340;;;;:::o;10713:509::-;10782:6;10831:2;10819:9;10810:7;10806:23;10802:32;10799:119;;;10837:79;;:::i;:::-;10799:119;10985:1;10974:9;10970:17;10957:31;11015:18;11007:6;11004:30;11001:117;;;11037:79;;:::i;:::-;11001:117;11142:63;11197:7;11188:6;11177:9;11173:22;11142:63;:::i;:::-;11132:73;;10928:287;10713:509;;;;:::o;11228:116::-;11298:21;11313:5;11298:21;:::i;:::-;11291:5;11288:32;11278:60;;11334:1;11331;11324:12;11278:60;11228:116;:::o;11350:133::-;11393:5;11431:6;11418:20;11409:29;;11447:30;11471:5;11447:30;:::i;:::-;11350:133;;;;:::o;11489:468::-;11554:6;11562;11611:2;11599:9;11590:7;11586:23;11582:32;11579:119;;;11617:79;;:::i;:::-;11579:119;11737:1;11762:53;11807:7;11798:6;11787:9;11783:22;11762:53;:::i;:::-;11752:63;;11708:117;11864:2;11890:50;11932:7;11923:6;11912:9;11908:22;11890:50;:::i;:::-;11880:60;;11835:115;11489:468;;;;;:::o;11963:307::-;12024:4;12114:18;12106:6;12103:30;12100:56;;;12136:18;;:::i;:::-;12100:56;12174:29;12196:6;12174:29;:::i;:::-;12166:37;;12258:4;12252;12248:15;12240:23;;11963:307;;;:::o;12276:423::-;12353:5;12378:65;12394:48;12435:6;12394:48;:::i;:::-;12378:65;:::i;:::-;12369:74;;12466:6;12459:5;12452:21;12504:4;12497:5;12493:16;12542:3;12533:6;12528:3;12524:16;12521:25;12518:112;;;12549:79;;:::i;:::-;12518:112;12639:54;12686:6;12681:3;12676;12639:54;:::i;:::-;12359:340;12276:423;;;;;:::o;12718:338::-;12773:5;12822:3;12815:4;12807:6;12803:17;12799:27;12789:122;;12830:79;;:::i;:::-;12789:122;12947:6;12934:20;12972:78;13046:3;13038:6;13031:4;13023:6;13019:17;12972:78;:::i;:::-;12963:87;;12779:277;12718:338;;;;:::o;13062:943::-;13157:6;13165;13173;13181;13230:3;13218:9;13209:7;13205:23;13201:33;13198:120;;;13237:79;;:::i;:::-;13198:120;13357:1;13382:53;13427:7;13418:6;13407:9;13403:22;13382:53;:::i;:::-;13372:63;;13328:117;13484:2;13510:53;13555:7;13546:6;13535:9;13531:22;13510:53;:::i;:::-;13500:63;;13455:118;13612:2;13638:53;13683:7;13674:6;13663:9;13659:22;13638:53;:::i;:::-;13628:63;;13583:118;13768:2;13757:9;13753:18;13740:32;13799:18;13791:6;13788:30;13785:117;;;13821:79;;:::i;:::-;13785:117;13926:62;13980:7;13971:6;13960:9;13956:22;13926:62;:::i;:::-;13916:72;;13711:287;13062:943;;;;;;;:::o;14011:474::-;14079:6;14087;14136:2;14124:9;14115:7;14111:23;14107:32;14104:119;;;14142:79;;:::i;:::-;14104:119;14262:1;14287:53;14332:7;14323:6;14312:9;14308:22;14287:53;:::i;:::-;14277:63;;14233:117;14389:2;14415:53;14460:7;14451:6;14440:9;14436:22;14415:53;:::i;:::-;14405:63;;14360:118;14011:474;;;;;:::o;14491:180::-;14539:77;14536:1;14529:88;14636:4;14633:1;14626:15;14660:4;14657:1;14650:15;14677:320;14721:6;14758:1;14752:4;14748:12;14738:22;;14805:1;14799:4;14795:12;14826:18;14816:81;;14882:4;14874:6;14870:17;14860:27;;14816:81;14944:2;14936:6;14933:14;14913:18;14910:38;14907:84;;14963:18;;:::i;:::-;14907:84;14728:269;14677:320;;;:::o;15003:221::-;15143:34;15139:1;15131:6;15127:14;15120:58;15212:4;15207:2;15199:6;15195:15;15188:29;15003:221;:::o;15230:366::-;15372:3;15393:67;15457:2;15452:3;15393:67;:::i;:::-;15386:74;;15469:93;15558:3;15469:93;:::i;:::-;15587:2;15582:3;15578:12;15571:19;;15230:366;;;:::o;15602:419::-;15768:4;15806:2;15795:9;15791:18;15783:26;;15855:9;15849:4;15845:20;15841:1;15830:9;15826:17;15819:47;15883:131;16009:4;15883:131;:::i;:::-;15875:139;;15602:419;;;:::o;16027:233::-;16167:34;16163:1;16155:6;16151:14;16144:58;16236:16;16231:2;16223:6;16219:15;16212:41;16027:233;:::o;16266:366::-;16408:3;16429:67;16493:2;16488:3;16429:67;:::i;:::-;16422:74;;16505:93;16594:3;16505:93;:::i;:::-;16623:2;16618:3;16614:12;16607:19;;16266:366;;;:::o;16638:419::-;16804:4;16842:2;16831:9;16827:18;16819:26;;16891:9;16885:4;16881:20;16877:1;16866:9;16862:17;16855:47;16919:131;17045:4;16919:131;:::i;:::-;16911:139;;16638:419;;;:::o;17063:181::-;17203:33;17199:1;17191:6;17187:14;17180:57;17063:181;:::o;17250:366::-;17392:3;17413:67;17477:2;17472:3;17413:67;:::i;:::-;17406:74;;17489:93;17578:3;17489:93;:::i;:::-;17607:2;17602:3;17598:12;17591:19;;17250:366;;;:::o;17622:419::-;17788:4;17826:2;17815:9;17811:18;17803:26;;17875:9;17869:4;17865:20;17861:1;17850:9;17846:17;17839:47;17903:131;18029:4;17903:131;:::i;:::-;17895:139;;17622:419;;;:::o;18047:147::-;18148:11;18185:3;18170:18;;18047:147;;;;:::o;18200:114::-;;:::o;18320:398::-;18479:3;18500:83;18581:1;18576:3;18500:83;:::i;:::-;18493:90;;18592:93;18681:3;18592:93;:::i;:::-;18710:1;18705:3;18701:11;18694:18;;18320:398;;;:::o;18724:379::-;18908:3;18930:147;19073:3;18930:147;:::i;:::-;18923:154;;19094:3;19087:10;;18724:379;;;:::o;19109:166::-;19249:18;19245:1;19237:6;19233:14;19226:42;19109:166;:::o;19281:366::-;19423:3;19444:67;19508:2;19503:3;19444:67;:::i;:::-;19437:74;;19520:93;19609:3;19520:93;:::i;:::-;19638:2;19633:3;19629:12;19622:19;;19281:366;;;:::o;19653:419::-;19819:4;19857:2;19846:9;19842:18;19834:26;;19906:9;19900:4;19896:20;19892:1;19881:9;19877:17;19870:47;19934:131;20060:4;19934:131;:::i;:::-;19926:139;;19653:419;;;:::o;20078:222::-;20218:34;20214:1;20206:6;20202:14;20195:58;20287:5;20282:2;20274:6;20270:15;20263:30;20078:222;:::o;20306:366::-;20448:3;20469:67;20533:2;20528:3;20469:67;:::i;:::-;20462:74;;20545:93;20634:3;20545:93;:::i;:::-;20663:2;20658:3;20654:12;20647:19;;20306:366;;;:::o;20678:419::-;20844:4;20882:2;20871:9;20867:18;20859:26;;20931:9;20925:4;20921:20;20917:1;20906:9;20902:17;20895:47;20959:131;21085:4;20959:131;:::i;:::-;20951:139;;20678:419;;;:::o;21103:180::-;21151:77;21148:1;21141:88;21248:4;21245:1;21238:15;21272:4;21269:1;21262:15;21289:191;21329:3;21348:20;21366:1;21348:20;:::i;:::-;21343:25;;21382:20;21400:1;21382:20;:::i;:::-;21377:25;;21425:1;21422;21418:9;21411:16;;21446:3;21443:1;21440:10;21437:36;;;21453:18;;:::i;:::-;21437:36;21289:191;;;;:::o;21486:177::-;21626:29;21622:1;21614:6;21610:14;21603:53;21486:177;:::o;21669:366::-;21811:3;21832:67;21896:2;21891:3;21832:67;:::i;:::-;21825:74;;21908:93;21997:3;21908:93;:::i;:::-;22026:2;22021:3;22017:12;22010:19;;21669:366;;;:::o;22041:419::-;22207:4;22245:2;22234:9;22230:18;22222:26;;22294:9;22288:4;22284:20;22280:1;22269:9;22265:17;22258:47;22322:131;22448:4;22322:131;:::i;:::-;22314:139;;22041:419;;;:::o;22466:172::-;22606:24;22602:1;22594:6;22590:14;22583:48;22466:172;:::o;22644:366::-;22786:3;22807:67;22871:2;22866:3;22807:67;:::i;:::-;22800:74;;22883:93;22972:3;22883:93;:::i;:::-;23001:2;22996:3;22992:12;22985:19;;22644:366;;;:::o;23016:419::-;23182:4;23220:2;23209:9;23205:18;23197:26;;23269:9;23263:4;23259:20;23255:1;23244:9;23240:17;23233:47;23297:131;23423:4;23297:131;:::i;:::-;23289:139;;23016:419;;;:::o;23441:194::-;23481:4;23501:20;23519:1;23501:20;:::i;:::-;23496:25;;23535:20;23553:1;23535:20;:::i;:::-;23530:25;;23579:1;23576;23572:9;23564:17;;23603:1;23597:4;23594:11;23591:37;;;23608:18;;:::i;:::-;23591:37;23441:194;;;;:::o;23641:176::-;23781:28;23777:1;23769:6;23765:14;23758:52;23641:176;:::o;23823:366::-;23965:3;23986:67;24050:2;24045:3;23986:67;:::i;:::-;23979:74;;24062:93;24151:3;24062:93;:::i;:::-;24180:2;24175:3;24171:12;24164:19;;23823:366;;;:::o;24195:419::-;24361:4;24399:2;24388:9;24384:18;24376:26;;24448:9;24442:4;24438:20;24434:1;24423:9;24419:17;24412:47;24476:131;24602:4;24476:131;:::i;:::-;24468:139;;24195:419;;;:::o;24620:242::-;24760:34;24756:1;24748:6;24744:14;24737:58;24829:25;24824:2;24816:6;24812:15;24805:50;24620:242;:::o;24868:366::-;25010:3;25031:67;25095:2;25090:3;25031:67;:::i;:::-;25024:74;;25107:93;25196:3;25107:93;:::i;:::-;25225:2;25220:3;25216:12;25209:19;;24868:366;;;:::o;25240:419::-;25406:4;25444:2;25433:9;25429:18;25421:26;;25493:9;25487:4;25483:20;25479:1;25468:9;25464:17;25457:47;25521:131;25647:4;25521:131;:::i;:::-;25513:139;;25240:419;;;:::o;25665:180::-;25713:77;25710:1;25703:88;25810:4;25807:1;25800:15;25834:4;25831:1;25824:15;25851:170;25991:22;25987:1;25979:6;25975:14;25968:46;25851:170;:::o;26027:366::-;26169:3;26190:67;26254:2;26249:3;26190:67;:::i;:::-;26183:74;;26266:93;26355:3;26266:93;:::i;:::-;26384:2;26379:3;26375:12;26368:19;;26027:366;;;:::o;26399:419::-;26565:4;26603:2;26592:9;26588:18;26580:26;;26652:9;26646:4;26642:20;26638:1;26627:9;26623:17;26616:47;26680:131;26806:4;26680:131;:::i;:::-;26672:139;;26399:419;;;:::o;26824:233::-;26863:3;26886:24;26904:5;26886:24;:::i;:::-;26877:33;;26932:66;26925:5;26922:77;26919:103;;27002:18;;:::i;:::-;26919:103;27049:1;27042:5;27038:13;27031:20;;26824:233;;;:::o;27063:170::-;27203:22;27199:1;27191:6;27187:14;27180:46;27063:170;:::o;27239:366::-;27381:3;27402:67;27466:2;27461:3;27402:67;:::i;:::-;27395:74;;27478:93;27567:3;27478:93;:::i;:::-;27596:2;27591:3;27587:12;27580:19;;27239:366;;;:::o;27611:419::-;27777:4;27815:2;27804:9;27800:18;27792:26;;27864:9;27858:4;27854:20;27850:1;27839:9;27835:17;27828:47;27892:131;28018:4;27892:131;:::i;:::-;27884:139;;27611:419;;;:::o;28036:157::-;28176:9;28172:1;28164:6;28160:14;28153:33;28036:157;:::o;28199:365::-;28341:3;28362:66;28426:1;28421:3;28362:66;:::i;:::-;28355:73;;28437:93;28526:3;28437:93;:::i;:::-;28555:2;28550:3;28546:12;28539:19;;28199:365;;;:::o;28570:419::-;28736:4;28774:2;28763:9;28759:18;28751:26;;28823:9;28817:4;28813:20;28809:1;28798:9;28794:17;28787:47;28851:131;28977:4;28851:131;:::i;:::-;28843:139;;28570:419;;;:::o;28995:169::-;29135:21;29131:1;29123:6;29119:14;29112:45;28995:169;:::o;29170:366::-;29312:3;29333:67;29397:2;29392:3;29333:67;:::i;:::-;29326:74;;29409:93;29498:3;29409:93;:::i;:::-;29527:2;29522:3;29518:12;29511:19;;29170:366;;;:::o;29542:419::-;29708:4;29746:2;29735:9;29731:18;29723:26;;29795:9;29789:4;29785:20;29781:1;29770:9;29766:17;29759:47;29823:131;29949:4;29823:131;:::i;:::-;29815:139;;29542:419;;;:::o;29967:410::-;30007:7;30030:20;30048:1;30030:20;:::i;:::-;30025:25;;30064:20;30082:1;30064:20;:::i;:::-;30059:25;;30119:1;30116;30112:9;30141:30;30159:11;30141:30;:::i;:::-;30130:41;;30320:1;30311:7;30307:15;30304:1;30301:22;30281:1;30274:9;30254:83;30231:139;;30350:18;;:::i;:::-;30231:139;30015:362;29967:410;;;;:::o;30383:182::-;30523:34;30519:1;30511:6;30507:14;30500:58;30383:182;:::o;30571:366::-;30713:3;30734:67;30798:2;30793:3;30734:67;:::i;:::-;30727:74;;30810:93;30899:3;30810:93;:::i;:::-;30928:2;30923:3;30919:12;30912:19;;30571:366;;;:::o;30943:419::-;31109:4;31147:2;31136:9;31132:18;31124:26;;31196:9;31190:4;31186:20;31182:1;31171:9;31167:17;31160:47;31224:131;31350:4;31224:131;:::i;:::-;31216:139;;30943:419;;;:::o;31368:141::-;31417:4;31440:3;31432:11;;31463:3;31460:1;31453:14;31497:4;31494:1;31484:18;31476:26;;31368:141;;;:::o;31515:93::-;31552:6;31599:2;31594;31587:5;31583:14;31579:23;31569:33;;31515:93;;;:::o;31614:107::-;31658:8;31708:5;31702:4;31698:16;31677:37;;31614:107;;;;:::o;31727:393::-;31796:6;31846:1;31834:10;31830:18;31869:97;31899:66;31888:9;31869:97;:::i;:::-;31987:39;32017:8;32006:9;31987:39;:::i;:::-;31975:51;;32059:4;32055:9;32048:5;32044:21;32035:30;;32108:4;32098:8;32094:19;32087:5;32084:30;32074:40;;31803:317;;31727:393;;;;;:::o;32126:142::-;32176:9;32209:53;32227:34;32236:24;32254:5;32236:24;:::i;:::-;32227:34;:::i;:::-;32209:53;:::i;:::-;32196:66;;32126:142;;;:::o;32274:75::-;32317:3;32338:5;32331:12;;32274:75;;;:::o;32355:269::-;32465:39;32496:7;32465:39;:::i;:::-;32526:91;32575:41;32599:16;32575:41;:::i;:::-;32567:6;32560:4;32554:11;32526:91;:::i;:::-;32520:4;32513:105;32431:193;32355:269;;;:::o;32630:73::-;32675:3;32630:73;:::o;32709:189::-;32786:32;;:::i;:::-;32827:65;32885:6;32877;32871:4;32827:65;:::i;:::-;32762:136;32709:189;;:::o;32904:186::-;32964:120;32981:3;32974:5;32971:14;32964:120;;;33035:39;33072:1;33065:5;33035:39;:::i;:::-;33008:1;33001:5;32997:13;32988:22;;32964:120;;;32904:186;;:::o;33096:543::-;33197:2;33192:3;33189:11;33186:446;;;33231:38;33263:5;33231:38;:::i;:::-;33315:29;33333:10;33315:29;:::i;:::-;33305:8;33301:44;33498:2;33486:10;33483:18;33480:49;;;33519:8;33504:23;;33480:49;33542:80;33598:22;33616:3;33598:22;:::i;:::-;33588:8;33584:37;33571:11;33542:80;:::i;:::-;33201:431;;33186:446;33096:543;;;:::o;33645:117::-;33699:8;33749:5;33743:4;33739:16;33718:37;;33645:117;;;;:::o;33768:169::-;33812:6;33845:51;33893:1;33889:6;33881:5;33878:1;33874:13;33845:51;:::i;:::-;33841:56;33926:4;33920;33916:15;33906:25;;33819:118;33768:169;;;;:::o;33942:295::-;34018:4;34164:29;34189:3;34183:4;34164:29;:::i;:::-;34156:37;;34226:3;34223:1;34219:11;34213:4;34210:21;34202:29;;33942:295;;;;:::o;34242:1395::-;34359:37;34392:3;34359:37;:::i;:::-;34461:18;34453:6;34450:30;34447:56;;;34483:18;;:::i;:::-;34447:56;34527:38;34559:4;34553:11;34527:38;:::i;:::-;34612:67;34672:6;34664;34658:4;34612:67;:::i;:::-;34706:1;34730:4;34717:17;;34762:2;34754:6;34751:14;34779:1;34774:618;;;;35436:1;35453:6;35450:77;;;35502:9;35497:3;35493:19;35487:26;35478:35;;35450:77;35553:67;35613:6;35606:5;35553:67;:::i;:::-;35547:4;35540:81;35409:222;34744:887;;34774:618;34826:4;34822:9;34814:6;34810:22;34860:37;34892:4;34860:37;:::i;:::-;34919:1;34933:208;34947:7;34944:1;34941:14;34933:208;;;35026:9;35021:3;35017:19;35011:26;35003:6;34996:42;35077:1;35069:6;35065:14;35055:24;;35124:2;35113:9;35109:18;35096:31;;34970:4;34967:1;34963:12;34958:17;;34933:208;;;35169:6;35160:7;35157:19;35154:179;;;35227:9;35222:3;35218:19;35212:26;35270:48;35312:4;35304:6;35300:17;35289:9;35270:48;:::i;:::-;35262:6;35255:64;35177:156;35154:179;35379:1;35375;35367:6;35363:14;35359:22;35353:4;35346:36;34781:611;;;34744:887;;34334:1303;;;34242:1395;;:::o;35643:234::-;35783:34;35779:1;35771:6;35767:14;35760:58;35852:17;35847:2;35839:6;35835:15;35828:42;35643:234;:::o;35883:366::-;36025:3;36046:67;36110:2;36105:3;36046:67;:::i;:::-;36039:74;;36122:93;36211:3;36122:93;:::i;:::-;36240:2;36235:3;36231:12;36224:19;;35883:366;;;:::o;36255:419::-;36421:4;36459:2;36448:9;36444:18;36436:26;;36508:9;36502:4;36498:20;36494:1;36483:9;36479:17;36472:47;36536:131;36662:4;36536:131;:::i;:::-;36528:139;;36255:419;;;:::o;36680:148::-;36782:11;36819:3;36804:18;;36680:148;;;;:::o;36834:390::-;36940:3;36968:39;37001:5;36968:39;:::i;:::-;37023:89;37105:6;37100:3;37023:89;:::i;:::-;37016:96;;37121:65;37179:6;37174:3;37167:4;37160:5;37156:16;37121:65;:::i;:::-;37211:6;37206:3;37202:16;37195:23;;36944:280;36834:390;;;;:::o;37230:155::-;37370:7;37366:1;37358:6;37354:14;37347:31;37230:155;:::o;37391:400::-;37551:3;37572:84;37654:1;37649:3;37572:84;:::i;:::-;37565:91;;37665:93;37754:3;37665:93;:::i;:::-;37783:1;37778:3;37774:11;37767:18;;37391:400;;;:::o;37797:701::-;38078:3;38100:95;38191:3;38182:6;38100:95;:::i;:::-;38093:102;;38212:95;38303:3;38294:6;38212:95;:::i;:::-;38205:102;;38324:148;38468:3;38324:148;:::i;:::-;38317:155;;38489:3;38482:10;;37797:701;;;;;:::o;38504:225::-;38644:34;38640:1;38632:6;38628:14;38621:58;38713:8;38708:2;38700:6;38696:15;38689:33;38504:225;:::o;38735:366::-;38877:3;38898:67;38962:2;38957:3;38898:67;:::i;:::-;38891:74;;38974:93;39063:3;38974:93;:::i;:::-;39092:2;39087:3;39083:12;39076:19;;38735:366;;;:::o;39107:419::-;39273:4;39311:2;39300:9;39296:18;39288:26;;39360:9;39354:4;39350:20;39346:1;39335:9;39331:17;39324:47;39388:131;39514:4;39388:131;:::i;:::-;39380:139;;39107:419;;;:::o;39532:332::-;39653:4;39691:2;39680:9;39676:18;39668:26;;39704:71;39772:1;39761:9;39757:17;39748:6;39704:71;:::i;:::-;39785:72;39853:2;39842:9;39838:18;39829:6;39785:72;:::i;:::-;39532:332;;;;;:::o;39870:137::-;39924:5;39955:6;39949:13;39940:22;;39971:30;39995:5;39971:30;:::i;:::-;39870:137;;;;:::o;40013:345::-;40080:6;40129:2;40117:9;40108:7;40104:23;40100:32;40097:119;;;40135:79;;:::i;:::-;40097:119;40255:1;40280:61;40333:7;40324:6;40313:9;40309:22;40280:61;:::i;:::-;40270:71;;40226:125;40013:345;;;;:::o;40364:221::-;40504:34;40500:1;40492:6;40488:14;40481:58;40573:4;40568:2;40560:6;40556:15;40549:29;40364:221;:::o;40591:366::-;40733:3;40754:67;40818:2;40813:3;40754:67;:::i;:::-;40747:74;;40830:93;40919:3;40830:93;:::i;:::-;40948:2;40943:3;40939:12;40932:19;;40591:366;;;:::o;40963:419::-;41129:4;41167:2;41156:9;41152:18;41144:26;;41216:9;41210:4;41206:20;41202:1;41191:9;41187:17;41180:47;41244:131;41370:4;41244:131;:::i;:::-;41236:139;;40963:419;;;:::o;41388:244::-;41528:34;41524:1;41516:6;41512:14;41505:58;41597:27;41592:2;41584:6;41580:15;41573:52;41388:244;:::o;41638:366::-;41780:3;41801:67;41865:2;41860:3;41801:67;:::i;:::-;41794:74;;41877:93;41966:3;41877:93;:::i;:::-;41995:2;41990:3;41986:12;41979:19;;41638:366;;;:::o;42010:419::-;42176:4;42214:2;42203:9;42199:18;42191:26;;42263:9;42257:4;42253:20;42249:1;42238:9;42234:17;42227:47;42291:131;42417:4;42291:131;:::i;:::-;42283:139;;42010:419;;;:::o;42435:182::-;42575:34;42571:1;42563:6;42559:14;42552:58;42435:182;:::o;42623:366::-;42765:3;42786:67;42850:2;42845:3;42786:67;:::i;:::-;42779:74;;42862:93;42951:3;42862:93;:::i;:::-;42980:2;42975:3;42971:12;42964:19;;42623:366;;;:::o;42995:419::-;43161:4;43199:2;43188:9;43184:18;43176:26;;43248:9;43242:4;43238:20;43234:1;43223:9;43219:17;43212:47;43276:131;43402:4;43276:131;:::i;:::-;43268:139;;42995:419;;;:::o;43420:176::-;43560:28;43556:1;43548:6;43544:14;43537:52;43420:176;:::o;43602:366::-;43744:3;43765:67;43829:2;43824:3;43765:67;:::i;:::-;43758:74;;43841:93;43930:3;43841:93;:::i;:::-;43959:2;43954:3;43950:12;43943:19;;43602:366;;;:::o;43974:419::-;44140:4;44178:2;44167:9;44163:18;44155:26;;44227:9;44221:4;44217:20;44213:1;44202:9;44198:17;44191:47;44255:131;44381:4;44255:131;:::i;:::-;44247:139;;43974:419;;;:::o;44399:180::-;44447:77;44444:1;44437:88;44544:4;44541:1;44534:15;44568:4;44565:1;44558:15;44585:98;44636:6;44670:5;44664:12;44654:22;;44585:98;;;:::o;44689:168::-;44772:11;44806:6;44801:3;44794:19;44846:4;44841:3;44837:14;44822:29;;44689:168;;;;:::o;44863:373::-;44949:3;44977:38;45009:5;44977:38;:::i;:::-;45031:70;45094:6;45089:3;45031:70;:::i;:::-;45024:77;;45110:65;45168:6;45163:3;45156:4;45149:5;45145:16;45110:65;:::i;:::-;45200:29;45222:6;45200:29;:::i;:::-;45195:3;45191:39;45184:46;;44953:283;44863:373;;;;:::o;45242:640::-;45437:4;45475:3;45464:9;45460:19;45452:27;;45489:71;45557:1;45546:9;45542:17;45533:6;45489:71;:::i;:::-;45570:72;45638:2;45627:9;45623:18;45614:6;45570:72;:::i;:::-;45652;45720:2;45709:9;45705:18;45696:6;45652:72;:::i;:::-;45771:9;45765:4;45761:20;45756:2;45745:9;45741:18;45734:48;45799:76;45870:4;45861:6;45799:76;:::i;:::-;45791:84;;45242:640;;;;;;;:::o;45888:141::-;45944:5;45975:6;45969:13;45960:22;;45991:32;46017:5;45991:32;:::i;:::-;45888:141;;;;:::o;46035:349::-;46104:6;46153:2;46141:9;46132:7;46128:23;46124:32;46121:119;;;46159:79;;:::i;:::-;46121:119;46279:1;46304:63;46359:7;46350:6;46339:9;46335:22;46304:63;:::i;:::-;46294:73;;46250:127;46035:349;;;;:::o

Swarm Source

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