ETH Price: $1,853.28 (-0.75%)
 

Overview

Max Total Supply

800 LASTMEM

Holders

800

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 LASTMEM
0xed1f03f0eded78e862bb03925def4866fd1bb18d
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:
LastMemoriesHalfAnniversarySBT

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2025-02-26
*/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20 ^0.8.28 ^0.8.4;

// lib/closedsea/lib/erc721a/contracts/IERC721A.sol

// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

// lib/closedsea/src/OperatorFilterer.sol

/// @notice Optimized and flexible operator filterer to abide to OpenSea's
/// mandatory on-chain royalty enforcement in order for new collections to
/// receive royalties.
/// For more information, see:
/// See: https://github.com/ProjectOpenSea/operator-filter-registry
abstract contract OperatorFilterer {
    /// @dev The default OpenSea operator blocklist subscription.
    address internal constant _DEFAULT_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;

    /// @dev The OpenSea operator filter registry.
    address internal constant _OPERATOR_FILTER_REGISTRY = 0x000000000000AAeB6D7670E522A718067333cd4E;

    /// @dev Registers the current contract to OpenSea's operator filter,
    /// and subscribe to the default OpenSea operator blocklist.
    /// Note: Will not revert nor update existing settings for repeated registration.
    function _registerForOperatorFiltering() internal virtual {
        _registerForOperatorFiltering(_DEFAULT_SUBSCRIPTION, true);
    }

    /// @dev Registers the current contract to OpenSea's operator filter.
    /// Note: Will not revert nor update existing settings for repeated registration.
    function _registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe)
        internal
        virtual
    {
        /// @solidity memory-safe-assembly
        assembly {
            let functionSelector := 0x7d3e3dbe // `registerAndSubscribe(address,address)`.

            // Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty.
            subscriptionOrRegistrantToCopy := shr(96, shl(96, subscriptionOrRegistrantToCopy))

            for {} iszero(subscribe) {} {
                if iszero(subscriptionOrRegistrantToCopy) {
                    functionSelector := 0x4420e486 // `register(address)`.
                    break
                }
                functionSelector := 0xa0af2903 // `registerAndCopyEntries(address,address)`.
                break
            }
            // Store the function selector.
            mstore(0x00, shl(224, functionSelector))
            // Store the `address(this)`.
            mstore(0x04, address())
            // Store the `subscriptionOrRegistrantToCopy`.
            mstore(0x24, subscriptionOrRegistrantToCopy)
            // Register into the registry.
            if iszero(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x04)) {
                // If the function selector has not been overwritten,
                // it is an out-of-gas error.
                if eq(shr(224, mload(0x00)), functionSelector) {
                    // To prevent gas under-estimation.
                    revert(0, 0)
                }
            }
            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, because of Solidity's memory size limits.
            mstore(0x24, 0)
        }
    }

    /// @dev Modifier to guard a function and revert if the caller is a blocked operator.
    modifier onlyAllowedOperator(address from) virtual {
        if (from != msg.sender) {
            if (!_isPriorityOperator(msg.sender)) {
                if (_operatorFilteringEnabled()) _revertIfBlocked(msg.sender);
            }
        }
        _;
    }

    /// @dev Modifier to guard a function from approving a blocked operator..
    modifier onlyAllowedOperatorApproval(address operator) virtual {
        if (!_isPriorityOperator(operator)) {
            if (_operatorFilteringEnabled()) _revertIfBlocked(operator);
        }
        _;
    }

    /// @dev Helper function that reverts if the `operator` is blocked by the registry.
    function _revertIfBlocked(address operator) private view {
        /// @solidity memory-safe-assembly
        assembly {
            // Store the function selector of `isOperatorAllowed(address,address)`,
            // shifted left by 6 bytes, which is enough for 8tb of memory.
            // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).
            mstore(0x00, 0xc6171134001122334455)
            // Store the `address(this)`.
            mstore(0x1a, address())
            // Store the `operator`.
            mstore(0x3a, operator)

            // `isOperatorAllowed` always returns true if it does not revert.
            if iszero(staticcall(gas(), _OPERATOR_FILTER_REGISTRY, 0x16, 0x44, 0x00, 0x00)) {
                // Bubble up the revert if the staticcall reverts.
                returndatacopy(0x00, 0x00, returndatasize())
                revert(0x00, returndatasize())
            }

            // We'll skip checking if `from` is inside the blacklist.
            // Even though that can block transferring out of wrapper contracts,
            // we don't want tokens to be stuck.

            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, if less than 8tb of memory is used.
            mstore(0x3a, 0)
        }
    }

    /// @dev For deriving contracts to override, so that operator filtering
    /// can be turned on / off.
    /// Returns true by default.
    function _operatorFilteringEnabled() internal view virtual returns (bool) {
        return true;
    }

    /// @dev For deriving contracts to override, so that preferred marketplaces can
    /// skip operator filtering, helping users save gas.
    /// Returns false for all inputs by default.
    function _isPriorityOperator(address) internal view virtual returns (bool) {
        return false;
    }
}

// lib/openzeppelin-contracts/contracts/utils/Context.sol

// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// lib/openzeppelin-contracts/contracts/utils/cryptography/Hashes.sol

// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol)

/**
 * @dev Library of standard hash functions.
 *
 * _Available since v5.1._
 */
library Hashes {
    /**
     * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.
     *
     * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
     */
    function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
        return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a);
    }

    /**
     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
     */
    function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) {
        assembly ("memory-safe") {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol

// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

// lib/openzeppelin-contracts/contracts/utils/structs/BitMaps.sol

// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol)

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, provided the keys are sequential.
 * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 *
 * BitMaps pack 256 booleans across each bit of a single 256-bit slot of `uint256` type.
 * Hence booleans corresponding to 256 _sequential_ indices would only consume a single slot,
 * unlike the regular `bool` which would consume an entire slot for a single value.
 *
 * This results in gas savings in two ways:
 *
 * - Setting a zero value to non-zero only once every 256 times
 * - Accessing the same warm slot for every 256 _sequential_ indices
 */
library BitMaps {
    struct BitMap {
        mapping(uint256 bucket => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(BitMap storage bitmap, uint256 index, bool value) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }
}

// lib/closedsea/lib/erc721a/contracts/ERC721A.sol

// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _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 {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

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

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

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

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than `_currentIndex - _startTokenId()` times.
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

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

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

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

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

    /**
     * Sets the auxiliary 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 virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

    /**
     * @dev Returns the token collection name.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    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, _toString(tokenId))) : '';
    }

    /**
     * @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, it can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return '';
    }

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {
        if (_startTokenId() <= tokenId) {
            packed = _packedOwnerships[tokenId];
            // If not burned.
            if (packed & _BITMASK_BURNED == 0) {
                // If the data at the starting slot does not exist, start the scan.
                if (packed == 0) {
                    if (tokenId >= _currentIndex) revert OwnerQueryForNonexistentToken();
                    // Invariant:
                    // There will always be an initialized ownership slot
                    // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                    // before an unintialized ownership slot
                    // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                    // Hence, `tokenId` will not underflow.
                    //
                    // We can directly compare the packed value.
                    // If the address is zero, packed will be zero.
                    for (;;) {
                        unchecked {
                            packed = _packedOwnerships[--tokenId];
                        }
                        if (packed == 0) continue;
                        return packed;
                    }
                }
                // Otherwise, the data exists and is not burned. We can skip the scan.
                // This is possible because we have already achieved the target condition.
                // This saves 2143 gas on transfers of initialized tokens.
                return packed;
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     */
    function approve(address to, uint256 tokenId) public payable virtual override {
        _approve(to, tokenId, true);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId].value;
    }

    /**
     * @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) public virtual override {
        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

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

    /**
     * @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. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
            if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();

        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // 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 {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @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 memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @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 Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @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 for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

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

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

            // Use assembly to loop and emit the `Transfer` event for gas savings.
            // The duplicated `log4` removes an extra check and reduces stack juggling.
            // The assembly, together with the surrounding Solidity code, have been
            // delicately arranged to nudge the compiler into producing optimized opcodes.
            assembly {
                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
                toMasked := and(to, _BITMASK_ADDRESS)
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    startTokenId // `tokenId`.
                )

                // The `iszero(eq(,))` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
                // The compiler will optimize the `iszero` away for performance.
                for {
                    let tokenId := add(startTokenId, 1)
                } iszero(eq(tokenId, end)) {
                    tokenId := add(tokenId, 1)
                } {
                    // Emit the `Transfer` event. Similar to above.
                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
                }
            }
            if (toMasked == 0) revert MintToZeroAddress();

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();

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

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, 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.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (index < end);
                // Reentrancy protection.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, '');
    }

    // =============================================================
    //                       APPROVAL OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_approve(to, tokenId, false)`.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _approve(to, tokenId, false);
    }

    /**
     * @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:
     *
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function _approve(
        address to,
        uint256 tokenId,
        bool approvalCheck
    ) internal virtual {
        address owner = ownerOf(tokenId);

        if (approvalCheck)
            if (_msgSenderERC721A() != owner)
                if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                    revert ApprovalCallerNotOwnerNorApproved();
                }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev 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 {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        address from = address(uint160(prevOwnershipPacked));

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
                if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();
        }

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

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // 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 {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

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

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

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) revert OwnershipNotInitializedForExtraData();
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * 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 _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }
}

// lib/openzeppelin-contracts/contracts/access/Ownable.sol

// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

/**
 * @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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

// lib/openzeppelin-contracts/contracts/interfaces/IERC2981.sol

// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol)

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     *
     * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the
     * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers.
     */
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (address receiver, uint256 royaltyAmount);
}

// lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol

// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol)
// This file was procedurally generated from scripts/generate/templates/MerkleProof.js.

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the Merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates Merkle trees that are safe
 * against this attack out of the box.
 *
 * IMPORTANT: Consider memory side-effects when using custom hashing functions
 * that access memory in an unsafe way.
 *
 * NOTE: This library supports proof verification for merkle trees built using
 * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving
 * leaf inclusion in trees built using non-commutative hashing functions requires
 * additional logic that is not supported by this library.
 */
library MerkleProof {
    /**
     *@dev The multiproof provided is not valid.
     */
    error MerkleProofInvalidMultiproof();

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     *
     * This version handles proofs in memory with the default hashing function.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in memory with the default hashing function.
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     *
     * This version handles proofs in memory with a custom hashing function.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processProof(proof, leaf, hasher) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in memory with a custom hashing function.
     */
    function processProof(
        bytes32[] memory proof,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = hasher(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with the default hashing function.
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with the default hashing function.
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with a custom hashing function.
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processProofCalldata(proof, leaf, hasher) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with a custom hashing function.
     */
    function processProofCalldata(
        bytes32[] calldata proof,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = hasher(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in memory with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProof}.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in memory with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proof.length != proofFlagsLen + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](proofFlagsLen);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < proofFlagsLen; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = Hashes.commutativeKeccak256(a, b);
        }

        if (proofFlagsLen > 0) {
            if (proofPos != proof.length) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[proofFlagsLen - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in memory with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProof}.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processMultiProof(proof, proofFlags, leaves, hasher) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in memory with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proof.length != proofFlagsLen + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](proofFlagsLen);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < proofFlagsLen; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = hasher(a, b);
        }

        if (proofFlagsLen > 0) {
            if (proofPos != proof.length) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[proofFlagsLen - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in calldata with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProofCalldata}.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in calldata with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proof.length != proofFlagsLen + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](proofFlagsLen);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < proofFlagsLen; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = Hashes.commutativeKeccak256(a, b);
        }

        if (proofFlagsLen > 0) {
            if (proofPos != proof.length) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[proofFlagsLen - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in calldata with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProofCalldata}.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in calldata with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proof.length != proofFlagsLen + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](proofFlagsLen);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < proofFlagsLen; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = hasher(a, b);
        }

        if (proofFlagsLen > 0) {
            if (proofPos != proof.length) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[proofFlagsLen - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }
}

// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol

// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// lib/openzeppelin-contracts/contracts/token/common/ERC2981.sol

// OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol)

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;

    /**
     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);

    /**
     * @dev The default royalty receiver is invalid.
     */
    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);

    /**
     * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);

    /**
     * @dev The royalty receiver for `tokenId` is invalid.
     */
    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);

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

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) public view virtual returns (address receiver, uint256 amount) {
        RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];
        address royaltyReceiver = _royaltyInfo.receiver;
        uint96 royaltyFraction = _royaltyInfo.royaltyFraction;

        if (royaltyReceiver == address(0)) {
            royaltyReceiver = _defaultRoyaltyInfo.receiver;
            royaltyFraction = _defaultRoyaltyInfo.royaltyFraction;
        }

        uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator();

        return (royaltyReceiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
        }

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
        }

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// output/contracts/LastMemoriesHalfAnniversarySBT.sol

error MaxSupplyExceeded();
error PublicSaleClosed();
error TransfersLocked();
error NotAllowedByRegistry();
error RegistryNotSet();
error WrongWeiSent();
error MaxFeeExceeded();
error InputLengthsMismatch();
error InvalidMerkleProof();
error InvalidLaunchpadFee();
error InvalidLaunchpadFeeAddress();
error TransferFailed();

interface IRegistry {
    function isAllowedOperator(address operator) external view returns (bool);
}

