APE Price: $0.61 (-5.90%)

Token

EternalSundials (ES)

Overview

Max Total Supply

65 ES

Holders

7

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
0 ES
0x0000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
EternalSundials

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 17 : EternalSundials.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.28;

import "erc721a/contracts/extensions/ERC721AQueryable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";

contract EternalSundials is ERC721AQueryable, Ownable, ReentrancyGuard, ERC2981 {
    using Strings for uint256;

    string public uriPrefix = "";
    string public uriSuffix = ".json";

    uint256 public cost;
    uint256 public maxSupply;
    uint256 public maxMintAmountPerTx;

    bool public paused = true;

    constructor(
        string memory _tokenName,
        string memory _tokenSymbol,
        uint256 _maxSupply
    )
        ERC721A(_tokenName, _tokenSymbol)
        Ownable(_msgSender())
    {
        // Set defaults at deployment
        cost = 10 ether;           // 10 Apecoin
        maxSupply = _maxSupply;     // Passed in constructor
        maxMintAmountPerTx = 10;    // Default max mint per transaction

        // Set default royalty to 8% (800 basis points)
        _setDefaultRoyalty(0xE0Fb2232D81B4cD9BBFE2Ade1402C2De018a9225, 800);
    }

    modifier mintCompliance(uint256 _mintAmount) {
        require(
            _mintAmount > 0 && _mintAmount <= maxMintAmountPerTx,
            "Invalid mint amount!"
        );
        require(
            totalSupply() + _mintAmount <= maxSupply,
            "Max supply exceeded!"
        );
        _;
    }

    modifier mintPriceCompliance(uint256 _mintAmount) {
        require(msg.value >= cost * _mintAmount, "Insufficient funds!");
        _;
    }

    function mint(uint256 _mintAmount)
        public
        payable
        mintCompliance(_mintAmount)
        mintPriceCompliance(_mintAmount)
    {
        require(!paused, "The contract is paused!");
        _safeMint(_msgSender(), _mintAmount);
    }

    function mintForAddress(uint256 _mintAmount, address _receiver)
        public
        mintCompliance(_mintAmount)
        onlyOwner
    {
        _safeMint(_receiver, _mintAmount);
    }

    function setMaxSupply(uint256 _newMaxSupply) public onlyOwner {
        require(_newMaxSupply >= totalSupply(), "Cannot set maxSupply below minted tokens");
        maxSupply = _newMaxSupply;
    }

    // Override _startTokenId to start token IDs at 1 instead of 0.
    function _startTokenId() internal view virtual override returns (uint256) {
        return 1;
    }

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

    function setCost(uint256 _cost) public onlyOwner {
        cost = _cost;
    }

    function setMaxMintAmountPerTx(uint256 _maxMintAmountPerTx) public onlyOwner {
        maxMintAmountPerTx = _maxMintAmountPerTx;
    }

    function setUriPrefix(string memory _uriPrefix) public onlyOwner {
        uriPrefix = _uriPrefix;
    }

    function setUriSuffix(string memory _uriSuffix) public onlyOwner {
        uriSuffix = _uriSuffix;
    }

    function setPaused(bool _state) public onlyOwner {
        paused = _state;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721A, IERC721A, ERC2981)
        returns (bool)
    {
        return ERC721A.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId);
    }

    function withdraw() public onlyOwner nonReentrant {
        (bool os, ) = payable(owner()).call{value: address(this).balance}("");
        require(os, "Withdraw failed");
    }

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

File 2 of 17 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.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);
    }
}

File 3 of 17 : IERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.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);
}

File 4 of 17 : ERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.20;

import {IERC2981} from "../../interfaces/IERC2981.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.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 an 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];
    }
}

File 5 of 17 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

File 6 of 17 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.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;
    }
}

File 7 of 17 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

File 8 of 17 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

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

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

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

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

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

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
            if (denominator <= prod1) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
            }

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

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

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

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

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

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

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

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

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

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

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

    /**
     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
     *
     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
     *
     * NOTE: this function does NOT check that `p` is a prime greater than `2`.
     */
    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 exp;
        unchecked {
            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
            value >>= exp;
            result += exp;

            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
            value >>= exp;
            result += exp;

            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
            value >>= exp;
            result += exp;

            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
            value >>= exp;
            result += exp;

            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
            value >>= exp;
            result += exp;

            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
            value >>= exp;
            result += exp;

            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
            value >>= exp;
            result += exp;

            result += SafeCast.toUint(value > 1);
        }
        return result;
    }

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

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

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

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 isGt;
        unchecked {
            isGt = SafeCast.toUint(value > (1 << 128) - 1);
            value >>= isGt * 128;
            result += isGt * 16;

            isGt = SafeCast.toUint(value > (1 << 64) - 1);
            value >>= isGt * 64;
            result += isGt * 8;

            isGt = SafeCast.toUint(value > (1 << 32) - 1);
            value >>= isGt * 32;
            result += isGt * 4;

            isGt = SafeCast.toUint(value > (1 << 16) - 1);
            value >>= isGt * 16;
            result += isGt * 2;

            result += SafeCast.toUint(value > (1 << 8) - 1);
        }
        return result;
    }

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

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 9 of 17 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

File 10 of 17 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

import {SafeCast} from "./SafeCast.sol";

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

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

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

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
            // taking advantage of the most significant (or "sign" bit) in two's complement representation.
            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
            int256 mask = n >> 255;

            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
            return uint256((n + mask) ^ mask);
        }
    }
}

File 11 of 17 : Panic.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 *
 * _Available since v5.1._
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

File 12 of 17 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

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

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

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

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

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 13 of 17 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SafeCast} from "./math/SafeCast.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    using SafeCast for *;

    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev The string being parsed contains characters that are not in scope of the given base.
     */
    error StringsInvalidChar();

    /**
     * @dev The string being parsed is not a properly formatted address.
     */
    error StringsInvalidAddressFormat();

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

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

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

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

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

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
     * representation, according to EIP-55.
     */
    function toChecksumHexString(address addr) internal pure returns (string memory) {
        bytes memory buffer = bytes(toHexString(addr));

        // hash the hex part of buffer (skip length + 2 bytes, length 40)
        uint256 hashValue;
        assembly ("memory-safe") {
            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
        }

        for (uint256 i = 41; i > 1; --i) {
            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
                // case shift by xoring with 0x20
                buffer[i] ^= 0x20;
            }
            hashValue >>= 4;
        }
        return string(buffer);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }

    /**
     * @dev Parse a decimal string and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(string memory input) internal pure returns (uint256) {
        return parseUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        uint256 result = 0;
        for (uint256 i = begin; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 9) return (false, 0);
            result *= 10;
            result += chr;
        }
        return (true, result);
    }

    /**
     * @dev Parse a decimal string and returns the value as a `int256`.
     *
     * Requirements:
     * - The string must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(string memory input) internal pure returns (int256) {
        return parseInt(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
        (bool success, int256 value) = tryParseInt(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
     * the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
    }

    uint256 private constant ABS_MIN_INT256 = 2 ** 255;

    /**
     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character or if the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, int256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseIntUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseIntUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, int256 value) {
        bytes memory buffer = bytes(input);

        // Check presence of a negative sign.
        bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        bool positiveSign = sign == bytes1("+");
        bool negativeSign = sign == bytes1("-");
        uint256 offset = (positiveSign || negativeSign).toUint();

        (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);

        if (absSuccess && absValue < ABS_MIN_INT256) {
            return (true, negativeSign ? -int256(absValue) : int256(absValue));
        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
            return (true, type(int256).min);
        } else return (false, 0);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(string memory input) internal pure returns (uint256) {
        return parseHexUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseHexUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
     * invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseHexUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseHexUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        // skip 0x prefix if present
        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 offset = hasPrefix.toUint() * 2;

        uint256 result = 0;
        for (uint256 i = begin + offset; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 15) return (false, 0);
            result *= 16;
            unchecked {
                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
                // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.
                result += chr;
            }
        }
        return (true, result);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(string memory input) internal pure returns (address) {
        return parseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
        (bool success, address value) = tryParseAddress(input, begin, end);
        if (!success) revert StringsInvalidAddressFormat();
        return value;
    }

    /**
     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
     * formatted address. See {parseAddress} requirements.
     */
    function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
        return tryParseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
     * formatted address. See {parseAddress} requirements.
     */
    function tryParseAddress(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, address value) {
        if (end > bytes(input).length || begin > end) return (false, address(0));

        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;

        // check that input is the correct length
        if (end - begin == expectedLength) {
            // length guarantees that this does not overflow, and value is at most type(uint160).max
            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
            return (s, address(uint160(v)));
        } else {
            return (false, address(0));
        }
    }

    function _tryParseChr(bytes1 chr) private pure returns (uint8) {
        uint8 value = uint8(chr);

        // Try to parse `chr`:
        // - Case 1: [0-9]
        // - Case 2: [a-f]
        // - Case 3: [A-F]
        // - otherwise not supported
        unchecked {
            if (value > 47 && value < 58) value -= 48;
            else if (value > 96 && value < 103) value -= 87;
            else if (value > 64 && value < 71) value -= 55;
            else return type(uint8).max;
        }

        return value;
    }

    /**
     * @dev Reads a bytes32 from a bytes array without bounds checking.
     *
     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
     * assembly block as such would prevent some optimizations.
     */
    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
        // This is not memory safe in the general case, but all calls to this private function are within bounds.
        assembly ("memory-safe") {
            value := mload(add(buffer, add(0x20, offset)))
        }
    }
}

File 14 of 17 : ERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import './IERC721A.sol';

/**
 * @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()`.
 *
 * The `_sequentialUpTo()` function can be overriden to enable spot mints
 * (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`.
 *
 * 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;

    // The amount of tokens minted above `_sequentialUpTo()`.
    // We call these spot mints (i.e. non-sequential mints).
    uint256 private _spotMinted;

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

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

        if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector);
    }

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

    /**
     * @dev Returns the starting token ID for sequential mints.
     *
     * Override this function to change the starting token ID for sequential mints.
     *
     * Note: The value returned must never change after any tokens have been minted.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the maximum token ID (inclusive) for sequential mints.
     *
     * Override this function to return a value less than 2**256 - 1,
     * but greater than `_startTokenId()`, to enable spot (non-sequential) mints.
     *
     * Note: The value returned must never change after any tokens have been minted.
     */
    function _sequentialUpTo() internal view virtual returns (uint256) {
        return type(uint256).max;
    }

    /**
     * @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 result) {
        // Counter underflow is impossible as `_burnCounter` cannot be incremented
        // more than `_currentIndex + _spotMinted - _startTokenId()` times.
        unchecked {
            // With spot minting, the intermediate `result` can be temporarily negative,
            // and the computation must be unchecked.
            result = _currentIndex - _burnCounter - _startTokenId();
            if (_sequentialUpTo() != type(uint256).max) result += _spotMinted;
        }
    }

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

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

    /**
     * @dev Returns the total number of tokens that are spot-minted.
     */
    function _totalSpotMinted() internal view virtual returns (uint256) {
        return _spotMinted;
    }

    // =============================================================
    //                    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.selector);
        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.selector);

        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 Returns whether the ownership slot at `index` is initialized.
     * An uninitialized slot does not necessarily mean that the slot has no owner.
     */
    function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) {
        return _packedOwnerships[index] != 0;
    }

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

    /**
     * @dev Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {
        if (_startTokenId() <= tokenId) {
            packed = _packedOwnerships[tokenId];

            if (tokenId > _sequentialUpTo()) {
                if (_packedOwnershipExists(packed)) return packed;
                _revert(OwnerQueryForNonexistentToken.selector);
            }

            // If the data at the starting slot does not exist, start the scan.
            if (packed == 0) {
                if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector);
                // 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;
                    if (packed & _BITMASK_BURNED == 0) return packed;
                    // Otherwise, the token is burned, and we must revert.
                    // This handles the case of batch burned tokens, where only the burned bit
                    // of the starting slot is set, and remaining slots are left uninitialized.
                    _revert(OwnerQueryForNonexistentToken.selector);
                }
            }
            // Otherwise, the data exists and 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.
            // If the token is not burned, return `packed`. Otherwise, revert.
            if (packed & _BITMASK_BURNED == 0) return packed;
        }
        _revert(OwnerQueryForNonexistentToken.selector);
    }

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

        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 result) {
        if (_startTokenId() <= tokenId) {
            if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]);

            if (tokenId < _currentIndex) {
                uint256 packed;
                while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId;
                result = packed & _BITMASK_BURNED == 0;
            }
        }
    }

    /**
     * @dev Returns whether `packed` represents a token that exists.
     */
    function _packedOwnershipExists(uint256 packed) private pure returns (bool result) {
        assembly {
            // The following is equivalent to `owner != address(0) && burned == false`.
            // Symbolically tested.
            result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_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);

        // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean.
        from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS));

        if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector);

        (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.selector);

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

        // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
        uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
        assembly {
            // 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.
                from, // `from`.
                toMasked, // `to`.
                tokenId // `tokenId`.
            )
        }
        if (toMasked == 0) _revert(TransferToZeroAddress.selector);

        _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.selector);
            }
    }

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

        _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:
            // - `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)
            );

            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
            uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;

            if (toMasked == 0) _revert(MintToZeroAddress.selector);

            uint256 end = startTokenId + quantity;
            uint256 tokenId = startTokenId;

            if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);

            do {
                assembly {
                    // 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`.
                        tokenId // `tokenId`.
                    )
                }
                // The `!=` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
            } while (++tokenId != end);

            _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.selector);
        if (quantity == 0) _revert(MintZeroQuantity.selector);
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector);

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

            if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);

            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.selector);
                    }
                } while (index < end);
                // This prevents reentrancy to `_safeMint`.
                // It does not prevent reentrancy to `_safeMintSpot`.
                if (_currentIndex != end) revert();
            }
        }
    }

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

    /**
     * @dev Mints a single token at `tokenId`.
     *
     * Note: A spot-minted `tokenId` that has been burned can be re-minted again.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` must be greater than `_sequentialUpTo()`.
     * - `tokenId` must not exist.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mintSpot(address to, uint256 tokenId) internal virtual {
        if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector);
        uint256 prevOwnershipPacked = _packedOwnerships[tokenId];
        if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector);

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

        // Overflows are incredibly unrealistic.
        // The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1.
        // `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1.
        unchecked {
            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `true` (as `quantity == 1`).
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked)
            );

            // Updates:
            // - `balance += 1`.
            // - `numberMinted += 1`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1;

            // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
            uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;

            if (toMasked == 0) _revert(MintToZeroAddress.selector);

            assembly {
                // 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`.
                    tokenId // `tokenId`.
                )
            }

            ++_spotMinted;
        }

        _afterTokenTransfers(address(0), to, tokenId, 1);
    }

    /**
     * @dev Safely mints a single token at `tokenId`.
     *
     * Note: A spot-minted `tokenId` that has been burned can be re-minted again.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}.
     * - `tokenId` must be greater than `_sequentialUpTo()`.
     * - `tokenId` must not exist.
     *
     * See {_mintSpot}.
     *
     * Emits a {Transfer} event.
     */
    function _safeMintSpot(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mintSpot(to, tokenId);

        unchecked {
            if (to.code.length != 0) {
                uint256 currentSpotMinted = _spotMinted;
                if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) {
                    _revert(TransferToNonERC721ReceiverImplementer.selector);
                }
                // This prevents reentrancy to `_safeMintSpot`.
                // It does not prevent reentrancy to `_safeMint`.
                if (_spotMinted != currentSpotMinted) revert();
            }
        }
    }

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

    // =============================================================
    //                       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 && _msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                _revert(ApprovalCallerNotOwnerNorApproved.selector);
            }

        _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.selector);
        }

        _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 + _spotMinted` 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.selector);
        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)
        }
    }

    /**
     * @dev For more efficient reverts.
     */
    function _revert(bytes4 errorSelector) internal pure {
        assembly {
            mstore(0x00, errorSelector)
            revert(0x00, 0x04)
        }
    }
}

File 15 of 17 : ERC721AQueryable.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import './IERC721AQueryable.sol';
import '../ERC721A.sol';

/**
 * @title ERC721AQueryable.
 *
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (TokenOwnership memory ownership)
    {
        unchecked {
            if (tokenId >= _startTokenId()) {
                if (tokenId > _sequentialUpTo()) return _ownershipAt(tokenId);

                if (tokenId < _nextTokenId()) {
                    // If the `tokenId` is within bounds,
                    // scan backwards for the initialized ownership slot.
                    while (!_ownershipIsInitialized(tokenId)) --tokenId;
                    return _ownershipAt(tokenId);
                }
            }
        }
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] calldata tokenIds)
        external
        view
        virtual
        override
        returns (TokenOwnership[] memory)
    {
        TokenOwnership[] memory ownerships;
        uint256 i = tokenIds.length;
        assembly {
            // Grab the free memory pointer.
            ownerships := mload(0x40)
            // Store the length.
            mstore(ownerships, i)
            // Allocate one word for the length,
            // `tokenIds.length` words for the pointers.
            i := shl(5, i) // Multiply `i` by 32.
            mstore(0x40, add(add(ownerships, 0x20), i))
        }
        while (i != 0) {
            uint256 tokenId;
            assembly {
                i := sub(i, 0x20)
                tokenId := calldataload(add(tokenIds.offset, i))
            }
            TokenOwnership memory ownership = explicitOwnershipOf(tokenId);
            assembly {
                // Store the pointer of `ownership` in the `ownerships` array.
                mstore(add(add(ownerships, 0x20), i), ownership)
            }
        }
        return ownerships;
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view virtual override returns (uint256[] memory) {
        return _tokensOfOwnerIn(owner, start, stop);
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {
        // If spot mints are enabled, full-range scan is disabled.
        if (_sequentialUpTo() != type(uint256).max) _revert(NotCompatibleWithSpotMints.selector);
        uint256 start = _startTokenId();
        uint256 stop = _nextTokenId();
        uint256[] memory tokenIds;
        if (start != stop) tokenIds = _tokensOfOwnerIn(owner, start, stop);
        return tokenIds;
    }

    /**
     * @dev Helper function for returning an array of token IDs owned by `owner`.
     *
     * Note that this function is optimized for smaller bytecode size over runtime gas,
     * since it is meant to be called off-chain.
     */
    function _tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) private view returns (uint256[] memory tokenIds) {
        unchecked {
            if (start >= stop) _revert(InvalidQueryRange.selector);
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) start = _startTokenId();
            uint256 nextTokenId = _nextTokenId();
            // If spot mints are enabled, scan all the way until the specified `stop`.
            uint256 stopLimit = _sequentialUpTo() != type(uint256).max ? stop : nextTokenId;
            // Set `stop = min(stop, stopLimit)`.
            if (stop >= stopLimit) stop = stopLimit;
            // Number of tokens to scan.
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength` to zero if the range contains no tokens.
            if (start >= stop) tokenIdsMaxLength = 0;
            // If there are one or more tokens to scan.
            if (tokenIdsMaxLength != 0) {
                // Set `tokenIdsMaxLength = min(balanceOf(owner), tokenIdsMaxLength)`.
                if (stop - start <= tokenIdsMaxLength) tokenIdsMaxLength = stop - start;
                uint256 m; // Start of available memory.
                assembly {
                    // Grab the free memory pointer.
                    tokenIds := mload(0x40)
                    // Allocate one word for the length, and `tokenIdsMaxLength` words
                    // for the data. `shl(5, x)` is equivalent to `mul(32, x)`.
                    m := add(tokenIds, shl(5, add(tokenIdsMaxLength, 1)))
                    mstore(0x40, m)
                }
                // We need to call `explicitOwnershipOf(start)`,
                // because the slot at `start` may not be initialized.
                TokenOwnership memory ownership = explicitOwnershipOf(start);
                address currOwnershipAddr;
                // If the starting slot exists (i.e. not burned),
                // initialize `currOwnershipAddr`.
                // `ownership.address` will not be zero,
                // as `start` is clamped to the valid token ID range.
                if (!ownership.burned) currOwnershipAddr = ownership.addr;
                uint256 tokenIdsIdx;
                // Use a do-while, which is slightly more efficient for this case,
                // as the array will at least contain one element.
                do {
                    if (_sequentialUpTo() != type(uint256).max) {
                        // Skip the remaining unused sequential slots.
                        if (start == nextTokenId) start = _sequentialUpTo() + 1;
                        // Reset `currOwnershipAddr`, as each spot-minted token is a batch of one.
                        if (start > _sequentialUpTo()) currOwnershipAddr = address(0);
                    }
                    ownership = _ownershipAt(start); // This implicitly allocates memory.
                    assembly {
                        switch mload(add(ownership, 0x40))
                        // if `ownership.burned == false`.
                        case 0 {
                            // if `ownership.addr != address(0)`.
                            // The `addr` already has it's upper 96 bits clearned,
                            // since it is written to memory with regular Solidity.
                            if mload(ownership) {
                                currOwnershipAddr := mload(ownership)
                            }
                            // if `currOwnershipAddr == owner`.
                            // The `shl(96, x)` is to make the comparison agnostic to any
                            // dirty upper 96 bits in `owner`.
                            if iszero(shl(96, xor(currOwnershipAddr, owner))) {
                                tokenIdsIdx := add(tokenIdsIdx, 1)
                                mstore(add(tokenIds, shl(5, tokenIdsIdx)), start)
                            }
                        }
                        // Otherwise, reset `currOwnershipAddr`.
                        // This handles the case of batch burned tokens
                        // (burned bit of first slot set, remaining slots left uninitialized).
                        default {
                            currOwnershipAddr := 0
                        }
                        start := add(start, 1)
                        // Free temporary memory implicitly allocated for ownership
                        // to avoid quadratic memory expansion costs.
                        mstore(0x40, m)
                    }
                } while (!(start == stop || tokenIdsIdx == tokenIdsMaxLength));
                // Store the length of the array.
                assembly {
                    mstore(tokenIds, tokenIdsIdx)
                }
            }
        }
    }
}

