ETH Price: $3,912.78 (-0.78%)

Token

Firstclass Pass (PASS)
 

Overview

Max Total Supply

48 PASS

Holders

35

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
0xdrnerd.eth
Balance
1 PASS
0x3be6e1d171e36c0fa42b4954dfa86248555e7d3e
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Firstclass Labs is a collective of unique individuals pushing the boundary of technology and culture, shaping a better future of humankind.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
FirstclassPass

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 1337 runs

Other Settings:
default evmVersion, GNU AGPLv3 license
File 1 of 14 : FirstclassPass.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.10;

/// @author: Firstclass Labs
/// @notice: "If you don’t get it, you don’t get it."

//////////////////////////////////////////////////////////////////////////////////
//      _______           __       __                   __          __          //
//     / ____(_)_________/ /______/ /___ ___________   / /   ____ _/ /_  _____  //
//    / /_  / / ___/ ___/ __/ ___/ / __ `/ ___/ ___/  / /   / __ `/ __ \/ ___/  //
//   / __/ / / /  (__  ) /_/ /__/ / /_/ (__  |__  )  / /___/ /_/ / /_/ (__  )   //
//  /_/   /_/_/  /____/\__/\___/_/\__,_/____/____/  /_____/\__,_/_.___/____/    //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

import "@firstclasslabs/erc4907/IERC4907Rentable.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "closedsea/src/OperatorFilterer.sol";
import "solady/src/utils/Base64.sol";
import "solady/src/utils/ECDSA.sol";
import "solmate/src/auth/Owned.sol";
import "solmate/src/tokens/ERC721.sol";
import "solmate/src/utils/LibString.sol";
import "solmate/src/utils/ReentrancyGuard.sol";

error F_BadInput();
error F_ExceededMaxSupply();
error F_ExceededPermitted();
error F_Forbidden();
error F_PaymentError();
error F_SignatureExpired();
error F_SignatureInvalid();
error F_SignatureUsed();
error F_TokenNotAvailable();
error F_TokenInUse();
error F_Underpaid();

contract FirstclassPass is
    ERC721,
    ERC2981,
    IERC4907Rentable,
    OperatorFilterer,
    Owned,
    ReentrancyGuard
{
    using LibString for uint256;

    // Maximum number of tokens that will be ever created
    uint256 public immutable maxSupply;

    // The number of tokens that currently exists
    uint256 private totalSupply_;

    // Mint price per token
    uint256 public immutable price;

    // Used to verify ECDSA signatures
    address private signer;

    // Keep track of used signatures
    mapping(bytes32 => bool) private signatures;

    /**
     * @notice Container for ERC4907Rentable data
     * @dev We're bullish on Ethereum but we'll likely be dead before `expires`
     * causes a problem in 2106. Also note that the `rate` is uint64 here as
     * opposed to uint256 defined in the interface. A non-zero `rate` means
     * the token is rentable.
     */
    struct Rentable {
        address user;
        uint32 expires;
        uint64 rate;
    }

    /**
     * @notice Mapping from token ID to packed {Rentable} data
     * @dev Bits layout: [255..192][191..160][159..0]
     *                       `rate` `expires`  `user`
     */
    mapping(uint256 => uint256) private rentables;

    // The mask of the lower 160 bits for `user`
    uint256 private constant BITMASK_USER = (1 << 160) - 1;

    // The mask of the lower 32 bits for `expires`
    uint256 private constant BITMASK_EXPIRES = (1 << 32) - 1;

    // The bit position of `expires`
    uint256 private constant BITPOS_EXPIRES = 160;

    // The bit position of `rate`
    uint256 private constant BITPOS_RATE = 192;

    // Minimum duration per rental
    uint256 private constant MIN_RENTAL_DURATION = 24 hours;

    // Maximum duration per rental
    uint256 private constant MAX_RENTAL_DURATION = 14 days;

    // Minimum rent per second
    uint256 private constant MIN_RENTAL_RATE = 100 gwei;

    // Where the funds should go to
    address private treasury;

    // See {ERC721Metadata}
    string private baseURI;

    // 💎 + 🖖
    uint256 private immutable initiation;

    // Keep track of the last transferred timestamps
    mapping(uint256 => uint256) private lastTransferred;

    // ERC2981 default royalty in bps
    uint96 private constant DEFAULT_ROYALTY_BPS = 1000;

    // See {_operatorFilteringEnabled}
    bool private operatorFiltering = true;

    /**
     * @notice Constructooooooor
     */
    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _maxSupply,
        uint256 _price,
        address _signer,
        address _treasury,
        uint256 _initiation,
        string memory _baseURI
    ) ERC721(_name, _symbol) Owned(msg.sender) {
        signer = _signer;
        treasury = _treasury;
        maxSupply = _maxSupply;
        price = _price;
        initiation = _initiation;
        baseURI = _baseURI;

        _setDefaultRoyalty(_treasury, DEFAULT_ROYALTY_BPS);
        _registerForOperatorFiltering();
    }

    /**
     * @notice Reverts if the queried token does not exist
     */
    modifier exists(uint256 _tokenId) {
        if (_ownerOf[_tokenId] == address(0)) revert F_BadInput();

        _;
    }

    /**
     * @notice Set the ECDSA signer address
     */
    function setSigner(address _signer) external onlyOwner {
        if (_signer == address(0)) revert F_BadInput();

        signer = _signer;
    }

    /**
     * @notice Set the treasury address
     */
    function setTreasury(address _treasury) external onlyOwner {
        if (_treasury == address(0)) revert F_BadInput();

        treasury = _treasury;
        _setDefaultRoyalty(_treasury, DEFAULT_ROYALTY_BPS);
    }

    /**
     * @notice See {ERC2981}
     */
    function setDefaultRoyalty(address _receiver, uint96 _feeNumerator) external onlyOwner {
        _setDefaultRoyalty(_receiver, _feeNumerator);
    }

    /**
     * @notice See {_operatorFilteringEnabled}
     */
    function setOperatorFiltering(bool _operatorFiltering) external onlyOwner {
        operatorFiltering = _operatorFiltering;
    }

    /**
     * @notice Mint tokens with ECDSA signatures
     */
    function mint(
        uint256 _quantity,
        uint256 _permitted,
        uint256 _deadline,
        bytes calldata _signature
    ) external payable {
        if (_quantity > _permitted) revert F_ExceededPermitted();
        if (totalSupply_ + _quantity > maxSupply) revert F_ExceededMaxSupply();
        if (msg.value < price * _quantity) revert F_Underpaid();
        if (block.timestamp > _deadline) revert F_SignatureExpired();
        if (!_signatureValid(_permitted, _deadline, _signature)) revert F_SignatureInvalid();

        bytes32 signatureHash = keccak256(_signature);
        if (_signatureUsed(signatureHash)) revert F_SignatureUsed();
        signatures[signatureHash] = true;

        (bool sent, ) = treasury.call{value: msg.value}("");
        if (!sent) revert F_PaymentError();

        unchecked {
            for (uint256 i = 0; i < _quantity; i++) {
                uint256 tokenId = ++totalSupply_;
                _safeMint(msg.sender, tokenId);
                lastTransferred[tokenId] = block.timestamp;
            }
        }
    }

    /**
     * @notice See {ERC4907}
     */
    function setUser(
        uint256 _tokenId,
        address _user,
        uint64 _expires
    ) external exists(_tokenId) {
        if (_expires > 2**32 - 1) revert F_BadInput();

        address owner = _ownerOf[_tokenId];
        if (msg.sender != owner)
            if (!isApprovedForAll[owner][msg.sender])
                if (getApproved[_tokenId] != msg.sender) revert F_Forbidden();

        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);
        if (rentable.expires > block.timestamp) revert F_TokenInUse();

        rentables[_tokenId] = _packRentable(_user, uint32(_expires), rentable.rate);

        emit UpdateUser(_tokenId, _user, _expires);
    }

    /**
     * @notice See {ERC4907}
     */
    function userOf(uint256 _tokenId) external view exists(_tokenId) returns (address) {
        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);
        return rentable.expires < block.timestamp ? address(0) : rentable.user;
    }

    /**
     * @notice See {ERC4907}
     */
    function userExpires(uint256 _tokenId) external view exists(_tokenId) returns (uint256) {
        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);
        return rentable.expires < block.timestamp ? 0 : rentable.expires;
    }

    /**
     * @notice See {ERC4907Rentable}
     */
    function rateOf(uint256 _tokenId) external view exists(_tokenId) returns (uint256) {
        return _unpackedRentable(rentables[_tokenId]).rate;
    }

    /**
     * @notice See {ERC4907Rentable}
     */
    function rent(uint256 _tokenId, uint64 _duration)
        external
        payable
        exists(_tokenId)
        nonReentrant
    {
        if (_duration < MIN_RENTAL_DURATION) revert F_BadInput();
        if (_duration > MAX_RENTAL_DURATION) revert F_BadInput();

        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);
        if (rentable.rate == 0) revert F_TokenNotAvailable();
        if (rentable.expires > block.timestamp) revert F_TokenInUse();

        uint256 rent_ = rentable.rate * _duration;
        if (msg.value < rent_) revert F_Underpaid();

        uint256 expires = block.timestamp + _duration;
        if (expires > 2**32 - 1) revert F_BadInput();

        // Rent distribution also conforms to the ERC2981 standard
        (address receiver, uint256 amount) = royaltyInfo(_tokenId, msg.value);
        (bool sent, ) = receiver.call{value: amount}("");
        if (!sent) revert F_PaymentError();

        address owner = _ownerOf[_tokenId];
        (sent, ) = owner.call{value: msg.value - amount}("");
        if (!sent) revert F_PaymentError();

        rentables[_tokenId] = _packRentable(msg.sender, uint32(expires), rentable.rate);

        emit UpdateUser(_tokenId, msg.sender, uint64(expires));
    }

    /**
     * @notice See {ERC4907Rentable}
     */
    function setRate(uint256 _tokenId, uint256 _rate) external exists(_tokenId) {
        if (_rate > 2**64 - 1) revert F_BadInput();
        if (_rate < MIN_RENTAL_RATE) revert F_BadInput();

        address owner = _ownerOf[_tokenId];
        if (msg.sender != owner)
            if (!isApprovedForAll[owner][msg.sender])
                if (getApproved[_tokenId] != msg.sender) revert F_Forbidden();

        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);
        if (rentable.expires > block.timestamp) revert F_TokenInUse();

        rentables[_tokenId] = _packRentable(rentable.user, rentable.expires, uint64(_rate));

        emit UpdateRate(_tokenId, _rate);
    }

    /**
     * @notice See {ERC721Metadata}
     */
    function setBaseURI(string calldata _uri) external onlyOwner {
        if (bytes(_uri).length == 0) revert F_BadInput();

        baseURI = _uri;
    }

    /**
     * @notice See {ERC721Metadata}
     */
    function tokenURI(uint256 _tokenId)
        public
        view
        override
        exists(_tokenId)
        returns (string memory)
    {
        if (bytes(baseURI).length == 0) return "";

        string memory id = _tokenId.toString();
        uint256 since = lastTransferred[_tokenId];
        string memory level = (block.timestamp - since) < initiation ? "Silver" : "Black";
        Rentable memory rentable = _unpackedRentable(rentables[_tokenId]);

        /* prettier-ignore */
        string memory encoded = Base64.encode(bytes(string(abi.encodePacked(
            /* solhint-disable */
            '{"name":"', name, ' #', id, '","image":"', baseURI, level, '.png",'
            '"animation_url":"', baseURI, level, '.mp4",'
            '"attributes":[{"trait_type":"Level","value":"', level, '"},',
            rentable.rate > 0 && rentable.expires < block.timestamp ? '{"value":"Rentable"},' : '',
            '{"display_type":"date","trait_type":"Member Since","value":', since.toString(), '}]}'
            /* solhint-enable */
        ))));

        return string(abi.encodePacked("data:application/json;base64,", encoded));
    }

    /**
     * @notice Query when did the membership start
     */
    function memberSince(uint256 _tokenId) public view exists(_tokenId) returns (uint256) {
        return lastTransferred[_tokenId];
    }

    /**
     * @notice See {ERC721Enumerable}
     */
    function totalSupply() public view returns (uint256) {
        return totalSupply_;
    }

    /**
     * @notice See {ERC721}
     */
    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override onlyAllowedOperator(_from) {
        ERC721.transferFrom(_from, _to, _tokenId);
        lastTransferred[_tokenId] = block.timestamp;
    }

    /**
     * @notice See {ERC165}
     */
    function supportsInterface(bytes4 _interfaceId)
        public
        view
        override(ERC721, ERC2981)
        returns (bool)
    {
        return
            ERC721.supportsInterface(_interfaceId) ||
            ERC2981.supportsInterface(_interfaceId) ||
            _interfaceId == type(IERC4907).interfaceId ||
            _interfaceId == type(IERC4907Rentable).interfaceId;
    }

    /**
     * @notice Read packed {Rentable} data from uint256
     */
    function _unpackedRentable(uint256 _packed) internal pure returns (Rentable memory rentable) {
        rentable.user = address(uint160(_packed));
        rentable.expires = uint32(_packed >> BITPOS_EXPIRES);
        rentable.rate = uint64(_packed >> BITPOS_RATE);
    }

    /**
     * @notice Pack {Rentable} data into uint256
     */
    function _packRentable(
        address _user,
        uint32 _expires,
        uint64 _rate
    ) internal pure returns (uint256 result) {
        assembly {
            // In case the upper bits somehow aren't clean
            _user := and(_user, BITMASK_USER)
            _expires := and(_expires, BITMASK_EXPIRES)
            // `_user` | (`_expires` << BITPOS_EXPIRES) | (`_rate` << BITPOS_RATE)
            result := or(_user, or(shl(BITPOS_EXPIRES, _expires), shl(BITPOS_RATE, _rate)))
        }
    }

    /**
     * @notice Validate ECDSA signatures
     */
    function _signatureValid(
        uint256 _permitted,
        uint256 _deadline,
        bytes calldata _signature
    ) internal view returns (bool) {
        bytes32 hash = keccak256(abi.encodePacked(msg.sender, _permitted, _deadline));
        address signer_ = ECDSA.recover(hash, _signature);
        return signer_ == signer ? true : false;
    }

    /**
     * @notice Check if an ECDSA signature has been used
     */
    function _signatureUsed(bytes32 _signatureHash) internal view returns (bool) {
        return signatures[_signatureHash];
    }

    /**
     * @dev For context, OpenSea has turned off royalties (yet they still
     * collect their 2.5% platform fees) on new collections that don't block
     * optional royalty marketplaces. As creators we unfortunately have to
     * follow the rule set by OpenSea since they still dominate the market at
     * the moment.
     *
     * This overhead adds ~3k gas to each {transferFrom} call 🖕
     */
    function _operatorFilteringEnabled() internal view override returns (bool) {
        return operatorFiltering;
    }
}