contract LastMemoriesHalfAnniversarySBT is Ownable, OperatorFilterer, ERC2981, ERC721A {

    // Launchpad Fee
    uint256 public launchpadFee = 0;
    uint256 public launchpadCutBps = 0;
    address public launchpadFeeAddress = 0x2DCC7c4Ab800bF67380e2553BE1E6891A36F18E7;
    event LaunchpadFeeSent(address indexed feeAddress, uint256 feeAmount);

    using BitMaps for BitMaps.BitMap;
    uint256 public maxSupply = 800;
    bool public operatorFilteringEnabled = true;
    bool public initialTransferLockOn = true;
    bool public isRegistryActive;
    address public registryAddress;
    string private _baseTokenURI = "";
    string private _placeHolderTokenURI = "https://mintify-launchpad.nyc3.cdn.digitaloceanspaces.com/b3aef5aa-c42e-41e4-8fd3-8177707f2617.png";

    
    // Phase 1 variables
    uint256 public startTimePhase1 = 1740654000;
    uint256 public endTimePhase1 = 1740740400;
    uint256 public maxSupplyPhase1 = 0;
    uint256 public totalSupplyPhase1;
    uint256 public pricePhase1 = 0;
    uint256 public maxPerWalletPhase1 = 1;
    bytes32 public merkleRootPhase1 = 0x0f6350b3e7f38fd57a5695b8c95fedd0aafd93975dabb17640911e6b8c0f74a0;
    mapping(address => uint256) public walletMintsPhase1;
    
    // Phase 2 variables
    uint256 public startTimePhase2 = 1740740400;
    uint256 public endTimePhase2 = 1740754800;
    uint256 public maxSupplyPhase2 = 0;
    uint256 public totalSupplyPhase2;
    uint256 public pricePhase2 = 0;
    uint256 public maxPerWalletPhase2 = 1;
    bytes32 public merkleRootPhase2 = 0x0;
    mapping(address => uint256) public walletMintsPhase2;
    

    constructor() ERC721A("LastMemoriesHalfAnniversarySBT", "LASTMEM") Ownable(msg.sender) {

        // Register operator filtering
        _registerForOperatorFiltering();

        // Set initial royalty
        _setDefaultRoyalty(owner(), 0);
        

    }

    // Phase 1 Mint
    function mintPhase1(bytes32[] calldata merkleProof, uint256 quantity) external payable {

        // Check if mint has started
        if (startTimePhase1 != 0 && block.timestamp < startTimePhase1) {
            revert PublicSaleClosed();
        }

        // Check if mint has ended
        if (endTimePhase1 != 0 && block.timestamp > endTimePhase1) {
            revert PublicSaleClosed();
        }

        // Check if the mint will exceed total max supply, if set.
        if (maxSupply != 0 && totalSupply() + quantity > maxSupply) {
            revert MaxSupplyExceeded();
        }

        // If phase max supply is set, check if it's exceeded
        if (maxSupplyPhase1 != 0 && totalSupplyPhase1 + quantity > maxSupplyPhase1) {
            revert MaxSupplyExceeded();
        }

        // Check if the price is correct
        if (msg.value != (pricePhase1 + launchpadFee) * quantity) {
            revert WrongWeiSent();
        }
         

        // Check if the proof is set, and if it is valid
        if (merkleRootPhase1 != bytes32(0)) {
            // Using Merkle Tree
            bytes32 node = keccak256(abi.encodePacked(msg.sender));
            if (!MerkleProof.verify(merkleProof, merkleRootPhase1, node)) {
                revert InvalidMerkleProof();
            }
        }
            
        // Check if we have exceeded phase max per wallet if set.
        if (maxPerWalletPhase1 != 0 && walletMintsPhase1[msg.sender] + quantity > maxPerWalletPhase1) {
            revert MaxSupplyExceeded();
        }

        uint256 flatFees = 0;
        // Get the Launchpad Flat Fee if set
        if (launchpadFee != 0 && launchpadFeeAddress != address(0)) {
            flatFees = launchpadFee * quantity;
        }

        // Get the Launchpad Percentage Fee if set
        uint256 percentageFees = 0;
        if (launchpadCutBps != 0 && launchpadFeeAddress != address(0)) {
            percentageFees = (launchpadCutBps * (msg.value - flatFees)) / 10000;
        }

        // Send the fees
        uint256 totalFees = flatFees + percentageFees;
        if (totalFees != 0) {
            _sendLaunchpadFee(totalFees);
        }

        // Mint the tokens
        walletMintsPhase1[msg.sender] += quantity;
        totalSupplyPhase1 += quantity;
        _mint(msg.sender, quantity);

    }

    // Phase 2 Mint
    function mintPhase2(uint256 quantity) external payable {

        // Check if mint has started
        if (startTimePhase2 != 0 && block.timestamp < startTimePhase2) {
            revert PublicSaleClosed();
        }

        // Check if mint has ended
        if (endTimePhase2 != 0 && block.timestamp > endTimePhase2) {
            revert PublicSaleClosed();
        }

        // Check if the mint will exceed total max supply, if set.
        if (maxSupply != 0 && totalSupply() + quantity > maxSupply) {
            revert MaxSupplyExceeded();
        }

        // If phase max supply is set, check if it's exceeded
        if (maxSupplyPhase2 != 0 && totalSupplyPhase2 + quantity > maxSupplyPhase2) {
            revert MaxSupplyExceeded();
        }

        // Check if the price is correct
        if (msg.value != (pricePhase2 + launchpadFee) * quantity) {
            revert WrongWeiSent();
        }
         
        // Check if we have exceeded phase max per wallet if set.
        if (maxPerWalletPhase2 != 0 && walletMintsPhase2[msg.sender] + quantity > maxPerWalletPhase2) {
            revert MaxSupplyExceeded();
        }

        uint256 flatFees = 0;
        // Get the Launchpad Flat Fee if set
        if (launchpadFee != 0 && launchpadFeeAddress != address(0)) {
            flatFees = launchpadFee * quantity;
        }

        // Get the Launchpad Percentage Fee if set
        uint256 percentageFees = 0;
        if (launchpadCutBps != 0 && launchpadFeeAddress != address(0)) {
            percentageFees = (launchpadCutBps * (msg.value - flatFees)) / 10000;
        }

        // Send the fees
        uint256 totalFees = flatFees + percentageFees;
        if (totalFees != 0) {
            _sendLaunchpadFee(totalFees);
        }

        // Mint the tokens
        walletMintsPhase2[msg.sender] += quantity;
        totalSupplyPhase2 += quantity;
        _mint(msg.sender, quantity);

    }

    

    // =========================================================================
    //                           Owner Only Functions
    // =========================================================================

    // Owner airdrop
    function airDrop(address[] memory users, uint256[] memory amounts) external onlyOwner {

        // iterate over users and amounts
        if (users.length != amounts.length) {
            revert InputLengthsMismatch();
        }
        for (uint256 i; i < users.length;) {
            if (maxSupply != 0 && totalSupply() + amounts[i] > maxSupply) {
                revert MaxSupplyExceeded();
            }
            _mint(users[i], amounts[i]);
            unchecked {
                ++i;
            }
        }

    }

    // Owner unrestricted mint
    function ownerMint(address to, uint256 quantity) external onlyOwner {
        if (maxSupply != 0 && totalSupply() + quantity > maxSupply) {
            revert MaxSupplyExceeded();
        }
        _mint(to, quantity);
    }

    // Set max supply
    function setMaxSupply(uint256 newMaxSupply) external onlyOwner {
        maxSupply = newMaxSupply;
    }

    // Withdraw Balance to owner
    function withdraw() public onlyOwner {
        (bool success, ) = payable(owner()).call{value: address(this).balance}("");
        if (!success) {
            revert TransferFailed();
        }
    }

    // Withdraw Balance to Address
    function withdrawTo(address payable _to) public onlyOwner {
        (bool success, ) = payable(_to).call{value: address(this).balance}("");
        if (!success) {
            revert TransferFailed();
        }
    }

    // Send Launchpad Flat Fee
    function _sendLaunchpadFee(uint256 feeAmount) private {
        if (feeAmount == 0) {
            revert InvalidLaunchpadFee();
        }
        if (launchpadFeeAddress == address(0)) {
            revert InvalidLaunchpadFeeAddress();
        }
        (bool success, ) = payable(launchpadFeeAddress).call{value: feeAmount}("");
        if (!success) {
            revert TransferFailed();
        }
        emit LaunchpadFeeSent(launchpadFeeAddress, feeAmount);
    }

    

    // Set the start time for the phase
    function setStartTimePhase1(uint256 newStartTime) external onlyOwner {
        startTimePhase1 = newStartTime;
    }

    // Set the end time for the phase
    function setEndTimePhase1(uint256 newEndTime) external onlyOwner {
        endTimePhase1 = newEndTime;
    }

    // Set the max supply for the phase
    function setMaxSupplyPhase1(uint256 newMaxSupply) external onlyOwner {
        maxSupplyPhase1 = newMaxSupply;
    }

    // Set max per wallet for the phase
    function setMaxPerWalletPhase1(uint256 newMaxPerWallet) external onlyOwner {
        maxPerWalletPhase1 = newMaxPerWallet;
    }

    // Set the price for the phase
    function setPricePhase1(uint256 newPrice) external onlyOwner {
        pricePhase1 = newPrice;
    }

    // Set the merkle root for the phase
    function setMerkleRootPhase1(bytes32 newMerkleRoot) external onlyOwner {
        merkleRootPhase1 = newMerkleRoot;
    }// Set the start time for the phase
    function setStartTimePhase2(uint256 newStartTime) external onlyOwner {
        startTimePhase2 = newStartTime;
    }

    // Set the end time for the phase
    function setEndTimePhase2(uint256 newEndTime) external onlyOwner {
        endTimePhase2 = newEndTime;
    }

    // Set the max supply for the phase
    function setMaxSupplyPhase2(uint256 newMaxSupply) external onlyOwner {
        maxSupplyPhase2 = newMaxSupply;
    }

    // Set max per wallet for the phase
    function setMaxPerWalletPhase2(uint256 newMaxPerWallet) external onlyOwner {
        maxPerWalletPhase2 = newMaxPerWallet;
    }

    // Set the price for the phase
    function setPricePhase2(uint256 newPrice) external onlyOwner {
        pricePhase2 = newPrice;
    }

    // Set the merkle root for the phase
    function setMerkleRootPhase2(bytes32 newMerkleRoot) external onlyOwner {
        merkleRootPhase2 = newMerkleRoot;
    }

    // =========================================================================
    //                             ERC721A Misc
    // =========================================================================

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

    // =========================================================================
    //                           Operator filtering
    // =========================================================================

    function setApprovalForAll(address operator, bool approved)
        public
        override (ERC721A)
        onlyAllowedOperatorApproval(operator)
    {
        if (initialTransferLockOn) {
            revert TransfersLocked();
        }
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId)
        public
        payable
        override (ERC721A)
        onlyAllowedOperatorApproval(operator)
    {
        if (initialTransferLockOn) {
            revert TransfersLocked();
        }
        super.approve(operator, tokenId);
    }

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

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

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

    function setOperatorFilteringEnabled(bool value) public onlyOwner {
        operatorFilteringEnabled = value;
    }

    function _operatorFilteringEnabled() internal view override returns (bool) {
        return operatorFilteringEnabled;
    }

    // =========================================================================
    //                             Registry Check
    // =========================================================================
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal override {
        if (initialTransferLockOn && from != address(0) && to != address(0)) {
            revert TransfersLocked();
        }
        if (_isValidAgainstRegistry(msg.sender)) {
            super._beforeTokenTransfers(from, to, startTokenId, quantity);
        } else {
            revert NotAllowedByRegistry();
        }
    }

    function _isValidAgainstRegistry(address operator)
        internal
        view
        returns (bool)
    {
        if (isRegistryActive) {
            IRegistry registry = IRegistry(registryAddress);
            return registry.isAllowedOperator(operator);
        }
        return true;
    }

    function setIsRegistryActive(bool _isRegistryActive) external onlyOwner {
        if (registryAddress == address(0)) revert RegistryNotSet();
        isRegistryActive = _isRegistryActive;
    }

    function setRegistryAddress(address _registryAddress) external onlyOwner {
        registryAddress = _registryAddress;
    }

    // =========================================================================
    //                                  ERC165
    // =========================================================================

    function supportsInterface(bytes4 interfaceId) public view override (ERC721A, ERC2981) returns (bool) {
        // Supports the following interfaceIds:
        // - IERC165: 0x01ffc9a7
        // - IERC721: 0x80ac58cd
        // - IERC721Metadata: 0x5b5e139f
        // - IERC2981: 0x2a55205a
        return ERC721A.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId);
    }

    // =========================================================================
    //                                 ERC2891
    // =========================================================================

    function setDefaultRoyalty(address receiver, uint96 feeNumerator) public onlyOwner {
        if (feeNumerator > 1000) {
            revert MaxFeeExceeded();
        }
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    function setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) external onlyOwner {
        if (feeNumerator > 1000) {
            revert MaxFeeExceeded();
        }
        _setTokenRoyalty(tokenId, receiver, feeNumerator);
    }

    // =========================================================================
    //                                 Metadata
    // =========================================================================

    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }

    function setPlaceholderBaseURI(string calldata placeholderURI) external onlyOwner {
        _placeHolderTokenURI = placeholderURI;
    }

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

    function _placeHolderURI() internal view returns (string memory) {
        return _placeHolderTokenURI;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        string memory placeHolderURI = _placeHolderURI();
        if (bytes(baseURI).length != 0) {
            return string(abi.encodePacked(baseURI, "/", _toString(tokenId), ".json"));
        }
        if (bytes(placeHolderURI).length != 0) {
            return placeHolderURI;
        }
        return "";

    }

}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"InputLengthsMismatch","type":"error"},{"inputs":[],"name":"InvalidLaunchpadFee","type":"error"},{"inputs":[],"name":"InvalidLaunchpadFeeAddress","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"MaxFeeExceeded","type":"error"},{"inputs":[],"name":"MaxSupplyExceeded","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotAllowedByRegistry","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"PublicSaleClosed","type":"error"},{"inputs":[],"name":"RegistryNotSet","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"TransfersLocked","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"WrongWeiSent","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":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"LaunchpadFeeSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"airDrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTimePhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTimePhase2","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":"initialTransferLockOn","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":"isRegistryActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchpadCutBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchpadFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchpadFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerWalletPhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerWalletPhase2","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":"maxSupplyPhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupplyPhase2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRootPhase1","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRootPhase2","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintPhase1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintPhase2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilteringEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePhase2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","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":"payable","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":"payable","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":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newEndTime","type":"uint256"}],"name":"setEndTimePhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newEndTime","type":"uint256"}],"name":"setEndTimePhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isRegistryActive","type":"bool"}],"name":"setIsRegistryActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxPerWallet","type":"uint256"}],"name":"setMaxPerWalletPhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxPerWallet","type":"uint256"}],"name":"setMaxPerWalletPhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxSupply","type":"uint256"}],"name":"setMaxSupplyPhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxSupply","type":"uint256"}],"name":"setMaxSupplyPhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"}],"name":"setMerkleRootPhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"}],"name":"setMerkleRootPhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setOperatorFilteringEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"placeholderURI","type":"string"}],"name":"setPlaceholderBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setPricePhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setPricePhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_registryAddress","type":"address"}],"name":"setRegistryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newStartTime","type":"uint256"}],"name":"setStartTimePhase1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newStartTime","type":"uint256"}],"name":"setStartTimePhase2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimePhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTimePhase2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyPhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyPhase2","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"walletMintsPhase1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"walletMintsPhase2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]