File 16 of 17 : IERC721AQueryable.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import '../IERC721A.sol';

/**
 * @dev Interface of ERC721AQueryable.
 */
interface IERC721AQueryable is IERC721A {
    /**
     * Invalid query range (`start` >= `stop`).
     */
    error InvalidQueryRange();

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view returns (uint256[] memory);
}

File 17 of 17 : IERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

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

    /**
     * `_sequentialUpTo()` must be greater than `_startTokenId()`.
     */
    error SequentialUpToTooSmall();

    /**
     * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`.
     */
    error SequentialMintExceedsLimit();

    /**
     * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`.
     */
    error SpotMintTokenIdTooSmall();

    /**
     * Cannot mint over a token that already exists.
     */
    error TokenAlreadyExists();

    /**
     * The feature is not compatible with spot mints.
     */
    error NotCompatibleWithSpotMints();

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

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_tokenName","type":"string"},{"internalType":"string","name":"_tokenSymbol","type":"string"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"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":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","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":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":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":"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":"to","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":"cost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"ownership","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmountPerTx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintForAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint256","name":"_cost","type":"uint256"}],"name":"setCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMintAmountPerTx","type":"uint256"}],"name":"setMaxMintAmountPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriPrefix","type":"string"}],"name":"setUriPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uriSuffix","type":"string"}],"name":"setUriSuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","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":[],"name":"uriPrefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uriSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260405180602001604052806000815250600d90816100229190610711565b506040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250600e90816100679190610711565b506001601260006101000a81548160ff02191690831515021790555034801561008f57600080fd5b5060405161496f38038061496f83398181016040528101906100b19190610955565b6100bf61020660201b60201c565b838381600290816100d09190610711565b5080600390816100e09190610711565b506100ef61020e60201b60201c565b60008190555061010361020e60201b60201c565b61011161021760201b60201c565b101561012e5761012d63fed8210f60e01b61023f60201b60201c565b5b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036101a25760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016101999190610a21565b60405180910390fd5b6101b18161024960201b60201c565b506001600a81905550678ac7230489e80000600f8190555080601081905550600a6011819055506101fe73e0fb2232d81b4cd9bbfe2ade1402c2de018a922561032061030f60201b60201c565b505050610abd565b600033905090565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b8060005260046000fd5b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600061031f6104b760201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156103845781816040517f6f483d0900000000000000000000000000000000000000000000000000000000815260040161037b929190610a94565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036103f65760006040517fb6d9900a0000000000000000000000000000000000000000000000000000000081526004016103ed9190610a21565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b60008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b6000612710905090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061054257607f821691505b602082108103610555576105546104fb565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026105bd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610580565b6105c78683610580565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600061060e610609610604846105df565b6105e9565b6105df565b9050919050565b6000819050919050565b610628836105f3565b61063c61063482610615565b84845461058d565b825550505050565b600090565b610651610644565b61065c81848461061f565b505050565b5b8181101561068057610675600082610649565b600181019050610662565b5050565b601f8211156106c5576106968161055b565b61069f84610570565b810160208510156106ae578190505b6106c26106ba85610570565b830182610661565b50505b505050565b600082821c905092915050565b60006106e8600019846008026106ca565b1980831691505092915050565b600061070183836106d7565b9150826002028217905092915050565b61071a826104c1565b67ffffffffffffffff811115610733576107326104cc565b5b61073d825461052a565b610748828285610684565b600060209050601f83116001811461077b5760008415610769578287015190505b61077385826106f5565b8655506107db565b601f1984166107898661055b565b60005b828110156107b15784890151825560018201915060208501945060208101905061078c565b868310156107ce57848901516107ca601f8916826106d7565b8355505b6001600288020188555050505b505050505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b61081b82610801565b810181811067ffffffffffffffff8211171561083a576108396104cc565b5b80604052505050565b600061084d6107e3565b90506108598282610812565b919050565b600067ffffffffffffffff821115610879576108786104cc565b5b61088282610801565b9050602081019050919050565b60005b838110156108ad578082015181840152602081019050610892565b60008484015250505050565b60006108cc6108c78461085e565b610843565b9050828152602081018484840111156108e8576108e76107fc565b5b6108f384828561088f565b509392505050565b600082601f8301126109105761090f6107f7565b5b81516109208482602086016108b9565b91505092915050565b610932816105df565b811461093d57600080fd5b50565b60008151905061094f81610929565b92915050565b60008060006060848603121561096e5761096d6107ed565b5b600084015167ffffffffffffffff81111561098c5761098b6107f2565b5b610998868287016108fb565b935050602084015167ffffffffffffffff8111156109b9576109b86107f2565b5b6109c5868287016108fb565b92505060406109d686828701610940565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610a0b826109e0565b9050919050565b610a1b81610a00565b82525050565b6000602082019050610a366000830184610a12565b92915050565b60006bffffffffffffffffffffffff82169050919050565b6000610a6f610a6a610a6584610a3c565b6105e9565b6105df565b9050919050565b610a7f81610a54565b82525050565b610a8e816105df565b82525050565b6000604082019050610aa96000830185610a76565b610ab66020830184610a85565b9392505050565b613ea380610acc6000396000f3fe60806040526004361061021a5760003560e01c80636f8b44b011610123578063a0712d68116100ab578063c87b56dd1161006f578063c87b56dd146107a1578063d5abeb01146107de578063e985e9c514610809578063efbd73f414610846578063f2fde38b1461086f5761021a565b8063a0712d68146106da578063a22cb465146106f6578063b071401b1461071f578063b88d4fde14610748578063c23dc68f146107645761021a565b80638462151c116100f25780638462151c146105df5780638da5cb5b1461061c57806394354fd01461064757806395d89b411461067257806399a2557a1461069d5761021a565b80636f8b44b01461053957806370a0823114610562578063715018a61461059f5780637ec4a659146105b65761021a565b80632a55205a116101a65780635503a0e8116101755780635503a0e81461043e5780635bbb2177146104695780635c975abb146104a657806362b99ad4146104d15780636352211e146104fc5761021a565b80632a55205a146103a45780633ccfd60b146103e257806342842e0e146103f957806344a0d68a146104155761021a565b806313faede6116101ed57806313faede6146102e057806316ba10e01461030b57806316c38b3c1461033457806318160ddd1461035d57806323b872dd146103885761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612a25565b610898565b6040516102539190612a6d565b60405180910390f35b34801561026857600080fd5b506102716108ba565b60405161027e9190612b18565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190612b70565b61094c565b6040516102bb9190612bde565b60405180910390f35b6102de60048036038101906102d99190612c25565b6109aa565b005b3480156102ec57600080fd5b506102f56109ba565b6040516103029190612c74565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190612dc4565b6109c0565b005b34801561034057600080fd5b5061035b60048036038101906103569190612e39565b6109db565b005b34801561036957600080fd5b50610372610a00565b60405161037f9190612c74565b60405180910390f35b6103a2600480360381019061039d9190612e66565b610a4d565b005b3480156103b057600080fd5b506103cb60048036038101906103c69190612eb9565b610d0e565b6040516103d9929190612ef9565b60405180910390f35b3480156103ee57600080fd5b506103f7610e3e565b005b610413600480360381019061040e9190612e66565b610f0c565b005b34801561042157600080fd5b5061043c60048036038101906104379190612b70565b610f2c565b005b34801561044a57600080fd5b50610453610f3e565b6040516104609190612b18565b60405180910390f35b34801561047557600080fd5b50610490600480360381019061048b9190612f82565b610fcc565b60405161049d9190613132565b60405180910390f35b3480156104b257600080fd5b506104bb61102c565b6040516104c89190612a6d565b60405180910390f35b3480156104dd57600080fd5b506104e661103f565b6040516104f39190612b18565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e9190612b70565b6110cd565b6040516105309190612bde565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b9190612b70565b6110df565b005b34801561056e57600080fd5b5061058960048036038101906105849190613154565b61113b565b6040516105969190612c74565b60405180910390f35b3480156105ab57600080fd5b506105b46111d2565b005b3480156105c257600080fd5b506105dd60048036038101906105d89190612dc4565b6111e6565b005b3480156105eb57600080fd5b5061060660048036038101906106019190613154565b611201565b604051610613919061323f565b60405180910390f35b34801561062857600080fd5b5061063161127c565b60405161063e9190612bde565b60405180910390f35b34801561065357600080fd5b5061065c6112a6565b6040516106699190612c74565b60405180910390f35b34801561067e57600080fd5b506106876112ac565b6040516106949190612b18565b60405180910390f35b3480156106a957600080fd5b506106c460048036038101906106bf9190613261565b61133e565b6040516106d1919061323f565b60405180910390f35b6106f460048036038101906106ef9190612b70565b611354565b005b34801561070257600080fd5b5061071d600480360381019061071891906132b4565b6114b4565b005b34801561072b57600080fd5b5061074660048036038101906107419190612b70565b6115bf565b005b610762600480360381019061075d9190613395565b6115d1565b005b34801561077057600080fd5b5061078b60048036038101906107869190612b70565b611623565b604051610798919061346d565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190612b70565b611698565b6040516107d59190612b18565b60405180910390f35b3480156107ea57600080fd5b506107f3611742565b6040516108009190612c74565b60405180910390f35b34801561081557600080fd5b50610830600480360381019061082b9190613488565b611748565b60405161083d9190612a6d565b60405180910390f35b34801561085257600080fd5b5061086d600480360381019061086891906134c8565b6117dc565b005b34801561087b57600080fd5b5061089660048036038101906108919190613154565b61189c565b005b60006108a382611922565b806108b357506108b2826119b4565b5b9050919050565b6060600280546108c990613537565b80601f01602080910402602001604051908101604052809291908181526020018280546108f590613537565b80156109425780601f1061091757610100808354040283529160200191610942565b820191906000526020600020905b81548152906001019060200180831161092557829003601f168201915b5050505050905090565b600061095782611a2e565b61096c5761096b63cf4700e460e01b611ada565b5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b682826001611ae4565b5050565b600f5481565b6109c8611c13565b80600e90816109d79190613714565b5050565b6109e3611c13565b80601260006101000a81548160ff02191690831515021790555050565b6000610a0a611c9a565b600154600054030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a3d611ca3565b14610a4a57600854810190505b90565b6000610a5882611ccb565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acd57610acc63a114810060e01b611ada565b5b600080610ad984611de4565b91509150610aef8187610aea611e0b565b611e13565b610b1a57610b0486610aff611e0b565b611748565b610b1957610b186359c896be60e01b611ada565b5b5b610b278686866001611e57565b8015610b3257600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610c0085610bdc888887611e5d565b7c020000000000000000000000000000000000000000000000000000000017611e85565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610c865760006001850190506000600460008381526020019081526020016000205403610c84576000548114610c83578360046000838152602001908152602001600020819055505b5b505b600073ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a460008103610cf857610cf763ea553b3460e01b611ada565b5b610d058787876001611eb0565b50505050505050565b6000806000600c6000868152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a90046bffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610def57600b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600b60000160149054906101000a90046bffffffffffffffffffffffff1690505b6000610df9611eb6565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610e219190613815565b610e2b9190613886565b9050828195509550505050509250929050565b610e46611c13565b610e4e611ec0565b6000610e5861127c565b73ffffffffffffffffffffffffffffffffffffffff1647604051610e7b906138e8565b60006040518083038185875af1925050503d8060008114610eb8576040519150601f19603f3d011682016040523d82523d6000602084013e610ebd565b606091505b5050905080610f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef890613949565b60405180910390fd5b50610f0a611f06565b565b610f27838383604051806020016040528060008152506115d1565b505050565b610f34611c13565b80600f8190555050565b600e8054610f4b90613537565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7790613537565b8015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b505050505081565b606080600084849050905060405191508082528060051b90508060208301016040525b60008114611021576000602082039150818601359050600061101082611623565b905080836020860101525050610fef565b819250505092915050565b601260009054906101000a900460ff1681565b600d805461104c90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461107890613537565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b505050505081565b60006110d882611ccb565b9050919050565b6110e7611c13565b6110ef610a00565b811015611131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128906139db565b60405180910390fd5b8060108190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118157611180638f4eb60460e01b611ada565b5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6111da611c13565b6111e46000611f10565b565b6111ee611c13565b80600d90816111fd9190613714565b5050565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61122c611ca3565b146112425761124163bdba09d760e01b611ada565b5b600061124c611c9a565b90506000611258611fd6565b905060608183146112715761126e858484611fdf565b90505b809350505050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b6060600380546112bb90613537565b80601f01602080910402602001604051908101604052809291908181526020018280546112e790613537565b80156113345780601f1061130957610100808354040283529160200191611334565b820191906000526020600020905b81548152906001019060200180831161131757829003601f168201915b5050505050905090565b606061134b848484611fdf565b90509392505050565b8060008111801561136757506011548111155b6113a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139d90613a47565b60405180910390fd5b601054816113b2610a00565b6113bc9190613a67565b11156113fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f490613ae7565b60405180910390fd5b8180600f5461140c9190613815565b34101561144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144590613b53565b60405180910390fd5b601260009054906101000a900460ff161561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590613bbf565b60405180910390fd5b6114af6114a961219b565b846121a3565b505050565b80600760006114c1611e0b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661156e611e0b565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115b39190612a6d565b60405180910390a35050565b6115c7611c13565b8060118190555050565b6115dc848484610a4d565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461161d57611607848484846121c1565b61161c5761161b63d1a57ed660e01b611ada565b5b5b50505050565b61162b61296a565b611633611c9a565b821061169257611641611ca3565b82111561165857611651826122f0565b9050611693565b611660611fd6565b821015611691575b6116718261231b565b6116815781600190039150611668565b61168a826122f0565b9050611693565b5b5b919050565b60606116a382611a2e565b6116e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d990613c51565b60405180910390fd5b60006116ec61233b565b9050600081511161170c576040518060200160405280600081525061173a565b80611716846123cd565b600e60405160200161172a93929190613d30565b6040516020818303038152906040525b915050919050565b60105481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816000811180156117ef57506011548111155b61182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590613a47565b60405180910390fd5b6010548161183a610a00565b6118449190613a67565b1115611885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187c90613ae7565b60405180910390fd5b61188d611c13565b61189782846121a3565b505050565b6118a4611c13565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119165760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161190d9190612bde565b60405180910390fd5b61191f81611f10565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061197d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806119ad5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a275750611a268261249b565b5b9050919050565b600081611a39611c9a565b11611ad457611a46611ca3565b821115611a7057611a696004600084815260200190815260200160002054612505565b9050611ad5565b600054821015611ad35760005b6000600460008581526020019081526020016000205491508103611aac5782611aa590613d61565b9250611a7d565b60007c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b8060005260046000fd5b6000611aef836110cd565b9050818015611b3157508073ffffffffffffffffffffffffffffffffffffffff16611b18611e0b565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611b5d57611b4781611b42611e0b565b611748565b611b5c57611b5b63cfb3b94260e01b611ada565b5b5b836006600085815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b611c1b61219b565b73ffffffffffffffffffffffffffffffffffffffff16611c3961127c565b73ffffffffffffffffffffffffffffffffffffffff1614611c9857611c5c61219b565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c8f9190612bde565b60405180910390fd5b565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b600081611cd6611c9a565b11611dce5760046000838152602001908152602001600020549050611cf9611ca3565b821115611d1e57611d0981612505565b611ddf57611d1d63df2d9b4260e01b611ada565b5b60008103611da5576000548210611d4057611d3f63df2d9b4260e01b611ada565b5b5b60046000836001900393508381526020019081526020016000205490506000810315611da05760007c010000000000000000000000000000000000000000000000000000000082160315611ddf57611d9f63df2d9b4260e01b611ada565b5b611d41565b60007c010000000000000000000000000000000000000000000000000000000082160315611ddf575b611dde63df2d9b4260e01b611ada565b5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611e74868684612546565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000612710905090565b6002600a5403611efc576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a81905550565b6001600a81905550565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008054905090565b6060818310611ff957611ff86332c1995a60e01b611ada565b5b612001611c9a565b83101561201357612010611c9a565b92505b600061201d611fd6565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61204a611ca3565b036120555781612057565b835b9050808410612064578093505b600061206f8761113b565b905084861061207d57600090505b600081146121915780868603116120945785850390505b600060405194506001820160051b850190508060405260006120b588611623565b9050600081604001516120ca57816000015190505b60005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6120f6611ca3565b1461212557868a0361211057600161210c611ca3565b0199505b612118611ca3565b8a111561212457600091505b5b61212e8a6122f0565b9250604083015160008114612146576000925061216c565b83511561215257835192505b8b831860601b61216b576001820191508a8260051b8a01525b5b5060018a01995083604052888a148061218457508481145b156120cd57808852505050505b5050509392505050565b600033905090565b6121bd82826040518060200160405280600081525061254f565b5050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026121e7611e0b565b8786866040518563ffffffff1660e01b81526004016122099493929190613ddf565b6020604051808303816000875af192505050801561224557506040513d601f19601f820116820180604052508101906122429190613e40565b60015b61229d573d8060008114612275576040519150601f19603f3d011682016040523d82523d6000602084013e61227a565b606091505b5060008151036122955761229463d1a57ed660e01b611ada565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6122f861296a565b61231460046000848152602001908152602001600020546125cb565b9050919050565b600080600460008481526020019081526020016000205414159050919050565b6060600d805461234a90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461237690613537565b80156123c35780601f10612398576101008083540402835291602001916123c3565b820191906000526020600020905b8154815290600101906020018083116123a657829003601f168201915b5050505050905090565b6060600060016123dc84612681565b01905060008167ffffffffffffffff8111156123fb576123fa612c99565b5b6040519080825280601f01601f19166020018201604052801561242d5781602001600182028036833780820191505090505b509050600082602001820190505b600115612490578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248457612483613857565b5b0494506000850361243b575b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60007c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b60009392505050565b61255983836127d4565b60008373ffffffffffffffffffffffffffffffffffffffff163b146125c657600080549050600083820390505b61259960008683806001019450866121c1565b6125ae576125ad63d1a57ed660e01b611ada565b5b8181106125865781600054146125c357600080fd5b50505b505050565b6125d361296a565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106126df577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816126d5576126d4613857565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061271c576d04ee2d6d415b85acef8100000000838161271257612711613857565b5b0492506020810190505b662386f26fc10000831061274b57662386f26fc10000838161274157612740613857565b5b0492506010810190505b6305f5e1008310612774576305f5e100838161276a57612769613857565b5b0492506008810190505b612710831061279957612710838161278f5761278e613857565b5b0492506004810190505b606483106127bc57606483816127b2576127b1613857565b5b0492506002810190505b600a83106127cb576001810190505b80915050919050565b600080549050600082036127f3576127f263b562e8dd60e01b611ada565b5b6128006000848385611e57565b612820836128116000866000611e5d565b61281a8561295a565b17611e85565b6004600083815260200190815260200160002081905550600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff16169050600081036128d8576128d7632e07630060e01b611ada565b5b6000838301905060008390506128ec611ca3565b600183031115612907576129066381647e3a60e01b611ada565b5b5b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a481816001019150810361290857816000819055505050506129556000848385611eb0565b505050565b60006001821460e11b9050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612a02816129cd565b8114612a0d57600080fd5b50565b600081359050612a1f816129f9565b92915050565b600060208284031215612a3b57612a3a6129c3565b5b6000612a4984828501612a10565b91505092915050565b60008115159050919050565b612a6781612a52565b82525050565b6000602082019050612a826000830184612a5e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ac2578082015181840152602081019050612aa7565b60008484015250505050565b6000601f19601f8301169050919050565b6000612aea82612a88565b612af48185612a93565b9350612b04818560208601612aa4565b612b0d81612ace565b840191505092915050565b60006020820190508181036000830152612b328184612adf565b905092915050565b6000819050919050565b612b4d81612b3a565b8114612b5857600080fd5b50565b600081359050612b6a81612b44565b92915050565b600060208284031215612b8657612b856129c3565b5b6000612b9484828501612b5b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612bc882612b9d565b9050919050565b612bd881612bbd565b82525050565b6000602082019050612bf36000830184612bcf565b92915050565b612c0281612bbd565b8114612c0d57600080fd5b50565b600081359050612c1f81612bf9565b92915050565b60008060408385031215612c3c57612c3b6129c3565b5b6000612c4a85828601612c10565b9250506020612c5b85828601612b5b565b9150509250929050565b612c6e81612b3a565b82525050565b6000602082019050612c896000830184612c65565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cd182612ace565b810181811067ffffffffffffffff82111715612cf057612cef612c99565b5b80604052505050565b6000612d036129b9565b9050612d0f8282612cc8565b919050565b600067ffffffffffffffff821115612d2f57612d2e612c99565b5b612d3882612ace565b9050602081019050919050565b82818337600083830152505050565b6000612d67612d6284612d14565b612cf9565b905082815260208101848484011115612d8357612d82612c94565b5b612d8e848285612d45565b509392505050565b600082601f830112612dab57612daa612c8f565b5b8135612dbb848260208601612d54565b91505092915050565b600060208284031215612dda57612dd96129c3565b5b600082013567ffffffffffffffff811115612df857612df76129c8565b5b612e0484828501612d96565b91505092915050565b612e1681612a52565b8114612e2157600080fd5b50565b600081359050612e3381612e0d565b92915050565b600060208284031215612e4f57612e4e6129c3565b5b6000612e5d84828501612e24565b91505092915050565b600080600060608486031215612e7f57612e7e6129c3565b5b6000612e8d86828701612c10565b9350506020612e9e86828701612c10565b9250506040612eaf86828701612b5b565b9150509250925092565b60008060408385031215612ed057612ecf6129c3565b5b6000612ede85828601612b5b565b9250506020612eef85828601612b5b565b9150509250929050565b6000604082019050612f0e6000830185612bcf565b612f1b6020830184612c65565b9392505050565b600080fd5b600080fd5b60008083601f840112612f4257612f41612c8f565b5b8235905067ffffffffffffffff811115612f5f57612f5e612f22565b5b602083019150836020820283011115612f7b57612f7a612f27565b5b9250929050565b60008060208385031215612f9957612f986129c3565b5b600083013567ffffffffffffffff811115612fb757612fb66129c8565b5b612fc385828601612f2c565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61300481612bbd565b82525050565b600067ffffffffffffffff82169050919050565b6130278161300a565b82525050565b61303681612a52565b82525050565b600062ffffff82169050919050565b6130548161303c565b82525050565b6080820160008201516130706000850182612ffb565b506020820151613083602085018261301e565b506040820151613096604085018261302d565b5060608201516130a9606085018261304b565b50505050565b60006130bb838361305a565b60808301905092915050565b6000602082019050919050565b60006130df82612fcf565b6130e98185612fda565b93506130f483612feb565b8060005b8381101561312557815161310c88826130af565b9750613117836130c7565b9250506001810190506130f8565b5085935050505092915050565b6000602082019050818103600083015261314c81846130d4565b905092915050565b60006020828403121561316a576131696129c3565b5b600061317884828501612c10565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6131b681612b3a565b82525050565b60006131c883836131ad565b60208301905092915050565b6000602082019050919050565b60006131ec82613181565b6131f6818561318c565b93506132018361319d565b8060005b8381101561323257815161321988826131bc565b9750613224836131d4565b925050600181019050613205565b5085935050505092915050565b6000602082019050818103600083015261325981846131e1565b905092915050565b60008060006060848603121561327a576132796129c3565b5b600061328886828701612c10565b935050602061329986828701612b5b565b92505060406132aa86828701612b5b565b9150509250925092565b600080604083850312156132cb576132ca6129c3565b5b60006132d985828601612c10565b92505060206132ea85828601612e24565b9150509250929050565b600067ffffffffffffffff82111561330f5761330e612c99565b5b61331882612ace565b9050602081019050919050565b6000613338613333846132f4565b612cf9565b90508281526020810184848401111561335457613353612c94565b5b61335f848285612d45565b509392505050565b600082601f83011261337c5761337b612c8f565b5b813561338c848260208601613325565b91505092915050565b600080600080608085870312156133af576133ae6129c3565b5b60006133bd87828801612c10565b94505060206133ce87828801612c10565b93505060406133df87828801612b5b565b925050606085013567ffffffffffffffff811115613400576133ff6129c8565b5b61340c87828801613367565b91505092959194509250565b60808201600082015161342e6000850182612ffb565b506020820151613441602085018261301e565b506040820151613454604085018261302d565b506060820151613467606085018261304b565b50505050565b60006080820190506134826000830184613418565b92915050565b6000806040838503121561349f5761349e6129c3565b5b60006134ad85828601612c10565b92505060206134be85828601612c10565b9150509250929050565b600080604083850312156134df576134de6129c3565b5b60006134ed85828601612b5b565b92505060206134fe85828601612c10565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061354f57607f821691505b60208210810361356257613561613508565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261358d565b6135d4868361358d565b95508019841693508086168417925050509392505050565b6000819050919050565b600061361161360c61360784612b3a565b6135ec565b612b3a565b9050919050565b6000819050919050565b61362b836135f6565b61363f61363782613618565b84845461359a565b825550505050565b600090565b613654613647565b61365f818484613622565b505050565b5b818110156136835761367860008261364c565b600181019050613665565b5050565b601f8211156136c85761369981613568565b6136a28461357d565b810160208510156136b1578190505b6136c56136bd8561357d565b830182613664565b50505b505050565b600082821c905092915050565b60006136eb600019846008026136cd565b1980831691505092915050565b600061370483836136da565b9150826002028217905092915050565b61371d82612a88565b67ffffffffffffffff81111561373657613735612c99565b5b6137408254613537565b61374b828285613687565b600060209050601f83116001811461377e576000841561376c578287015190505b61377685826136f8565b8655506137de565b601f19841661378c86613568565b60005b828110156137b45784890151825560018201915060208501945060208101905061378f565b868310156137d157848901516137cd601f8916826136da565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061382082612b3a565b915061382b83612b3a565b925082820261383981612b3a565b915082820484148315176138505761384f6137e6565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061389182612b3a565b915061389c83612b3a565b9250826138ac576138ab613857565b5b828204905092915050565b600081905092915050565b50565b60006138d26000836138b7565b91506138dd826138c2565b600082019050919050565b60006138f3826138c5565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b6000613933600f83612a93565b915061393e826138fd565b602082019050919050565b6000602082019050818103600083015261396281613926565b9050919050565b7f43616e6e6f7420736574206d6178537570706c792062656c6f77206d696e746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006139c5602883612a93565b91506139d082613969565b604082019050919050565b600060208201905081810360008301526139f4816139b8565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000613a31601483612a93565b9150613a3c826139fb565b602082019050919050565b60006020820190508181036000830152613a6081613a24565b9050919050565b6000613a7282612b3a565b9150613a7d83612b3a565b9250828201905080821115613a9557613a946137e6565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b6000613ad1601483612a93565b9150613adc82613a9b565b602082019050919050565b60006020820190508181036000830152613b0081613ac4565b9050919050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000613b3d601383612a93565b9150613b4882613b07565b602082019050919050565b60006020820190508181036000830152613b6c81613b30565b9050919050565b7f54686520636f6e74726163742069732070617573656421000000000000000000600082015250565b6000613ba9601783612a93565b9150613bb482613b73565b602082019050919050565b60006020820190508181036000830152613bd881613b9c565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613c3b602f83612a93565b9150613c4682613bdf565b604082019050919050565b60006020820190508181036000830152613c6a81613c2e565b9050919050565b600081905092915050565b6000613c8782612a88565b613c918185613c71565b9350613ca1818560208601612aa4565b80840191505092915050565b60008154613cba81613537565b613cc48186613c71565b94506001821660008114613cdf5760018114613cf457613d27565b60ff1983168652811515820286019350613d27565b613cfd85613568565b60005b83811015613d1f57815481890152600182019150602081019050613d00565b838801955050505b50505092915050565b6000613d3c8286613c7c565b9150613d488285613c7c565b9150613d548284613cad565b9150819050949350505050565b6000613d6c82612b3a565b915060008203613d7f57613d7e6137e6565b5b600182039050919050565b600081519050919050565b600082825260208201905092915050565b6000613db182613d8a565b613dbb8185613d95565b9350613dcb818560208601612aa4565b613dd481612ace565b840191505092915050565b6000608082019050613df46000830187612bcf565b613e016020830186612bcf565b613e0e6040830185612c65565b8181036060830152613e208184613da6565b905095945050505050565b600081519050613e3a816129f9565b92915050565b600060208284031215613e5657613e556129c3565b5b6000613e6484828501613e2b565b9150509291505056fea2646970667358221220cdd3a427bc75354e732226c42cc1dd4859a936a190695fec7921723072aefb1c64736f6c634300081c0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000f457465726e616c53756e6469616c73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024553000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061021a5760003560e01c80636f8b44b011610123578063a0712d68116100ab578063c87b56dd1161006f578063c87b56dd146107a1578063d5abeb01146107de578063e985e9c514610809578063efbd73f414610846578063f2fde38b1461086f5761021a565b8063a0712d68146106da578063a22cb465146106f6578063b071401b1461071f578063b88d4fde14610748578063c23dc68f146107645761021a565b80638462151c116100f25780638462151c146105df5780638da5cb5b1461061c57806394354fd01461064757806395d89b411461067257806399a2557a1461069d5761021a565b80636f8b44b01461053957806370a0823114610562578063715018a61461059f5780637ec4a659146105b65761021a565b80632a55205a116101a65780635503a0e8116101755780635503a0e81461043e5780635bbb2177146104695780635c975abb146104a657806362b99ad4146104d15780636352211e146104fc5761021a565b80632a55205a146103a45780633ccfd60b146103e257806342842e0e146103f957806344a0d68a146104155761021a565b806313faede6116101ed57806313faede6146102e057806316ba10e01461030b57806316c38b3c1461033457806318160ddd1461035d57806323b872dd146103885761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612a25565b610898565b6040516102539190612a6d565b60405180910390f35b34801561026857600080fd5b506102716108ba565b60405161027e9190612b18565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190612b70565b61094c565b6040516102bb9190612bde565b60405180910390f35b6102de60048036038101906102d99190612c25565b6109aa565b005b3480156102ec57600080fd5b506102f56109ba565b6040516103029190612c74565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190612dc4565b6109c0565b005b34801561034057600080fd5b5061035b60048036038101906103569190612e39565b6109db565b005b34801561036957600080fd5b50610372610a00565b60405161037f9190612c74565b60405180910390f35b6103a2600480360381019061039d9190612e66565b610a4d565b005b3480156103b057600080fd5b506103cb60048036038101906103c69190612eb9565b610d0e565b6040516103d9929190612ef9565b60405180910390f35b3480156103ee57600080fd5b506103f7610e3e565b005b610413600480360381019061040e9190612e66565b610f0c565b005b34801561042157600080fd5b5061043c60048036038101906104379190612b70565b610f2c565b005b34801561044a57600080fd5b50610453610f3e565b6040516104609190612b18565b60405180910390f35b34801561047557600080fd5b50610490600480360381019061048b9190612f82565b610fcc565b60405161049d9190613132565b60405180910390f35b3480156104b257600080fd5b506104bb61102c565b6040516104c89190612a6d565b60405180910390f35b3480156104dd57600080fd5b506104e661103f565b6040516104f39190612b18565b60405180910390f35b34801561050857600080fd5b50610523600480360381019061051e9190612b70565b6110cd565b6040516105309190612bde565b60405180910390f35b34801561054557600080fd5b50610560600480360381019061055b9190612b70565b6110df565b005b34801561056e57600080fd5b5061058960048036038101906105849190613154565b61113b565b6040516105969190612c74565b60405180910390f35b3480156105ab57600080fd5b506105b46111d2565b005b3480156105c257600080fd5b506105dd60048036038101906105d89190612dc4565b6111e6565b005b3480156105eb57600080fd5b5061060660048036038101906106019190613154565b611201565b604051610613919061323f565b60405180910390f35b34801561062857600080fd5b5061063161127c565b60405161063e9190612bde565b60405180910390f35b34801561065357600080fd5b5061065c6112a6565b6040516106699190612c74565b60405180910390f35b34801561067e57600080fd5b506106876112ac565b6040516106949190612b18565b60405180910390f35b3480156106a957600080fd5b506106c460048036038101906106bf9190613261565b61133e565b6040516106d1919061323f565b60405180910390f35b6106f460048036038101906106ef9190612b70565b611354565b005b34801561070257600080fd5b5061071d600480360381019061071891906132b4565b6114b4565b005b34801561072b57600080fd5b5061074660048036038101906107419190612b70565b6115bf565b005b610762600480360381019061075d9190613395565b6115d1565b005b34801561077057600080fd5b5061078b60048036038101906107869190612b70565b611623565b604051610798919061346d565b60405180910390f35b3480156107ad57600080fd5b506107c860048036038101906107c39190612b70565b611698565b6040516107d59190612b18565b60405180910390f35b3480156107ea57600080fd5b506107f3611742565b6040516108009190612c74565b60405180910390f35b34801561081557600080fd5b50610830600480360381019061082b9190613488565b611748565b60405161083d9190612a6d565b60405180910390f35b34801561085257600080fd5b5061086d600480360381019061086891906134c8565b6117dc565b005b34801561087b57600080fd5b5061089660048036038101906108919190613154565b61189c565b005b60006108a382611922565b806108b357506108b2826119b4565b5b9050919050565b6060600280546108c990613537565b80601f01602080910402602001604051908101604052809291908181526020018280546108f590613537565b80156109425780601f1061091757610100808354040283529160200191610942565b820191906000526020600020905b81548152906001019060200180831161092557829003601f168201915b5050505050905090565b600061095782611a2e565b61096c5761096b63cf4700e460e01b611ada565b5b6006600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6109b682826001611ae4565b5050565b600f5481565b6109c8611c13565b80600e90816109d79190613714565b5050565b6109e3611c13565b80601260006101000a81548160ff02191690831515021790555050565b6000610a0a611c9a565b600154600054030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610a3d611ca3565b14610a4a57600854810190505b90565b6000610a5882611ccb565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610acd57610acc63a114810060e01b611ada565b5b600080610ad984611de4565b91509150610aef8187610aea611e0b565b611e13565b610b1a57610b0486610aff611e0b565b611748565b610b1957610b186359c896be60e01b611ada565b5b5b610b278686866001611e57565b8015610b3257600082555b600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081546001900391905081905550600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815460010191905081905550610c0085610bdc888887611e5d565b7c020000000000000000000000000000000000000000000000000000000017611e85565b600460008681526020019081526020016000208190555060007c0200000000000000000000000000000000000000000000000000000000841603610c865760006001850190506000600460008381526020019081526020016000205403610c84576000548114610c83578360046000838152602001908152602001600020819055505b5b505b600073ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a460008103610cf857610cf763ea553b3460e01b611ada565b5b610d058787876001611eb0565b50505050505050565b6000806000600c6000868152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a90046bffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610def57600b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600b60000160149054906101000a90046bffffffffffffffffffffffff1690505b6000610df9611eb6565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610e219190613815565b610e2b9190613886565b9050828195509550505050509250929050565b610e46611c13565b610e4e611ec0565b6000610e5861127c565b73ffffffffffffffffffffffffffffffffffffffff1647604051610e7b906138e8565b60006040518083038185875af1925050503d8060008114610eb8576040519150601f19603f3d011682016040523d82523d6000602084013e610ebd565b606091505b5050905080610f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef890613949565b60405180910390fd5b50610f0a611f06565b565b610f27838383604051806020016040528060008152506115d1565b505050565b610f34611c13565b80600f8190555050565b600e8054610f4b90613537565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7790613537565b8015610fc45780601f10610f9957610100808354040283529160200191610fc4565b820191906000526020600020905b815481529060010190602001808311610fa757829003601f168201915b505050505081565b606080600084849050905060405191508082528060051b90508060208301016040525b60008114611021576000602082039150818601359050600061101082611623565b905080836020860101525050610fef565b819250505092915050565b601260009054906101000a900460ff1681565b600d805461104c90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461107890613537565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b505050505081565b60006110d882611ccb565b9050919050565b6110e7611c13565b6110ef610a00565b811015611131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128906139db565b60405180910390fd5b8060108190555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361118157611180638f4eb60460e01b611ada565b5b67ffffffffffffffff600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054169050919050565b6111da611c13565b6111e46000611f10565b565b6111ee611c13565b80600d90816111fd9190613714565b5050565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61122c611ca3565b146112425761124163bdba09d760e01b611ada565b5b600061124c611c9a565b90506000611258611fd6565b905060608183146112715761126e858484611fdf565b90505b809350505050919050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b6060600380546112bb90613537565b80601f01602080910402602001604051908101604052809291908181526020018280546112e790613537565b80156113345780601f1061130957610100808354040283529160200191611334565b820191906000526020600020905b81548152906001019060200180831161131757829003601f168201915b5050505050905090565b606061134b848484611fdf565b90509392505050565b8060008111801561136757506011548111155b6113a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139d90613a47565b60405180910390fd5b601054816113b2610a00565b6113bc9190613a67565b11156113fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f490613ae7565b60405180910390fd5b8180600f5461140c9190613815565b34101561144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144590613b53565b60405180910390fd5b601260009054906101000a900460ff161561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590613bbf565b60405180910390fd5b6114af6114a961219b565b846121a3565b505050565b80600760006114c1611e0b565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661156e611e0b565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516115b39190612a6d565b60405180910390a35050565b6115c7611c13565b8060118190555050565b6115dc848484610a4d565b60008373ffffffffffffffffffffffffffffffffffffffff163b1461161d57611607848484846121c1565b61161c5761161b63d1a57ed660e01b611ada565b5b5b50505050565b61162b61296a565b611633611c9a565b821061169257611641611ca3565b82111561165857611651826122f0565b9050611693565b611660611fd6565b821015611691575b6116718261231b565b6116815781600190039150611668565b61168a826122f0565b9050611693565b5b5b919050565b60606116a382611a2e565b6116e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d990613c51565b60405180910390fd5b60006116ec61233b565b9050600081511161170c576040518060200160405280600081525061173a565b80611716846123cd565b600e60405160200161172a93929190613d30565b6040516020818303038152906040525b915050919050565b60105481565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816000811180156117ef57506011548111155b61182e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182590613a47565b60405180910390fd5b6010548161183a610a00565b6118449190613a67565b1115611885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187c90613ae7565b60405180910390fd5b61188d611c13565b61189782846121a3565b505050565b6118a4611c13565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119165760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161190d9190612bde565b60405180910390fd5b61191f81611f10565b50565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061197d57506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806119ad5750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611a275750611a268261249b565b5b9050919050565b600081611a39611c9a565b11611ad457611a46611ca3565b821115611a7057611a696004600084815260200190815260200160002054612505565b9050611ad5565b600054821015611ad35760005b6000600460008581526020019081526020016000205491508103611aac5782611aa590613d61565b9250611a7d565b60007c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b8060005260046000fd5b6000611aef836110cd565b9050818015611b3157508073ffffffffffffffffffffffffffffffffffffffff16611b18611e0b565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611b5d57611b4781611b42611e0b565b611748565b611b5c57611b5b63cfb3b94260e01b611ada565b5b5b836006600085815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b611c1b61219b565b73ffffffffffffffffffffffffffffffffffffffff16611c3961127c565b73ffffffffffffffffffffffffffffffffffffffff1614611c9857611c5c61219b565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c8f9190612bde565b60405180910390fd5b565b60006001905090565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b600081611cd6611c9a565b11611dce5760046000838152602001908152602001600020549050611cf9611ca3565b821115611d1e57611d0981612505565b611ddf57611d1d63df2d9b4260e01b611ada565b5b60008103611da5576000548210611d4057611d3f63df2d9b4260e01b611ada565b5b5b60046000836001900393508381526020019081526020016000205490506000810315611da05760007c010000000000000000000000000000000000000000000000000000000082160315611ddf57611d9f63df2d9b4260e01b611ada565b5b611d41565b60007c010000000000000000000000000000000000000000000000000000000082160315611ddf575b611dde63df2d9b4260e01b611ada565b5b919050565b60008060006006600085815260200190815260200160002090508092508254915050915091565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b60008060e883901c905060e8611e74868684612546565b62ffffff16901b9150509392505050565b600073ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b6000612710905090565b6002600a5403611efc576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600a81905550565b6001600a81905550565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008054905090565b6060818310611ff957611ff86332c1995a60e01b611ada565b5b612001611c9a565b83101561201357612010611c9a565b92505b600061201d611fd6565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61204a611ca3565b036120555781612057565b835b9050808410612064578093505b600061206f8761113b565b905084861061207d57600090505b600081146121915780868603116120945785850390505b600060405194506001820160051b850190508060405260006120b588611623565b9050600081604001516120ca57816000015190505b60005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6120f6611ca3565b1461212557868a0361211057600161210c611ca3565b0199505b612118611ca3565b8a111561212457600091505b5b61212e8a6122f0565b9250604083015160008114612146576000925061216c565b83511561215257835192505b8b831860601b61216b576001820191508a8260051b8a01525b5b5060018a01995083604052888a148061218457508481145b156120cd57808852505050505b5050509392505050565b600033905090565b6121bd82826040518060200160405280600081525061254f565b5050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a026121e7611e0b565b8786866040518563ffffffff1660e01b81526004016122099493929190613ddf565b6020604051808303816000875af192505050801561224557506040513d601f19601f820116820180604052508101906122429190613e40565b60015b61229d573d8060008114612275576040519150601f19603f3d011682016040523d82523d6000602084013e61227a565b606091505b5060008151036122955761229463d1a57ed660e01b611ada565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6122f861296a565b61231460046000848152602001908152602001600020546125cb565b9050919050565b600080600460008481526020019081526020016000205414159050919050565b6060600d805461234a90613537565b80601f016020809104026020016040519081016040528092919081815260200182805461237690613537565b80156123c35780601f10612398576101008083540402835291602001916123c3565b820191906000526020600020905b8154815290600101906020018083116123a657829003601f168201915b5050505050905090565b6060600060016123dc84612681565b01905060008167ffffffffffffffff8111156123fb576123fa612c99565b5b6040519080825280601f01601f19166020018201604052801561242d5781602001600182028036833780820191505090505b509050600082602001820190505b600115612490578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248457612483613857565b5b0494506000850361243b575b819350505050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60007c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b60009392505050565b61255983836127d4565b60008373ffffffffffffffffffffffffffffffffffffffff163b146125c657600080549050600083820390505b61259960008683806001019450866121c1565b6125ae576125ad63d1a57ed660e01b611ada565b5b8181106125865781600054146125c357600080fd5b50505b505050565b6125d361296a565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a082901c816020019067ffffffffffffffff16908167ffffffffffffffff168152505060007c01000000000000000000000000000000000000000000000000000000008316141581604001901515908115158152505060e882901c816060019062ffffff16908162ffffff1681525050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106126df577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816126d5576126d4613857565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061271c576d04ee2d6d415b85acef8100000000838161271257612711613857565b5b0492506020810190505b662386f26fc10000831061274b57662386f26fc10000838161274157612740613857565b5b0492506010810190505b6305f5e1008310612774576305f5e100838161276a57612769613857565b5b0492506008810190505b612710831061279957612710838161278f5761278e613857565b5b0492506004810190505b606483106127bc57606483816127b2576127b1613857565b5b0492506002810190505b600a83106127cb576001810190505b80915050919050565b600080549050600082036127f3576127f263b562e8dd60e01b611ada565b5b6128006000848385611e57565b612820836128116000866000611e5d565b61281a8561295a565b17611e85565b6004600083815260200190815260200160002081905550600160406001901b178202600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff16169050600081036128d8576128d7632e07630060e01b611ada565b5b6000838301905060008390506128ec611ca3565b600183031115612907576129066381647e3a60e01b611ada565b5b5b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a481816001019150810361290857816000819055505050506129556000848385611eb0565b505050565b60006001821460e11b9050919050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152602001600062ffffff1681525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612a02816129cd565b8114612a0d57600080fd5b50565b600081359050612a1f816129f9565b92915050565b600060208284031215612a3b57612a3a6129c3565b5b6000612a4984828501612a10565b91505092915050565b60008115159050919050565b612a6781612a52565b82525050565b6000602082019050612a826000830184612a5e565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ac2578082015181840152602081019050612aa7565b60008484015250505050565b6000601f19601f8301169050919050565b6000612aea82612a88565b612af48185612a93565b9350612b04818560208601612aa4565b612b0d81612ace565b840191505092915050565b60006020820190508181036000830152612b328184612adf565b905092915050565b6000819050919050565b612b4d81612b3a565b8114612b5857600080fd5b50565b600081359050612b6a81612b44565b92915050565b600060208284031215612b8657612b856129c3565b5b6000612b9484828501612b5b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612bc882612b9d565b9050919050565b612bd881612bbd565b82525050565b6000602082019050612bf36000830184612bcf565b92915050565b612c0281612bbd565b8114612c0d57600080fd5b50565b600081359050612c1f81612bf9565b92915050565b60008060408385031215612c3c57612c3b6129c3565b5b6000612c4a85828601612c10565b9250506020612c5b85828601612b5b565b9150509250929050565b612c6e81612b3a565b82525050565b6000602082019050612c896000830184612c65565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612cd182612ace565b810181811067ffffffffffffffff82111715612cf057612cef612c99565b5b80604052505050565b6000612d036129b9565b9050612d0f8282612cc8565b919050565b600067ffffffffffffffff821115612d2f57612d2e612c99565b5b612d3882612ace565b9050602081019050919050565b82818337600083830152505050565b6000612d67612d6284612d14565b612cf9565b905082815260208101848484011115612d8357612d82612c94565b5b612d8e848285612d45565b509392505050565b600082601f830112612dab57612daa612c8f565b5b8135612dbb848260208601612d54565b91505092915050565b600060208284031215612dda57612dd96129c3565b5b600082013567ffffffffffffffff811115612df857612df76129c8565b5b612e0484828501612d96565b91505092915050565b612e1681612a52565b8114612e2157600080fd5b50565b600081359050612e3381612e0d565b92915050565b600060208284031215612e4f57612e4e6129c3565b5b6000612e5d84828501612e24565b91505092915050565b600080600060608486031215612e7f57612e7e6129c3565b5b6000612e8d86828701612c10565b9350506020612e9e86828701612c10565b9250506040612eaf86828701612b5b565b9150509250925092565b60008060408385031215612ed057612ecf6129c3565b5b6000612ede85828601612b5b565b9250506020612eef85828601612b5b565b9150509250929050565b6000604082019050612f0e6000830185612bcf565b612f1b6020830184612c65565b9392505050565b600080fd5b600080fd5b60008083601f840112612f4257612f41612c8f565b5b8235905067ffffffffffffffff811115612f5f57612f5e612f22565b5b602083019150836020820283011115612f7b57612f7a612f27565b5b9250929050565b60008060208385031215612f9957612f986129c3565b5b600083013567ffffffffffffffff811115612fb757612fb66129c8565b5b612fc385828601612f2c565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61300481612bbd565b82525050565b600067ffffffffffffffff82169050919050565b6130278161300a565b82525050565b61303681612a52565b82525050565b600062ffffff82169050919050565b6130548161303c565b82525050565b6080820160008201516130706000850182612ffb565b506020820151613083602085018261301e565b506040820151613096604085018261302d565b5060608201516130a9606085018261304b565b50505050565b60006130bb838361305a565b60808301905092915050565b6000602082019050919050565b60006130df82612fcf565b6130e98185612fda565b93506130f483612feb565b8060005b8381101561312557815161310c88826130af565b9750613117836130c7565b9250506001810190506130f8565b5085935050505092915050565b6000602082019050818103600083015261314c81846130d4565b905092915050565b60006020828403121561316a576131696129c3565b5b600061317884828501612c10565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6131b681612b3a565b82525050565b60006131c883836131ad565b60208301905092915050565b6000602082019050919050565b60006131ec82613181565b6131f6818561318c565b93506132018361319d565b8060005b8381101561323257815161321988826131bc565b9750613224836131d4565b925050600181019050613205565b5085935050505092915050565b6000602082019050818103600083015261325981846131e1565b905092915050565b60008060006060848603121561327a576132796129c3565b5b600061328886828701612c10565b935050602061329986828701612b5b565b92505060406132aa86828701612b5b565b9150509250925092565b600080604083850312156132cb576132ca6129c3565b5b60006132d985828601612c10565b92505060206132ea85828601612e24565b9150509250929050565b600067ffffffffffffffff82111561330f5761330e612c99565b5b61331882612ace565b9050602081019050919050565b6000613338613333846132f4565b612cf9565b90508281526020810184848401111561335457613353612c94565b5b61335f848285612d45565b509392505050565b600082601f83011261337c5761337b612c8f565b5b813561338c848260208601613325565b91505092915050565b600080600080608085870312156133af576133ae6129c3565b5b60006133bd87828801612c10565b94505060206133ce87828801612c10565b93505060406133df87828801612b5b565b925050606085013567ffffffffffffffff811115613400576133ff6129c8565b5b61340c87828801613367565b91505092959194509250565b60808201600082015161342e6000850182612ffb565b506020820151613441602085018261301e565b506040820151613454604085018261302d565b506060820151613467606085018261304b565b50505050565b60006080820190506134826000830184613418565b92915050565b6000806040838503121561349f5761349e6129c3565b5b60006134ad85828601612c10565b92505060206134be85828601612c10565b9150509250929050565b600080604083850312156134df576134de6129c3565b5b60006134ed85828601612b5b565b92505060206134fe85828601612c10565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061354f57607f821691505b60208210810361356257613561613508565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026135ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261358d565b6135d4868361358d565b95508019841693508086168417925050509392505050565b6000819050919050565b600061361161360c61360784612b3a565b6135ec565b612b3a565b9050919050565b6000819050919050565b61362b836135f6565b61363f61363782613618565b84845461359a565b825550505050565b600090565b613654613647565b61365f818484613622565b505050565b5b818110156136835761367860008261364c565b600181019050613665565b5050565b601f8211156136c85761369981613568565b6136a28461357d565b810160208510156136b1578190505b6136c56136bd8561357d565b830182613664565b50505b505050565b600082821c905092915050565b60006136eb600019846008026136cd565b1980831691505092915050565b600061370483836136da565b9150826002028217905092915050565b61371d82612a88565b67ffffffffffffffff81111561373657613735612c99565b5b6137408254613537565b61374b828285613687565b600060209050601f83116001811461377e576000841561376c578287015190505b61377685826136f8565b8655506137de565b601f19841661378c86613568565b60005b828110156137b45784890151825560018201915060208501945060208101905061378f565b868310156137d157848901516137cd601f8916826136da565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061382082612b3a565b915061382b83612b3a565b925082820261383981612b3a565b915082820484148315176138505761384f6137e6565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061389182612b3a565b915061389c83612b3a565b9250826138ac576138ab613857565b5b828204905092915050565b600081905092915050565b50565b60006138d26000836138b7565b91506138dd826138c2565b600082019050919050565b60006138f3826138c5565b9150819050919050565b7f5769746864726177206661696c65640000000000000000000000000000000000600082015250565b6000613933600f83612a93565b915061393e826138fd565b602082019050919050565b6000602082019050818103600083015261396281613926565b9050919050565b7f43616e6e6f7420736574206d6178537570706c792062656c6f77206d696e746560008201527f6420746f6b656e73000000000000000000000000000000000000000000000000602082015250565b60006139c5602883612a93565b91506139d082613969565b604082019050919050565b600060208201905081810360008301526139f4816139b8565b9050919050565b7f496e76616c6964206d696e7420616d6f756e7421000000000000000000000000600082015250565b6000613a31601483612a93565b9150613a3c826139fb565b602082019050919050565b60006020820190508181036000830152613a6081613a24565b9050919050565b6000613a7282612b3a565b9150613a7d83612b3a565b9250828201905080821115613a9557613a946137e6565b5b92915050565b7f4d617820737570706c7920657863656564656421000000000000000000000000600082015250565b6000613ad1601483612a93565b9150613adc82613a9b565b602082019050919050565b60006020820190508181036000830152613b0081613ac4565b9050919050565b7f496e73756666696369656e742066756e64732100000000000000000000000000600082015250565b6000613b3d601383612a93565b9150613b4882613b07565b602082019050919050565b60006020820190508181036000830152613b6c81613b30565b9050919050565b7f54686520636f6e74726163742069732070617573656421000000000000000000600082015250565b6000613ba9601783612a93565b9150613bb482613b73565b602082019050919050565b60006020820190508181036000830152613bd881613b9c565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b6000613c3b602f83612a93565b9150613c4682613bdf565b604082019050919050565b60006020820190508181036000830152613c6a81613c2e565b9050919050565b600081905092915050565b6000613c8782612a88565b613c918185613c71565b9350613ca1818560208601612aa4565b80840191505092915050565b60008154613cba81613537565b613cc48186613c71565b94506001821660008114613cdf5760018114613cf457613d27565b60ff1983168652811515820286019350613d27565b613cfd85613568565b60005b83811015613d1f57815481890152600182019150602081019050613d00565b838801955050505b50505092915050565b6000613d3c8286613c7c565b9150613d488285613c7c565b9150613d548284613cad565b9150819050949350505050565b6000613d6c82612b3a565b915060008203613d7f57613d7e6137e6565b5b600182039050919050565b600081519050919050565b600082825260208201905092915050565b6000613db182613d8a565b613dbb8185613d95565b9350613dcb818560208601612aa4565b613dd481612ace565b840191505092915050565b6000608082019050613df46000830187612bcf565b613e016020830186612bcf565b613e0e6040830185612c65565b8181036060830152613e208184613da6565b905095945050505050565b600081519050613e3a816129f9565b92915050565b600060208284031215613e5657613e556129c3565b5b6000613e6484828501613e2b565b9150509291505056fea2646970667358221220cdd3a427bc75354e732226c42cc1dd4859a936a190695fec7921723072aefb1c64736f6c634300081c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000000f457465726e616c53756e6469616c73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024553000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _tokenName (string): EternalSundials
Arg [1] : _tokenSymbol (string): ES
Arg [2] : _maxSupply (uint256): 10000

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [4] : 457465726e616c53756e6469616c730000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [6] : 4553000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