File 2 of 14 : IERC4907.sol
// SPDX-License-Identifier: CC0
pragma solidity ^0.8.10;

/**
 * @dev Required interface of an ERC4907 compliant contract.
 */
interface IERC4907 {
    /**
     * @notice Emits when the `user` or the `expires` is changed
     */
    event UpdateUser(
        uint256 indexed tokenId,
        address indexed user,
        uint64 expires
    );

    /**
     * @notice Set the user and an expiration time of an NFT
     */
    function setUser(
        uint256 tokenId,
        address user,
        uint64 expires
    ) external;

    /**
     * @notice Query the current user of an NFT
     * @dev The zero address indicates that there is no user
     */
    function userOf(uint256 tokenId) external view returns (address);

    /**
     * @notice Query the end time of the current rental period
     * @dev The zero value indicates that there is no user
     */
    function userExpires(uint256 tokenId) external view returns (uint256);
}

File 3 of 14 : IERC4907Rentable.sol
// SPDX-License-Identifier: CC0
pragma solidity ^0.8.10;

import "./IERC4907.sol";

/**
 * @dev Required interface of an ERC4907Rentable compliant contract.
 */
interface IERC4907Rentable is IERC4907 {
    /**
     * @dev This emits when the rental rate of an NFT changes.
     */
    event UpdateRate(uint256 indexed tokenId, uint256 rate);

    /**
     * @notice Rent an NFT for a period of time
     * @dev Emit the {UpdateUser} event. This function is called by the renter,
     *  while {setUser} is called by the owner or approved operators.
     * @param tokenId The identifier for an NFT
     * @param duration The duration of rental
     */
    function rent(uint256 tokenId, uint64 duration) external payable;

    /**
     * @notice Set the rental price per second for an NFT
     * @dev Emit the {UpdateRate} event.
     * @param tokenId The identifier for an NFT
     * @param rate The rental price per second
     */
    function setRate(uint256 tokenId, uint256 rate) external;

    /**
     * @notice Query the rental price for an NFT
     * @dev A zero rate indicates the NFT is not available for rent.
     * @param tokenId The identifier for an NFT
     * @return The rental price per second, or zero if not available for rent
     */
    function rateOf(uint256 tokenId) external view returns (uint256);
}

File 4 of 14 : IERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "../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.
 *
 * _Available since v4.5._
 */
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.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

File 5 of 14 : ERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.0;