5f600b819055600c819055600d80546001600160a01b031916732dcc7c4ab800bf67380e2553be1e6891a36f18e7179055610320600e55600f805461010161ffff1990911617905560a0604052608090815260109061005e90826103dc565b506040518060a001604052806062815260200161349b6062913960119061008590826103dc565b506367c045b06012556367c197306013555f6014555f60165560016017557f0f6350b3e7f38fd57a5695b8c95fedd0aafd93975dabb17640911e6b8c0f74a05f1b6018556367c19730601a556367c1cf70601b555f601c555f601e556001601f555f5f1b6020553480156100f7575f5ffd5b50604080518082018252601e81527f4c6173744d656d6f7269657348616c66416e6e69766572736172795342540000602080830191909152825180840190935260078352664c4153544d454d60c81b9083015290338061017157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61017a816101c3565b50600561018783826103dc565b50600661019482826103dc565b50506001600355506101a4610212565b6101be6101b85f546001600160a01b031690565b5f610233565b610496565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610231733cc6cdda760b79bafa08df41ecfa224f810dceb660016102d5565b565b6127106001600160601b03821681101561027257604051636f483d0960e01b81526001600160601b038316600482015260248101829052604401610168565b6001600160a01b03831661029b57604051635b6cc80560e11b81525f6004820152602401610168565b50604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600155565b6001600160a01b0390911690637d3e3dbe8161030257826102fb5750634420e486610302565b5063a0af29035b8060e01b5f52306004528260245260045f60445f5f6daaeb6d7670e522a718067333cd4e5af161033b57805f5160e01c0361033b575f5ffd5b505f6024525050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061036c57607f821691505b60208210810361038a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156103d757805f5260205f20601f840160051c810160208510156103b55750805b601f840160051c820191505b818110156103d4575f81556001016103c1565b50505b505050565b81516001600160401b038111156103f5576103f5610344565b610409816104038454610358565b84610390565b6020601f82116001811461043b575f83156104245750848201515b5f19600385901b1c1916600184901b1784556103d4565b5f84815260208120601f198516915b8281101561046a578785015182556020948501946001909201910161044a565b508482101561048757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b612ff8806104a35f395ff3fe60806040526004361061041b575f3560e01c806364f52a1f1161021d578063abd017ea11610122578063e079e461116100b7578063e985e9c511610087578063f2fde38b1161006d578063f2fde38b14610b92578063f3f119f114610bb1578063fb796e6c14610bc6575f5ffd5b8063e985e9c514610b25578063ed9aab5114610b6c575f5ffd5b8063e079e46114610abd578063e1136b3d14610adc578063e56e9ac014610afb578063e5e2a0f614610b10575f5ffd5b8063c3d923a6116100f2578063c3d923a614610a55578063c87b56dd14610a74578063d2762b4614610a93578063d5abeb0114610aa8575f5ffd5b8063abd017ea146109e5578063ac19701b14610a04578063b7c0b8e814610a23578063b88d4fde14610a42575f5ffd5b8063858633f2116101b257806396db3e8911610182578063aa0678ff11610168578063aa0678ff14610992578063aa60bdd0146109a7578063ab7b4993146109c6575f5ffd5b806396db3e8914610954578063a22cb46514610973575f5ffd5b8063858633f2146108f0578063871215d41461090f5780638da5cb5b1461092457806395d89b4114610940575f5ffd5b8063715018a6116101ed578063715018a61461089557806372b0d90c146108a957806379544c86146108c85780637d4b5a21146108dd575f5ffd5b806364f52a1f1461082357806365216a41146108385780636f8b44b01461085757806370a0823114610876575f5ffd5b80633ccfd60b116103235780634f115db1116102b85780635944c753116102885780635c1afecb1161026e5780635c1afecb146107da5780635d99a0cf146107ef5780636352211e14610804575f5ffd5b80635944c753146107a657806359a2f3bd146107c5575f5ffd5b80634f115db11461073e578063545b70b21461075357806355f5f0661461076857806355f804b314610787575f5ffd5b806346fff98d116102f357806346fff98d146106c2578063484b973c146106e15780634b21839e146107005780634ed69eaf1461071f575f5ffd5b80633ccfd60b1461066757806341d94c981461067b57806342842e0e14610690578063462fed14146106a3575f5ffd5b806318160ddd116103b35780633073dbfd1161038357806330db1d5b1161036957806330db1d5b146106085780633bf30394146106275780633c6d57621461063c575f5ffd5b80633073dbfd146105d657806330a08965146105e9575f5ffd5b806318160ddd1461054b57806323b872dd14610566578063251c21ec146105795780632a55205a14610598575f5ffd5b8063081812fc116103ee578063081812fc146104b8578063095ea7b3146104ef5780630d4c18281461050257806312b365101461052d575f5ffd5b806301ffc9a71461041f57806304634d8d1461045357806306fdde03146104745780630759f2d814610495575b5f5ffd5b34801561042a575f5ffd5b5061043e610439366004612798565b610bdf565b60405190151581526020015b60405180910390f35b34801561045e575f5ffd5b5061047261046d3660046127e2565b610bfe565b005b34801561047f575f5ffd5b50610488610c45565b60405161044a9190612843565b3480156104a0575f5ffd5b506104aa60145481565b60405190815260200161044a565b3480156104c3575f5ffd5b506104d76104d2366004612855565b610cd5565b6040516001600160a01b03909116815260200161044a565b6104726104fd36600461286c565b610d30565b34801561050d575f5ffd5b506104aa61051c366004612896565b60216020525f908152604090205481565b348015610538575f5ffd5b50600f5461043e90610100900460ff1681565b348015610556575f5ffd5b50600454600354035f19016104aa565b6104726105743660046128b1565b610d7d565b348015610584575f5ffd5b50610472610593366004612855565b610db3565b3480156105a3575f5ffd5b506105b76105b23660046128ef565b610dc0565b604080516001600160a01b03909316835260208301919091520161044a565b6104726105e4366004612855565b610e52565b3480156105f4575f5ffd5b50600d546104d7906001600160a01b031681565b348015610613575f5ffd5b50610472610622366004612855565b611096565b348015610632575f5ffd5b506104aa601c5481565b348015610647575f5ffd5b506104aa610656366004612896565b60196020525f908152604090205481565b348015610672575f5ffd5b506104726110a3565b348015610686575f5ffd5b506104aa60135481565b61047261069e3660046128b1565b61111f565b3480156106ae575f5ffd5b506104726106bd366004612855565b61114f565b3480156106cd575f5ffd5b506104726106dc36600461291c565b61115c565b3480156106ec575f5ffd5b506104726106fb36600461286c565b6111c9565b34801561070b575f5ffd5b5061047261071a366004612855565b611221565b34801561072a575f5ffd5b50610472610739366004612937565b61122e565b348015610749575f5ffd5b506104aa601a5481565b34801561075e575f5ffd5b506104aa60155481565b348015610773575f5ffd5b50610472610782366004612855565b611243565b348015610792575f5ffd5b506104726107a1366004612937565b611250565b3480156107b1575f5ffd5b506104726107c03660046129a5565b611265565b3480156107d0575f5ffd5b506104aa601f5481565b3480156107e5575f5ffd5b506104aa601d5481565b3480156107fa575f5ffd5b506104aa601e5481565b34801561080f575f5ffd5b506104d761081e366004612855565b6112a9565b34801561082e575f5ffd5b506104aa60185481565b348015610843575f5ffd5b50610472610852366004612ab2565b6112b3565b348015610862575f5ffd5b50610472610871366004612855565b6113aa565b348015610881575f5ffd5b506104aa610890366004612896565b6113b7565b3480156108a0575f5ffd5b5061047261141d565b3480156108b4575f5ffd5b506104726108c3366004612896565b611430565b3480156108d3575f5ffd5b506104aa601b5481565b6104726108eb366004612b77565b6114a8565b3480156108fb575f5ffd5b5061047261090a366004612855565b6117ac565b34801561091a575f5ffd5b506104aa600b5481565b34801561092f575f5ffd5b505f546001600160a01b03166104d7565b34801561094b575f5ffd5b506104886117b9565b34801561095f575f5ffd5b5061047261096e366004612855565b6117c8565b34801561097e575f5ffd5b5061047261098d366004612bec565b6117d5565b34801561099d575f5ffd5b506104aa60125481565b3480156109b2575f5ffd5b506104726109c1366004612855565b61181d565b3480156109d1575f5ffd5b506104726109e0366004612896565b61182a565b3480156109f0575f5ffd5b50600f5461043e9062010000900460ff1681565b348015610a0f575f5ffd5b50610472610a1e366004612855565b611873565b348015610a2e575f5ffd5b50610472610a3d36600461291c565b611880565b610472610a50366004612c23565b61189b565b348015610a60575f5ffd5b50610472610a6f366004612855565b6118d3565b348015610a7f575f5ffd5b50610488610a8e366004612855565b6118e0565b348015610a9e575f5ffd5b506104aa600c5481565b348015610ab3575f5ffd5b506104aa600e5481565b348015610ac8575f5ffd5b50610472610ad7366004612855565b611996565b348015610ae7575f5ffd5b50610472610af6366004612855565b6119a3565b348015610b06575f5ffd5b506104aa60175481565b348015610b1b575f5ffd5b506104aa60165481565b348015610b30575f5ffd5b5061043e610b3f366004612ce5565b6001600160a01b039182165f908152600a6020908152604080832093909416825291909152205460ff1690565b348015610b77575f5ffd5b50600f546104d790630100000090046001600160a01b031681565b348015610b9d575f5ffd5b50610472610bac366004612896565b6119b0565b348015610bbc575f5ffd5b506104aa60205481565b348015610bd1575f5ffd5b50600f5461043e9060ff1681565b5f610be982611a08565b80610bf85750610bf882611a87565b92915050565b610c06611ad4565b6103e8816bffffffffffffffffffffffff161115610c375760405163f4df6ae560e01b815260040160405180910390fd5b610c418282611b19565b5050565b606060058054610c5490612d11565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8090612d11565b8015610ccb5780601f10610ca257610100808354040283529160200191610ccb565b820191905f5260205f20905b815481529060010190602001808311610cae57829003601f168201915b5050505050905090565b5f610cdf82611bfc565b610d15576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505f908152600960205260409020546001600160a01b031690565b81600f5460ff1615610d4557610d4581611c2f565b600f54610100900460ff1615610d6e576040516336e278fd60e21b815260040160405180910390fd5b610d788383611c6e565b505050565b826001600160a01b0381163314610da257600f5460ff1615610da257610da233611c2f565b610dad848484611c7a565b50505050565b610dbb611ad4565b601255565b5f82815260026020526040812080548291906001600160a01b03811690600160a01b90046bffffffffffffffffffffffff1681610e1d5750506001546001600160a01b03811690600160a01b90046bffffffffffffffffffffffff165b5f612710610e396bffffffffffffffffffffffff841689612d5d565b610e439190612d74565b92989297509195505050505050565b601a5415801590610e645750601a5442105b15610e8257604051636ea7008360e11b815260040160405180910390fd5b601b5415801590610e945750601b5442115b15610eb257604051636ea7008360e11b815260040160405180910390fd5b600e5415801590610eda5750600e54600454600354839190035f1901610ed89190612d93565b115b15610ef857604051638a164f6360e01b815260040160405180910390fd5b601c5415801590610f175750601c5481601d54610f159190612d93565b115b15610f3557604051638a164f6360e01b815260040160405180910390fd5b80600b54601e54610f469190612d93565b610f509190612d5d565b3414610f6f5760405163193e352b60e11b815260040160405180910390fd5b601f5415801590610f9a5750601f54335f90815260216020526040902054610f98908390612d93565b115b15610fb857604051638a164f6360e01b815260040160405180910390fd5b600b545f9015801590610fd55750600d546001600160a01b031615155b15610feb5781600b54610fe89190612d5d565b90505b600c545f90158015906110085750600d546001600160a01b031615155b156110345761271061101a8334612da6565b600c546110279190612d5d565b6110319190612d74565b90505b5f61103f8284612d93565b905080156110505761105081611e7c565b335f908152602160205260408120805486929061106e908490612d93565b9250508190555083601d5f8282546110869190612d93565b90915550610dad90503385611fae565b61109e611ad4565b601e55565b6110ab611ad4565b5f80546040516001600160a01b039091169047908381818185875af1925050503d805f81146110f5576040519150601f19603f3d011682016040523d82523d5f602084013e6110fa565b606091505b505090508061111c576040516312171d8360e31b815260040160405180910390fd5b50565b826001600160a01b038116331461114457600f5460ff16156111445761114433611c2f565b610dad8484846120e6565b611157611ad4565b601f55565b611164611ad4565b600f54630100000090046001600160a01b03166111ad576040517fe048e71000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f8054911515620100000262ff000019909216919091179055565b6111d1611ad4565b600e54158015906111f95750600e54600454600354839190035f19016111f79190612d93565b115b1561121757604051638a164f6360e01b815260040160405180910390fd5b610c418282611fae565b611229611ad4565b601755565b611236611ad4565b6011610d78828483612dfd565b61124b611ad4565b601855565b611258611ad4565b6010610d78828483612dfd565b61126d611ad4565b6103e8816bffffffffffffffffffffffff16111561129e5760405163f4df6ae560e01b815260040160405180910390fd5b610d78838383612100565b5f610bf882612201565b6112bb611ad4565b80518251146112f6576040517ffc4c603600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8251811015610d7857600e54158015906113485750600e5482828151811061132257611322612eb7565b602002602001015161133c6004546003545f199190030190565b6113469190612d93565b115b1561136657604051638a164f6360e01b815260040160405180910390fd5b6113a283828151811061137b5761137b612eb7565b602002602001015183838151811061139557611395612eb7565b6020026020010151611fae565b6001016112f8565b6113b2611ad4565b600e55565b5f6001600160a01b0382166113f8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b03165f9081526008602052604090205467ffffffffffffffff1690565b611425611ad4565b61142e5f612288565b565b611438611ad4565b5f816001600160a01b0316476040515f6040518083038185875af1925050503d805f8114611481576040519150601f19603f3d011682016040523d82523d5f602084013e611486565b606091505b5050905080610c41576040516312171d8360e31b815260040160405180910390fd5b601254158015906114ba575060125442105b156114d857604051636ea7008360e11b815260040160405180910390fd5b601354158015906114ea575060135442115b1561150857604051636ea7008360e11b815260040160405180910390fd5b600e54158015906115305750600e54600454600354839190035f190161152e9190612d93565b115b1561154e57604051638a164f6360e01b815260040160405180910390fd5b6014541580159061156d57506014548160155461156b9190612d93565b115b1561158b57604051638a164f6360e01b815260040160405180910390fd5b80600b5460165461159c9190612d93565b6115a69190612d5d565b34146115c55760405163193e352b60e11b815260040160405180910390fd5b6018541561167d576040516bffffffffffffffffffffffff193360601b1660208201525f906034016040516020818303038152906040528051906020012090506116458484808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505060185491508490506122e4565b61167b576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b601754158015906116a85750601754335f908152601960205260409020546116a6908390612d93565b115b156116c657604051638a164f6360e01b815260040160405180910390fd5b600b545f90158015906116e35750600d546001600160a01b031615155b156116f95781600b546116f69190612d5d565b90505b600c545f90158015906117165750600d546001600160a01b031615155b15611742576127106117288334612da6565b600c546117359190612d5d565b61173f9190612d74565b90505b5f61174d8284612d93565b9050801561175e5761175e81611e7c565b335f908152601960205260408120805486929061177c908490612d93565b925050819055508360155f8282546117949190612d93565b909155506117a490503385611fae565b505050505050565b6117b4611ad4565b601455565b606060068054610c5490612d11565b6117d0611ad4565b602055565b81600f5460ff16156117ea576117ea81611c2f565b600f54610100900460ff1615611813576040516336e278fd60e21b815260040160405180910390fd5b610d7883836122f9565b611825611ad4565b601a55565b611832611ad4565b600f80546001600160a01b039092166301000000027fffffffffffffffffff0000000000000000000000000000000000000000ffffff909216919091179055565b61187b611ad4565b601355565b611888611ad4565b600f805460ff1916911515919091179055565b836001600160a01b03811633146118c057600f5460ff16156118c0576118c033611c2f565b6118cc85858585612364565b5050505050565b6118db611ad4565b601c55565b60606118eb82611bfc565b611921576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61192a6123a8565b90505f6119356123b7565b905081515f146119725781611949856123c6565b60405160200161195a929190612ee2565b60405160208183030381529060405292505050919050565b805115611980579392505050565b505060408051602081019091525f815292915050565b61199e611ad4565b601b55565b6119ab611ad4565b601655565b6119b8611ad4565b6001600160a01b0381166119ff576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61111c81612288565b5f6301ffc9a760e01b6001600160e01b031983161480611a5157507f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bf85750506001600160e01b0319167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b5f6001600160e01b031982167f2a55205a000000000000000000000000000000000000000000000000000000001480610bf857506301ffc9a760e01b6001600160e01b0319831614610bf8565b5f546001600160a01b0316331461142e576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016119f6565b6127106bffffffffffffffffffffffff8216811015611b7b576040517f6f483d090000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff83166004820152602481018290526044016119f6565b6001600160a01b038316611bbd576040517fb6d9900a0000000000000000000000000000000000000000000000000000000081525f60048201526024016119f6565b50604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600155565b5f81600111158015611c0f575060035482105b8015610bf85750505f90815260076020526040902054600160e01b161590565b69c61711340011223344555f5230601a5280603a525f5f604460166daaeb6d7670e522a718067333cd4e5afa611c67573d5f5f3e3d5ffd5b5f603a5250565b610c4182826001612409565b5f611c8482612201565b9050836001600160a01b0316816001600160a01b031614611cd1576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8281526009602052604090208054338082146001600160a01b03881690911417611d52576001600160a01b0386165f908152600a6020908152604080832033845290915290205460ff16611d52576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038516611d92576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d9f86868660016124f0565b8015611da9575f82555b6001600160a01b038681165f9081526008602052604080822080545f19019055918716808252919020805460010190554260a01b17600160e11b175f85815260076020526040812091909155600160e11b84169003611e3657600184015f818152600760205260408120549003611e34576003548114611e34575f8181526007602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46117a4565b805f03611eb5576040517f5e2a89dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d546001600160a01b0316611ef7576040517fcd0081c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d546040515f916001600160a01b03169083908381818185875af1925050503d805f8114611f41576040519150601f19603f3d011682016040523d82523d5f602084013e611f46565b606091505b5050905080611f68576040516312171d8360e31b815260040160405180910390fd5b600d546040518381526001600160a01b03909116907f2b5dffd9914ddb43acdb6963bacf053a87bf9354300844f6339f17741e25145a9060200160405180910390a25050565b6003545f829003611feb576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ff75f8483856124f0565b6001600160a01b0383165f8181526008602090815260408083208054680100000000000000018802019055848352600790915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b8181146120a35780835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa460010161206d565b50815f036120dd576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035550505050565b610d7883838360405180602001604052805f81525061189b565b6127106bffffffffffffffffffffffff8216811015612169576040517fdfd1fc1b000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff83166024820152604481018290526064016119f6565b6001600160a01b0383166121b2576040517f969f0852000000000000000000000000000000000000000000000000000000008152600481018590525f60248201526044016119f6565b506040805180820182526001600160a01b0393841681526bffffffffffffffffffffffff92831660208083019182525f968752600290529190942093519051909116600160a01b029116179055565b5f8160011161226f57505f8181526007602052604081205490600160e01b8216900361226f57805f0361226a57600354821061225057604051636f96cda160e11b815260040160405180910390fd5b5b505f19015f818152600760205260409020548015612251575b919050565b604051636f96cda160e11b815260040160405180910390fd5b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f826122f08584612580565b14949350505050565b335f818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61236f848484610d7d565b6001600160a01b0383163b15610dad5761238b848484846125c2565b610dad576040516368d2bf6b60e11b815260040160405180910390fd5b606060108054610c5490612d11565b606060118054610c5490612d11565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806123df5750819003601f19909101908152919050565b5f612413836112a9565b9050811561248757336001600160a01b03821614612487576001600160a01b0381165f908152600a6020908152604080832033845290915290205460ff16612487576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260096020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388811691821790925591518693918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b600f54610100900460ff16801561250f57506001600160a01b03841615155b801561252357506001600160a01b03831615155b15612541576040516336e278fd60e21b815260040160405180910390fd5b61254a336126a9565b610dad576040517f4c80d8be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81815b84518110156125ba576125b0828683815181106125a3576125a3612eb7565b602002602001015161275a565b9150600101612584565b509392505050565b604051630a85bd0160e11b81525f906001600160a01b0385169063150b7a02906125f6903390899088908890600401612f4c565b6020604051808303815f875af1925050508015612630575060408051601f3d908101601f1916820190925261262d91810190612f8c565b60015b61268c573d80801561265d576040519150601f19603f3d011682016040523d82523d5f602084013e612662565b606091505b5080515f03612684576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b600f545f9062010000900460ff161561275257600f546040517fe18bc08a0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152630100000090920490911690819063e18bc08a90602401602060405180830381865afa158015612727573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061274b9190612fa7565b9392505050565b506001919050565b5f818310612774575f82815260208490526040902061274b565b505f9182526020526040902090565b6001600160e01b03198116811461111c575f5ffd5b5f602082840312156127a8575f5ffd5b813561274b81612783565b6001600160a01b038116811461111c575f5ffd5b80356bffffffffffffffffffffffff8116811461226a575f5ffd5b5f5f604083850312156127f3575f5ffd5b82356127fe816127b3565b915061280c602084016127c7565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61274b6020830184612815565b5f60208284031215612865575f5ffd5b5035919050565b5f5f6040838503121561287d575f5ffd5b8235612888816127b3565b946020939093013593505050565b5f602082840312156128a6575f5ffd5b813561274b816127b3565b5f5f5f606084860312156128c3575f5ffd5b83356128ce816127b3565b925060208401356128de816127b3565b929592945050506040919091013590565b5f5f60408385031215612900575f5ffd5b50508035926020909101359150565b801515811461111c575f5ffd5b5f6020828403121561292c575f5ffd5b813561274b8161290f565b5f5f60208385031215612948575f5ffd5b823567ffffffffffffffff81111561295e575f5ffd5b8301601f8101851361296e575f5ffd5b803567ffffffffffffffff811115612984575f5ffd5b856020828401011115612995575f5ffd5b6020919091019590945092505050565b5f5f5f606084860312156129b7575f5ffd5b8335925060208401356129c9816127b3565b91506129d7604085016127c7565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a1d57612a1d6129e0565b604052919050565b5f67ffffffffffffffff821115612a3e57612a3e6129e0565b5060051b60200190565b5f82601f830112612a57575f5ffd5b8135612a6a612a6582612a25565b6129f4565b8082825260208201915060208360051b860101925085831115612a8b575f5ffd5b602085015b83811015612aa8578035835260209283019201612a90565b5095945050505050565b5f5f60408385031215612ac3575f5ffd5b823567ffffffffffffffff811115612ad9575f5ffd5b8301601f81018513612ae9575f5ffd5b8035612af7612a6582612a25565b8082825260208201915060208360051b850101925087831115612b18575f5ffd5b6020840193505b82841015612b43578335612b32816127b3565b825260209384019390910190612b1f565b9450505050602083013567ffffffffffffffff811115612b61575f5ffd5b612b6d85828601612a48565b9150509250929050565b5f5f5f60408486031215612b89575f5ffd5b833567ffffffffffffffff811115612b9f575f5ffd5b8401601f81018613612baf575f5ffd5b803567ffffffffffffffff811115612bc5575f5ffd5b8660208260051b8401011115612bd9575f5ffd5b6020918201979096509401359392505050565b5f5f60408385031215612bfd575f5ffd5b8235612c08816127b3565b91506020830135612c188161290f565b809150509250929050565b5f5f5f5f60808587031215612c36575f5ffd5b8435612c41816127b3565b93506020850135612c51816127b3565b925060408501359150606085013567ffffffffffffffff811115612c73575f5ffd5b8501601f81018713612c83575f5ffd5b803567ffffffffffffffff811115612c9d57612c9d6129e0565b612cb0601f8201601f19166020016129f4565b818152886020838501011115612cc4575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f60408385031215612cf6575f5ffd5b8235612d01816127b3565b91506020830135612c18816127b3565b600181811c90821680612d2557607f821691505b602082108103612d4357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610bf857610bf8612d49565b5f82612d8e57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610bf857610bf8612d49565b81810381811115610bf857610bf8612d49565b601f821115610d7857805f5260205f20601f840160051c81016020851015612dde5750805b601f840160051c820191505b818110156118cc575f8155600101612dea565b67ffffffffffffffff831115612e1557612e156129e0565b612e2983612e238354612d11565b83612db9565b5f601f841160018114612e5a575f8515612e435750838201355b5f19600387901b1c1916600186901b1783556118cc565b5f83815260208120601f198716915b82811015612e895786850135825560209485019460019092019101612e69565b5086821015612ea5575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f612eed8285612ecb565b7f2f000000000000000000000000000000000000000000000000000000000000008152612f1d6001820185612ecb565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000815260050195945050505050565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f612f826080830184612815565b9695505050505050565b5f60208284031215612f9c575f5ffd5b815161274b81612783565b5f60208284031215612fb7575f5ffd5b815161274b8161290f56fea26469706673582212206ad5e2c728c8a04cc1b2a5641b2dc9870a9ca6e7ff944cc2173e560df334e04664736f6c634300081c003368747470733a2f2f6d696e746966792d6c61756e63687061642e6e7963332e63646e2e6469676974616c6f6365616e7370616365732e636f6d2f62336165663561612d633432652d343165342d386664332d3831373737303766323631372e706e67