344:3720:12:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3499:267;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11573:98:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18636:223;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18364:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;536:19:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3302:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3412:81;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6890:564:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;22796:3447;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2379:657:2;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;3772:176:12;;;;;;;;;;;;;:::i;:::-;;26334:187:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2968:78:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;496:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1882:1131:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;631:25:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;462:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12934:150:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2136:197:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8570:239:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2293:101:0;;;;;;;;;;;;;:::i;:::-;;3192:104:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4039:484:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1638:85:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;591:33:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11742:102:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3387:217:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1684:253:12;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;19186:231:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3052:134:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;27102:405:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1070:659:15;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2512:450:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;561:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;19567:162:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1943:187:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2543:215:0;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3499:267:12;3652:4;3679:38;3705:11;3679:25;:38::i;:::-;:80;;;;3721:38;3747:11;3721:25;:38::i;:::-;3679:80;3672:87;;3499:267;;;:::o;11573:98:13:-;11627:13;11659:5;11652:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11573:98;:::o;18636:223::-;18712:7;18736:16;18744:7;18736;:16::i;:::-;18731:73;;18754:50;18762:41;;;18754:7;:50::i;:::-;18731:73;18822:15;:24;18838:7;18822:24;;;;;;;;;;;:30;;;;;;;;;;;;18815:37;;18636:223;;;:::o;18364:122::-;18452:27;18461:2;18465:7;18474:4;18452:8;:27::i;:::-;18364:122;;:::o;536:19:12:-;;;;:::o;3302:104::-;1531:13:0;:11;:13::i;:::-;3389:10:12::1;3377:9;:22;;;;;;:::i;:::-;;3302:104:::0;:::o;3412:81::-;1531:13:0;:11;:13::i;:::-;3480:6:12::1;3471;;:15;;;;;;;;;;;;;;;;;;3412:81:::0;:::o;6890:564:13:-;6951:14;7343:15;:13;:15::i;:::-;7328:12;;7312:13;;:28;:46;7303:55;;7397:17;7376;:15;:17::i;:::-;:38;7372:65;;7426:11;;7416:21;;;;7372:65;6890:564;:::o;22796:3447::-;22933:27;22963;22982:7;22963:18;:27::i;:::-;22933:57;;2943:14;23131:4;23115:22;;:41;23092:66;;23214:4;23173:45;;23189:19;23173:45;;;23169:95;;23220:44;23228:35;;;23220:7;:44::i;:::-;23169:95;23276:27;23305:23;23332:35;23359:7;23332:26;:35::i;:::-;23275:92;;;;23464:68;23489:15;23506:4;23512:19;:17;:19::i;:::-;23464:24;:68::i;:::-;23459:188;;23551:43;23568:4;23574:19;:17;:19::i;:::-;23551:16;:43::i;:::-;23546:101;;23596:51;23604:42;;;23596:7;:51::i;:::-;23546:101;23459:188;23658:43;23680:4;23686:2;23690:7;23699:1;23658:21;:43::i;:::-;23790:15;23787:157;;;23928:1;23907:19;23900:30;23787:157;24316:18;:24;24335:4;24316:24;;;;;;;;;;;;;;;;24314:26;;;;;;;;;;;;24384:18;:22;24403:2;24384:22;;;;;;;;;;;;;;;;24382:24;;;;;;;;;;;24699:143;24735:2;24783:45;24798:4;24804:2;24808:19;24783:14;:45::i;:::-;2550:8;24755:73;24699:18;:143::i;:::-;24670:17;:26;24688:7;24670:26;;;;;;;;;;;:172;;;;25010:1;2550:8;24959:19;:47;:52;24955:617;;25031:19;25063:1;25053:7;:11;25031:33;;25218:1;25184:17;:30;25202:11;25184:30;;;;;;;;;;;;:35;25180:378;;25320:13;;25305:11;:28;25301:239;;25498:19;25465:17;:30;25483:11;25465:30;;;;;;;;;;;:52;;;;25301:239;25180:378;25013:559;24955:617;25681:16;2943:14;25716:2;25700:20;;:39;25681:58;;26071:7;26036:8;26003:4;25946:25;25892:1;25836;25814:292;26141:1;26129:8;:13;26125:58;;26144:39;26152:30;;;26144:7;:39::i;:::-;26125:58;26194:42;26215:4;26221:2;26225:7;26234:1;26194:20;:42::i;:::-;22923:3320;;;;22796:3447;;;:::o;2379:657:2:-;2487:16;2505:14;2531:32;2566:17;:26;2584:7;2566:26;;;;;;;;;;;2531:61;;2602:23;2628:12;:21;;;;;;;;;;;;2602:47;;2659:22;2684:12;:28;;;;;;;;;;;;2659:53;;2754:1;2727:29;;:15;:29;;;2723:173;;2790:19;:28;;;;;;;;;;;;2772:46;;2850:19;:35;;;;;;;;;;;;2832:53;;2723:173;2906:21;2962:17;:15;:17::i;:::-;2930:49;;2943:15;2931:27;;:9;:27;;;;:::i;:::-;2930:49;;;;:::i;:::-;2906:73;;2998:15;3015:13;2990:39;;;;;;;;2379:657;;;;;:::o;3772:176:12:-;1531:13:0;:11;:13::i;:::-;2500:21:5::1;:19;:21::i;:::-;3833:7:12::2;3854;:5;:7::i;:::-;3846:21;;3875;3846:55;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3832:69;;;3919:2;3911:30;;;;;;;;;;;;:::i;:::-;;;;;;;;;3822:126;2542:20:5::1;:18;:20::i;:::-;3772:176:12:o:0;26334:187:13:-;26475:39;26492:4;26498:2;26502:7;26475:39;;;;;;;;;;;;:16;:39::i;:::-;26334:187;;;:::o;2968:78:12:-;1531:13:0;:11;:13::i;:::-;3034:5:12::1;3027:4;:12;;;;2968:78:::0;:::o;496:33::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1882:1131:15:-;2021:23;2060:34;2104:9;2116:8;;:15;;2104:27;;2229:4;2223:11;2209:25;;2299:1;2287:10;2280:21;2432:1;2429;2425:9;2420:14;;2510:1;2503:4;2491:10;2487:21;2483:29;2477:4;2470:43;2532:448;2544:1;2539;:6;2532:448;;2561:15;2629:4;2626:1;2622:12;2617:17;;2696:1;2679:15;2675:23;2662:37;2651:48;;2726:31;2760:28;2780:7;2760:19;:28::i;:::-;2726:62;;2946:9;2942:1;2935:4;2923:10;2919:21;2915:29;2908:48;2811:159;;2532:448;;;2996:10;2989:17;;;;1882:1131;;;;:::o;631:25:12:-;;;;;;;;;;;;;:::o;462:28::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;12934:150:13:-;13006:7;13048:27;13067:7;13048:18;:27::i;:::-;13025:52;;12934:150;;;:::o;2136:197:12:-;1531:13:0;:11;:13::i;:::-;2233::12::1;:11;:13::i;:::-;2216;:30;;2208:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;2313:13;2301:9;:25;;;;2136:197:::0;:::o;8570:239:13:-;8642:7;8682:1;8665:19;;:5;:19;;;8661:69;;8686:44;8694:35;;;8686:7;:44::i;:::-;8661:69;1518:13;8747:18;:25;8766:5;8747:25;;;;;;;;;;;;;;;;:55;8740:62;;8570:239;;;:::o;2293:101:0:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;3192:104:12:-;1531:13:0;:11;:13::i;:::-;3279:10:12::1;3267:9;:22;;;;;;:::i;:::-;;3192:104:::0;:::o;4039:484:15:-;4117:16;4237:17;4216;:15;:17::i;:::-;:38;4212:88;;4256:44;4264:35;;;4256:7;:44::i;:::-;4212:88;4310:13;4326:15;:13;:15::i;:::-;4310:31;;4351:12;4366:14;:12;:14::i;:::-;4351:29;;4390:25;4438:4;4429:5;:13;4425:66;;4455:36;4472:5;4479;4486:4;4455:16;:36::i;:::-;4444:47;;4425:66;4508:8;4501:15;;;;;4039:484;;;:::o;1638:85:0:-;1684:7;1710:6;;;;;;;;;;;1703:13;;1638:85;:::o;591:33:12:-;;;;:::o;11742:102:13:-;11798:13;11830:7;11823:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11742:102;:::o;3387:217:15:-;3526:16;3561:36;3578:5;3585;3592:4;3561:16;:36::i;:::-;3554:43;;3387:217;;;;;:::o;1684:253:12:-;1773:11;1312:1;1298:11;:15;:52;;;;;1332:18;;1317:11;:33;;1298:52;1277:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;1458:9;;1443:11;1427:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1406:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;1814:11:::1;1625;1618:4;;:18;;;;:::i;:::-;1605:9;:31;;1597:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;1850:6:::2;;;;;;;;;;;1849:7;1841:43;;;;;;;;;;;;:::i;:::-;;;;;;;;;1894:36;1904:12;:10;:12::i;:::-;1918:11;1894:9;:36::i;:::-;1523:1:::1;1684:253:::0;;:::o;19186:231:13:-;19332:8;19280:18;:39;19299:19;:17;:19::i;:::-;19280:39;;;;;;;;;;;;;;;:49;19320:8;19280:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;19391:8;19355:55;;19370:19;:17;:19::i;:::-;19355:55;;;19401:8;19355:55;;;;;;:::i;:::-;;;;;;;;19186:231;;:::o;3052:134:12:-;1531:13:0;:11;:13::i;:::-;3160:19:12::1;3139:18;:40;;;;3052:134:::0;:::o;27102:405:13:-;27271:31;27284:4;27290:2;27294:7;27271:12;:31::i;:::-;27334:1;27316:2;:14;;;:19;27312:189;;27354:56;27385:4;27391:2;27395:7;27404:5;27354:30;:56::i;:::-;27349:152;;27430:56;27438:47;;;27430:7;:56::i;:::-;27349:152;27312:189;27102:405;;;;:::o;1070:659:15:-;1194:31;;:::i;:::-;1280:15;:13;:15::i;:::-;1269:7;:26;1265:448;;1329:17;:15;:17::i;:::-;1319:7;:27;1315:61;;;1355:21;1368:7;1355:12;:21::i;:::-;1348:28;;;;1315:61;1409:14;:12;:14::i;:::-;1399:7;:24;1395:304;;;1579:51;1587:32;1611:7;1587:23;:32::i;:::-;1579:51;;1621:9;;;;;;1579:51;;;1659:21;1672:7;1659:12;:21::i;:::-;1652:28;;;;1395:304;1265:448;1070:659;;;;:::o;2512:450:12:-;2645:13;2682:17;2690:8;2682:7;:17::i;:::-;2674:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;2761:28;2792:10;:8;:10::i;:::-;2761:41;;2850:1;2825:14;2819:28;:32;:136;;;;;;;;;;;;;;;;;2890:14;2906:19;:8;:17;:19::i;:::-;2927:9;2873:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2819:136;2812:143;;;2512:450;;;:::o;561:24::-;;;;:::o;19567:162:13:-;19664:4;19687:18;:25;19706:5;19687:25;;;;;;;;;;;;;;;:35;19713:8;19687:35;;;;;;;;;;;;;;;;;;;;;;;;;19680:42;;19567:162;;;;:::o;1943:187:12:-;2045:11;1312:1;1298:11;:15;:52;;;;;1332:18;;1317:11;:33;;1298:52;1277:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;1458:9;;1443:11;1427:13;:11;:13::i;:::-;:27;;;;:::i;:::-;:40;;1406:107;;;;;;;;;;;;:::i;:::-;;;;;;;;;1531:13:0::1;:11;:13::i;:::-;2090:33:12::2;2100:9;2111:11;2090:9;:33::i;:::-;1943:187:::0;;;:::o;2543:215:0:-;1531:13;:11;:13::i;:::-;2647:1:::1;2627:22;;:8;:22;;::::0;2623:91:::1;;2700:1;2672:31;;;;;;;;;;;:::i;:::-;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;10689:630:13:-;10774:4;11107:10;11092:25;;:11;:25;;;;:101;;;;11183:10;11168:25;;:11;:25;;;;11092:101;:177;;;;11259:10;11244:25;;:11;:25;;;;11092:177;11073:196;;10689:630;;;:::o;2116:213:2:-;2218:4;2256:26;2241:41;;;:11;:41;;;;:81;;;;2286:36;2310:11;2286:23;:36::i;:::-;2241:81;2234:88;;2116:213;;;:::o;19978:465:13:-;20043:11;20089:7;20070:15;:13;:15::i;:::-;:26;20066:371;;20126:17;:15;:17::i;:::-;20116:7;:27;20112:90;;;20152:50;20175:17;:26;20193:7;20175:26;;;;;;;;;;;;20152:22;:50::i;:::-;20145:57;;;;20112:90;20231:13;;20221:7;:23;20217:210;;;20264:14;20296:60;20344:1;20313:17;:26;20331:7;20313:26;;;;;;;;;;;;20304:35;;;20303:42;20296:60;;20347:9;;;;:::i;:::-;;;20296:60;;;20411:1;2276:8;20383:6;:24;:29;20374:38;;20246:181;20217:210;20066:371;19978:465;;;;:::o;49703:160::-;49802:13;49796:4;49789:27;49842:4;49836;49829:18;41333:460;41457:13;41473:16;41481:7;41473;:16::i;:::-;41457:32;;41504:13;:45;;;;;41544:5;41521:28;;:19;:17;:19::i;:::-;:28;;;;41504:45;41500:198;;;41568:44;41585:5;41592:19;:17;:19::i;:::-;41568:16;:44::i;:::-;41563:135;;41632:51;41640:42;;;41632:7;:51::i;:::-;41563:135;41500:198;41741:2;41708:15;:24;41724:7;41708:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;41778:7;41774:2;41758:28;;41767:5;41758:28;;;;;;;;;;;;41447:346;41333:460;;;:::o;1796:162:0:-;1866:12;:10;:12::i;:::-;1855:23;;:7;:5;:7::i;:::-;:23;;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;;;;;;;;;;:::i;:::-;;;;;;;;1851:101;1796:162::o;2407:99:12:-;2472:7;2498:1;2491:8;;2407:99;:::o;6404:108:13:-;6462:7;6488:17;6481:24;;6404:108;:::o;14380:2173::-;14447:14;14496:7;14477:15;:13;:15::i;:::-;:26;14473:2017;;14528:17;:26;14546:7;14528:26;;;;;;;;;;;;14519:35;;14583:17;:15;:17::i;:::-;14573:7;:27;14569:180;;;14624:30;14647:6;14624:22;:30::i;:::-;14656:13;14620:49;14687:47;14695:38;;;14687:7;:47::i;:::-;14569:180;14857:1;14847:6;:11;14843:1270;;14893:13;;14882:7;:24;14878:77;;14908:47;14916:38;;;14908:7;:47::i;:::-;14878:77;15502:597;15578:17;:28;15596:9;;;;;;;15578:28;;;;;;;;;;;;15569:37;;15664:1;15654:6;:11;15650:25;15667:8;15650:25;15729:1;2276:8;15701:6;:24;:29;15697:48;15732:13;15697:48;16033:47;16041:38;;;16033:7;:47::i;:::-;15502:597;;;14843:1270;16463:1;2276:8;16435:6;:24;:29;16431:48;16466:13;16431:48;14473:2017;16499:47;16507:38;;;16499:7;:47::i;:::-;14380:2173;;;;:::o;21721:474::-;21820:27;21849:23;21888:38;21929:15;:24;21945:7;21929:24;;;;;;;;;;;21888:65;;22103:18;22080:41;;22159:19;22153:26;22134:45;;22066:123;21721:474;;;:::o;47733:103::-;47793:7;47819:10;47812:17;;47733:103;:::o;20967:646::-;21112:11;21274:16;21267:5;21263:28;21254:37;;21432:16;21421:9;21417:32;21404:45;;21580:15;21569:9;21566:30;21558:5;21547:9;21544:20;21541:56;21531:66;;20967:646;;;;;:::o;28151:154::-;;;;;:::o;47060:304::-;47191:7;47210:16;2671:3;47236:19;:41;;47210:68;;2671:3;47303:31;47314:4;47320:2;47324:9;47303:10;:31::i;:::-;47295:40;;:62;;47288:69;;;47060:304;;;;;:::o;17086:443::-;17166:14;17331:16;17324:5;17320:28;17311:37;;17506:5;17492:11;17467:23;17463:41;17460:52;17453:5;17450:63;17440:73;;17086:443;;;;:::o;28952:153::-;;;;;:::o;3311:95:2:-;3369:6;3394:5;3387:12;;3311:95;:::o;2575:307:5:-;1899:1;2702:7;;:18;2698:86;;2743:30;;;;;;;;;;;;;;2698:86;1899:1;2858:7;:17;;;;2575:307::o;2888:208::-;1857:1;3068:7;:21;;;;2888:208::o;2912:187:0:-;2985:16;3004:6;;;;;;;;;;;2985:25;;3029:8;3020:6;;:17;;;;;;;;;;;;;;;;;;3083:8;3052:40;;3073:8;3052:40;;;;;;;;;;;;2975:124;2912:187;:::o;6586:101:13:-;6641:7;6667:13;;6660:20;;6586:101;:::o;4771:4906:15:-;4893:25;4967:4;4958:5;:13;4954:54;;4973:35;4981:26;;;4973:7;:35::i;:::-;4954:54;5092:15;:13;:15::i;:::-;5084:5;:23;5080:52;;;5117:15;:13;:15::i;:::-;5109:23;;5080:52;5146:19;5168:14;:12;:14::i;:::-;5146:36;;5283:17;5324;5303;:15;:17::i;:::-;:38;:59;;5351:11;5303:59;;;5344:4;5303:59;5283:79;;5438:9;5430:4;:17;5426:39;;5456:9;5449:16;;5426:39;5520:25;5548:16;5558:5;5548:9;:16::i;:::-;5520:44;;5671:4;5662:5;:13;5658:40;;5697:1;5677:21;;5658:40;5793:1;5772:17;:22;5768:3893;;5921:17;5912:5;5905:4;:12;:33;5901:71;;5967:5;5960:4;:12;5940:32;;5901:71;5990:9;6149:4;6143:11;6131:23;;6391:1;6372:17;6368:25;6365:1;6361:33;6351:8;6347:48;6342:53;;6429:1;6423:4;6416:15;6602:31;6636:26;6656:5;6636:19;:26::i;:::-;6602:60;;6680:25;6972:9;:16;;;6967:57;;7010:9;:14;;;6990:34;;6967:57;7042:19;7229:2273;7279:17;7258;:15;:17::i;:::-;:38;7254:405;;7408:11;7399:5;:20;7395:55;;7449:1;7429:17;:15;:17::i;:::-;:21;7421:29;;7395:55;7587:17;:15;:17::i;:::-;7579:5;:25;7575:61;;;7634:1;7606:30;;7575:61;7254:405;7692:19;7705:5;7692:12;:19::i;:::-;7680:31;;7833:4;7822:9;7818:20;7812:27;7928:1;7923:893;;;;9132:1;9111:22;;7805:1354;;7923:893;8202:9;8196:16;8193:121;;;8274:9;8268:16;8247:37;;8193:121;8601:5;8582:17;8578:29;8574:2;8570:38;8560:230;;8676:1;8663:11;8659:19;8644:34;;8754:5;8739:11;8736:1;8732:19;8722:8;8718:34;8711:49;8560:230;7805:1354;;9204:1;9197:5;9193:13;9184:22;;9398:1;9392:4;9385:15;9459:4;9450:5;:13;:49;;;;9482:17;9467:11;:32;9450:49;9448:52;7229:2273;;9617:11;9607:8;9600:29;9578:69;;;;5768:3893;4930:4741;;;4771:4906;;;;;:::o;656:96:3:-;709:7;735:10;728:17;;656:96;:::o;36661:110:13:-;36737:27;36747:2;36751:8;36737:27;;;;;;;;;;;;:9;:27::i;:::-;36661:110;;:::o;29533:673::-;29691:4;29736:2;29711:45;;;29757:19;:17;:19::i;:::-;29778:4;29784:7;29793:5;29711:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;29707:493;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30006:1;29989:6;:13;:18;29985:113;;30027:56;30035:47;;;30027:7;:56::i;:::-;29985:113;30168:6;30162:13;30153:6;30149:2;30145:15;30138:38;29707:493;29877:54;;;29867:64;;;:6;:64;;;;29860:71;;;29533:673;;;;;;:::o;13522:159::-;13590:21;;:::i;:::-;13630:44;13649:17;:24;13667:5;13649:24;;;;;;;;;;;;13630:18;:44::i;:::-;13623:51;;13522:159;;;:::o;13860:138::-;13939:4;13990:1;13962:17;:24;13980:5;13962:24;;;;;;;;;;;;:29;;13955:36;;13860:138;;;:::o;3954:108:12:-;4014:13;4046:9;4039:16;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3954:108;:::o;987:632:6:-;1043:13;1092:14;1129:1;1109:17;1120:5;1109:10;:17::i;:::-;:21;1092:38;;1144:20;1178:6;1167:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1144:41;;1199:11;1294:6;1290:2;1286:15;1278:6;1274:28;1267:35;;1329:247;1336:4;1329:247;;;1360:5;;;;;;;;1464:10;1459:2;1452:5;1448:14;1443:32;1438:3;1430:46;1520:2;1511:11;;;;;;:::i;:::-;;;;;1553:1;1544:5;:10;1329:247;1540:21;1329:247;1596:6;1589:13;;;;;987:632;;;:::o;763:146:7:-;839:4;877:25;862:40;;;:11;:40;;;;855:47;;763:146;;;:::o;20534:329:13:-;20604:11;20830:15;20822:6;20818:28;20799:16;20791:6;20787:29;20784:63;20774:73;;20534:329;;;:::o;46771:143::-;46904:6;46771:143;;;;;:::o;35816:766::-;35942:19;35948:2;35952:8;35942:5;:19::i;:::-;36018:1;36000:2;:14;;;:19;35996:570;;36039:11;36053:13;;36039:27;;36084:13;36106:8;36100:3;:14;36084:30;;36132:238;36162:62;36201:1;36205:2;36209:7;;;;;;36218:5;36162:30;:62::i;:::-;36157:174;;36252:56;36260:47;;;36252:7;:56::i;:::-;36157:174;36365:3;36357:5;:11;36132:238;;36538:3;36521:13;;:20;36517:34;;36543:8;;;36517:34;36021:545;;35996:570;35816:766;;;:::o;16647:361::-;16713:31;;:::i;:::-;16789:6;16756:9;:14;;:41;;;;;;;;;;;2162:3;16841:6;:33;;16807:9;:24;;:68;;;;;;;;;;;16932:1;2276:8;16904:6;:24;:29;;16885:9;:16;;:48;;;;;;;;;;;2671:3;16972:6;:28;;16943:9;:19;;:58;;;;;;;;;;;16647:361;;;:::o;25316:916:9:-;25369:7;25388:14;25405:1;25388:18;;25453:8;25444:5;:17;25440:103;;25490:8;25481:17;;;;;;:::i;:::-;;;;;25526:2;25516:12;;;;25440:103;25569:8;25560:5;:17;25556:103;;25606:8;25597:17;;;;;;:::i;:::-;;;;;25642:2;25632:12;;;;25556:103;25685:8;25676:5;:17;25672:103;;25722:8;25713:17;;;;;;:::i;:::-;;;;;25758:2;25748:12;;;;25672:103;25801:7;25792:5;:16;25788:100;;25837:7;25828:16;;;;;;:::i;:::-;;;;;25872:1;25862:11;;;;25788:100;25914:7;25905:5;:16;25901:100;;25950:7;25941:16;;;;;;:::i;:::-;;;;;25985:1;25975:11;;;;25901:100;26027:7;26018:5;:16;26014:100;;26063:7;26054:16;;;;;;:::i;:::-;;;;;26098:1;26088:11;;;;26014:100;26140:7;26131:5;:16;26127:66;;26177:1;26167:11;;;;26127:66;26219:6;26212:13;;;25316:916;;;:::o;30652:2343:13:-;30724:20;30747:13;;30724:36;;30786:1;30774:8;:13;30770:53;;30789:34;30797:25;;;30789:7;:34::i;:::-;30770:53;30834:61;30864:1;30868:2;30872:12;30886:8;30834:21;:61::i;:::-;31357:136;31393:2;31446:33;31469:1;31473:2;31477:1;31446:14;:33::i;:::-;31413:30;31434:8;31413:20;:30::i;:::-;:66;31357:18;:136::i;:::-;31323:17;:31;31341:12;31323:31;;;;;;;;;;;:170;;;;31773:1;1653:2;31743:1;:26;;31742:32;31730:8;:45;31704:18;:22;31723:2;31704:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;31883:16;2943:14;31918:2;31902:20;;:39;31883:58;;31972:1;31960:8;:13;31956:54;;31975:35;31983:26;;;31975:7;:35::i;:::-;31956:54;32025:11;32054:8;32039:12;:23;32025:37;;32076:15;32094:12;32076:30;;32135:17;:15;:17::i;:::-;32131:1;32125:3;:7;:27;32121:77;;;32154:44;32162:35;;;32154:7;:44::i;:::-;32121:77;32213:662;32623:7;32580:8;32536:1;32471:25;32409:1;32345;32315:351;32870:3;32857:9;;;;;;:16;32213:662;;32905:3;32889:13;:19;;;;31078:1841;;;32928:60;32957:1;32961:2;32965:12;32979:8;32928:20;:60::i;:::-;30714:2281;30652:2343;;:::o;17626:318::-;17696:14;17925:1;17915:8;17912:15;17886:24;17882:46;17872:56;;17626:318;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:17:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:248::-;1880:1;1890:113;1904:6;1901:1;1898:13;1890:113;;;1989:1;1984:3;1980:11;1974:18;1970:1;1965:3;1961:11;1954:39;1926:2;1923:1;1919:10;1914:15;;1890:113;;;2037:1;2028:6;2023:3;2019:16;2012:27;1860:186;1798:248;;;:::o;2052:102::-;2093:6;2144:2;2140:7;2135:2;2128:5;2124:14;2120:28;2110:38;;2052:102;;;:::o;2160:377::-;2248:3;2276:39;2309:5;2276:39;:::i;:::-;2331:71;2395:6;2390:3;2331:71;:::i;:::-;2324:78;;2411:65;2469:6;2464:3;2457:4;2450:5;2446:16;2411:65;:::i;:::-;2501:29;2523:6;2501:29;:::i;:::-;2496:3;2492:39;2485:46;;2252:285;2160:377;;;;:::o;2543:313::-;2656:4;2694:2;2683:9;2679:18;2671:26;;2743:9;2737:4;2733:20;2729:1;2718:9;2714:17;2707:47;2771:78;2844:4;2835:6;2771:78;:::i;:::-;2763:86;;2543:313;;;;:::o;2862:77::-;2899:7;2928:5;2917:16;;2862:77;;;:::o;2945:122::-;3018:24;3036:5;3018:24;:::i;:::-;3011:5;3008:35;2998:63;;3057:1;3054;3047:12;2998:63;2945:122;:::o;3073:139::-;3119:5;3157:6;3144:20;3135:29;;3173:33;3200:5;3173:33;:::i;:::-;3073:139;;;;:::o;3218:329::-;3277:6;3326:2;3314:9;3305:7;3301:23;3297:32;3294:119;;;3332:79;;:::i;:::-;3294:119;3452:1;3477:53;3522:7;3513:6;3502:9;3498:22;3477:53;:::i;:::-;3467:63;;3423:117;3218:329;;;;:::o;3553:126::-;3590:7;3630:42;3623:5;3619:54;3608:65;;3553:126;;;:::o;3685:96::-;3722:7;3751:24;3769:5;3751:24;:::i;:::-;3740:35;;3685:96;;;:::o;3787:118::-;3874:24;3892:5;3874:24;:::i;:::-;3869:3;3862:37;3787:118;;:::o;3911:222::-;4004:4;4042:2;4031:9;4027:18;4019:26;;4055:71;4123:1;4112:9;4108:17;4099:6;4055:71;:::i;:::-;3911:222;;;;:::o;4139:122::-;4212:24;4230:5;4212:24;:::i;:::-;4205:5;4202:35;4192:63;;4251:1;4248;4241:12;4192:63;4139:122;:::o;4267:139::-;4313:5;4351:6;4338:20;4329:29;;4367:33;4394:5;4367:33;:::i;:::-;4267:139;;;;:::o;4412:474::-;4480:6;4488;4537:2;4525:9;4516:7;4512:23;4508:32;4505:119;;;4543:79;;:::i;:::-;4505:119;4663:1;4688:53;4733:7;4724:6;4713:9;4709:22;4688:53;:::i;:::-;4678:63;;4634:117;4790:2;4816:53;4861:7;4852:6;4841:9;4837:22;4816:53;:::i;:::-;4806:63;;4761:118;4412:474;;;;;:::o;4892:118::-;4979:24;4997:5;4979:24;:::i;:::-;4974:3;4967:37;4892:118;;:::o;5016:222::-;5109:4;5147:2;5136:9;5132:18;5124:26;;5160:71;5228:1;5217:9;5213:17;5204:6;5160:71;:::i;:::-;5016:222;;;;:::o;5244:117::-;5353:1;5350;5343:12;5367:117;5476:1;5473;5466:12;5490:180;5538:77;5535:1;5528:88;5635:4;5632:1;5625:15;5659:4;5656:1;5649:15;5676:281;5759:27;5781:4;5759:27;:::i;:::-;5751:6;5747:40;5889:6;5877:10;5874:22;5853:18;5841:10;5838:34;5835:62;5832:88;;;5900:18;;:::i;:::-;5832:88;5940:10;5936:2;5929:22;5719:238;5676:281;;:::o;5963:129::-;5997:6;6024:20;;:::i;:::-;6014:30;;6053:33;6081:4;6073:6;6053:33;:::i;:::-;5963:129;;;:::o;6098:308::-;6160:4;6250:18;6242:6;6239:30;6236:56;;;6272:18;;:::i;:::-;6236:56;6310:29;6332:6;6310:29;:::i;:::-;6302:37;;6394:4;6388;6384:15;6376:23;;6098:308;;;:::o;6412:148::-;6510:6;6505:3;6500;6487:30;6551:1;6542:6;6537:3;6533:16;6526:27;6412:148;;;:::o;6566:425::-;6644:5;6669:66;6685:49;6727:6;6685:49;:::i;:::-;6669:66;:::i;:::-;6660:75;;6758:6;6751:5;6744:21;6796:4;6789:5;6785:16;6834:3;6825:6;6820:3;6816:16;6813:25;6810:112;;;6841:79;;:::i;:::-;6810:112;6931:54;6978:6;6973:3;6968;6931:54;:::i;:::-;6650:341;6566:425;;;;;:::o;7011:340::-;7067:5;7116:3;7109:4;7101:6;7097:17;7093:27;7083:122;;7124:79;;:::i;:::-;7083:122;7241:6;7228:20;7266:79;7341:3;7333:6;7326:4;7318:6;7314:17;7266:79;:::i;:::-;7257:88;;7073:278;7011:340;;;;:::o;7357:509::-;7426:6;7475:2;7463:9;7454:7;7450:23;7446:32;7443:119;;;7481:79;;:::i;:::-;7443:119;7629:1;7618:9;7614:17;7601:31;7659:18;7651:6;7648:30;7645:117;;;7681:79;;:::i;:::-;7645:117;7786:63;7841:7;7832:6;7821:9;7817:22;7786:63;:::i;:::-;7776:73;;7572:287;7357:509;;;;:::o;7872:116::-;7942:21;7957:5;7942:21;:::i;:::-;7935:5;7932:32;7922:60;;7978:1;7975;7968:12;7922:60;7872:116;:::o;7994:133::-;8037:5;8075:6;8062:20;8053:29;;8091:30;8115:5;8091:30;:::i;:::-;7994:133;;;;:::o;8133:323::-;8189:6;8238:2;8226:9;8217:7;8213:23;8209:32;8206:119;;;8244:79;;:::i;:::-;8206:119;8364:1;8389:50;8431:7;8422:6;8411:9;8407:22;8389:50;:::i;:::-;8379:60;;8335:114;8133:323;;;;:::o;8462:619::-;8539:6;8547;8555;8604:2;8592:9;8583:7;8579:23;8575:32;8572:119;;;8610:79;;:::i;:::-;8572:119;8730:1;8755:53;8800:7;8791:6;8780:9;8776:22;8755:53;:::i;:::-;8745:63;;8701:117;8857:2;8883:53;8928:7;8919:6;8908:9;8904:22;8883:53;:::i;:::-;8873:63;;8828:118;8985:2;9011:53;9056:7;9047:6;9036:9;9032:22;9011:53;:::i;:::-;9001:63;;8956:118;8462:619;;;;;:::o;9087:474::-;9155:6;9163;9212:2;9200:9;9191:7;9187:23;9183:32;9180:119;;;9218:79;;:::i;:::-;9180:119;9338:1;9363:53;9408:7;9399:6;9388:9;9384:22;9363:53;:::i;:::-;9353:63;;9309:117;9465:2;9491:53;9536:7;9527:6;9516:9;9512:22;9491:53;:::i;:::-;9481:63;;9436:118;9087:474;;;;;:::o;9567:332::-;9688:4;9726:2;9715:9;9711:18;9703:26;;9739:71;9807:1;9796:9;9792:17;9783:6;9739:71;:::i;:::-;9820:72;9888:2;9877:9;9873:18;9864:6;9820:72;:::i;:::-;9567:332;;;;;:::o;9905:117::-;10014:1;10011;10004:12;10028:117;10137:1;10134;10127:12;10168:568;10241:8;10251:6;10301:3;10294:4;10286:6;10282:17;10278:27;10268:122;;10309:79;;:::i;:::-;10268:122;10422:6;10409:20;10399:30;;10452:18;10444:6;10441:30;10438:117;;;10474:79;;:::i;:::-;10438:117;10588:4;10580:6;10576:17;10564:29;;10642:3;10634:4;10626:6;10622:17;10612:8;10608:32;10605:41;10602:128;;;10649:79;;:::i;:::-;10602:128;10168:568;;;;;:::o;10742:559::-;10828:6;10836;10885:2;10873:9;10864:7;10860:23;10856:32;10853:119;;;10891:79;;:::i;:::-;10853:119;11039:1;11028:9;11024:17;11011:31;11069:18;11061:6;11058:30;11055:117;;;11091:79;;:::i;:::-;11055:117;11204:80;11276:7;11267:6;11256:9;11252:22;11204:80;:::i;:::-;11186:98;;;;10982:312;10742:559;;;;;:::o;11307:146::-;11406:6;11440:5;11434:12;11424:22;;11307:146;;;:::o;11459:216::-;11590:11;11624:6;11619:3;11612:19;11664:4;11659:3;11655:14;11640:29;;11459:216;;;;:::o;11681:164::-;11780:4;11803:3;11795:11;;11833:4;11828:3;11824:14;11816:22;;11681:164;;;:::o;11851:108::-;11928:24;11946:5;11928:24;:::i;:::-;11923:3;11916:37;11851:108;;:::o;11965:101::-;12001:7;12041:18;12034:5;12030:30;12019:41;;11965:101;;;:::o;12072:105::-;12147:23;12164:5;12147:23;:::i;:::-;12142:3;12135:36;12072:105;;:::o;12183:99::-;12254:21;12269:5;12254:21;:::i;:::-;12249:3;12242:34;12183:99;;:::o;12288:91::-;12324:7;12364:8;12357:5;12353:20;12342:31;;12288:91;;;:::o;12385:105::-;12460:23;12477:5;12460:23;:::i;:::-;12455:3;12448:36;12385:105;;:::o;12568:866::-;12719:4;12714:3;12710:14;12806:4;12799:5;12795:16;12789:23;12825:63;12882:4;12877:3;12873:14;12859:12;12825:63;:::i;:::-;12734:164;12990:4;12983:5;12979:16;12973:23;13009:61;13064:4;13059:3;13055:14;13041:12;13009:61;:::i;:::-;12908:172;13164:4;13157:5;13153:16;13147:23;13183:57;13234:4;13229:3;13225:14;13211:12;13183:57;:::i;:::-;13090:160;13337:4;13330:5;13326:16;13320:23;13356:61;13411:4;13406:3;13402:14;13388:12;13356:61;:::i;:::-;13260:167;12688:746;12568:866;;:::o;13440:307::-;13573:10;13594:110;13700:3;13692:6;13594:110;:::i;:::-;13736:4;13731:3;13727:14;13713:28;;13440:307;;;;:::o;13753:145::-;13855:4;13887;13882:3;13878:14;13870:22;;13753:145;;;:::o;13980:988::-;14163:3;14192:86;14272:5;14192:86;:::i;:::-;14294:118;14405:6;14400:3;14294:118;:::i;:::-;14287:125;;14436:88;14518:5;14436:88;:::i;:::-;14547:7;14578:1;14563:380;14588:6;14585:1;14582:13;14563:380;;;14664:6;14658:13;14691:127;14814:3;14799:13;14691:127;:::i;:::-;14684:134;;14841:92;14926:6;14841:92;:::i;:::-;14831:102;;14623:320;14610:1;14607;14603:9;14598:14;;14563:380;;;14567:14;14959:3;14952:10;;14168:800;;;13980:988;;;;:::o;14974:501::-;15181:4;15219:2;15208:9;15204:18;15196:26;;15268:9;15262:4;15258:20;15254:1;15243:9;15239:17;15232:47;15296:172;15463:4;15454:6;15296:172;:::i;:::-;15288:180;;14974:501;;;;:::o;15481:329::-;15540:6;15589:2;15577:9;15568:7;15564:23;15560:32;15557:119;;;15595:79;;:::i;:::-;15557:119;15715:1;15740:53;15785:7;15776:6;15765:9;15761:22;15740:53;:::i;:::-;15730:63;;15686:117;15481:329;;;;:::o;15816:114::-;15883:6;15917:5;15911:12;15901:22;;15816:114;;;:::o;15936:184::-;16035:11;16069:6;16064:3;16057:19;16109:4;16104:3;16100:14;16085:29;;15936:184;;;;:::o;16126:132::-;16193:4;16216:3;16208:11;;16246:4;16241:3;16237:14;16229:22;;16126:132;;;:::o;16264:108::-;16341:24;16359:5;16341:24;:::i;:::-;16336:3;16329:37;16264:108;;:::o;16378:179::-;16447:10;16468:46;16510:3;16502:6;16468:46;:::i;:::-;16546:4;16541:3;16537:14;16523:28;;16378:179;;;;:::o;16563:113::-;16633:4;16665;16660:3;16656:14;16648:22;;16563:113;;;:::o;16712:732::-;16831:3;16860:54;16908:5;16860:54;:::i;:::-;16930:86;17009:6;17004:3;16930:86;:::i;:::-;16923:93;;17040:56;17090:5;17040:56;:::i;:::-;17119:7;17150:1;17135:284;17160:6;17157:1;17154:13;17135:284;;;17236:6;17230:13;17263:63;17322:3;17307:13;17263:63;:::i;:::-;17256:70;;17349:60;17402:6;17349:60;:::i;:::-;17339:70;;17195:224;17182:1;17179;17175:9;17170:14;;17135:284;;;17139:14;17435:3;17428:10;;16836:608;;;16712:732;;;;:::o;17450:373::-;17593:4;17631:2;17620:9;17616:18;17608:26;;17680:9;17674:4;17670:20;17666:1;17655:9;17651:17;17644:47;17708:108;17811:4;17802:6;17708:108;:::i;:::-;17700:116;;17450:373;;;;:::o;17829:619::-;17906:6;17914;17922;17971:2;17959:9;17950:7;17946:23;17942:32;17939:119;;;17977:79;;:::i;:::-;17939:119;18097:1;18122:53;18167:7;18158:6;18147:9;18143:22;18122:53;:::i;:::-;18112:63;;18068:117;18224:2;18250:53;18295:7;18286:6;18275:9;18271:22;18250:53;:::i;:::-;18240:63;;18195:118;18352:2;18378:53;18423:7;18414:6;18403:9;18399:22;18378:53;:::i;:::-;18368:63;;18323:118;17829:619;;;;;:::o;18454:468::-;18519:6;18527;18576:2;18564:9;18555:7;18551:23;18547:32;18544:119;;;18582:79;;:::i;:::-;18544:119;18702:1;18727:53;18772:7;18763:6;18752:9;18748:22;18727:53;:::i;:::-;18717:63;;18673:117;18829:2;18855:50;18897:7;18888:6;18877:9;18873:22;18855:50;:::i;:::-;18845:60;;18800:115;18454:468;;;;;:::o;18928:307::-;18989:4;19079:18;19071:6;19068:30;19065:56;;;19101:18;;:::i;:::-;19065:56;19139:29;19161:6;19139:29;:::i;:::-;19131:37;;19223:4;19217;19213:15;19205:23;;18928:307;;;:::o;19241:423::-;19318:5;19343:65;19359:48;19400:6;19359:48;:::i;:::-;19343:65;:::i;:::-;19334:74;;19431:6;19424:5;19417:21;19469:4;19462:5;19458:16;19507:3;19498:6;19493:3;19489:16;19486:25;19483:112;;;19514:79;;:::i;:::-;19483:112;19604:54;19651:6;19646:3;19641;19604:54;:::i;:::-;19324:340;19241:423;;;;;:::o;19683:338::-;19738:5;19787:3;19780:4;19772:6;19768:17;19764:27;19754:122;;19795:79;;:::i;:::-;19754:122;19912:6;19899:20;19937:78;20011:3;20003:6;19996:4;19988:6;19984:17;19937:78;:::i;:::-;19928:87;;19744:277;19683:338;;;;:::o;20027:943::-;20122:6;20130;20138;20146;20195:3;20183:9;20174:7;20170:23;20166:33;20163:120;;;20202:79;;:::i;:::-;20163:120;20322:1;20347:53;20392:7;20383:6;20372:9;20368:22;20347:53;:::i;:::-;20337:63;;20293:117;20449:2;20475:53;20520:7;20511:6;20500:9;20496:22;20475:53;:::i;:::-;20465:63;;20420:118;20577:2;20603:53;20648:7;20639:6;20628:9;20624:22;20603:53;:::i;:::-;20593:63;;20548:118;20733:2;20722:9;20718:18;20705:32;20764:18;20756:6;20753:30;20750:117;;;20786:79;;:::i;:::-;20750:117;20891:62;20945:7;20936:6;20925:9;20921:22;20891:62;:::i;:::-;20881:72;;20676:287;20027:943;;;;;;;:::o;21048:876::-;21209:4;21204:3;21200:14;21296:4;21289:5;21285:16;21279:23;21315:63;21372:4;21367:3;21363:14;21349:12;21315:63;:::i;:::-;21224:164;21480:4;21473:5;21469:16;21463:23;21499:61;21554:4;21549:3;21545:14;21531:12;21499:61;:::i;:::-;21398:172;21654:4;21647:5;21643:16;21637:23;21673:57;21724:4;21719:3;21715:14;21701:12;21673:57;:::i;:::-;21580:160;21827:4;21820:5;21816:16;21810:23;21846:61;21901:4;21896:3;21892:14;21878:12;21846:61;:::i;:::-;21750:167;21178:746;21048:876;;:::o;21930:351::-;22087:4;22125:3;22114:9;22110:19;22102:27;;22139:135;22271:1;22260:9;22256:17;22247:6;22139:135;:::i;:::-;21930:351;;;;:::o;22287:474::-;22355:6;22363;22412:2;22400:9;22391:7;22387:23;22383:32;22380:119;;;22418:79;;:::i;:::-;22380:119;22538:1;22563:53;22608:7;22599:6;22588:9;22584:22;22563:53;:::i;:::-;22553:63;;22509:117;22665:2;22691:53;22736:7;22727:6;22716:9;22712:22;22691:53;:::i;:::-;22681:63;;22636:118;22287:474;;;;;:::o;22767:::-;22835:6;22843;22892:2;22880:9;22871:7;22867:23;22863:32;22860:119;;;22898:79;;:::i;:::-;22860:119;23018:1;23043:53;23088:7;23079:6;23068:9;23064:22;23043:53;:::i;:::-;23033:63;;22989:117;23145:2;23171:53;23216:7;23207:6;23196:9;23192:22;23171:53;:::i;:::-;23161:63;;23116:118;22767:474;;;;;:::o;23247:180::-;23295:77;23292:1;23285:88;23392:4;23389:1;23382:15;23416:4;23413:1;23406:15;23433:320;23477:6;23514:1;23508:4;23504:12;23494:22;;23561:1;23555:4;23551:12;23582:18;23572:81;;23638:4;23630:6;23626:17;23616:27;;23572:81;23700:2;23692:6;23689:14;23669:18;23666:38;23663:84;;23719:18;;:::i;:::-;23663:84;23484:269;23433:320;;;:::o;23759:141::-;23808:4;23831:3;23823:11;;23854:3;23851:1;23844:14;23888:4;23885:1;23875:18;23867:26;;23759:141;;;:::o;23906:93::-;23943:6;23990:2;23985;23978:5;23974:14;23970:23;23960:33;;23906:93;;;:::o;24005:107::-;24049:8;24099:5;24093:4;24089:16;24068:37;;24005:107;;;;:::o;24118:393::-;24187:6;24237:1;24225:10;24221:18;24260:97;24290:66;24279:9;24260:97;:::i;:::-;24378:39;24408:8;24397:9;24378:39;:::i;:::-;24366:51;;24450:4;24446:9;24439:5;24435:21;24426:30;;24499:4;24489:8;24485:19;24478:5;24475:30;24465:40;;24194:317;;24118:393;;;;;:::o;24517:60::-;24545:3;24566:5;24559:12;;24517:60;;;:::o;24583:142::-;24633:9;24666:53;24684:34;24693:24;24711:5;24693:24;:::i;:::-;24684:34;:::i;:::-;24666:53;:::i;:::-;24653:66;;24583:142;;;:::o;24731:75::-;24774:3;24795:5;24788:12;;24731:75;;;:::o;24812:269::-;24922:39;24953:7;24922:39;:::i;:::-;24983:91;25032:41;25056:16;25032:41;:::i;:::-;25024:6;25017:4;25011:11;24983:91;:::i;:::-;24977:4;24970:105;24888:193;24812:269;;;:::o;25087:73::-;25132:3;25087:73;:::o;25166:189::-;25243:32;;:::i;:::-;25284:65;25342:6;25334;25328:4;25284:65;:::i;:::-;25219:136;25166:189;;:::o;25361:186::-;25421:120;25438:3;25431:5;25428:14;25421:120;;;25492:39;25529:1;25522:5;25492:39;:::i;:::-;25465:1;25458:5;25454:13;25445:22;;25421:120;;;25361:186;;:::o;25553:543::-;25654:2;25649:3;25646:11;25643:446;;;25688:38;25720:5;25688:38;:::i;:::-;25772:29;25790:10;25772:29;:::i;:::-;25762:8;25758:44;25955:2;25943:10;25940:18;25937:49;;;25976:8;25961:23;;25937:49;25999:80;26055:22;26073:3;26055:22;:::i;:::-;26045:8;26041:37;26028:11;25999:80;:::i;:::-;25658:431;;25643:446;25553:543;;;:::o;26102:117::-;26156:8;26206:5;26200:4;26196:16;26175:37;;26102:117;;;;:::o;26225:169::-;26269:6;26302:51;26350:1;26346:6;26338:5;26335:1;26331:13;26302:51;:::i;:::-;26298:56;26383:4;26377;26373:15;26363:25;;26276:118;26225:169;;;;:::o;26399:295::-;26475:4;26621:29;26646:3;26640:4;26621:29;:::i;:::-;26613:37;;26683:3;26680:1;26676:11;26670:4;26667:21;26659:29;;26399:295;;;;:::o;26699:1395::-;26816:37;26849:3;26816:37;:::i;:::-;26918:18;26910:6;26907:30;26904:56;;;26940:18;;:::i;:::-;26904:56;26984:38;27016:4;27010:11;26984:38;:::i;:::-;27069:67;27129:6;27121;27115:4;27069:67;:::i;:::-;27163:1;27187:4;27174:17;;27219:2;27211:6;27208:14;27236:1;27231:618;;;;27893:1;27910:6;27907:77;;;27959:9;27954:3;27950:19;27944:26;27935:35;;27907:77;28010:67;28070:6;28063:5;28010:67;:::i;:::-;28004:4;27997:81;27866:222;27201:887;;27231:618;27283:4;27279:9;27271:6;27267:22;27317:37;27349:4;27317:37;:::i;:::-;27376:1;27390:208;27404:7;27401:1;27398:14;27390:208;;;27483:9;27478:3;27474:19;27468:26;27460:6;27453:42;27534:1;27526:6;27522:14;27512:24;;27581:2;27570:9;27566:18;27553:31;;27427:4;27424:1;27420:12;27415:17;;27390:208;;;27626:6;27617:7;27614:19;27611:179;;;27684:9;27679:3;27675:19;27669:26;27727:48;27769:4;27761:6;27757:17;27746:9;27727:48;:::i;:::-;27719:6;27712:64;27634:156;27611:179;27836:1;27832;27824:6;27820:14;27816:22;27810:4;27803:36;27238:611;;;27201:887;;26791:1303;;;26699:1395;;:::o;28100:180::-;28148:77;28145:1;28138:88;28245:4;28242:1;28235:15;28269:4;28266:1;28259:15;28286:410;28326:7;28349:20;28367:1;28349:20;:::i;:::-;28344:25;;28383:20;28401:1;28383:20;:::i;:::-;28378:25;;28438:1;28435;28431:9;28460:30;28478:11;28460:30;:::i;:::-;28449:41;;28639:1;28630:7;28626:15;28623:1;28620:22;28600:1;28593:9;28573:83;28550:139;;28669:18;;:::i;:::-;28550:139;28334:362;28286:410;;;;:::o;28702:180::-;28750:77;28747:1;28740:88;28847:4;28844:1;28837:15;28871:4;28868:1;28861:15;28888:185;28928:1;28945:20;28963:1;28945:20;:::i;:::-;28940:25;;28979:20;28997:1;28979:20;:::i;:::-;28974:25;;29018:1;29008:35;;29023:18;;:::i;:::-;29008:35;29065:1;29062;29058:9;29053:14;;28888:185;;;;:::o;29079:147::-;29180:11;29217:3;29202:18;;29079:147;;;;:::o;29232:114::-;;:::o;29352:398::-;29511:3;29532:83;29613:1;29608:3;29532:83;:::i;:::-;29525:90;;29624:93;29713:3;29624:93;:::i;:::-;29742:1;29737:3;29733:11;29726:18;;29352:398;;;:::o;29756:379::-;29940:3;29962:147;30105:3;29962:147;:::i;:::-;29955:154;;30126:3;30119:10;;29756:379;;;:::o;30141:165::-;30281:17;30277:1;30269:6;30265:14;30258:41;30141:165;:::o;30312:366::-;30454:3;30475:67;30539:2;30534:3;30475:67;:::i;:::-;30468:74;;30551:93;30640:3;30551:93;:::i;:::-;30669:2;30664:3;30660:12;30653:19;;30312:366;;;:::o;30684:419::-;30850:4;30888:2;30877:9;30873:18;30865:26;;30937:9;30931:4;30927:20;30923:1;30912:9;30908:17;30901:47;30965:131;31091:4;30965:131;:::i;:::-;30957:139;;30684:419;;;:::o;31109:227::-;31249:34;31245:1;31237:6;31233:14;31226:58;31318:10;31313:2;31305:6;31301:15;31294:35;31109:227;:::o;31342:366::-;31484:3;31505:67;31569:2;31564:3;31505:67;:::i;:::-;31498:74;;31581:93;31670:3;31581:93;:::i;:::-;31699:2;31694:3;31690:12;31683:19;;31342:366;;;:::o;31714:419::-;31880:4;31918:2;31907:9;31903:18;31895:26;;31967:9;31961:4;31957:20;31953:1;31942:9;31938:17;31931:47;31995:131;32121:4;31995:131;:::i;:::-;31987:139;;31714:419;;;:::o;32139:170::-;32279:22;32275:1;32267:6;32263:14;32256:46;32139:170;:::o;32315:366::-;32457:3;32478:67;32542:2;32537:3;32478:67;:::i;:::-;32471:74;;32554:93;32643:3;32554:93;:::i;:::-;32672:2;32667:3;32663:12;32656:19;;32315:366;;;:::o;32687:419::-;32853:4;32891:2;32880:9;32876:18;32868:26;;32940:9;32934:4;32930:20;32926:1;32915:9;32911:17;32904:47;32968:131;33094:4;32968:131;:::i;:::-;32960:139;;32687:419;;;:::o;33112:191::-;33152:3;33171:20;33189:1;33171:20;:::i;:::-;33166:25;;33205:20;33223:1;33205:20;:::i;:::-;33200:25;;33248:1;33245;33241:9;33234:16;;33269:3;33266:1;33263:10;33260:36;;;33276:18;;:::i;:::-;33260:36;33112:191;;;;:::o;33309:170::-;33449:22;33445:1;33437:6;33433:14;33426:46;33309:170;:::o;33485:366::-;33627:3;33648:67;33712:2;33707:3;33648:67;:::i;:::-;33641:74;;33724:93;33813:3;33724:93;:::i;:::-;33842:2;33837:3;33833:12;33826:19;;33485:366;;;:::o;33857:419::-;34023:4;34061:2;34050:9;34046:18;34038:26;;34110:9;34104:4;34100:20;34096:1;34085:9;34081:17;34074:47;34138:131;34264:4;34138:131;:::i;:::-;34130:139;;33857:419;;;:::o;34282:169::-;34422:21;34418:1;34410:6;34406:14;34399:45;34282:169;:::o;34457:366::-;34599:3;34620:67;34684:2;34679:3;34620:67;:::i;:::-;34613:74;;34696:93;34785:3;34696:93;:::i;:::-;34814:2;34809:3;34805:12;34798:19;;34457:366;;;:::o;34829:419::-;34995:4;35033:2;35022:9;35018:18;35010:26;;35082:9;35076:4;35072:20;35068:1;35057:9;35053:17;35046:47;35110:131;35236:4;35110:131;:::i;:::-;35102:139;;34829:419;;;:::o;35254:173::-;35394:25;35390:1;35382:6;35378:14;35371:49;35254:173;:::o;35433:366::-;35575:3;35596:67;35660:2;35655:3;35596:67;:::i;:::-;35589:74;;35672:93;35761:3;35672:93;:::i;:::-;35790:2;35785:3;35781:12;35774:19;;35433:366;;;:::o;35805:419::-;35971:4;36009:2;35998:9;35994:18;35986:26;;36058:9;36052:4;36048:20;36044:1;36033:9;36029:17;36022:47;36086:131;36212:4;36086:131;:::i;:::-;36078:139;;35805:419;;;:::o;36230:234::-;36370:34;36366:1;36358:6;36354:14;36347:58;36439:17;36434:2;36426:6;36422:15;36415:42;36230:234;:::o;36470:366::-;36612:3;36633:67;36697:2;36692:3;36633:67;:::i;:::-;36626:74;;36709:93;36798:3;36709:93;:::i;:::-;36827:2;36822:3;36818:12;36811:19;;36470:366;;;:::o;36842:419::-;37008:4;37046:2;37035:9;37031:18;37023:26;;37095:9;37089:4;37085:20;37081:1;37070:9;37066:17;37059:47;37123:131;37249:4;37123:131;:::i;:::-;37115:139;;36842:419;;;:::o;37267:148::-;37369:11;37406:3;37391:18;;37267:148;;;;:::o;37421:390::-;37527:3;37555:39;37588:5;37555:39;:::i;:::-;37610:89;37692:6;37687:3;37610:89;:::i;:::-;37603:96;;37708:65;37766:6;37761:3;37754:4;37747:5;37743:16;37708:65;:::i;:::-;37798:6;37793:3;37789:16;37782:23;;37531:280;37421:390;;;;:::o;37841:874::-;37944:3;37981:5;37975:12;38010:36;38036:9;38010:36;:::i;:::-;38062:89;38144:6;38139:3;38062:89;:::i;:::-;38055:96;;38182:1;38171:9;38167:17;38198:1;38193:166;;;;38373:1;38368:341;;;;38160:549;;38193:166;38277:4;38273:9;38262;38258:25;38253:3;38246:38;38339:6;38332:14;38325:22;38317:6;38313:35;38308:3;38304:45;38297:52;;38193:166;;38368:341;38435:38;38467:5;38435:38;:::i;:::-;38495:1;38509:154;38523:6;38520:1;38517:13;38509:154;;;38597:7;38591:14;38587:1;38582:3;38578:11;38571:35;38647:1;38638:7;38634:15;38623:26;;38545:4;38542:1;38538:12;38533:17;;38509:154;;;38692:6;38687:3;38683:16;38676:23;;38375:334;;38160:549;;37948:767;;37841:874;;;;:::o;38721:589::-;38946:3;38968:95;39059:3;39050:6;38968:95;:::i;:::-;38961:102;;39080:95;39171:3;39162:6;39080:95;:::i;:::-;39073:102;;39192:92;39280:3;39271:6;39192:92;:::i;:::-;39185:99;;39301:3;39294:10;;38721:589;;;;;;:::o;39316:171::-;39355:3;39378:24;39396:5;39378:24;:::i;:::-;39369:33;;39424:4;39417:5;39414:15;39411:41;;39432:18;;:::i;:::-;39411:41;39479:1;39472:5;39468:13;39461:20;;39316:171;;;:::o;39493:98::-;39544:6;39578:5;39572:12;39562:22;;39493:98;;;:::o;39597:168::-;39680:11;39714:6;39709:3;39702:19;39754:4;39749:3;39745:14;39730:29;;39597:168;;;;:::o;39771:373::-;39857:3;39885:38;39917:5;39885:38;:::i;:::-;39939:70;40002:6;39997:3;39939:70;:::i;:::-;39932:77;;40018:65;40076:6;40071:3;40064:4;40057:5;40053:16;40018:65;:::i;:::-;40108:29;40130:6;40108:29;:::i;:::-;40103:3;40099:39;40092:46;;39861:283;39771:373;;;;:::o;40150:640::-;40345:4;40383:3;40372:9;40368:19;40360:27;;40397:71;40465:1;40454:9;40450:17;40441:6;40397:71;:::i;:::-;40478:72;40546:2;40535:9;40531:18;40522:6;40478:72;:::i;:::-;40560;40628:2;40617:9;40613:18;40604:6;40560:72;:::i;:::-;40679:9;40673:4;40669:20;40664:2;40653:9;40649:18;40642:48;40707:76;40778:4;40769:6;40707:76;:::i;:::-;40699:84;;40150:640;;;;;;;:::o;40796:141::-;40852:5;40883:6;40877:13;40868:22;;40899:32;40925:5;40899:32;:::i;:::-;40796:141;;;;:::o;40943:349::-;41012:6;41061:2;41049:9;41040:7;41036:23;41032:32;41029:119;;;41067:79;;:::i;:::-;41029:119;41187:1;41212:63;41267:7;41258:6;41247:9;41243:22;41212:63;:::i;:::-;41202:73;;41158:127;40943:349;;;;:::o

Swarm Source

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