import "../../interfaces/IERC2981.sol";
import "../../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 EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

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

    /**
     * @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 override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

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

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, 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 {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _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 {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _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 6 of 14 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 7 of 14 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 8 of 14 : OperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

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

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

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

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

            // Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty.
            subscriptionOrRegistrantToCopy := shr(96, shl(96, subscriptionOrRegistrantToCopy))
            // prettier-ignore
            for {} iszero(subscribe) {} {
                if iszero(subscriptionOrRegistrantToCopy) {
                    functionSelector := 0x4420e486 // `register(address)`.
                    break
                }
                functionSelector := 0xa0af2903 // `registerAndCopyEntries(address,address)`.
                break
            }
            // Store the function selector.
            mstore(0x00, shl(224, functionSelector))
            // Store the `address(this)`.
            mstore(0x04, address())
            // Store the `subscriptionOrRegistrantToCopy`.
            mstore(0x24, subscriptionOrRegistrantToCopy)
            // Register into the registry.
            pop(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x00))
            // Restore the part of the free memory pointer that was overwritten,
            // which is guaranteed to be zero, because of Solidity's memory size limits.
            mstore(0x24, 0)
        }
    }

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

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

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

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

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

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

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

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

File 9 of 14 : Base64.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library to encode strings in Base64.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol)
/// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>.
library Base64 {
    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// See: https://datatracker.ietf.org/doc/html/rfc4648
    /// @param fileSafe  Whether to replace '+' with '-' and '/' with '_'.
    /// @param noPadding Whether to strip away the padding.
    function encode(
        bytes memory data,
        bool fileSafe,
        bool noPadding
    ) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                // Multiply by 4/3 rounded up.
                // The `shl(2, ...)` is equivalent to multiplying by 4.
                let encodedLength := shl(2, div(add(dataLength, 2), 3))

                // Set `result` to point to the start of the free memory.
                result := mload(0x40)

                // Store the table into the scratch space.
                // Offsetted by -1 byte so that the `mload` will load the character.
                // We will rewrite the free memory pointer at `0x40` later with
                // the allocated size.
                // The magic constant 0x0230 will translate "-_" + "+/".
                mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
                mstore(0x3f, sub("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0230)))

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)
                let end := add(ptr, encodedLength)

                // Run over the input, 3 bytes at a time.
                // prettier-ignore
                for {} 1 {} {
                    data := add(data, 3) // Advance 3 bytes.
                    let input := mload(data)

                    // Write 4 bytes. Optimized for fewer stack operations.
                    mstore8(    ptr    , mload(and(shr(18, input), 0x3F)))
                    mstore8(add(ptr, 1), mload(and(shr(12, input), 0x3F)))
                    mstore8(add(ptr, 2), mload(and(shr( 6, input), 0x3F)))
                    mstore8(add(ptr, 3), mload(and(        input , 0x3F)))
                    
                    ptr := add(ptr, 4) // Advance 4 bytes.
                    // prettier-ignore
                    if iszero(lt(ptr, end)) { break }
                }

                let r := mod(dataLength, 3)

                switch noPadding
                case 0 {
                    // Offset `ptr` and pad with '='. We can simply write over the end.
                    mstore8(sub(ptr, iszero(iszero(r))), 0x3d) // Pad at `ptr - 1` if `r > 0`.
                    mstore8(sub(ptr, shl(1, eq(r, 1))), 0x3d) // Pad at `ptr - 2` if `r == 1`.
                    // Write the length of the string.
                    mstore(result, encodedLength)
                }
                default {
                    // Write the length of the string.
                    mstore(result, sub(encodedLength, add(iszero(iszero(r)), eq(r, 1))))
                }

                // Allocate the memory for the string.
                // Add 31 and mask with `not(31)` to round the
                // free memory pointer up the next multiple of 32.
                mstore(0x40, and(add(end, 31), not(31)))
            }
        }
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, false, false)`.
    function encode(bytes memory data) internal pure returns (string memory result) {
        result = encode(data, false, false);
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, fileSafe, false)`.
    function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) {
        result = encode(data, fileSafe, false);
    }

    /// @dev Encodes base64 encoded `data`.
    ///
    /// Supports:
    /// - RFC 4648 (both standard and file-safe mode).
    /// - RFC 3501 (63: ',').
    ///
    /// Does not support:
    /// - Line breaks.
    ///
    /// Note: For performance reasons,
    /// this function will NOT revert on invalid `data` inputs.
    /// Outputs for invalid inputs will simply be undefined behaviour.
    /// It is the user's responsibility to ensure that the `data`
    /// is a valid base64 encoded string.
    function decode(string memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                let end := add(data, dataLength)
                let decodedLength := mul(shr(2, dataLength), 3)

                switch and(dataLength, 3)
                case 0 {
                    // If padded.
                    decodedLength := sub(
                        decodedLength,
                        add(eq(and(mload(end), 0xFF), 0x3d), eq(and(mload(end), 0xFFFF), 0x3d3d))
                    )
                }
                default {
                    // If non-padded.
                    decodedLength := add(decodedLength, sub(and(dataLength, 3), 1))
                }

                result := mload(0x40)

                // Write the length of the string.
                mstore(result, decodedLength)

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)

                // Load the table into the scratch space.
                // Constants are optimized for smaller bytecode with zero gas overhead.
                // `m` also doubles as the mask of the upper 6 bits.
                let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc
                mstore(0x5b, m)
                mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064)
                mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4)

                // prettier-ignore
                for {} 1 {} {
                    // Read 4 bytes.
                    data := add(data, 4)
                    let input := mload(data)

                    // Write 3 bytes.
                    mstore(ptr, or(
                        and(m, mload(byte(28, input))),
                        shr(6, or(
                            and(m, mload(byte(29, input))),
                            shr(6, or(
                                and(m, mload(byte(30, input))),
                                shr(6, mload(byte(31, input)))
                            ))
                        ))
                    ))

                    ptr := add(ptr, 3)
                    
                    // prettier-ignore
                    if iszero(lt(data, end)) { break }
                }

                // Allocate the memory for the string.
                // Add 32 + 31 and mask with `not(31)` to round the
                // free memory pointer up the next multiple of 32.
                mstore(0x40, and(add(add(result, decodedLength), 63), not(31)))

                // Restore the zero slot.
                mstore(0x60, 0)
            }
        }
    }
}

File 10 of 14 : ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The number which `s` must not exceed in order for
    /// the signature to be non-malleable.
    bytes32 private constant _MALLEABILITY_THRESHOLD =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(bytes32 hash, bytes calldata signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(signature.length, 65) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Directly copy `r` and `s` from the calldata.
                calldatacopy(0x40, signature.offset, 0x40)

                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) {
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(sub(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal view returns (address result) {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = recover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    ///
    /// WARNING!
    /// The `result` will be the zero address upon recovery failure.
    /// As such, it is extremely important to ensure that the address which
    /// the `result` is compared against is never zero.
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)

            // If `s` in lower half order, such that the signature is not malleable.
            if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                mstore(0x00, hash)
                mstore(0x20, v)
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        0x01, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                // Restore the zero slot.
                mstore(0x60, 0)
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(sub(0x60, returndatasize()))
            }
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Store into scratch space for keccak256.
            mstore(0x20, hash)
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32")
            // 0x40 - 0x04 = 0x3c
            result := keccak256(0x04, 0x3c)
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        assembly {
            // We need at most 128 bytes for Ethereum signed message header.
            // The max length of the ASCII reprenstation of a uint256 is 78 bytes.
            // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a).
            // The next multiple of 32 above 78 + 26 is 128 (i.e. 0x80).

            // Instead of allocating, we temporarily copy the 128 bytes before the
            // start of `s` data to some variables.
            let m3 := mload(sub(s, 0x60))
            let m2 := mload(sub(s, 0x40))
            let m1 := mload(sub(s, 0x20))
            // The length of `s` is in bytes.
            let sLength := mload(s)

            let ptr := add(s, 0x20)

            // `end` marks the end of the memory which we will compute the keccak256 of.
            let end := add(ptr, sLength)

            // Convert the length of the bytes to ASCII decimal representation
            // and store it into the memory.
            // prettier-ignore
            for { let temp := sLength } 1 {} {
                ptr := sub(ptr, 1)
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            // Copy the header over to the memory.
            mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n")
            // Compute the keccak256 of the memory.
            result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a)))

            // Restore the previous memory.
            mstore(s, sLength)
            mstore(sub(s, 0x20), m1)
            mstore(sub(s, 0x40), m2)
            mstore(sub(s, 0x60), m3)
        }
    }
}

File 11 of 14 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 12 of 14 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 13 of 14 : LibString.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Efficient library for creating string representations of integers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
library LibString {
    function toString(uint256 value) internal pure returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
            // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
            // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
            let newFreeMemoryPointer := add(mload(0x40), 160)

            // Update the free memory pointer to avoid overriding our string.
            mstore(0x40, newFreeMemoryPointer)

            // Assign str to the end of the zone of newly allocated memory.
            str := sub(newFreeMemoryPointer, 32)

            // Clean the last word of memory it may not be overwritten.
            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 {} {
                // Move the pointer 1 byte to the left.
                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 }
            }

            // Compute and cache the final total length of the string.
            let length := sub(end, str)

            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 32)

            // Store the string's length at the start of memory allocated for our string.
            mstore(str, length)
        }
    }
}

File 14 of 14 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 1337
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint256","name":"_initiation","type":"uint256"},{"internalType":"string","name":"_baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"F_BadInput","type":"error"},{"inputs":[],"name":"F_ExceededMaxSupply","type":"error"},{"inputs":[],"name":"F_ExceededPermitted","type":"error"},{"inputs":[],"name":"F_Forbidden","type":"error"},{"inputs":[],"name":"F_PaymentError","type":"error"},{"inputs":[],"name":"F_SignatureExpired","type":"error"},{"inputs":[],"name":"F_SignatureInvalid","type":"error"},{"inputs":[],"name":"F_SignatureUsed","type":"error"},{"inputs":[],"name":"F_TokenInUse","type":"error"},{"inputs":[],"name":"F_TokenNotAvailable","type":"error"},{"inputs":[],"name":"F_Underpaid","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"UpdateRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"expires","type":"uint64"}],"name":"UpdateUser","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"memberSince","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_permitted","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","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":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"rateOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint64","name":"_duration","type":"uint64"}],"name":"rent","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint96","name":"_feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_operatorFiltering","type":"bool"}],"name":"setOperatorFiltering","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_rate","type":"uint256"}],"name":"setRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint64","name":"_expires","type":"uint64"}],"name":"setUser","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":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"userExpires","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"userOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60e0604052600160098190556011805460ff191690911790553480156200002557600080fd5b50604051620036c7380380620036c7833981016040819052620000489162000398565b3388886000620000598382620004fb565b506001620000688282620004fb565b5050600880546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600b80546001600160a01b038087166001600160a01b031992831617909255600e805492861692909116919091179055608086905260a085905260c0829052600f620001048282620004fb565b5062000113836103e86200012b565b6200011d62000230565b5050505050505050620005c7565b6127106001600160601b03821611156200019f5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084015b60405180910390fd5b6001600160a01b038216620001f75760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640162000196565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600655565b62000251733cc6cdda760b79bafa08df41ecfa224f810dceb6600162000253565b565b6001600160a01b0390911690637d3e3dbe816200028357826200027c5750634420e48662000283565b5063a0af29035b8060e01b60005250306004528160245260008060446000806daaeb6d7670e522a718067333cd4e5af15060006024525050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620002de57600080fd5b81516001600160401b0380821115620002fb57620002fb620002b6565b604051601f8301601f19908116603f01168101908282118183101715620003265762000326620002b6565b816040528381526020925086838588010111156200034357600080fd5b600091505b8382101562000367578582018301518183018401529082019062000348565b600093810190920192909252949350505050565b80516001600160a01b03811681146200039357600080fd5b919050565b600080600080600080600080610100898b031215620003b657600080fd5b88516001600160401b0380821115620003ce57600080fd5b620003dc8c838d01620002cc565b995060208b0151915080821115620003f357600080fd5b620004018c838d01620002cc565b985060408b0151975060608b015196506200041f60808c016200037b565b95506200042f60a08c016200037b565b945060c08b0151935060e08b01519150808211156200044d57600080fd5b506200045c8b828c01620002cc565b9150509295985092959890939650565b600181811c908216806200048157607f821691505b602082108103620004a257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620004f657600081815260208120601f850160051c81016020861015620004d15750805b601f850160051c820191505b81811015620004f257828155600101620004dd565b5050505b505050565b81516001600160401b03811115620005175762000517620002b6565b6200052f816200052884546200046c565b84620004a8565b602080601f8311600181146200056757600084156200054e5750858301515b600019600386901b1c1916600185901b178555620004f2565b600085815260208120601f198616915b82811015620005985788860151825594840194600190910190840162000577565b5085821015620005b75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516130c26200060560003960006119460152600081816104da01526111250152600081816105ae01526110ba01526130c26000f3fe6080604052600436106101e35760003560e01c806370a0823111610102578063c2f1f14a11610095578063e030565e11610064578063e030565e146105d0578063e985e9c5146105f0578063f0f442601461062b578063f2fde38b1461064b57600080fd5b8063c2f1f14a1461053c578063c87b56dd1461055c578063cac80e781461057c578063d5abeb011461059c57600080fd5b806395d89b41116100d157806395d89b41146104b3578063a035b1fe146104c8578063a22cb465146104fc578063b88d4fde1461051c57600080fd5b806370a08231146104335780638da5cb5b146104535780638fc88c4814610473578063932c75eb1461049357600080fd5b80632ed2d4291161017a57806352ae32c71161014957806352ae32c7146103b357806355f804b3146103d35780636352211e146103f35780636c19e7831461041357600080fd5b80632ed2d4291461034d57806342842e0e1461036057806346df2ccb146103805780634a9eee69146103a057600080fd5b8063095ea7b3116101b6578063095ea7b3146102af57806318160ddd146102cf57806323b872dd146102ee5780632a55205a1461030e57600080fd5b806301ffc9a7146101e857806304634d8d1461021d57806306fdde031461023f578063081812fc14610261575b600080fd5b3480156101f457600080fd5b5061020861020336600461275d565b61066b565b60405190151581526020015b60405180910390f35b34801561022957600080fd5b5061023d610238366004612791565b6106f3565b005b34801561024b57600080fd5b5061025461074f565b60405161021491906127fd565b34801561026d57600080fd5b5061029761027c366004612830565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610214565b3480156102bb57600080fd5b5061023d6102ca366004612849565b6107dd565b3480156102db57600080fd5b50600a545b604051908152602001610214565b3480156102fa57600080fd5b5061023d610309366004612873565b6108db565b34801561031a57600080fd5b5061032e6103293660046128af565b610921565b604080516001600160a01b039093168352602083019190915201610214565b61023d61035b3660046128e9565b6109de565b34801561036c57600080fd5b5061023d61037b366004612873565b610d89565b34801561038c57600080fd5b5061023d61039b3660046128af565b610e8e565b61023d6103ae366004612957565b61107e565b3480156103bf57600080fd5b506102e06103ce366004612830565b611320565b3480156103df57600080fd5b5061023d6103ee3660046129b8565b6113b4565b3480156103ff57600080fd5b5061029761040e366004612830565b61142c565b34801561041f57600080fd5b5061023d61042e3660046129fa565b611496565b34801561043f57600080fd5b506102e061044e3660046129fa565b611535565b34801561045f57600080fd5b50600854610297906001600160a01b031681565b34801561047f57600080fd5b506102e061048e366004612830565b6115a9565b34801561049f57600080fd5b5061023d6104ae366004612a25565b611654565b3480156104bf57600080fd5b506102546116b0565b3480156104d457600080fd5b506102e07f000000000000000000000000000000000000000000000000000000000000000081565b34801561050857600080fd5b5061023d610517366004612a40565b6116bd565b34801561052857600080fd5b5061023d610537366004612a6a565b611729565b34801561054857600080fd5b50610297610557366004612830565b61181e565b34801561056857600080fd5b50610254610577366004612830565b6118c0565b34801561058857600080fd5b506102e0610597366004612830565b611b1c565b3480156105a857600080fd5b506102e07f000000000000000000000000000000000000000000000000000000000000000081565b3480156105dc57600080fd5b5061023d6105eb366004612abc565b611b67565b3480156105fc57600080fd5b5061020861060b366004612af8565b600560209081526000928352604080842090915290825290205460ff1681565b34801561063757600080fd5b5061023d6106463660046129fa565b611d4a565b34801561065757600080fd5b5061023d6106663660046129fa565b611df1565b600061067682611e93565b80610685575061068582611f13565b806106b957506001600160e01b031982167fad092b5c00000000000000000000000000000000000000000000000000000000145b806106ed57506001600160e01b031982167f3aa3ca2500000000000000000000000000000000000000000000000000000000145b92915050565b6008546001600160a01b031633146107415760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b61074b8282611f61565b5050565b6000805461075c90612b22565b80601f016020809104026020016040519081016040528092919081815260200182805461078890612b22565b80156107d55780601f106107aa576101008083540402835291602001916107d5565b820191906000526020600020905b8154815290600101906020018083116107b857829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061082657506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6108725760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610738565b600082815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b826001600160a01b03811633146109005760115460ff1615610900576109003361207b565b61090b8484846120bf565b5060009081526010602052604090204290555050565b60008281526007602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046bffffffffffffffffffffffff169282019290925282916109a05750604080518082019091526006546001600160a01b0381168252600160a01b90046bffffffffffffffffffffffff1660208201525b6020810151600090612710906109c4906bffffffffffffffffffffffff1687612b6c565b6109ce9190612b83565b91519350909150505b9250929050565b60008281526002602052604090205482906001600160a01b0316610a155760405163d29e844f60e01b815260040160405180910390fd5b600954600114610a675760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610738565b60026009556201518067ffffffffffffffff83161015610a9a5760405163d29e844f60e01b815260040160405180910390fd5b621275008267ffffffffffffffff161115610ac85760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d6020526040812054610b0e90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b9050806040015167ffffffffffffffff16600003610b58576040517ff34c1eb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015163ffffffff161115610b8357604051630ccb4b8360e01b815260040160405180910390fd5b6000838260400151610b959190612ba5565b67ffffffffffffffff16905080341015610bc257604051631059010b60e21b815260040160405180910390fd5b6000610bd867ffffffffffffffff861642612bd1565b905063ffffffff811115610bff5760405163d29e844f60e01b815260040160405180910390fd5b600080610c0c8834610921565b915091506000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610c5d576040519150601f19603f3d011682016040523d82523d6000602084013e610c62565b606091505b5050905080610c845760405163351930e760e21b815260040160405180910390fd5b6000898152600260205260409020546001600160a01b031680610ca78434612be4565b604051600081818185875af1925050503d8060008114610ce3576040519150601f19603f3d011682016040523d82523d6000602084013e610ce8565b606091505b50508092505081610d0c5760405163351930e760e21b815260040160405180910390fd5b604087015160c01b60a086901b63ffffffff60a01b1617331760008b8152600d6020908152604091829020929092555167ffffffffffffffff8716815233918c917f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe910160405180910390a3505060016009555050505050505050565b610d948383836108db565b6001600160a01b0382163b1580610e3d5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e319190612bf7565b6001600160e01b031916145b610e895760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b505050565b60008281526002602052604090205482906001600160a01b0316610ec55760405163d29e844f60e01b815260040160405180910390fd5b67ffffffffffffffff821115610eee5760405163d29e844f60e01b815260040160405180910390fd5b64174876e800821015610f145760405163d29e844f60e01b815260040160405180910390fd5b6000838152600260205260409020546001600160a01b0316338114610f95576001600160a01b038116600090815260056020908152604080832033845290915290205460ff16610f95576000848152600460205260409020546001600160a01b03163314610f9557604051637e83d05f60e11b815260040160405180910390fd5b6000848152600d6020526040812054610fdb90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff16111561100857604051630ccb4b8360e01b815260040160405180910390fd5b8051602082015163ffffffff60a01b60a09190911b1660c086901b176001600160a01b03909116176000868152600d6020908152604091829020929092555185815286917ffe3b4c3f6e2efdc3dd612c3eb2817308b7568ad72d3f9c9200a08a069c27dff8910160405180910390a25050505050565b838511156110b8576040517fd0ef050f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000085600a546110e79190612bd1565b111561111f576040517f35ecb02100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611149857f0000000000000000000000000000000000000000000000000000000000000000612b6c565b34101561116957604051631059010b60e21b815260040160405180910390fd5b824211156111a3576040517f601a8f3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af848484846122c1565b6111e5576040517fdfab322b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082826040516111f7929190612c14565b6040518091039020905061121a816000908152600c602052604090205460ff1690565b15611251576040517f9943862900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600c6020526040808220805460ff19166001179055600e5490516001600160a01b039091169034908381818185875af1925050503d80600081146112b6576040519150601f19603f3d011682016040523d82523d6000602084013e6112bb565b606091505b50509050806112dd5760405163351930e760e21b815260040160405180910390fd5b60005b8781101561131657600a8054600101908190556112fd3382612357565b60009081526010602052604090204290556001016112e0565b5050505050505050565b60008181526002602052604081205482906001600160a01b03166113575760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604090205461139d90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b6040015167ffffffffffffffff1691505b50919050565b6008546001600160a01b031633146113fd5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b600081900361141f5760405163d29e844f60e01b815260040160405180910390fd5b600f610e89828483612c88565b6000818152600260205260409020546001600160a01b0316806114915760405162461bcd60e51b815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610738565b919050565b6008546001600160a01b031633146114df5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6001600160a01b0381166115065760405163d29e844f60e01b815260040160405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006001600160a01b03821661158d5760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610738565b506001600160a01b031660009081526003602052604090205490565b60008181526002602052604081205482906001600160a01b03166115e05760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604081205461162690604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff1610611643578060200151611646565b60005b63ffffffff16949350505050565b6008546001600160a01b0316331461169d5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6011805460ff1916911515919091179055565b6001805461075c90612b22565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6117348585856108db565b6001600160a01b0384163b15806117cb5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061177c9033908a90899089908990600401612d48565b6020604051808303816000875af115801561179b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bf9190612bf7565b6001600160e01b031916145b6118175760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b5050505050565b60008181526002602052604081205482906001600160a01b03166118555760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604081205461189b90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff16106118b55780516118b8565b60005b949350505050565b60008181526002602052604090205460609082906001600160a01b03166118fa5760405163d29e844f60e01b815260040160405180910390fd5b600f805461190790612b22565b9050600003611927576040518060200160405280600081525091506113ae565b600061193284612453565b6000858152601060205260408120549192507f000000000000000000000000000000000000000000000000000000000000000061196f8342612be4565b106119af576040518060400160405280600581526020017f426c61636b0000000000000000000000000000000000000000000000000000008152506119e6565b6040518060400160405280600681526020017f53696c76657200000000000000000000000000000000000000000000000000008152505b6000878152600d602052604081205491925090611a3090604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b90506000611aed600086600f86600f888960008a6040015167ffffffffffffffff16118015611a685750428a6020015163ffffffff16105b611a815760405180602001604052806000815250611ab8565b6040518060400160405280601581526020017f7b2276616c7565223a2252656e7461626c65227d2c00000000000000000000008152505b611ac18d612453565b604051602001611ad999989796959493929190612e2b565b604051602081830303815290604052612497565b905080604051602001611b009190613047565b6040516020818303038152906040529650505050505050919050565b60008181526002602052604081205482906001600160a01b0316611b535760405163d29e844f60e01b815260040160405180910390fd5b505060009081526010602052604090205490565b60008381526002602052604090205483906001600160a01b0316611b9e5760405163d29e844f60e01b815260040160405180910390fd5b63ffffffff8267ffffffffffffffff161115611bcd5760405163d29e844f60e01b815260040160405180910390fd5b6000848152600260205260409020546001600160a01b0316338114611c4e576001600160a01b038116600090815260056020908152604080832033845290915290205460ff16611c4e576000858152600460205260409020546001600160a01b03163314611c4e57604051637e83d05f60e11b815260040160405180910390fd5b6000858152600d6020526040812054611c9490604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff161115611cc157604051630ccb4b8360e01b815260040160405180910390fd5b60408101516001600160a01b03861660c09190911b60a086901b63ffffffff60a01b1617176000878152600d6020908152604091829020929092555167ffffffffffffffff861681526001600160a01b0387169188917f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe910160405180910390a3505050505050565b6008546001600160a01b03163314611d935760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6001600160a01b038116611dba5760405163d29e844f60e01b815260040160405180910390fd5b600e805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316179055611dee816103e8611f61565b50565b6008546001600160a01b03163314611e3a5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6008805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b60006301ffc9a760e01b6001600160e01b031983161480611edd57507f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b806106ed5750506001600160e01b0319167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b60006001600160e01b031982167f2a55205a0000000000000000000000000000000000000000000000000000000014806106ed57506301ffc9a760e01b6001600160e01b03198316146106ed565b6127106bffffffffffffffffffffffff82161115611fe75760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c2065786365656460448201527f2073616c655072696365000000000000000000000000000000000000000000006064820152608401610738565b6001600160a01b03821661203d5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610738565b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600655565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa6120b7573d6000803e3d6000fd5b6000603a5250565b6000818152600260205260409020546001600160a01b038481169116146121285760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610738565b6001600160a01b03821661217e5760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610738565b336001600160a01b03841614806121b857506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806121d957506000818152600460205260409020546001600160a01b031633145b6122255760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610738565b6001600160a01b03808416600081815260036020908152604080832080546000190190559386168083528483208054600101905585835260028252848320805473ffffffffffffffffffffffffffffffffffffffff199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052605481018490526000908190607401604051602081830303815290604052805190602001209050600061232a8286866124a5565b600b549091506001600160a01b0380831691161461234957600061234c565b60015b979650505050505050565b6123618282612515565b6001600160a01b0382163b15806124075750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af11580156123d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fb9190612bf7565b6001600160e01b031916145b61074b5760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061246d5750819003601f19909101908152919050565b60606106ed82600080612648565b60006041820361250e576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a06060511161250a5784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b6040525b9392505050565b6001600160a01b03821661256b5760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610738565b6000818152600260205260409020546001600160a01b0316156125d05760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610738565b6001600160a01b0382166000818152600360209081526040808320805460010190558483526002909152808220805473ffffffffffffffffffffffffffffffffffffffff19168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60608351801561273f576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f8116516003840153506004820191508082106126b8576003840686801561271857600182148215150185038752612730565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b6001600160e01b031981168114611dee57600080fd5b60006020828403121561276f57600080fd5b813561250e81612747565b80356001600160a01b038116811461149157600080fd5b600080604083850312156127a457600080fd5b6127ad8361277a565b915060208301356bffffffffffffffffffffffff811681146127ce57600080fd5b809150509250929050565b60005b838110156127f45781810151838201526020016127dc565b50506000910152565b602081526000825180602084015261281c8160408501602087016127d9565b601f01601f19169190910160400192915050565b60006020828403121561284257600080fd5b5035919050565b6000806040838503121561285c57600080fd5b6128658361277a565b946020939093013593505050565b60008060006060848603121561288857600080fd5b6128918461277a565b925061289f6020850161277a565b9150604084013590509250925092565b600080604083850312156128c257600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461149157600080fd5b600080604083850312156128fc57600080fd5b8235915061290c602084016128d1565b90509250929050565b60008083601f84011261292757600080fd5b50813567ffffffffffffffff81111561293f57600080fd5b6020830191508360208285010111156109d757600080fd5b60008060008060006080868803121561296f57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561299b57600080fd5b6129a788828901612915565b969995985093965092949392505050565b600080602083850312156129cb57600080fd5b823567ffffffffffffffff8111156129e257600080fd5b6129ee85828601612915565b90969095509350505050565b600060208284031215612a0c57600080fd5b61250e8261277a565b8035801515811461149157600080fd5b600060208284031215612a3757600080fd5b61250e82612a15565b60008060408385031215612a5357600080fd5b612a5c8361277a565b915061290c60208401612a15565b600080600080600060808688031215612a8257600080fd5b612a8b8661277a565b9450612a996020870161277a565b935060408601359250606086013567ffffffffffffffff81111561299b57600080fd5b600080600060608486031215612ad157600080fd5b83359250612ae16020850161277a565b9150612aef604085016128d1565b90509250925092565b60008060408385031215612b0b57600080fd5b612b148361277a565b915061290c6020840161277a565b600181811c90821680612b3657607f821691505b6020821081036113ae57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176106ed576106ed612b56565b600082612ba057634e487b7160e01b600052601260045260246000fd5b500490565b67ffffffffffffffff818116838216028082169190828114612bc957612bc9612b56565b505092915050565b808201808211156106ed576106ed612b56565b818103818111156106ed576106ed612b56565b600060208284031215612c0957600080fd5b815161250e81612747565b8183823760009101908152919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610e8957600081815260208120601f850160051c81016020861015612c615750805b601f850160051c820191505b81811015612c8057828155600101612c6d565b505050505050565b67ffffffffffffffff831115612ca057612ca0612c24565b612cb483612cae8354612b22565b83612c3a565b6000601f841160018114612ce85760008515612cd05750838201355b600019600387901b1c1916600186901b178355611817565b600083815260209020601f19861690835b82811015612d195786850135825560209485019460019092019101612cf9565b5086821015612d365760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60008154612da981612b22565b60018281168015612dc15760018114612dd657612e05565b60ff1984168752821515830287019450612e05565b8560005260208060002060005b85811015612dfc5781548a820152908401908201612de3565b50505082870194505b5050505092915050565b60008151612e218185602086016127d9565b9290920192915050565b7f7b226e616d65223a22000000000000000000000000000000000000000000000081526000612e5d600983018c612d9c565b7f202300000000000000000000000000000000000000000000000000000000000081528a51612e93816002840160208f016127d9565b7f222c22696d616765223a2200000000000000000000000000000000000000000060029290910191820152612ecb600d82018b612d9c565b90508851612edd818360208d016127d9565b7f2e706e67222c22616e696d6174696f6e5f75726c223a220000000000000000009101908152612f106017820189612d9c565b90508651612f22818360208b016127d9565b7f2e6d7034222c2261747472696275746573223a5b7b2274726169745f7479706591019081527f223a224c6576656c222c2276616c7565223a2200000000000000000000000000602082015261303761300e613008612fb9612fb3612f8a603387018c612e0f565b7f227d2c0000000000000000000000000000000000000000000000000000000000815260030190565b89612e0f565b7f7b22646973706c61795f74797065223a2264617465222c2274726169745f747981527f7065223a224d656d6265722053696e6365222c2276616c7565223a00000000006020820152603b0190565b86612e0f565b7f7d5d7d0000000000000000000000000000000000000000000000000000000000815260030190565b9c9b505050505050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161307f81601d8501602087016127d9565b91909101601d019291505056fea26469706673582212205d7ab335ebc614b99b6b049c2737289383ed32876ce1467449e1da4d58ee1e4464736f6c634300081100330000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000b630a873e7a73a7a31232b5b4b3890717546000000000000000000000000725d80f337a8cb585a5b8b3f803fe7238c26c80d000000000000000000000000000000000000000000000000000000000076a7000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000f4669727374636c6173732050617373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045041535300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004068747470733a2f2f617277656176652e6e65742f7332534132742d3659594461614464337956547a4977644635664379694c71516e7679374a69345256456b2f

Deployed Bytecode

0x6080604052600436106101e35760003560e01c806370a0823111610102578063c2f1f14a11610095578063e030565e11610064578063e030565e146105d0578063e985e9c5146105f0578063f0f442601461062b578063f2fde38b1461064b57600080fd5b8063c2f1f14a1461053c578063c87b56dd1461055c578063cac80e781461057c578063d5abeb011461059c57600080fd5b806395d89b41116100d157806395d89b41146104b3578063a035b1fe146104c8578063a22cb465146104fc578063b88d4fde1461051c57600080fd5b806370a08231146104335780638da5cb5b146104535780638fc88c4814610473578063932c75eb1461049357600080fd5b80632ed2d4291161017a57806352ae32c71161014957806352ae32c7146103b357806355f804b3146103d35780636352211e146103f35780636c19e7831461041357600080fd5b80632ed2d4291461034d57806342842e0e1461036057806346df2ccb146103805780634a9eee69146103a057600080fd5b8063095ea7b3116101b6578063095ea7b3146102af57806318160ddd146102cf57806323b872dd146102ee5780632a55205a1461030e57600080fd5b806301ffc9a7146101e857806304634d8d1461021d57806306fdde031461023f578063081812fc14610261575b600080fd5b3480156101f457600080fd5b5061020861020336600461275d565b61066b565b60405190151581526020015b60405180910390f35b34801561022957600080fd5b5061023d610238366004612791565b6106f3565b005b34801561024b57600080fd5b5061025461074f565b60405161021491906127fd565b34801561026d57600080fd5b5061029761027c366004612830565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610214565b3480156102bb57600080fd5b5061023d6102ca366004612849565b6107dd565b3480156102db57600080fd5b50600a545b604051908152602001610214565b3480156102fa57600080fd5b5061023d610309366004612873565b6108db565b34801561031a57600080fd5b5061032e6103293660046128af565b610921565b604080516001600160a01b039093168352602083019190915201610214565b61023d61035b3660046128e9565b6109de565b34801561036c57600080fd5b5061023d61037b366004612873565b610d89565b34801561038c57600080fd5b5061023d61039b3660046128af565b610e8e565b61023d6103ae366004612957565b61107e565b3480156103bf57600080fd5b506102e06103ce366004612830565b611320565b3480156103df57600080fd5b5061023d6103ee3660046129b8565b6113b4565b3480156103ff57600080fd5b5061029761040e366004612830565b61142c565b34801561041f57600080fd5b5061023d61042e3660046129fa565b611496565b34801561043f57600080fd5b506102e061044e3660046129fa565b611535565b34801561045f57600080fd5b50600854610297906001600160a01b031681565b34801561047f57600080fd5b506102e061048e366004612830565b6115a9565b34801561049f57600080fd5b5061023d6104ae366004612a25565b611654565b3480156104bf57600080fd5b506102546116b0565b3480156104d457600080fd5b506102e07f00000000000000000000000000000000000000000000000029a2241af62c000081565b34801561050857600080fd5b5061023d610517366004612a40565b6116bd565b34801561052857600080fd5b5061023d610537366004612a6a565b611729565b34801561054857600080fd5b50610297610557366004612830565b61181e565b34801561056857600080fd5b50610254610577366004612830565b6118c0565b34801561058857600080fd5b506102e0610597366004612830565b611b1c565b3480156105a857600080fd5b506102e07f00000000000000000000000000000000000000000000000000000000000003e881565b3480156105dc57600080fd5b5061023d6105eb366004612abc565b611b67565b3480156105fc57600080fd5b5061020861060b366004612af8565b600560209081526000928352604080842090915290825290205460ff1681565b34801561063757600080fd5b5061023d6106463660046129fa565b611d4a565b34801561065757600080fd5b5061023d6106663660046129fa565b611df1565b600061067682611e93565b80610685575061068582611f13565b806106b957506001600160e01b031982167fad092b5c00000000000000000000000000000000000000000000000000000000145b806106ed57506001600160e01b031982167f3aa3ca2500000000000000000000000000000000000000000000000000000000145b92915050565b6008546001600160a01b031633146107415760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b61074b8282611f61565b5050565b6000805461075c90612b22565b80601f016020809104026020016040519081016040528092919081815260200182805461078890612b22565b80156107d55780601f106107aa576101008083540402835291602001916107d5565b820191906000526020600020905b8154815290600101906020018083116107b857829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b03163381148061082657506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6108725760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610738565b600082815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b826001600160a01b03811633146109005760115460ff1615610900576109003361207b565b61090b8484846120bf565b5060009081526010602052604090204290555050565b60008281526007602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046bffffffffffffffffffffffff169282019290925282916109a05750604080518082019091526006546001600160a01b0381168252600160a01b90046bffffffffffffffffffffffff1660208201525b6020810151600090612710906109c4906bffffffffffffffffffffffff1687612b6c565b6109ce9190612b83565b91519350909150505b9250929050565b60008281526002602052604090205482906001600160a01b0316610a155760405163d29e844f60e01b815260040160405180910390fd5b600954600114610a675760405162461bcd60e51b815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610738565b60026009556201518067ffffffffffffffff83161015610a9a5760405163d29e844f60e01b815260040160405180910390fd5b621275008267ffffffffffffffff161115610ac85760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d6020526040812054610b0e90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b9050806040015167ffffffffffffffff16600003610b58576040517ff34c1eb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015163ffffffff161115610b8357604051630ccb4b8360e01b815260040160405180910390fd5b6000838260400151610b959190612ba5565b67ffffffffffffffff16905080341015610bc257604051631059010b60e21b815260040160405180910390fd5b6000610bd867ffffffffffffffff861642612bd1565b905063ffffffff811115610bff5760405163d29e844f60e01b815260040160405180910390fd5b600080610c0c8834610921565b915091506000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610c5d576040519150601f19603f3d011682016040523d82523d6000602084013e610c62565b606091505b5050905080610c845760405163351930e760e21b815260040160405180910390fd5b6000898152600260205260409020546001600160a01b031680610ca78434612be4565b604051600081818185875af1925050503d8060008114610ce3576040519150601f19603f3d011682016040523d82523d6000602084013e610ce8565b606091505b50508092505081610d0c5760405163351930e760e21b815260040160405180910390fd5b604087015160c01b60a086901b63ffffffff60a01b1617331760008b8152600d6020908152604091829020929092555167ffffffffffffffff8716815233918c917f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe910160405180910390a3505060016009555050505050505050565b610d948383836108db565b6001600160a01b0382163b1580610e3d5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e319190612bf7565b6001600160e01b031916145b610e895760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b505050565b60008281526002602052604090205482906001600160a01b0316610ec55760405163d29e844f60e01b815260040160405180910390fd5b67ffffffffffffffff821115610eee5760405163d29e844f60e01b815260040160405180910390fd5b64174876e800821015610f145760405163d29e844f60e01b815260040160405180910390fd5b6000838152600260205260409020546001600160a01b0316338114610f95576001600160a01b038116600090815260056020908152604080832033845290915290205460ff16610f95576000848152600460205260409020546001600160a01b03163314610f9557604051637e83d05f60e11b815260040160405180910390fd5b6000848152600d6020526040812054610fdb90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff16111561100857604051630ccb4b8360e01b815260040160405180910390fd5b8051602082015163ffffffff60a01b60a09190911b1660c086901b176001600160a01b03909116176000868152600d6020908152604091829020929092555185815286917ffe3b4c3f6e2efdc3dd612c3eb2817308b7568ad72d3f9c9200a08a069c27dff8910160405180910390a25050505050565b838511156110b8576040517fd0ef050f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000003e885600a546110e79190612bd1565b111561111f576040517f35ecb02100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611149857f00000000000000000000000000000000000000000000000029a2241af62c0000612b6c565b34101561116957604051631059010b60e21b815260040160405180910390fd5b824211156111a3576040517f601a8f3200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111af848484846122c1565b6111e5576040517fdfab322b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082826040516111f7929190612c14565b6040518091039020905061121a816000908152600c602052604090205460ff1690565b15611251576040517f9943862900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600c6020526040808220805460ff19166001179055600e5490516001600160a01b039091169034908381818185875af1925050503d80600081146112b6576040519150601f19603f3d011682016040523d82523d6000602084013e6112bb565b606091505b50509050806112dd5760405163351930e760e21b815260040160405180910390fd5b60005b8781101561131657600a8054600101908190556112fd3382612357565b60009081526010602052604090204290556001016112e0565b5050505050505050565b60008181526002602052604081205482906001600160a01b03166113575760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604090205461139d90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b6040015167ffffffffffffffff1691505b50919050565b6008546001600160a01b031633146113fd5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b600081900361141f5760405163d29e844f60e01b815260040160405180910390fd5b600f610e89828483612c88565b6000818152600260205260409020546001600160a01b0316806114915760405162461bcd60e51b815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610738565b919050565b6008546001600160a01b031633146114df5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6001600160a01b0381166115065760405163d29e844f60e01b815260040160405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006001600160a01b03821661158d5760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610738565b506001600160a01b031660009081526003602052604090205490565b60008181526002602052604081205482906001600160a01b03166115e05760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604081205461162690604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff1610611643578060200151611646565b60005b63ffffffff16949350505050565b6008546001600160a01b0316331461169d5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6011805460ff1916911515919091179055565b6001805461075c90612b22565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6117348585856108db565b6001600160a01b0384163b15806117cb5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061177c9033908a90899089908990600401612d48565b6020604051808303816000875af115801561179b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bf9190612bf7565b6001600160e01b031916145b6118175760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b5050505050565b60008181526002602052604081205482906001600160a01b03166118555760405163d29e844f60e01b815260040160405180910390fd5b6000838152600d602052604081205461189b90604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff16106118b55780516118b8565b60005b949350505050565b60008181526002602052604090205460609082906001600160a01b03166118fa5760405163d29e844f60e01b815260040160405180910390fd5b600f805461190790612b22565b9050600003611927576040518060200160405280600081525091506113ae565b600061193284612453565b6000858152601060205260408120549192507f000000000000000000000000000000000000000000000000000000000076a70061196f8342612be4565b106119af576040518060400160405280600581526020017f426c61636b0000000000000000000000000000000000000000000000000000008152506119e6565b6040518060400160405280600681526020017f53696c76657200000000000000000000000000000000000000000000000000008152505b6000878152600d602052604081205491925090611a3090604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b90506000611aed600086600f86600f888960008a6040015167ffffffffffffffff16118015611a685750428a6020015163ffffffff16105b611a815760405180602001604052806000815250611ab8565b6040518060400160405280601581526020017f7b2276616c7565223a2252656e7461626c65227d2c00000000000000000000008152505b611ac18d612453565b604051602001611ad999989796959493929190612e2b565b604051602081830303815290604052612497565b905080604051602001611b009190613047565b6040516020818303038152906040529650505050505050919050565b60008181526002602052604081205482906001600160a01b0316611b535760405163d29e844f60e01b815260040160405180910390fd5b505060009081526010602052604090205490565b60008381526002602052604090205483906001600160a01b0316611b9e5760405163d29e844f60e01b815260040160405180910390fd5b63ffffffff8267ffffffffffffffff161115611bcd5760405163d29e844f60e01b815260040160405180910390fd5b6000848152600260205260409020546001600160a01b0316338114611c4e576001600160a01b038116600090815260056020908152604080832033845290915290205460ff16611c4e576000858152600460205260409020546001600160a01b03163314611c4e57604051637e83d05f60e11b815260040160405180910390fd5b6000858152600d6020526040812054611c9490604080516060810182526001600160a01b038316815260a083901c63ffffffff16602082015260c09290921c9082015290565b905042816020015163ffffffff161115611cc157604051630ccb4b8360e01b815260040160405180910390fd5b60408101516001600160a01b03861660c09190911b60a086901b63ffffffff60a01b1617176000878152600d6020908152604091829020929092555167ffffffffffffffff861681526001600160a01b0387169188917f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe910160405180910390a3505050505050565b6008546001600160a01b03163314611d935760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6001600160a01b038116611dba5760405163d29e844f60e01b815260040160405180910390fd5b600e805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316179055611dee816103e8611f61565b50565b6008546001600160a01b03163314611e3a5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610738565b6008805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b60006301ffc9a760e01b6001600160e01b031983161480611edd57507f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b806106ed5750506001600160e01b0319167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b60006001600160e01b031982167f2a55205a0000000000000000000000000000000000000000000000000000000014806106ed57506301ffc9a760e01b6001600160e01b03198316146106ed565b6127106bffffffffffffffffffffffff82161115611fe75760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c2065786365656460448201527f2073616c655072696365000000000000000000000000000000000000000000006064820152608401610738565b6001600160a01b03821661203d5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610738565b604080518082019091526001600160a01b039092168083526bffffffffffffffffffffffff9091166020909201829052600160a01b90910217600655565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa6120b7573d6000803e3d6000fd5b6000603a5250565b6000818152600260205260409020546001600160a01b038481169116146121285760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610738565b6001600160a01b03821661217e5760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610738565b336001600160a01b03841614806121b857506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b806121d957506000818152600460205260409020546001600160a01b031633145b6122255760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610738565b6001600160a01b03808416600081815260036020908152604080832080546000190190559386168083528483208054600101905585835260028252848320805473ffffffffffffffffffffffffffffffffffffffff199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052605481018490526000908190607401604051602081830303815290604052805190602001209050600061232a8286866124a5565b600b549091506001600160a01b0380831691161461234957600061234c565b60015b979650505050505050565b6123618282612515565b6001600160a01b0382163b15806124075750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af11580156123d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fb9190612bf7565b6001600160e01b031916145b61074b5760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610738565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a90048061246d5750819003601f19909101908152919050565b60606106ed82600080612648565b60006041820361250e576040516040846040377f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a06060511161250a5784600052604084013560001a602052602060406080600060015afa5060006060523d6060035191505b6040525b9392505050565b6001600160a01b03821661256b5760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610738565b6000818152600260205260409020546001600160a01b0316156125d05760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610738565b6001600160a01b0382166000818152600360209081526040808320805460010190558483526002909152808220805473ffffffffffffffffffffffffffffffffffffffff19168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60608351801561273f576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f8116516003840153506004820191508082106126b8576003840686801561271857600182148215150185038752612730565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b6001600160e01b031981168114611dee57600080fd5b60006020828403121561276f57600080fd5b813561250e81612747565b80356001600160a01b038116811461149157600080fd5b600080604083850312156127a457600080fd5b6127ad8361277a565b915060208301356bffffffffffffffffffffffff811681146127ce57600080fd5b809150509250929050565b60005b838110156127f45781810151838201526020016127dc565b50506000910152565b602081526000825180602084015261281c8160408501602087016127d9565b601f01601f19169190910160400192915050565b60006020828403121561284257600080fd5b5035919050565b6000806040838503121561285c57600080fd5b6128658361277a565b946020939093013593505050565b60008060006060848603121561288857600080fd5b6128918461277a565b925061289f6020850161277a565b9150604084013590509250925092565b600080604083850312156128c257600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461149157600080fd5b600080604083850312156128fc57600080fd5b8235915061290c602084016128d1565b90509250929050565b60008083601f84011261292757600080fd5b50813567ffffffffffffffff81111561293f57600080fd5b6020830191508360208285010111156109d757600080fd5b60008060008060006080868803121561296f57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561299b57600080fd5b6129a788828901612915565b969995985093965092949392505050565b600080602083850312156129cb57600080fd5b823567ffffffffffffffff8111156129e257600080fd5b6129ee85828601612915565b90969095509350505050565b600060208284031215612a0c57600080fd5b61250e8261277a565b8035801515811461149157600080fd5b600060208284031215612a3757600080fd5b61250e82612a15565b60008060408385031215612a5357600080fd5b612a5c8361277a565b915061290c60208401612a15565b600080600080600060808688031215612a8257600080fd5b612a8b8661277a565b9450612a996020870161277a565b935060408601359250606086013567ffffffffffffffff81111561299b57600080fd5b600080600060608486031215612ad157600080fd5b83359250612ae16020850161277a565b9150612aef604085016128d1565b90509250925092565b60008060408385031215612b0b57600080fd5b612b148361277a565b915061290c6020840161277a565b600181811c90821680612b3657607f821691505b6020821081036113ae57634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176106ed576106ed612b56565b600082612ba057634e487b7160e01b600052601260045260246000fd5b500490565b67ffffffffffffffff818116838216028082169190828114612bc957612bc9612b56565b505092915050565b808201808211156106ed576106ed612b56565b818103818111156106ed576106ed612b56565b600060208284031215612c0957600080fd5b815161250e81612747565b8183823760009101908152919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610e8957600081815260208120601f850160051c81016020861015612c615750805b601f850160051c820191505b81811015612c8057828155600101612c6d565b505050505050565b67ffffffffffffffff831115612ca057612ca0612c24565b612cb483612cae8354612b22565b83612c3a565b6000601f841160018114612ce85760008515612cd05750838201355b600019600387901b1c1916600186901b178355611817565b600083815260209020601f19861690835b82811015612d195786850135825560209485019460019092019101612cf9565b5086821015612d365760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60008154612da981612b22565b60018281168015612dc15760018114612dd657612e05565b60ff1984168752821515830287019450612e05565b8560005260208060002060005b85811015612dfc5781548a820152908401908201612de3565b50505082870194505b5050505092915050565b60008151612e218185602086016127d9565b9290920192915050565b7f7b226e616d65223a22000000000000000000000000000000000000000000000081526000612e5d600983018c612d9c565b7f202300000000000000000000000000000000000000000000000000000000000081528a51612e93816002840160208f016127d9565b7f222c22696d616765223a2200000000000000000000000000000000000000000060029290910191820152612ecb600d82018b612d9c565b90508851612edd818360208d016127d9565b7f2e706e67222c22616e696d6174696f6e5f75726c223a220000000000000000009101908152612f106017820189612d9c565b90508651612f22818360208b016127d9565b7f2e6d7034222c2261747472696275746573223a5b7b2274726169745f7479706591019081527f223a224c6576656c222c2276616c7565223a2200000000000000000000000000602082015261303761300e613008612fb9612fb3612f8a603387018c612e0f565b7f227d2c0000000000000000000000000000000000000000000000000000000000815260030190565b89612e0f565b7f7b22646973706c61795f74797065223a2264617465222c2274726169745f747981527f7065223a224d656d6265722053696e6365222c2276616c7565223a00000000006020820152603b0190565b86612e0f565b7f7d5d7d0000000000000000000000000000000000000000000000000000000000815260030190565b9c9b505050505050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161307f81601d8501602087016127d9565b91909101601d019291505056fea26469706673582212205d7ab335ebc614b99b6b049c2737289383ed32876ce1467449e1da4d58ee1e4464736f6c63430008110033

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

0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000b630a873e7a73a7a31232b5b4b3890717546000000000000000000000000725d80f337a8cb585a5b8b3f803fe7238c26c80d000000000000000000000000000000000000000000000000000000000076a7000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000f4669727374636c6173732050617373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045041535300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004068747470733a2f2f617277656176652e6e65742f7332534132742d3659594461614464337956547a4977644635664379694c71516e7679374a69345256456b2f

-----Decoded View---------------
Arg [0] : _name (string): Firstclass Pass
Arg [1] : _symbol (string): PASS
Arg [2] : _maxSupply (uint256): 1000
Arg [3] : _price (uint256): 3000000000000000000
Arg [4] : _signer (address): 0x0000B630a873E7A73a7a31232B5B4B3890717546
Arg [5] : _treasury (address): 0x725D80f337A8Cb585a5B8B3f803fe7238C26C80D
Arg [6] : _initiation (uint256): 7776000
Arg [7] : _baseURI (string): https://arweave.net/s2SA2t-6YYDaaDd3yVTzIwdF5fCyiLqQnvy7Ji4RVEk/

-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [3] : 00000000000000000000000000000000000000000000000029a2241af62c0000
Arg [4] : 0000000000000000000000000000b630a873e7a73a7a31232b5b4b3890717546
Arg [5] : 000000000000000000000000725d80f337a8cb585a5b8b3f803fe7238c26c80d
Arg [6] : 000000000000000000000000000000000000000000000000000000000076a700
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [9] : 4669727374636c61737320506173730000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [11] : 5041535300000000000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [13] : 68747470733a2f2f617277656176652e6e65742f7332534132742d3659594461
Arg [14] : 614464337956547a4977644635664379694c71516e7679374a69345256456b2f


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.