Deployed Bytecode

0x60806040526004361061041b575f3560e01c806364f52a1f1161021d578063abd017ea11610122578063e079e461116100b7578063e985e9c511610087578063f2fde38b1161006d578063f2fde38b14610b92578063f3f119f114610bb1578063fb796e6c14610bc6575f5ffd5b8063e985e9c514610b25578063ed9aab5114610b6c575f5ffd5b8063e079e46114610abd578063e1136b3d14610adc578063e56e9ac014610afb578063e5e2a0f614610b10575f5ffd5b8063c3d923a6116100f2578063c3d923a614610a55578063c87b56dd14610a74578063d2762b4614610a93578063d5abeb0114610aa8575f5ffd5b8063abd017ea146109e5578063ac19701b14610a04578063b7c0b8e814610a23578063b88d4fde14610a42575f5ffd5b8063858633f2116101b257806396db3e8911610182578063aa0678ff11610168578063aa0678ff14610992578063aa60bdd0146109a7578063ab7b4993146109c6575f5ffd5b806396db3e8914610954578063a22cb46514610973575f5ffd5b8063858633f2146108f0578063871215d41461090f5780638da5cb5b1461092457806395d89b4114610940575f5ffd5b8063715018a6116101ed578063715018a61461089557806372b0d90c146108a957806379544c86146108c85780637d4b5a21146108dd575f5ffd5b806364f52a1f1461082357806365216a41146108385780636f8b44b01461085757806370a0823114610876575f5ffd5b80633ccfd60b116103235780634f115db1116102b85780635944c753116102885780635c1afecb1161026e5780635c1afecb146107da5780635d99a0cf146107ef5780636352211e14610804575f5ffd5b80635944c753146107a657806359a2f3bd146107c5575f5ffd5b80634f115db11461073e578063545b70b21461075357806355f5f0661461076857806355f804b314610787575f5ffd5b806346fff98d116102f357806346fff98d146106c2578063484b973c146106e15780634b21839e146107005780634ed69eaf1461071f575f5ffd5b80633ccfd60b1461066757806341d94c981461067b57806342842e0e14610690578063462fed14146106a3575f5ffd5b806318160ddd116103b35780633073dbfd1161038357806330db1d5b1161036957806330db1d5b146106085780633bf30394146106275780633c6d57621461063c575f5ffd5b80633073dbfd146105d657806330a08965146105e9575f5ffd5b806318160ddd1461054b57806323b872dd14610566578063251c21ec146105795780632a55205a14610598575f5ffd5b8063081812fc116103ee578063081812fc146104b8578063095ea7b3146104ef5780630d4c18281461050257806312b365101461052d575f5ffd5b806301ffc9a71461041f57806304634d8d1461045357806306fdde03146104745780630759f2d814610495575b5f5ffd5b34801561042a575f5ffd5b5061043e610439366004612798565b610bdf565b60405190151581526020015b60405180910390f35b34801561045e575f5ffd5b5061047261046d3660046127e2565b610bfe565b005b34801561047f575f5ffd5b50610488610c45565b60405161044a9190612843565b3480156104a0575f5ffd5b506104aa60145481565b60405190815260200161044a565b3480156104c3575f5ffd5b506104d76104d2366004612855565b610cd5565b6040516001600160a01b03909116815260200161044a565b6104726104fd36600461286c565b610d30565b34801561050d575f5ffd5b506104aa61051c366004612896565b60216020525f908152604090205481565b348015610538575f5ffd5b50600f5461043e90610100900460ff1681565b348015610556575f5ffd5b50600454600354035f19016104aa565b6104726105743660046128b1565b610d7d565b348015610584575f5ffd5b50610472610593366004612855565b610db3565b3480156105a3575f5ffd5b506105b76105b23660046128ef565b610dc0565b604080516001600160a01b03909316835260208301919091520161044a565b6104726105e4366004612855565b610e52565b3480156105f4575f5ffd5b50600d546104d7906001600160a01b031681565b348015610613575f5ffd5b50610472610622366004612855565b611096565b348015610632575f5ffd5b506104aa601c5481565b348015610647575f5ffd5b506104aa610656366004612896565b60196020525f908152604090205481565b348015610672575f5ffd5b506104726110a3565b348015610686575f5ffd5b506104aa60135481565b61047261069e3660046128b1565b61111f565b3480156106ae575f5ffd5b506104726106bd366004612855565b61114f565b3480156106cd575f5ffd5b506104726106dc36600461291c565b61115c565b3480156106ec575f5ffd5b506104726106fb36600461286c565b6111c9565b34801561070b575f5ffd5b5061047261071a366004612855565b611221565b34801561072a575f5ffd5b50610472610739366004612937565b61122e565b348015610749575f5ffd5b506104aa601a5481565b34801561075e575f5ffd5b506104aa60155481565b348015610773575f5ffd5b50610472610782366004612855565b611243565b348015610792575f5ffd5b506104726107a1366004612937565b611250565b3480156107b1575f5ffd5b506104726107c03660046129a5565b611265565b3480156107d0575f5ffd5b506104aa601f5481565b3480156107e5575f5ffd5b506104aa601d5481565b3480156107fa575f5ffd5b506104aa601e5481565b34801561080f575f5ffd5b506104d761081e366004612855565b6112a9565b34801561082e575f5ffd5b506104aa60185481565b348015610843575f5ffd5b50610472610852366004612ab2565b6112b3565b348015610862575f5ffd5b50610472610871366004612855565b6113aa565b348015610881575f5ffd5b506104aa610890366004612896565b6113b7565b3480156108a0575f5ffd5b5061047261141d565b3480156108b4575f5ffd5b506104726108c3366004612896565b611430565b3480156108d3575f5ffd5b506104aa601b5481565b6104726108eb366004612b77565b6114a8565b3480156108fb575f5ffd5b5061047261090a366004612855565b6117ac565b34801561091a575f5ffd5b506104aa600b5481565b34801561092f575f5ffd5b505f546001600160a01b03166104d7565b34801561094b575f5ffd5b506104886117b9565b34801561095f575f5ffd5b5061047261096e366004612855565b6117c8565b34801561097e575f5ffd5b5061047261098d366004612bec565b6117d5565b34801561099d575f5ffd5b506104aa60125481565b3480156109b2575f5ffd5b506104726109c1366004612855565b61181d565b3480156109d1575f5ffd5b506104726109e0366004612896565b61182a565b3480156109f0575f5ffd5b50600f5461043e9062010000900460ff1681565b348015610a0f575f5ffd5b50610472610a1e366004612855565b611873565b348015610a2e575f5ffd5b50610472610a3d36600461291c565b611880565b610472610a50366004612c23565b61189b565b348015610a60575f5ffd5b50610472610a6f366004612855565b6118d3565b348015610a7f575f5ffd5b50610488610a8e366004612855565b6118e0565b348015610a9e575f5ffd5b506104aa600c5481565b348015610ab3575f5ffd5b506104aa600e5481565b348015610ac8575f5ffd5b50610472610ad7366004612855565b611996565b348015610ae7575f5ffd5b50610472610af6366004612855565b6119a3565b348015610b06575f5ffd5b506104aa60175481565b348015610b1b575f5ffd5b506104aa60165481565b348015610b30575f5ffd5b5061043e610b3f366004612ce5565b6001600160a01b039182165f908152600a6020908152604080832093909416825291909152205460ff1690565b348015610b77575f5ffd5b50600f546104d790630100000090046001600160a01b031681565b348015610b9d575f5ffd5b50610472610bac366004612896565b6119b0565b348015610bbc575f5ffd5b506104aa60205481565b348015610bd1575f5ffd5b50600f5461043e9060ff1681565b5f610be982611a08565b80610bf85750610bf882611a87565b92915050565b610c06611ad4565b6103e8816bffffffffffffffffffffffff161115610c375760405163f4df6ae560e01b815260040160405180910390fd5b610c418282611b19565b5050565b606060058054610c5490612d11565b80601f0160208091040260200160405190810160405280929190818152602001828054610c8090612d11565b8015610ccb5780601f10610ca257610100808354040283529160200191610ccb565b820191905f5260205f20905b815481529060010190602001808311610cae57829003601f168201915b5050505050905090565b5f610cdf82611bfc565b610d15576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505f908152600960205260409020546001600160a01b031690565b81600f5460ff1615610d4557610d4581611c2f565b600f54610100900460ff1615610d6e576040516336e278fd60e21b815260040160405180910390fd5b610d788383611c6e565b505050565b826001600160a01b0381163314610da257600f5460ff1615610da257610da233611c2f565b610dad848484611c7a565b50505050565b610dbb611ad4565b601255565b5f82815260026020526040812080548291906001600160a01b03811690600160a01b90046bffffffffffffffffffffffff1681610e1d5750506001546001600160a01b03811690600160a01b90046bffffffffffffffffffffffff165b5f612710610e396bffffffffffffffffffffffff841689612d5d565b610e439190612d74565b92989297509195505050505050565b601a5415801590610e645750601a5442105b15610e8257604051636ea7008360e11b815260040160405180910390fd5b601b5415801590610e945750601b5442115b15610eb257604051636ea7008360e11b815260040160405180910390fd5b600e5415801590610eda5750600e54600454600354839190035f1901610ed89190612d93565b115b15610ef857604051638a164f6360e01b815260040160405180910390fd5b601c5415801590610f175750601c5481601d54610f159190612d93565b115b15610f3557604051638a164f6360e01b815260040160405180910390fd5b80600b54601e54610f469190612d93565b610f509190612d5d565b3414610f6f5760405163193e352b60e11b815260040160405180910390fd5b601f5415801590610f9a5750601f54335f90815260216020526040902054610f98908390612d93565b115b15610fb857604051638a164f6360e01b815260040160405180910390fd5b600b545f9015801590610fd55750600d546001600160a01b031615155b15610feb5781600b54610fe89190612d5d565b90505b600c545f90158015906110085750600d546001600160a01b031615155b156110345761271061101a8334612da6565b600c546110279190612d5d565b6110319190612d74565b90505b5f61103f8284612d93565b905080156110505761105081611e7c565b335f908152602160205260408120805486929061106e908490612d93565b9250508190555083601d5f8282546110869190612d93565b90915550610dad90503385611fae565b61109e611ad4565b601e55565b6110ab611ad4565b5f80546040516001600160a01b039091169047908381818185875af1925050503d805f81146110f5576040519150601f19603f3d011682016040523d82523d5f602084013e6110fa565b606091505b505090508061111c576040516312171d8360e31b815260040160405180910390fd5b50565b826001600160a01b038116331461114457600f5460ff16156111445761114433611c2f565b610dad8484846120e6565b611157611ad4565b601f55565b611164611ad4565b600f54630100000090046001600160a01b03166111ad576040517fe048e71000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f8054911515620100000262ff000019909216919091179055565b6111d1611ad4565b600e54158015906111f95750600e54600454600354839190035f19016111f79190612d93565b115b1561121757604051638a164f6360e01b815260040160405180910390fd5b610c418282611fae565b611229611ad4565b601755565b611236611ad4565b6011610d78828483612dfd565b61124b611ad4565b601855565b611258611ad4565b6010610d78828483612dfd565b61126d611ad4565b6103e8816bffffffffffffffffffffffff16111561129e5760405163f4df6ae560e01b815260040160405180910390fd5b610d78838383612100565b5f610bf882612201565b6112bb611ad4565b80518251146112f6576040517ffc4c603600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8251811015610d7857600e54158015906113485750600e5482828151811061132257611322612eb7565b602002602001015161133c6004546003545f199190030190565b6113469190612d93565b115b1561136657604051638a164f6360e01b815260040160405180910390fd5b6113a283828151811061137b5761137b612eb7565b602002602001015183838151811061139557611395612eb7565b6020026020010151611fae565b6001016112f8565b6113b2611ad4565b600e55565b5f6001600160a01b0382166113f8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b03165f9081526008602052604090205467ffffffffffffffff1690565b611425611ad4565b61142e5f612288565b565b611438611ad4565b5f816001600160a01b0316476040515f6040518083038185875af1925050503d805f8114611481576040519150601f19603f3d011682016040523d82523d5f602084013e611486565b606091505b5050905080610c41576040516312171d8360e31b815260040160405180910390fd5b601254158015906114ba575060125442105b156114d857604051636ea7008360e11b815260040160405180910390fd5b601354158015906114ea575060135442115b1561150857604051636ea7008360e11b815260040160405180910390fd5b600e54158015906115305750600e54600454600354839190035f190161152e9190612d93565b115b1561154e57604051638a164f6360e01b815260040160405180910390fd5b6014541580159061156d57506014548160155461156b9190612d93565b115b1561158b57604051638a164f6360e01b815260040160405180910390fd5b80600b5460165461159c9190612d93565b6115a69190612d5d565b34146115c55760405163193e352b60e11b815260040160405180910390fd5b6018541561167d576040516bffffffffffffffffffffffff193360601b1660208201525f906034016040516020818303038152906040528051906020012090506116458484808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505060185491508490506122e4565b61167b576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b601754158015906116a85750601754335f908152601960205260409020546116a6908390612d93565b115b156116c657604051638a164f6360e01b815260040160405180910390fd5b600b545f90158015906116e35750600d546001600160a01b031615155b156116f95781600b546116f69190612d5d565b90505b600c545f90158015906117165750600d546001600160a01b031615155b15611742576127106117288334612da6565b600c546117359190612d5d565b61173f9190612d74565b90505b5f61174d8284612d93565b9050801561175e5761175e81611e7c565b335f908152601960205260408120805486929061177c908490612d93565b925050819055508360155f8282546117949190612d93565b909155506117a490503385611fae565b505050505050565b6117b4611ad4565b601455565b606060068054610c5490612d11565b6117d0611ad4565b602055565b81600f5460ff16156117ea576117ea81611c2f565b600f54610100900460ff1615611813576040516336e278fd60e21b815260040160405180910390fd5b610d7883836122f9565b611825611ad4565b601a55565b611832611ad4565b600f80546001600160a01b039092166301000000027fffffffffffffffffff0000000000000000000000000000000000000000ffffff909216919091179055565b61187b611ad4565b601355565b611888611ad4565b600f805460ff1916911515919091179055565b836001600160a01b03811633146118c057600f5460ff16156118c0576118c033611c2f565b6118cc85858585612364565b5050505050565b6118db611ad4565b601c55565b60606118eb82611bfc565b611921576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61192a6123a8565b90505f6119356123b7565b905081515f146119725781611949856123c6565b60405160200161195a929190612ee2565b60405160208183030381529060405292505050919050565b805115611980579392505050565b505060408051602081019091525f815292915050565b61199e611ad4565b601b55565b6119ab611ad4565b601655565b6119b8611ad4565b6001600160a01b0381166119ff576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61111c81612288565b5f6301ffc9a760e01b6001600160e01b031983161480611a5157507f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bf85750506001600160e01b0319167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b5f6001600160e01b031982167f2a55205a000000000000000000000000000000000000000000000000000000001480610bf857506301ffc9a760e01b6001600160e01b0319831614610bf8565b5f546001600160a01b0316331461142e576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016119f6565b6127106bffffffffffffffffffffffff8216811015611b7b576040517f6f483d090000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff83166004820152602481018290526044016119f6565b6001600160a01b038316611bbd576040517fb6d9900a0000000000000000000000000000000000000000000000000000000081525f60048201526024016119f6565b50604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600155565b5f81600111158015611c0f575060035482105b8015610bf85750505f90815260076020526040902054600160e01b161590565b69c61711340011223344555f5230601a5280603a525f5f604460166daaeb6d7670e522a718067333cd4e5afa611c67573d5f5f3e3d5ffd5b5f603a5250565b610c4182826001612409565b5f611c8482612201565b9050836001600160a01b0316816001600160a01b031614611cd1576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8281526009602052604090208054338082146001600160a01b03881690911417611d52576001600160a01b0386165f908152600a6020908152604080832033845290915290205460ff16611d52576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038516611d92576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d9f86868660016124f0565b8015611da9575f82555b6001600160a01b038681165f9081526008602052604080822080545f19019055918716808252919020805460010190554260a01b17600160e11b175f85815260076020526040812091909155600160e11b84169003611e3657600184015f818152600760205260408120549003611e34576003548114611e34575f8181526007602052604090208490555b505b83856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46117a4565b805f03611eb5576040517f5e2a89dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d546001600160a01b0316611ef7576040517fcd0081c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600d546040515f916001600160a01b03169083908381818185875af1925050503d805f8114611f41576040519150601f19603f3d011682016040523d82523d5f602084013e611f46565b606091505b5050905080611f68576040516312171d8360e31b815260040160405180910390fd5b600d546040518381526001600160a01b03909116907f2b5dffd9914ddb43acdb6963bacf053a87bf9354300844f6339f17741e25145a9060200160405180910390a25050565b6003545f829003611feb576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ff75f8483856124f0565b6001600160a01b0383165f8181526008602090815260408083208054680100000000000000018802019055848352600790915281206001851460e11b4260a01b178317905582840190839083907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4600183015b8181146120a35780835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa460010161206d565b50815f036120dd576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035550505050565b610d7883838360405180602001604052805f81525061189b565b6127106bffffffffffffffffffffffff8216811015612169576040517fdfd1fc1b000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff83166024820152604481018290526064016119f6565b6001600160a01b0383166121b2576040517f969f0852000000000000000000000000000000000000000000000000000000008152600481018590525f60248201526044016119f6565b506040805180820182526001600160a01b0393841681526bffffffffffffffffffffffff92831660208083019182525f968752600290529190942093519051909116600160a01b029116179055565b5f8160011161226f57505f8181526007602052604081205490600160e01b8216900361226f57805f0361226a57600354821061225057604051636f96cda160e11b815260040160405180910390fd5b5b505f19015f818152600760205260409020548015612251575b919050565b604051636f96cda160e11b815260040160405180910390fd5b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f826122f08584612580565b14949350505050565b335f818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61236f848484610d7d565b6001600160a01b0383163b15610dad5761238b848484846125c2565b610dad576040516368d2bf6b60e11b815260040160405180910390fd5b606060108054610c5490612d11565b606060118054610c5490612d11565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806123df5750819003601f19909101908152919050565b5f612413836112a9565b9050811561248757336001600160a01b03821614612487576001600160a01b0381165f908152600a6020908152604080832033845290915290205460ff16612487576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83815260096020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388811691821790925591518693918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b600f54610100900460ff16801561250f57506001600160a01b03841615155b801561252357506001600160a01b03831615155b15612541576040516336e278fd60e21b815260040160405180910390fd5b61254a336126a9565b610dad576040517f4c80d8be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81815b84518110156125ba576125b0828683815181106125a3576125a3612eb7565b602002602001015161275a565b9150600101612584565b509392505050565b604051630a85bd0160e11b81525f906001600160a01b0385169063150b7a02906125f6903390899088908890600401612f4c565b6020604051808303815f875af1925050508015612630575060408051601f3d908101601f1916820190925261262d91810190612f8c565b60015b61268c573d80801561265d576040519150601f19603f3d011682016040523d82523d5f602084013e612662565b606091505b5080515f03612684576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b600f545f9062010000900460ff161561275257600f546040517fe18bc08a0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152630100000090920490911690819063e18bc08a90602401602060405180830381865afa158015612727573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061274b9190612fa7565b9392505050565b506001919050565b5f818310612774575f82815260208490526040902061274b565b505f9182526020526040902090565b6001600160e01b03198116811461111c575f5ffd5b5f602082840312156127a8575f5ffd5b813561274b81612783565b6001600160a01b038116811461111c575f5ffd5b80356bffffffffffffffffffffffff8116811461226a575f5ffd5b5f5f604083850312156127f3575f5ffd5b82356127fe816127b3565b915061280c602084016127c7565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61274b6020830184612815565b5f60208284031215612865575f5ffd5b5035919050565b5f5f6040838503121561287d575f5ffd5b8235612888816127b3565b946020939093013593505050565b5f602082840312156128a6575f5ffd5b813561274b816127b3565b5f5f5f606084860312156128c3575f5ffd5b83356128ce816127b3565b925060208401356128de816127b3565b929592945050506040919091013590565b5f5f60408385031215612900575f5ffd5b50508035926020909101359150565b801515811461111c575f5ffd5b5f6020828403121561292c575f5ffd5b813561274b8161290f565b5f5f60208385031215612948575f5ffd5b823567ffffffffffffffff81111561295e575f5ffd5b8301601f8101851361296e575f5ffd5b803567ffffffffffffffff811115612984575f5ffd5b856020828401011115612995575f5ffd5b6020919091019590945092505050565b5f5f5f606084860312156129b7575f5ffd5b8335925060208401356129c9816127b3565b91506129d7604085016127c7565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a1d57612a1d6129e0565b604052919050565b5f67ffffffffffffffff821115612a3e57612a3e6129e0565b5060051b60200190565b5f82601f830112612a57575f5ffd5b8135612a6a612a6582612a25565b6129f4565b8082825260208201915060208360051b860101925085831115612a8b575f5ffd5b602085015b83811015612aa8578035835260209283019201612a90565b5095945050505050565b5f5f60408385031215612ac3575f5ffd5b823567ffffffffffffffff811115612ad9575f5ffd5b8301601f81018513612ae9575f5ffd5b8035612af7612a6582612a25565b8082825260208201915060208360051b850101925087831115612b18575f5ffd5b6020840193505b82841015612b43578335612b32816127b3565b825260209384019390910190612b1f565b9450505050602083013567ffffffffffffffff811115612b61575f5ffd5b612b6d85828601612a48565b9150509250929050565b5f5f5f60408486031215612b89575f5ffd5b833567ffffffffffffffff811115612b9f575f5ffd5b8401601f81018613612baf575f5ffd5b803567ffffffffffffffff811115612bc5575f5ffd5b8660208260051b8401011115612bd9575f5ffd5b6020918201979096509401359392505050565b5f5f60408385031215612bfd575f5ffd5b8235612c08816127b3565b91506020830135612c188161290f565b809150509250929050565b5f5f5f5f60808587031215612c36575f5ffd5b8435612c41816127b3565b93506020850135612c51816127b3565b925060408501359150606085013567ffffffffffffffff811115612c73575f5ffd5b8501601f81018713612c83575f5ffd5b803567ffffffffffffffff811115612c9d57612c9d6129e0565b612cb0601f8201601f19166020016129f4565b818152886020838501011115612cc4575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f60408385031215612cf6575f5ffd5b8235612d01816127b3565b91506020830135612c18816127b3565b600181811c90821680612d2557607f821691505b602082108103612d4357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610bf857610bf8612d49565b5f82612d8e57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610bf857610bf8612d49565b81810381811115610bf857610bf8612d49565b601f821115610d7857805f5260205f20601f840160051c81016020851015612dde5750805b601f840160051c820191505b818110156118cc575f8155600101612dea565b67ffffffffffffffff831115612e1557612e156129e0565b612e2983612e238354612d11565b83612db9565b5f601f841160018114612e5a575f8515612e435750838201355b5f19600387901b1c1916600186901b1783556118cc565b5f83815260208120601f198716915b82811015612e895786850135825560209485019460019092019101612e69565b5086821015612ea5575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f612eed8285612ecb565b7f2f000000000000000000000000000000000000000000000000000000000000008152612f1d6001820185612ecb565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000815260050195945050505050565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f612f826080830184612815565b9695505050505050565b5f60208284031215612f9c575f5ffd5b815161274b81612783565b5f60208284031215612fb7575f5ffd5b815161274b8161290f56fea26469706673582212206ad5e2c728c8a04cc1b2a5641b2dc9870a9ca6e7ff944cc2173e560df334e04664736f6c634300081c0033

Deployed Bytecode Sourcemap

99361:16700:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113656:402;;;;;;;;;;-1:-1:-1;113656:402:0;;;;;:::i;:::-;;:::i;:::-;;;611:14:1;;604:22;586:41;;574:2;559:18;113656:402:0;;;;;;;;114280:229;;;;;;;;;;-1:-1:-1;114280:229:0;;;;;:::i;:::-;;:::i;:::-;;30145:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;100284:34::-;;;;;;;;;;;;;;;;;;;1992:25:1;;;1980:2;1965:18;100284:34:0;1846:177:1;36545:218:0;;;;;;;;;;-1:-1:-1;36545:218:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2423:55:1;;;2405:74;;2393:2;2378:18;36545:218:0;2259:226:1;110769:304:0;;;;;;:::i;:::-;;:::i;100946:52::-;;;;;;;;;;-1:-1:-1;100946:52:0;;;;;:::i;:::-;;;;;;;;;;;;;;99848:40;;;;;;;;;;-1:-1:-1;99848:40:0;;;;;;;;;;;25896:323;;;;;;;;;;-1:-1:-1;26170:12:0;;26154:13;;:28;-1:-1:-1;;26154:46:0;25896:323;;111081:222;;;;;;:::i;:::-;;:::i;107993:118::-;;;;;;;;;;-1:-1:-1;107993:118:0;;;;;:::i;:::-;;:::i;95778:673::-;;;;;;;;;;-1:-1:-1;95778:673:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4170:55:1;;;4152:74;;4257:2;4242:18;;4235:34;;;;4125:18;95778:673:0;3978:297:1;103720:1978:0;;;;;;:::i;:::-;;:::i;99558:79::-;;;;;;;;;;-1:-1:-1;99558:79:0;;;;-1:-1:-1;;;;;99558:79:0;;;109638:102;;;;;;;;;;-1:-1:-1;109638:102:0;;;;;:::i;:::-;;:::i;100741:34::-;;;;;;;;;;;;;;;;100552:52;;;;;;;;;;-1:-1:-1;100552:52:0;;;;;:::i;:::-;;;;;;;;;;;;;;106946:204;;;;;;;;;;;;;:::i;100236:41::-;;;;;;;;;;;;;;;;111311:230;;;;;;:::i;:::-;;:::i;109464:130::-;;;;;;;;;;-1:-1:-1;109464:130:0;;;;;:::i;:::-;;:::i;113104:196::-;;;;;;;;;;-1:-1:-1;113104:196:0;;;;;:::i;:::-;;:::i;106538:229::-;;;;;;;;;;-1:-1:-1;106538:229:0;;;;;:::i;:::-;;:::i;108484:130::-;;;;;;;;;;-1:-1:-1;108484:130:0;;;;;:::i;:::-;;:::i;115141:138::-;;;;;;;;;;-1:-1:-1;115141:138:0;;;;;:::i;:::-;;:::i;100643:43::-;;;;;;;;;;;;;;;;100325:32;;;;;;;;;;;;;;;;108810:122;;;;;;;;;;-1:-1:-1;108810:122:0;;;;;:::i;:::-;;:::i;115027:106::-;;;;;;;;;;-1:-1:-1;115027:106:0;;;;;:::i;:::-;;:::i;114517:287::-;;;;;;;;;;-1:-1:-1;114517:287:0;;;;;:::i;:::-;;:::i;100858:37::-;;;;;;;;;;;;;;;;100782:32;;;;;;;;;;;;;;;;100821:30;;;;;;;;;;;;;;;;31538:152;;;;;;;;;;-1:-1:-1;31538:152:0;;;;;:::i;:::-;;:::i;100445:100::-;;;;;;;;;;;;;;;;105957:541;;;;;;;;;;-1:-1:-1;105957:541:0;;;;;:::i;:::-;;:::i;106798:106::-;;;;;;;;;;-1:-1:-1;106798:106:0;;;;;:::i;:::-;;:::i;27080:233::-;;;;;;;;;;-1:-1:-1;27080:233:0;;;;;:::i;:::-;;:::i;65801:103::-;;;;;;;;;;;;;:::i;107194:221::-;;;;;;;;;;-1:-1:-1;107194:221:0;;;;;:::i;:::-;;:::i;100693:41::-;;;;;;;;;;;;;;;;101308:2383;;;;;;:::i;:::-;;:::i;108317:118::-;;;;;;;;;;-1:-1:-1;108317:118:0;;;;;:::i;:::-;;:::i;99479:31::-;;;;;;;;;;;;;;;;65126:87;;;;;;;;;;-1:-1:-1;65172:7:0;65199:6;-1:-1:-1;;;;;65199:6:0;65126:87;;30321:104;;;;;;;;;;;;;:::i;109790:122::-;;;;;;;;;;-1:-1:-1;109790:122:0;;;;;:::i;:::-;;:::i;110455:306::-;;;;;;;;;;-1:-1:-1;110455:306:0;;;;;:::i;:::-;;:::i;100186:43::-;;;;;;;;;;;;;;;;108973:118;;;;;;;;;;-1:-1:-1;108973:118:0;;;;;:::i;:::-;;:::i;113308:126::-;;;;;;;;;;-1:-1:-1;113308:126:0;;;;;:::i;:::-;;:::i;99895:28::-;;;;;;;;;;-1:-1:-1;99895:28:0;;;;;;;;;;;108158:110;;;;;;;;;;-1:-1:-1;108158:110:0;;;;;:::i;:::-;;:::i;111812:117::-;;;;;;;;;;-1:-1:-1;111812:117:0;;;;;:::i;:::-;;:::i;111549:255::-;;;;;;:::i;:::-;;:::i;109297:118::-;;;;;;;;;;-1:-1:-1;109297:118:0;;;;;:::i;:::-;;:::i;115520:536::-;;;;;;;;;;-1:-1:-1;115520:536:0;;;;;:::i;:::-;;:::i;99517:34::-;;;;;;;;;;;;;;;;99761:30;;;;;;;;;;;;;;;;109138:110;;;;;;;;;;-1:-1:-1;109138:110:0;;;;;:::i;:::-;;:::i;108658:102::-;;;;;;;;;;-1:-1:-1;108658:102:0;;;;;:::i;:::-;;:::i;100401:37::-;;;;;;;;;;;;;;;;100364:30;;;;;;;;;;;;;;;;37494:164;;;;;;;;;;-1:-1:-1;37494:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;37615:25:0;;;37591:4;37615:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;37494:164;99930:30;;;;;;;;;;-1:-1:-1;99930:30:0;;;;;;;-1:-1:-1;;;;;99930:30:0;;;66059:220;;;;;;;;;;-1:-1:-1;66059:220:0;;;;;:::i;:::-;;:::i;100902:37::-;;;;;;;;;;;;;;;;99798:43;;;;;;;;;;-1:-1:-1;99798:43:0;;;;;;;;113656:402;113752:4;113970:38;113996:11;113970:25;:38::i;:::-;:80;;;;114012:38;114038:11;114012:25;:38::i;:::-;113963:87;113656:402;-1:-1:-1;;113656:402:0:o;114280:229::-;65012:13;:11;:13::i;:::-;114393:4:::1;114378:12;:19;;;114374:75;;;114421:16;;-1:-1:-1::0;;;114421:16:0::1;;;;;;;;;;;114374:75;114459:42;114478:8;114488:12;114459:18;:42::i;:::-;114280:229:::0;;:::o;30145:100::-;30199:13;30232:5;30225:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30145:100;:::o;36545:218::-;36621:7;36646:16;36654:7;36646;:16::i;:::-;36641:64;;36671:34;;;;;;;;;;;;;;36641:64;-1:-1:-1;36725:24:0;;;;:15;:24;;;;;:30;-1:-1:-1;;;;;36725:30:0;;36545:218::o;110769:304::-;110919:8;112030:24;;;;12677:59;;;12710:26;12727:8;12710:16;:26::i;:::-;110949:21:::1;::::0;::::1;::::0;::::1;;;110945:78;;;110994:17;;-1:-1:-1::0;;;110994:17:0::1;;;;;;;;;;;110945:78;111033:32;111047:8;111057:7;111033:13;:32::i;:::-;110769:304:::0;;;:::o;111081:222::-;111236:4;-1:-1:-1;;;;;12266:18:0;;12274:10;12266:18;12262:184;;112030:24;;;;12358:61;;;12391:28;12408:10;12391:16;:28::i;:::-;111258:37:::1;111277:4;111283:2;111287:7;111258:18;:37::i;:::-;111081:222:::0;;;;:::o;107993:118::-;65012:13;:11;:13::i;:::-;108073:15:::1;:30:::0;107993:118::o;95778:673::-;95889:16;95969:26;;;:17;:26;;;;;96032:21;;95889:16;;95969:26;-1:-1:-1;;;;;96032:21:0;;;-1:-1:-1;;;96089:28:0;;;;96032:21;96130:176;;-1:-1:-1;;96198:19:0;:28;-1:-1:-1;;;;;96198:28:0;;;-1:-1:-1;;;96259:35:0;;;;96130:176;96318:21;96817:5;96343:27;96342:49;96343:27;;:9;:27;:::i;:::-;96342:49;;;;:::i;:::-;96412:15;;;;-1:-1:-1;95778:673:0;;-1:-1:-1;;;;;;95778:673:0:o;103720:1978::-;103830:15;;:20;;;;:57;;;103872:15;;103854;:33;103830:57;103826:115;;;103911:18;;-1:-1:-1;;;103911:18:0;;;;;;;;;;;103826:115;103993:13;;:18;;;;:53;;;104033:13;;104015:15;:31;103993:53;103989:111;;;104070:18;;-1:-1:-1;;;104070:18:0;;;;;;;;;;;103989:111;104184:9;;:14;;;;:54;;-1:-1:-1;104229:9:0;;26170:12;;26154:13;;104218:8;;26154:28;;-1:-1:-1;;26154:46:0;104202:24;;;;:::i;:::-;:36;104184:54;104180:113;;;104262:19;;-1:-1:-1;;;104262:19:0;;;;;;;;;;;104180:113;104372:15;;:20;;;;:70;;;104427:15;;104416:8;104396:17;;:28;;;;:::i;:::-;:46;104372:70;104368:129;;;104466:19;;-1:-1:-1;;;104466:19:0;;;;;;;;;;;104368:129;104599:8;104583:12;;104569:11;;:26;;;;:::i;:::-;104568:39;;;;:::i;:::-;104555:9;:52;104551:106;;104631:14;;-1:-1:-1;;;104631:14:0;;;;;;;;;;;104551:106;104749:18;;:23;;;;:88;;-1:-1:-1;104819:18:0;;104794:10;104776:29;;;;:17;:29;;;;;;:40;;104808:8;;104776:40;:::i;:::-;:61;104749:88;104745:147;;;104861:19;;-1:-1:-1;;;104861:19:0;;;;;;;;;;;104745:147;104985:12;;104904:16;;104985:17;;;;:54;;-1:-1:-1;105006:19:0;;-1:-1:-1;;;;;105006:19:0;:33;;104985:54;104981:121;;;105082:8;105067:12;;:23;;;;:::i;:::-;105056:34;;104981:121;105207:15;;105166:22;;105207:20;;;;:57;;-1:-1:-1;105231:19:0;;-1:-1:-1;;;;;105231:19:0;:33;;105207:57;105203:157;;;105343:5;105318:20;105330:8;105318:9;:20;:::i;:::-;105299:15;;:40;;;;:::i;:::-;105298:50;;;;:::i;:::-;105281:67;;105203:157;105398:17;105418:25;105429:14;105418:8;:25;:::i;:::-;105398:45;-1:-1:-1;105458:14:0;;105454:75;;105489:28;105507:9;105489:17;:28::i;:::-;105587:10;105569:29;;;;:17;:29;;;;;:41;;105602:8;;105569:29;:41;;105602:8;;105569:41;:::i;:::-;;;;;;;;105642:8;105621:17;;:29;;;;;;;:::i;:::-;;;;-1:-1:-1;105661:27:0;;-1:-1:-1;105667:10:0;105679:8;105661:5;:27::i;109638:102::-;65012:13;:11;:13::i;:::-;109710:11:::1;:22:::0;109638:102::o;106946:204::-;65012:13;:11;:13::i;:::-;106995:12:::1;65199:6:::0;;107013:55:::1;::::0;-1:-1:-1;;;;;65199:6:0;;;;107042:21:::1;::::0;106995:12;107013:55;106995:12;107013:55;107042:21;65199:6;107013:55:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106994:74;;;107084:7;107079:64;;107115:16;;-1:-1:-1::0;;;107115:16:0::1;;;;;;;;;;;107079:64;106983:167;106946:204::o:0;111311:230::-;111470:4;-1:-1:-1;;;;;12266:18:0;;12274:10;12266:18;12262:184;;112030:24;;;;12358:61;;;12391:28;12408:10;12391:16;:28::i;:::-;111492:41:::1;111515:4;111521:2;111525:7;111492:22;:41::i;109464:130::-:0;65012:13;:11;:13::i;:::-;109550:18:::1;:36:::0;109464:130::o;113104:196::-;65012:13;:11;:13::i;:::-;113191:15:::1;::::0;;;::::1;-1:-1:-1::0;;;;;113191:15:0::1;113187:58;;113229:16;;;;;;;;;;;;;;113187:58;113256:16;:36:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;113256:36:0;;::::1;::::0;;;::::1;::::0;;113104:196::o;106538:229::-;65012:13;:11;:13::i;:::-;106621:9:::1;::::0;:14;;::::1;::::0;:54:::1;;-1:-1:-1::0;106666:9:0::1;::::0;26170:12;;26154:13;;106655:8;;26154:28;;-1:-1:-1;;26154:46:0;106639:24:::1;;;;:::i;:::-;:36;106621:54;106617:113;;;106699:19;;-1:-1:-1::0;;;106699:19:0::1;;;;;;;;;;;106617:113;106740:19;106746:2;106750:8;106740:5;:19::i;108484:130::-:0;65012:13;:11;:13::i;:::-;108570:18:::1;:36:::0;108484:130::o;115141:138::-;65012:13;:11;:13::i;:::-;115234:20:::1;:37;115257:14:::0;;115234:20;:37:::1;:::i;108810:122::-:0;65012:13;:11;:13::i;:::-;108892:16:::1;:32:::0;108810:122::o;115027:106::-;65012:13;:11;:13::i;:::-;115102::::1;:23;115118:7:::0;;115102:13;:23:::1;:::i;114517:287::-:0;65012:13;:11;:13::i;:::-;114681:4:::1;114666:12;:19;;;114662:75;;;114709:16;;-1:-1:-1::0;;;114709:16:0::1;;;;;;;;;;;114662:75;114747:49;114764:7;114773:8;114783:12;114747:16;:49::i;31538:152::-:0;31610:7;31653:27;31672:7;31653:18;:27::i;105957:541::-;65012:13;:11;:13::i;:::-;106119:7:::1;:14;106103:5;:12;:30;106099:92;;106157:22;;;;;;;;;;;;;;106099:92;106206:9;106201:288;106221:5;:12;106217:1;:16;106201:288;;;106255:9;::::0;:14;;::::1;::::0;:56:::1;;;106302:9;;106289:7;106297:1;106289:10;;;;;;;;:::i;:::-;;;;;;;106273:13;26170:12:::0;;26154:13;;-1:-1:-1;;26154:28:0;;;:46;;25896:323;106273:13:::1;:26;;;;:::i;:::-;:38;106255:56;106251:123;;;106339:19;;-1:-1:-1::0;;;106339:19:0::1;;;;;;;;;;;106251:123;106388:27;106394:5;106400:1;106394:8;;;;;;;;:::i;:::-;;;;;;;106404:7;106412:1;106404:10;;;;;;;;:::i;:::-;;;;;;;106388:5;:27::i;:::-;106459:3;;106201:288;;106798:106:::0;65012:13;:11;:13::i;:::-;106872:9:::1;:24:::0;106798:106::o;27080:233::-;27152:7;-1:-1:-1;;;;;27176:19:0;;27172:60;;27204:28;;;;;;;;;;;;;;27172:60;-1:-1:-1;;;;;;27250:25:0;;;;;:18;:25;;;;;;21239:13;27250:55;;27080:233::o;65801:103::-;65012:13;:11;:13::i;:::-;65866:30:::1;65893:1;65866:18;:30::i;:::-;65801:103::o:0;107194:221::-;65012:13;:11;:13::i;:::-;107264:12:::1;107290:3;-1:-1:-1::0;;;;;107282:17:0::1;107307:21;107282:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107263:70;;;107349:7;107344:64;;107380:16;;-1:-1:-1::0;;;107380:16:0::1;;;;;;;;;;;101308:2383:::0;101450:15;;:20;;;;:57;;;101492:15;;101474;:33;101450:57;101446:115;;;101531:18;;-1:-1:-1;;;101531:18:0;;;;;;;;;;;101446:115;101613:13;;:18;;;;:53;;;101653:13;;101635:15;:31;101613:53;101609:111;;;101690:18;;-1:-1:-1;;;101690:18:0;;;;;;;;;;;101609:111;101804:9;;:14;;;;:54;;-1:-1:-1;101849:9:0;;26170:12;;26154:13;;101838:8;;26154:28;;-1:-1:-1;;26154:46:0;101822:24;;;;:::i;:::-;:36;101804:54;101800:113;;;101882:19;;-1:-1:-1;;;101882:19:0;;;;;;;;;;;101800:113;101992:15;;:20;;;;:70;;;102047:15;;102036:8;102016:17;;:28;;;;:::i;:::-;:46;101992:70;101988:129;;;102086:19;;-1:-1:-1;;;102086:19:0;;;;;;;;;;;101988:129;102219:8;102203:12;;102189:11;;:26;;;;:::i;:::-;102188:39;;;;:::i;:::-;102175:9;:52;102171:106;;102251:14;;-1:-1:-1;;;102251:14:0;;;;;;;;;;;102171:106;102362:16;;:30;102358:289;;102468:28;;-1:-1:-1;;102485:10:0;15516:2:1;15512:15;15508:53;102468:28:0;;;15496:66:1;102443:12:0;;15578::1;;102468:28:0;;;;;;;;;;;;102458:39;;;;;;102443:54;;102517:55;102536:11;;102517:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;102549:16:0;;;-1:-1:-1;102567:4:0;;-1:-1:-1;102517:18:0;:55::i;:::-;102512:124;;102600:20;;;;;;;;;;;;;;102512:124;102394:253;102358:289;102742:18;;:23;;;;:88;;-1:-1:-1;102812:18:0;;102787:10;102769:29;;;;:17;:29;;;;;;:40;;102801:8;;102769:40;:::i;:::-;:61;102742:88;102738:147;;;102854:19;;-1:-1:-1;;;102854:19:0;;;;;;;;;;;102738:147;102978:12;;102897:16;;102978:17;;;;:54;;-1:-1:-1;102999:19:0;;-1:-1:-1;;;;;102999:19:0;:33;;102978:54;102974:121;;;103075:8;103060:12;;:23;;;;:::i;:::-;103049:34;;102974:121;103200:15;;103159:22;;103200:20;;;;:57;;-1:-1:-1;103224:19:0;;-1:-1:-1;;;;;103224:19:0;:33;;103200:57;103196:157;;;103336:5;103311:20;103323:8;103311:9;:20;:::i;:::-;103292:15;;:40;;;;:::i;:::-;103291:50;;;;:::i;:::-;103274:67;;103196:157;103391:17;103411:25;103422:14;103411:8;:25;:::i;:::-;103391:45;-1:-1:-1;103451:14:0;;103447:75;;103482:28;103500:9;103482:17;:28::i;:::-;103580:10;103562:29;;;;:17;:29;;;;;:41;;103595:8;;103562:29;:41;;103595:8;;103562:41;:::i;:::-;;;;;;;;103635:8;103614:17;;:29;;;;;;;:::i;:::-;;;;-1:-1:-1;103654:27:0;;-1:-1:-1;103660:10:0;103672:8;103654:5;:27::i;:::-;101395:2296;;;101308:2383;;;:::o;108317:118::-;65012:13;:11;:13::i;:::-;108397:15:::1;:30:::0;108317:118::o;30321:104::-;30377:13;30410:7;30403:14;;;;;:::i;109790:122::-;65012:13;:11;:13::i;:::-;109872:16:::1;:32:::0;109790:122::o;110455:306::-;110596:8;112030:24;;;;12677:59;;;12710:26;12727:8;12710:16;:26::i;:::-;110626:21:::1;::::0;::::1;::::0;::::1;;;110622:78;;;110671:17;;-1:-1:-1::0;;;110671:17:0::1;;;;;;;;;;;110622:78;110710:43;110734:8;110744;110710:23;:43::i;108973:118::-:0;65012:13;:11;:13::i;:::-;109053:15:::1;:30:::0;108973:118::o;113308:126::-;65012:13;:11;:13::i;:::-;113392:15:::1;:34:::0;;-1:-1:-1;;;;;113392:34:0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;113308:126::o;108158:110::-;65012:13;:11;:13::i;:::-;108234::::1;:26:::0;108158:110::o;111812:117::-;65012:13;:11;:13::i;:::-;111889:24:::1;:32:::0;;-1:-1:-1;;111889:32:0::1;::::0;::::1;;::::0;;;::::1;::::0;;111812:117::o;111549:255::-;111727:4;-1:-1:-1;;;;;12266:18:0;;12274:10;12266:18;12262:184;;112030:24;;;;12358:61;;;12391:28;12408:10;12391:16;:28::i;:::-;111749:47:::1;111772:4;111778:2;111782:7;111791:4;111749:22;:47::i;:::-;111549:255:::0;;;;;:::o;109297:118::-;65012:13;:11;:13::i;:::-;109377:15:::1;:30:::0;109297:118::o;115520:536::-;115585:13;115626:16;115634:7;115626;:16::i;:::-;115621:59;;115651:29;;;;;;;;;;;;;;115621:59;115693:21;115717:10;:8;:10::i;:::-;115693:34;;115738:28;115769:17;:15;:17::i;:::-;115738:48;;115807:7;115801:21;115826:1;115801:26;115797:133;;115875:7;115889:18;115899:7;115889:9;:18::i;:::-;115858:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;115844:74;;;;115520:536;;;:::o;115797:133::-;115944:28;;:33;115940:87;;116001:14;115520:536;-1:-1:-1;;;115520:536:0:o;115940:87::-;-1:-1:-1;;116037:9:0;;;;;;;;;-1:-1:-1;116037:9:0;;;115520:536;-1:-1:-1;;115520:536:0:o;109138:110::-;65012:13;:11;:13::i;:::-;109214::::1;:26:::0;109138:110::o;108658:102::-;65012:13;:11;:13::i;:::-;108730:11:::1;:22:::0;108658:102::o;66059:220::-;65012:13;:11;:13::i;:::-;-1:-1:-1;;;;;66144:22:0;::::1;66140:93;;66190:31;::::0;::::1;::::0;;66218:1:::1;66190:31;::::0;::::1;2405:74:1::0;2378:18;;66190:31:0::1;;;;;;;;66140:93;66243:28;66262:8;66243:18;:28::i;29243:639::-:0;29328:4;-1:-1:-1;;;;;;;;;29652:25:0;;;;:102;;-1:-1:-1;29729:25:0;-1:-1:-1;;;;;;29729:25:0;;;29652:102;:179;;;-1:-1:-1;;;;;;;;29806:25:0;;;;29243:639::o;95508:215::-;95610:4;-1:-1:-1;;;;;;95634:41:0;;95649:26;95634:41;;:81;;-1:-1:-1;;;;;;;;;;93408:40:0;;;95679:36;93308:148;65291:166;65172:7;65199:6;-1:-1:-1;;;;;65199:6:0;15545:10;65351:23;65347:103;;65398:40;;;;;15545:10;65398:40;;;2405:74:1;2378:18;;65398:40:0;2259:226:1;97101:518:0;96817:5;97196:39;97250:26;;;-1:-1:-1;97246:176:0;;;97355:55;;;;;16605:26:1;16593:39;;97355:55:0;;;16575:58:1;16649:18;;;16642:34;;;16548:18;;97355:55:0;16402:280:1;97246:176:0;-1:-1:-1;;;;;97436:22:0;;97432:110;;97482:48;;;;;97527:1;97482:48;;;2405:74:1;2378:18;;97482:48:0;2259:226:1;97432:110:0;-1:-1:-1;97576:35:0;;;;;;;;;-1:-1:-1;;;;;97576:35:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;97554:57:0;;;;:19;:57;97101:518::o;37916:282::-;37981:4;38037:7;110219:1;38018:26;;:66;;;;;38071:13;;38061:7;:23;38018:66;:153;;;;-1:-1:-1;;38122:26:0;;;;:17;:26;;;;;;-1:-1:-1;;;38122:44:0;:49;;37916:282::o;12864:1359::-;13257:22;13251:4;13244:36;13350:9;13344:4;13337:23;13425:8;13419:4;13412:22;13602:4;13596;13590;13584;13557:25;13550:5;13539:68;13529:274;;13723:16;13717:4;13711;13696:44;13771:16;13765:4;13758:30;13529:274;14203:1;14197:4;14190:15;12864:1359;:::o;36262:124::-;36351:27;36360:2;36364:7;36373:4;36351:8;:27::i;40184:2825::-;40326:27;40356;40375:7;40356:18;:27::i;:::-;40326:57;;40441:4;-1:-1:-1;;;;;40400:45:0;40416:19;-1:-1:-1;;;;;40400:45:0;;40396:86;;40454:28;;;;;;;;;;;;;;40396:86;40496:27;39292:24;;;:15;:24;;;;;39520:26;;15545:10;38917:30;;;-1:-1:-1;;;;;38610:28:0;;38895:20;;;38892:56;40682:180;;-1:-1:-1;;;;;37615:25:0;;37591:4;37615:25;;;:18;:25;;;;;;;;15545:10;37615:35;;;;;;;;;;40770:92;;40827:35;;;;;;;;;;;;;;40770:92;-1:-1:-1;;;;;40879:16:0;;40875:52;;40904:23;;;;;;;;;;;;;;40875:52;40940:43;40962:4;40968:2;40972:7;40981:1;40940:21;:43::i;:::-;41076:15;41073:160;;;41216:1;41195:19;41188:30;41073:160;-1:-1:-1;;;;;41613:24:0;;;;;;;:18;:24;;;;;;41611:26;;-1:-1:-1;;41611:26:0;;;41682:22;;;;;;;;;41680:24;;-1:-1:-1;41680:24:0;;;35364:11;35339:23;35335:41;35322:63;-1:-1:-1;;;35322:63:0;41975:26;;;;:17;:26;;;;;:175;;;;-1:-1:-1;;;42270:47:0;;:52;;42266:627;;42375:1;42365:11;;42343:19;42498:30;;;:17;:30;;;;;;:35;;42494:384;;42636:13;;42621:11;:28;42617:242;;42783:30;;;;:17;:30;;;;;:52;;;42617:242;42324:569;42266:627;42940:7;42936:2;-1:-1:-1;;;;;42921:27:0;42930:4;-1:-1:-1;;;;;42921:27:0;;;;;;;;;;;42959:42;111081:222;107455:481;107524:9;107537:1;107524:14;107520:75;;107562:21;;;;;;;;;;;;;;107520:75;107609:19;;-1:-1:-1;;;;;107609:19:0;107605:101;;107666:28;;;;;;;;;;;;;;107605:101;107743:19;;107735:55;;107717:12;;-1:-1:-1;;;;;107743:19:0;;107776:9;;107717:12;107735:55;107717:12;107735:55;107776:9;107743:19;107735:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107716:74;;;107806:7;107801:64;;107837:16;;-1:-1:-1;;;107837:16:0;;;;;;;;;;;107801:64;107897:19;;107880:48;;1992:25:1;;;-1:-1:-1;;;;;107897:19:0;;;;107880:48;;1980:2:1;1965:18;107880:48:0;;;;;;;107509:427;107455:481;:::o;47565:2966::-;47661:13;;47638:20;47689:13;;;47685:44;;47711:18;;;;;;;;;;;;;;47685:44;47742:61;47772:1;47776:2;47780:12;47794:8;47742:21;:61::i;:::-;-1:-1:-1;;;;;48217:22:0;;;;;;:18;:22;;;;21377:2;48217:22;;;:71;;48255:32;48243:45;;48217:71;;;48531:31;;;:17;:31;;;;;-1:-1:-1;35795:15:0;;35769:24;35765:46;35364:11;35339:23;35335:41;35332:52;35322:63;;48531:173;;48766:23;;;;48531:31;;48217:22;;49531:25;48217:22;;49384:335;50045:1;50031:12;50027:20;49985:346;50086:3;50077:7;50074:16;49985:346;;50304:7;50294:8;50291:1;50264:25;50261:1;50258;50253:59;50139:1;50126:15;49985:346;;;49989:77;50364:8;50376:1;50364:13;50360:45;;50386:19;;;;;;;;;;;;;;50360:45;50422:13;:19;-1:-1:-1;110769:304:0;;;:::o;43105:193::-;43251:39;43268:4;43274:2;43278:7;43251:39;;;;;;;;;;;;:16;:39::i;98070:554::-;96817:5;98180:39;98234:26;;;-1:-1:-1;98230:183:0;;;98339:62;;;;;;;;16888:25:1;;;16961:26;16949:39;;16929:18;;;16922:67;17005:18;;;16998:34;;;16861:18;;98339:62:0;16687:351:1;98230:183:0;-1:-1:-1;;;;;98427:22:0;;98423:117;;98473:55;;;;;;;;17217:25:1;;;98525:1:0;17258:18:1;;;17251:83;17190:18;;98473:55:0;17043:297:1;98423:117:0;-1:-1:-1;98581:35:0;;;;;;;;-1:-1:-1;;;;;98581:35:0;;;;;;;;;;;;;;;;-1:-1:-1;98552:26:0;;;:17;:26;;;;;;:64;;;;;;;-1:-1:-1;;;98552:64:0;;;;;;98070:554::o;32693:1712::-;32760:14;32810:7;110219:1;32791:26;32787:1562;;-1:-1:-1;32843:26:0;;;;:17;:26;;;;;;;-1:-1:-1;;;32919:24:0;;:29;;32915:1423;;33058:6;33068:1;33058:11;33054:981;;33109:13;;33098:7;:24;33094:68;;33131:31;;-1:-1:-1;;;33131:31:0;;;;;;;;;;;33094:68;33759:257;-1:-1:-1;;;33863:9:0;33845:28;;;;:17;:28;;;;;;33927:25;;33759:257;33927:25;;32693:1712;;;:::o;32915:1423::-;34366:31;;-1:-1:-1;;;34366:31:0;;;;;;;;;;;66439:191;66513:16;66532:6;;-1:-1:-1;;;;;66549:17:0;;;-1:-1:-1;;66549:17:0;;;;;;66582:40;;66532:6;;;;;;;66582:40;;66513:16;66582:40;66502:128;66439:191;:::o;69645:156::-;69736:4;69789;69760:25;69773:5;69780:4;69760:12;:25::i;:::-;:33;;69645:156;-1:-1:-1;;;;69645:156:0:o;37103:234::-;15545:10;37198:39;;;;:18;:39;;;;;;;;-1:-1:-1;;;;;37198:49:0;;;;;;;;;;;;:60;;-1:-1:-1;;37198:60:0;;;;;;;;;;37274:55;;586:41:1;;;37198:49:0;;15545:10;37274:55;;559:18:1;37274:55:0;;;;;;;37103:234;;:::o;43896:407::-;44071:31;44084:4;44090:2;44094:7;44071:12;:31::i;:::-;-1:-1:-1;;;;;44117:14:0;;;:19;44113:183;;44156:56;44187:4;44193:2;44197:7;44206:5;44156:30;:56::i;:::-;44151:145;;44240:40;;-1:-1:-1;;;44240:40:0;;;;;;;;;;;115287:106;115339:13;115372;115365:20;;;;;:::i;115401:111::-;115451:13;115484:20;115477:27;;;;;:::i;61729:1745::-;61794:17;62228:4;62221;62215:11;62211:22;62320:1;62314:4;62307:15;62395:4;62392:1;62388:12;62381:19;;;62477:1;62472:3;62465:14;62581:3;62820:5;62802:428;62868:1;62863:3;62859:11;62852:18;;63039:2;63033:4;63029:13;63025:2;63021:22;63016:3;63008:36;63133:2;63123:13;;63190:25;62802:428;63190:25;-1:-1:-1;63260:13:0;;;-1:-1:-1;;63375:14:0;;;63437:19;;;63375:14;61729:1745;-1:-1:-1;61729:1745:0:o;54974:492::-;55103:13;55119:16;55127:7;55119;:16::i;:::-;55103:32;;55152:13;55148:219;;;15545:10;-1:-1:-1;;;;;55184:28:0;;;55180:187;;-1:-1:-1;;;;;37615:25:0;;37591:4;37615:25;;;:18;:25;;;;;;;;15545:10;37615:35;;;;;;;;;;55231:136;;55312:35;;;;;;;;;;;;;;55231:136;55379:24;;;;:15;:24;;;;;;:35;;-1:-1:-1;;55379:35:0;-1:-1:-1;;;;;55379:35:0;;;;;;;;;55430:28;;55379:24;;55430:28;;;;;;;55092:374;54974:492;;;:::o;112285:497::-;112458:21;;;;;;;:43;;;;-1:-1:-1;;;;;;112483:18:0;;;;112458:43;:63;;;;-1:-1:-1;;;;;;112505:16:0;;;;112458:63;112454:120;;;112545:17;;-1:-1:-1;;;112545:17:0;;;;;;;;;;;112454:120;112588:35;112612:10;112588:23;:35::i;:::-;112584:191;;112741:22;;;;;;;;;;;;;;70212:314;70295:7;70338:4;70295:7;70353:136;70377:5;:12;70373:1;:16;70353:136;;;70426:51;70454:12;70468:5;70474:1;70468:8;;;;;;;;:::i;:::-;;;;;;;70426:27;:51::i;:::-;70411:66;-1:-1:-1;70391:3:0;;70353:136;;;-1:-1:-1;70506:12:0;70212:314;-1:-1:-1;;;70212:314:0:o;46387:716::-;46571:88;;-1:-1:-1;;;46571:88:0;;46550:4;;-1:-1:-1;;;;;46571:45:0;;;;;:88;;15545:10;;46638:4;;46644:7;;46653:5;;46571:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46571:88:0;;;;;;;;-1:-1:-1;;46571:88:0;;;;;;;;;;;;:::i;:::-;;;46567:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46854:6;:13;46871:1;46854:18;46850:235;;46900:40;;-1:-1:-1;;;46900:40:0;;;;;;;;;;;46850:235;47043:6;47037:13;47028:6;47024:2;47020:15;47013:38;46567:529;-1:-1:-1;;;;;;46730:64:0;-1:-1:-1;;;46730:64:0;;-1:-1:-1;46387:716:0;;;;;;:::o;112790:306::-;112917:16;;112891:4;;112917:16;;;;;112913:154;;;112981:15;;113019:36;;;;;-1:-1:-1;;;;;2423:55:1;;;113019:36:0;;;2405:74:1;112981:15:0;;;;;;;;;;113019:26;;2378:18:1;;113019:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113012:43;112790:306;-1:-1:-1;;;112790:306:0:o;112913:154::-;-1:-1:-1;113084:4:0;;112790:306;-1:-1:-1;112790:306:0:o;16318:169::-;16393:7;16424:1;16420;:5;:59;;16685:13;16751:15;;;16787:4;16780:15;;;16834:4;16818:21;;16420:59;;;-1:-1:-1;16685:13:0;16751:15;;;16787:4;16780:15;16834:4;16818:21;;;16318:169::o;14:177:1:-;-1:-1:-1;;;;;;92:5:1;88:78;81:5;78:89;68:117;;181:1;178;171:12;196:245;254:6;307:2;295:9;286:7;282:23;278:32;275:52;;;323:1;320;313:12;275:52;362:9;349:23;381:30;405:5;381:30;:::i;638:154::-;-1:-1:-1;;;;;717:5:1;713:54;706:5;703:65;693:93;;782:1;779;772:12;797:179;864:20;;924:26;913:38;;903:49;;893:77;;966:1;963;956:12;981:319;1048:6;1056;1109:2;1097:9;1088:7;1084:23;1080:32;1077:52;;;1125:1;1122;1115:12;1077:52;1164:9;1151:23;1183:31;1208:5;1183:31;:::i;:::-;1233:5;-1:-1:-1;1257:37:1;1290:2;1275:18;;1257:37;:::i;:::-;1247:47;;981:319;;;;;:::o;1305:300::-;1358:3;1396:5;1390:12;1423:6;1418:3;1411:19;1479:6;1472:4;1465:5;1461:16;1454:4;1449:3;1445:14;1439:47;1531:1;1524:4;1515:6;1510:3;1506:16;1502:27;1495:38;1594:4;1587:2;1583:7;1578:2;1570:6;1566:15;1562:29;1557:3;1553:39;1549:50;1542:57;;;1305:300;;;;:::o;1610:231::-;1759:2;1748:9;1741:21;1722:4;1779:56;1831:2;1820:9;1816:18;1808:6;1779:56;:::i;2028:226::-;2087:6;2140:2;2128:9;2119:7;2115:23;2111:32;2108:52;;;2156:1;2153;2146:12;2108:52;-1:-1:-1;2201:23:1;;2028:226;-1:-1:-1;2028:226:1:o;2490:367::-;2558:6;2566;2619:2;2607:9;2598:7;2594:23;2590:32;2587:52;;;2635:1;2632;2625:12;2587:52;2674:9;2661:23;2693:31;2718:5;2693:31;:::i;:::-;2743:5;2821:2;2806:18;;;;2793:32;;-1:-1:-1;;;2490:367:1:o;2862:247::-;2921:6;2974:2;2962:9;2953:7;2949:23;2945:32;2942:52;;;2990:1;2987;2980:12;2942:52;3029:9;3016:23;3048:31;3073:5;3048:31;:::i;3114:508::-;3191:6;3199;3207;3260:2;3248:9;3239:7;3235:23;3231:32;3228:52;;;3276:1;3273;3266:12;3228:52;3315:9;3302:23;3334:31;3359:5;3334:31;:::i;:::-;3384:5;-1:-1:-1;3441:2:1;3426:18;;3413:32;3454:33;3413:32;3454:33;:::i;:::-;3114:508;;3506:7;;-1:-1:-1;;;3586:2:1;3571:18;;;;3558:32;;3114:508::o;3627:346::-;3695:6;3703;3756:2;3744:9;3735:7;3731:23;3727:32;3724:52;;;3772:1;3769;3762:12;3724:52;-1:-1:-1;;3817:23:1;;;3937:2;3922:18;;;3909:32;;-1:-1:-1;3627:346:1:o;4280:118::-;4366:5;4359:13;4352:21;4345:5;4342:32;4332:60;;4388:1;4385;4378:12;4403:241;4459:6;4512:2;4500:9;4491:7;4487:23;4483:32;4480:52;;;4528:1;4525;4518:12;4480:52;4567:9;4554:23;4586:28;4608:5;4586:28;:::i;4649:587::-;4720:6;4728;4781:2;4769:9;4760:7;4756:23;4752:32;4749:52;;;4797:1;4794;4787:12;4749:52;4837:9;4824:23;4870:18;4862:6;4859:30;4856:50;;;4902:1;4899;4892:12;4856:50;4925:22;;4978:4;4970:13;;4966:27;-1:-1:-1;4956:55:1;;5007:1;5004;4997:12;4956:55;5047:2;5034:16;5073:18;5065:6;5062:30;5059:50;;;5105:1;5102;5095:12;5059:50;5150:7;5145:2;5136:6;5132:2;5128:15;5124:24;5121:37;5118:57;;;5171:1;5168;5161:12;5118:57;5202:2;5194:11;;;;;5224:6;;-1:-1:-1;4649:587:1;-1:-1:-1;;;4649:587:1:o;5426:439::-;5502:6;5510;5518;5571:2;5559:9;5550:7;5546:23;5542:32;5539:52;;;5587:1;5584;5577:12;5539:52;5632:23;;;-1:-1:-1;5731:2:1;5716:18;;5703:32;5744:33;5703:32;5744:33;:::i;:::-;5796:7;-1:-1:-1;5822:37:1;5855:2;5840:18;;5822:37;:::i;:::-;5812:47;;5426:439;;;;;:::o;6052:184::-;-1:-1:-1;;;6101:1:1;6094:88;6201:4;6198:1;6191:15;6225:4;6222:1;6215:15;6241:275;6312:2;6306:9;6377:2;6358:13;;-1:-1:-1;;6354:27:1;6342:40;;6412:18;6397:34;;6433:22;;;6394:62;6391:88;;;6459:18;;:::i;:::-;6495:2;6488:22;6241:275;;-1:-1:-1;6241:275:1:o;6521:183::-;6581:4;6614:18;6606:6;6603:30;6600:56;;;6636:18;;:::i;:::-;-1:-1:-1;6681:1:1;6677:14;6693:4;6673:25;;6521:183::o;6709:723::-;6763:5;6816:3;6809:4;6801:6;6797:17;6793:27;6783:55;;6834:1;6831;6824:12;6783:55;6874:6;6861:20;6901:64;6917:47;6957:6;6917:47;:::i;:::-;6901:64;:::i;:::-;6989:3;7013:6;7008:3;7001:19;7045:4;7040:3;7036:14;7029:21;;7106:4;7096:6;7093:1;7089:14;7081:6;7077:27;7073:38;7059:52;;7134:3;7126:6;7123:15;7120:35;;;7151:1;7148;7141:12;7120:35;7187:4;7179:6;7175:17;7201:200;7217:6;7212:3;7209:15;7201:200;;;7309:17;;7339:18;;7386:4;7377:14;;;;7234;7201:200;;;-1:-1:-1;7419:7:1;6709:723;-1:-1:-1;;;;;6709:723:1:o;7437:1215::-;7555:6;7563;7616:2;7604:9;7595:7;7591:23;7587:32;7584:52;;;7632:1;7629;7622:12;7584:52;7672:9;7659:23;7705:18;7697:6;7694:30;7691:50;;;7737:1;7734;7727:12;7691:50;7760:22;;7813:4;7805:13;;7801:27;-1:-1:-1;7791:55:1;;7842:1;7839;7832:12;7791:55;7882:2;7869:16;7905:64;7921:47;7961:6;7921:47;:::i;7905:64::-;7991:3;8015:6;8010:3;8003:19;8047:4;8042:3;8038:14;8031:21;;8104:4;8094:6;8091:1;8087:14;8083:2;8079:23;8075:34;8061:48;;8132:7;8124:6;8121:19;8118:39;;;8153:1;8150;8143:12;8118:39;8185:4;8181:2;8177:13;8166:24;;8199:221;8215:6;8210:3;8207:15;8199:221;;;8297:3;8284:17;8314:31;8339:5;8314:31;:::i;:::-;8358:18;;8405:4;8232:14;;;;8396;;;;8199:221;;;8439:5;-1:-1:-1;;;;8497:4:1;8482:20;;8469:34;8528:18;8515:32;;8512:52;;;8560:1;8557;8550:12;8512:52;8583:63;8638:7;8627:8;8616:9;8612:24;8583:63;:::i;:::-;8573:73;;;7437:1215;;;;;:::o;8917:730::-;9012:6;9020;9028;9081:2;9069:9;9060:7;9056:23;9052:32;9049:52;;;9097:1;9094;9087:12;9049:52;9137:9;9124:23;9170:18;9162:6;9159:30;9156:50;;;9202:1;9199;9192:12;9156:50;9225:22;;9278:4;9270:13;;9266:27;-1:-1:-1;9256:55:1;;9307:1;9304;9297:12;9256:55;9347:2;9334:16;9373:18;9365:6;9362:30;9359:50;;;9405:1;9402;9395:12;9359:50;9460:7;9453:4;9443:6;9440:1;9436:14;9432:2;9428:23;9424:34;9421:47;9418:67;;;9481:1;9478;9471:12;9418:67;9512:4;9504:13;;;;9536:6;;-1:-1:-1;9596:20:1;;9583:34;;8917:730;-1:-1:-1;;;8917:730:1:o;9652:382::-;9717:6;9725;9778:2;9766:9;9757:7;9753:23;9749:32;9746:52;;;9794:1;9791;9784:12;9746:52;9833:9;9820:23;9852:31;9877:5;9852:31;:::i;:::-;9902:5;-1:-1:-1;9959:2:1;9944:18;;9931:32;9972:30;9931:32;9972:30;:::i;:::-;10021:7;10011:17;;;9652:382;;;;;:::o;10039:1162::-;10134:6;10142;10150;10158;10211:3;10199:9;10190:7;10186:23;10182:33;10179:53;;;10228:1;10225;10218:12;10179:53;10267:9;10254:23;10286:31;10311:5;10286:31;:::i;:::-;10336:5;-1:-1:-1;10393:2:1;10378:18;;10365:32;10406:33;10365:32;10406:33;:::i;:::-;10458:7;-1:-1:-1;10538:2:1;10523:18;;10510:32;;-1:-1:-1;10619:2:1;10604:18;;10591:32;10646:18;10635:30;;10632:50;;;10678:1;10675;10668:12;10632:50;10701:22;;10754:4;10746:13;;10742:27;-1:-1:-1;10732:55:1;;10783:1;10780;10773:12;10732:55;10823:2;10810:16;10849:18;10841:6;10838:30;10835:56;;;10871:18;;:::i;:::-;10913:57;10960:2;10937:17;;-1:-1:-1;;10933:31:1;10966:2;10929:40;10913:57;:::i;:::-;10993:6;10986:5;10979:21;11041:7;11036:2;11027:6;11023:2;11019:15;11015:24;11012:37;11009:57;;;11062:1;11059;11052:12;11009:57;11117:6;11112:2;11108;11104:11;11099:2;11092:5;11088:14;11075:49;11169:1;11164:2;11155:6;11148:5;11144:18;11140:27;11133:38;11190:5;11180:15;;;;;10039:1162;;;;;;;:::o;11206:388::-;11274:6;11282;11335:2;11323:9;11314:7;11310:23;11306:32;11303:52;;;11351:1;11348;11341:12;11303:52;11390:9;11377:23;11409:31;11434:5;11409:31;:::i;:::-;11459:5;-1:-1:-1;11516:2:1;11501:18;;11488:32;11529:33;11488:32;11529:33;:::i;11599:437::-;11678:1;11674:12;;;;11721;;;11742:61;;11796:4;11788:6;11784:17;11774:27;;11742:61;11849:2;11841:6;11838:14;11818:18;11815:38;11812:218;;-1:-1:-1;;;11883:1:1;11876:88;11987:4;11984:1;11977:15;12015:4;12012:1;12005:15;11812:218;;11599:437;;;:::o;12041:184::-;-1:-1:-1;;;12090:1:1;12083:88;12190:4;12187:1;12180:15;12214:4;12211:1;12204:15;12230:168;12303:9;;;12334;;12351:15;;;12345:22;;12331:37;12321:71;;12372:18;;:::i;12403:274::-;12443:1;12469;12459:189;;-1:-1:-1;;;12501:1:1;12494:88;12605:4;12602:1;12595:15;12633:4;12630:1;12623:15;12459:189;-1:-1:-1;12662:9:1;;12403:274::o;12682:125::-;12747:9;;;12768:10;;;12765:36;;;12781:18;;:::i;12812:128::-;12879:9;;;12900:11;;;12897:37;;;12914:18;;:::i;13281:518::-;13383:2;13378:3;13375:11;13372:421;;;13419:5;13416:1;13409:16;13463:4;13460:1;13450:18;13533:2;13521:10;13517:19;13514:1;13510:27;13504:4;13500:38;13569:4;13557:10;13554:20;13551:47;;;-1:-1:-1;13592:4:1;13551:47;13647:2;13642:3;13638:12;13635:1;13631:20;13625:4;13621:31;13611:41;;13702:81;13720:2;13713:5;13710:13;13702:81;;;13779:1;13765:16;;13746:1;13735:13;13702:81;;13975:1198;14099:18;14094:3;14091:27;14088:53;;;14121:18;;:::i;:::-;14150:94;14240:3;14200:38;14232:4;14226:11;14200:38;:::i;:::-;14194:4;14150:94;:::i;:::-;14270:1;14295:2;14290:3;14287:11;14312:1;14307:608;;;;14959:1;14976:3;14973:93;;;-1:-1:-1;15032:19:1;;;15019:33;14973:93;-1:-1:-1;;13932:1:1;13928:11;;;13924:24;13920:29;13910:40;13956:1;13952:11;;;13907:57;15079:78;;14280:887;;14307:608;13228:1;13221:14;;;13265:4;13252:18;;-1:-1:-1;;14343:17:1;;;14458:229;14472:7;14469:1;14466:14;14458:229;;;14561:19;;;14548:33;14533:49;;14668:4;14653:20;;;;14621:1;14609:14;;;;14488:12;14458:229;;;14462:3;14715;14706:7;14703:16;14700:159;;;14839:1;14835:6;14829:3;14823;14820:1;14816:11;14812:21;14808:34;14804:39;14791:9;14786:3;14782:19;14769:33;14765:79;14757:6;14750:95;14700:159;;;14902:1;14896:3;14893:1;14889:11;14885:19;14879:4;14872:33;14280:887;;13975:1198;;;:::o;15178:184::-;-1:-1:-1;;;15227:1:1;15220:88;15327:4;15324:1;15317:15;15351:4;15348:1;15341:15;15601:212;15643:3;15681:5;15675:12;15725:6;15718:4;15711:5;15707:16;15702:3;15696:36;15787:1;15751:16;;15776:13;;;-1:-1:-1;15751:16:1;;15601:212;-1:-1:-1;15601:212:1:o;15818:579::-;16199:3;16227:30;16253:3;16245:6;16227:30;:::i;:::-;16277:3;16273:2;16266:15;16300:37;16334:1;16330:2;16326:10;16318:6;16300:37;:::i;:::-;16357:7;16346:19;;16389:1;16381:10;;15818:579;-1:-1:-1;;;;;15818:579:1:o;17345:542::-;-1:-1:-1;;;;;17580:6:1;17576:55;17565:9;17558:74;-1:-1:-1;;;;;17672:6:1;17668:55;17663:2;17652:9;17648:18;17641:83;17760:6;17755:2;17744:9;17740:18;17733:34;17803:3;17798:2;17787:9;17783:18;17776:31;17539:4;17824:57;17876:3;17865:9;17861:19;17853:6;17824:57;:::i;:::-;17816:65;17345:542;-1:-1:-1;;;;;;17345:542:1:o;17892:249::-;17961:6;18014:2;18002:9;17993:7;17989:23;17985:32;17982:52;;;18030:1;18027;18020:12;17982:52;18062:9;18056:16;18081:30;18105:5;18081:30;:::i;18146:245::-;18213:6;18266:2;18254:9;18245:7;18241:23;18237:32;18234:52;;;18282:1;18279;18272:12;18234:52;18314:9;18308:16;18333:28;18355:5;18333:28;:::i

Swarm Source

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