ETH Price: $3,335.41 (-0.12%)
 

Overview

Max Total Supply

0 DP

Holders

13

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 DP
0xe2e2c5809f6038de7dcabbcc65e41cc92d4fda95
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
DripPanda

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 15 : DripPanda.sol
// SPDX-License-Identifier: MIT

/**
 * Drip Panda Punk Contract
 * @author 
 */

pragma solidity ^0.8.0;

import '@openzeppelin/contracts/access/Ownable.sol';
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
import '@openzeppelin/contracts/utils/math/SafeMath.sol';

contract DripPanda is Ownable, ERC721URIStorage, ReentrancyGuard {
    using SafeMath for uint256;
    using Strings for uint256;


    uint256 public constant PANDAS_MAX = 2222;
    uint256 public maxCountPerClaim = 5;
    uint256 public maxCountPerWallet = 5;
    uint256 public pricePerPanda = 0.075 ether;
    address public feeToken = address(0x0);

    uint256 public totalMinted = 0;

    bool    private _isActive = false;
    string  private _tokenBaseURI = "";

    uint256[2222] private _availableTokens;
    uint256 private _numAvailableTokens = 2222;

    mapping(address => uint256) claims;

    address public walletA = 0xD599202E6a023f34427bDfe52d30632709525C08;
    address private devAddr;

    struct Item {
        address to;
        uint256 count;
        uint256 paidCount;
    }
    Item[] private whitelist;
    uint256 curIndex = 0;

    event StatusUpdated(bool active);
    event Claimed(address account, uint256 times);
    event BaseURIUpdated(string uri);

    event ClaimMaxCountUpdated(uint256 count);
    event ClaimMaxCountPerWalletUpdated(uint256 count);
    event PaymentTokenUpdated(address token);
    event PriceUpdated(uint256 price);
    event DevAddressUpdated(address addr);


    modifier onlyActive() {
        require(_isActive && totalMinted < PANDAS_MAX, 'DripPanda: not active');
        _;
    }

    constructor() ERC721("DripPanda", "DP") {
        whitelist.push(Item(0xfD4F4591137b09af43128550756Ef0744CC38703, 16, 0));
        whitelist.push(Item(0xeF8c798b48708e30357862A9BFA368Ee09609AA5, 65, 0));
        whitelist.push(Item(0xACA66dE7577907DA6a7a451ED8e8B3E23E87e6fd, 65, 0));

        devAddr = msg.sender;

        _premint();
    }

    function claim(uint256 numberOfTokens) external payable onlyActive nonReentrant{
        require(numberOfTokens > 0, "DripPanda: zero count");
        require(numberOfTokens <= _numAvailableTokens, "DripPanda: not enough panda");

        if(msg.sender != walletA) {
            require(numberOfTokens <= maxCountPerClaim, "DripPanda: exceeded max limit per claim");
            require(claims[msg.sender].add(numberOfTokens) <= maxCountPerWallet, "DripPanda: exceeded max limit per wallet");
        }

        uint256 fee = pricePerPanda.mul(numberOfTokens);
        if(feeToken == address(0x0)) {
            require(msg.value >= fee, "DripPanda: Too little sent, please send more eth");
            if(msg.value > fee) {
                payable(msg.sender).transfer(msg.value - fee);
            }
        }

        _distributeFee(numberOfTokens);

        uint256 updatedNumAvailableTokens = _numAvailableTokens;
        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 randomId =  useRandomAvailableToken(numberOfTokens, i);

            _safeMint(msg.sender, randomId);
            super._setTokenURI(randomId, randomId.toString());

            totalMinted = totalMinted.add(1);
            claims[msg.sender]++;
            updatedNumAvailableTokens--;
        }
        _numAvailableTokens = updatedNumAvailableTokens;

        emit Claimed(msg.sender, numberOfTokens);
    }

    function useRandomAvailableToken(uint256 _numToFetch, uint256 _idx) internal returns (uint256) {
        uint256 randomNum =
            uint256(
                keccak256(
                    abi.encode(
                        msg.sender,
                        tx.gasprice,
                        block.number,
                        block.timestamp,
                        blockhash(block.number - 1),
                        _numToFetch,
                        _idx
                    )
                )
            );

        uint256 randomIndex = randomNum % _numAvailableTokens;

        uint256 valAtIndex = _availableTokens[randomIndex];
        uint256 result;
        if (valAtIndex == 0) {
            // This means the index itself is still an available token
            result = randomIndex;
        } else {
            // This means the index itself is not an available token, but the val at that index is.
            result = valAtIndex;
        }

        uint256 lastIndex = _numAvailableTokens - 1;
        if (randomIndex != lastIndex) {
            // Replace the value at randomIndex, now that it's been used.
            // Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.
            uint256 lastValInArray = _availableTokens[lastIndex];
            if (lastValInArray == 0) {
                // This means the index itself is still an available token
                _availableTokens[randomIndex] = lastIndex;
            } else {
                // This means the index itself is not an available token, but the val at that index is.
                _availableTokens[randomIndex] = lastValInArray;
            }
        }

        _numAvailableTokens--;
        return result;
    }

    function _premint() internal {
        uint256[51] memory ids = [uint256(93), 169, 203, 215, 216, 254, 263, 293, 299, 385, 443, 405, 411, 434, 450, 463, 511, 512, 531, 549, 563, 575, 576, 610, 618, 628, 639, 642, 701, 755, 777, 875, 1021, 1087, 1459, 1552, 1611, 1716, 1802, 1860, 1895, 1921, 1994, 2010, 2028, 2053, 2072, 2122, 2139, 2177, 2187];

        for(uint i = 0; i < ids.length; i++) {
            uint256 randomIndex = ids[i];

            uint256 valAtIndex = _availableTokens[randomIndex];
            uint256 randomId;
            if (valAtIndex == 0) {
                // This means the index itself is still an available token
                randomId = randomIndex;
            } else {
                // This means the index itself is not an available token, but the val at that index is.
                randomId = valAtIndex;
            }

            uint256 lastIndex = _numAvailableTokens - 1;
            if (randomIndex != lastIndex) {
                // Replace the value at randomIndex, now that it's been used.
                // Replace it with the data from the last index in the array, since we are going to decrease the array size afterwards.
                uint256 lastValInArray = _availableTokens[lastIndex];
                if (lastValInArray == 0) {
                    // This means the index itself is still an available token
                    _availableTokens[randomIndex] = lastIndex;
                } else {
                    // This means the index itself is not an available token, but the val at that index is.
                    _availableTokens[randomIndex] = lastValInArray;
                }
            }

            _safeMint(walletA, randomId);
            super._setTokenURI(randomId, randomId.toString());

            totalMinted = totalMinted.add(1);
            _numAvailableTokens--;
        }
    }

    function _distributeFee(uint256 _count) internal {
        uint256 _whitelist_length = whitelist.length;
        if(curIndex > _whitelist_length) {
            _transferFee(devAddr, pricePerPanda.mul(_count));
            return;
        }

        uint256 count = _count;
        uint256 _startIndex = curIndex;
        for (uint256 i = _startIndex; i < _whitelist_length; i++) {
            if(count == 0) return;

            uint256 _remained = whitelist[i].count.sub(whitelist[i].paidCount);
            if(_remained > count) {
                _transferFee(whitelist[i].to, pricePerPanda.mul(count));

                whitelist[i].paidCount = whitelist[i].paidCount.add(count);
                return;
            } else {
                _transferFee(whitelist[i].to, pricePerPanda.mul(_remained));

                whitelist[i].paidCount = whitelist[i].paidCount.add(_remained);
                count = count.sub(_remained);

                curIndex = curIndex.add(1);
            }
        }

        if(count > 0) {
            _transferFee(devAddr, pricePerPanda.mul(count));
        }
    }

    function _transferFee(address _to, uint256 _amount) internal {
        if(feeToken == address(0x0)) {
            payable(_to).transfer(_amount);
        } else {
            require(IERC20(feeToken).transferFrom(msg.sender, _to, _amount), "DripPanda: failed to transfer tokens");
        }
    }

    function remainPunks() public view returns(uint256) {
        return _numAvailableTokens;
    }

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

    function tokenURI(uint256 tokenId) public view override(ERC721URIStorage) returns (string memory)
    {
        return super.tokenURI(tokenId);
    }
    
    function _baseURI() internal view override returns (string memory) {
        return _tokenBaseURI;
    }

    /////////////////////////////////////////////////////////////
    //////////////////   Admin Functions ////////////////////////
    /////////////////////////////////////////////////////////////
   
    function setActive(bool isActive) external onlyOwner {
        _isActive = isActive;

        emit StatusUpdated(isActive);
    }

    function setTokenBaseURI(string memory _uri) external onlyOwner {
        _tokenBaseURI = _uri;

        emit BaseURIUpdated(_uri);
    }

    function setFeeToken(address _token) external onlyOwner {
        require(feeToken != _token, "DripPanda: already set");
        feeToken = _token;

        emit PaymentTokenUpdated(_token);
    }

    function setDevAddress(address _addr) external onlyOwner {
        require(_addr != address(0x0), "DripPanda: Invalid address");
        require(_addr != devAddr, "DripPanda: already set");
        devAddr = _addr;

        emit DevAddressUpdated(_addr);
    }

    function setWalletA(address _addr) external onlyOwner {
        require(_addr != address(0x0), "DripPanda: Invalid address");
        require(_addr != devAddr, "DripPanda: already set");

        walletA = _addr;
    }

    function setPricePerPanda(uint _price) external onlyOwner {
        pricePerPanda = _price;

        emit PriceUpdated(_price);
    }

    function setMaxCountPerClaim(uint _count) external onlyOwner {
        require(_count <= 500);
        maxCountPerClaim = _count;

        emit ClaimMaxCountUpdated(_count);
    }

    function setMaxCountPerWallet(uint _count) external onlyOwner {
        require(_count <= 500);
        maxCountPerWallet = _count;

        emit ClaimMaxCountPerWalletUpdated(_count);
    }

    receive() external payable {}
}

File 2 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/Context.sol";

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

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 15 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

File 4 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 5 of 15 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

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

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

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

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

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

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

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

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

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

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

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

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

File 6 of 15 : ERC721URIStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../ERC721.sol";

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is ERC721 {
    using Strings for uint256;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual override {
        super._burn(tokenId);

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

File 7 of 15 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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

File 8 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

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

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 9 of 15 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

File 10 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT

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 11 of 15 : ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

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

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

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

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

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

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

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 12 of 15 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 13 of 15 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

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

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

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

File 14 of 15 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

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

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 15 of 15 : ERC165.sol
// SPDX-License-Identifier: MIT

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

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"ClaimMaxCountPerWalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"ClaimMaxCountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"times","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"DevAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"PaymentTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"StatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"PANDAS_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxCountPerClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxCountPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerPanda","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remainPunks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive","type":"bool"}],"name":"setActive","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":"address","name":"_addr","type":"address"}],"name":"setDevAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setFeeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"setMaxCountPerClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"setMaxCountPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPricePerPanda","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setTokenBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setWalletA","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":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60056009819055600a5567010a741a46278000600b55600c80546001600160a01b03191690556000600d819055600e805460ff1916905560a0604081905260808290526200005191600f919062000b48565b506108ae6108be556108c080546001600160a01b03191673d599202e6a023f34427bdfe52d30632709525c0817905560006108c3553480156200009357600080fd5b50604051806040016040528060098152602001684472697050616e646160b81b81525060405180604001604052806002815260200161044560f41b815250620000eb620000e56200035a60201b60201c565b6200035e565b81516200010090600190602085019062000b48565b5080516200011690600290602084019062000b48565b50505060016008819055506108c2604051806060016040528073fd4f4591137b09af43128550756ef0744cc387036001600160a01b03168152602001601081526020016000815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015550506108c2604051806060016040528073ef8c798b48708e30357862a9bfa368ee09609aa56001600160a01b03168152602001604181526020016000815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550602082015181600101556040820151816002015550506108c2604051806060016040528073aca66de7577907da6a7a451ed8e8b3e23e87e6fd6001600160a01b03168152602001604181526020016000815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010155604082015181600201555050336108c160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555062000354620003ae60201b60201c565b62000ea1565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000604051806106600160405280605d815260200160a9815260200160cb815260200160d7815260200160d8815260200160fe81526020016101078152602001610125815260200161012b815260200161018181526020016101bb8152602001610195815260200161019b81526020016101b281526020016101c281526020016101cf81526020016101ff8152602001610200815260200161021381526020016102258152602001610233815260200161023f81526020016102408152602001610262815260200161026a8152602001610274815260200161027f815260200161028281526020016102bd81526020016102f38152602001610309815260200161036b81526020016103fd815260200161043f81526020016105b38152602001610610815260200161064b81526020016106b4815260200161070a81526020016107448152602001610767815260200161078181526020016107ca81526020016107da81526020016107ec81526020016108058152602001610818815260200161084a815260200161085b8152602001610881815260200161088b815250905060005b6033811015620006fa5760008282603381106200057e57634e487b7160e01b600052603260045260246000fd5b6020020151905060006010826108ae8110620005aa57634e487b7160e01b600052603260045260246000fd5b01549050600081620005be575081620005c1565b50805b600060016108be54620005d5919062000dcf565b9050808414620006635760006010826108ae81106200060457634e487b7160e01b600052603260045260246000fd5b01549050806200063a57816010866108ae81106200063257634e487b7160e01b600052603260045260246000fd5b015562000661565b806010866108ae81106200065e57634e487b7160e01b600052603260045260246000fd5b01555b505b6108c0546200067c906001600160a01b031683620006fe565b620006a88262000697846200072060201b620011e11760201c565b6200085960201b620013041760201c565b620006c56001600d54620008b260201b620013481790919060201c565b600d556108be8054906000620006db8362000de9565b9190505550505050508080620006f19062000e40565b91505062000551565b5050565b620006fa828260405180602001604052806000815250620008c760201b60201c565b6060816200074757506040805180820190915260018152600360fc1b602082015262000854565b8160005b81156200077757806200075e8162000e40565b91506200076f9050600a8362000db8565b91506200074b565b6000816001600160401b03811115620007a057634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015620007cb576020820181803683370190505b5090505b84156200084f57620007e360018362000dcf565b9150620007f2600a8662000e5e565b620007ff90603062000d9d565b60f81b8183815181106200082357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535062000847600a8662000db8565b9450620007cf565b925050505b919050565b620008648262000901565b6200088c5760405162461bcd60e51b8152600401620008839062000d1a565b60405180910390fd5b60008281526007602090815260409091208251620008ad9284019062000b48565b505050565b6000620008c0828462000d9d565b9392505050565b620008d383836200091e565b620008e2600084848462000a09565b620008ad5760405162461bcd60e51b8152600401620008839062000c91565b6000908152600360205260409020546001600160a01b0316151590565b6001600160a01b038216620009475760405162461bcd60e51b8152600401620008839062000d68565b620009528162000901565b15620009725760405162461bcd60e51b8152600401620008839062000ce3565b6200098060008383620008ad565b6001600160a01b0382166000908152600460205260408120805460019290620009ab90849062000d9d565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600062000a2a846001600160a01b031662000b4260201b6200135b1760201c565b1562000b36576001600160a01b03841663150b7a0262000a496200035a565b8786866040518563ffffffff1660e01b815260040162000a6d949392919062000c18565b602060405180830381600087803b15801562000a8857600080fd5b505af192505050801562000abb575060408051601f3d908101601f1916820190925262000ab89181019062000bee565b60015b62000b1b573d80801562000aec576040519150601f19603f3d011682016040523d82523d6000602084013e62000af1565b606091505b50805162000b135760405162461bcd60e51b8152600401620008839062000c91565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905062000b3a565b5060015b949350505050565b3b151590565b82805462000b569062000e03565b90600052602060002090601f01602090048101928262000b7a576000855562000bc5565b82601f1062000b9557805160ff191683800117855562000bc5565b8280016001018555821562000bc5579182015b8281111562000bc557825182559160200191906001019062000ba8565b5062000bd392915062000bd7565b5090565b5b8082111562000bd3576000815560010162000bd8565b60006020828403121562000c00578081fd5b81516001600160e01b031981168114620008c0578182fd5b600060018060a01b0380871683526020818716818501528560408501526080606085015284519150816080850152825b8281101562000c665785810182015185820160a00152810162000c48565b8281111562000c78578360a084870101525b5050601f01601f19169190910160a00195945050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b6020808252602e908201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60408201526d32bc34b9ba32b73a103a37b5b2b760911b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b6000821982111562000db35762000db362000e75565b500190565b60008262000dca5762000dca62000e8b565b500490565b60008282101562000de45762000de462000e75565b500390565b60008162000dfb5762000dfb62000e75565b506000190190565b60028104600182168062000e1857607f821691505b6020821081141562000e3a57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141562000e575762000e5762000e75565b5060010190565b60008262000e705762000e7062000e8b565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b612cca8062000eb16000396000f3fe6080604052600436106101bd5760003560e01c80638ef79e91116100ed578063b88d4fde11610090578063b88d4fde146104a2578063c05fde7b146104c2578063c280a767146104d7578063c87b56dd146104f7578063d0d41fe114610517578063d8fee6bf14610537578063e87aad011461054c578063e985e9c51461056c578063f2fde38b1461058c576101c4565b80638ef79e91146103d957806395d89b41146103f9578063a035b1fe1461040e578063a22cb46514610423578063a2309ff814610443578063acec338a14610458578063af0adce114610478578063b77e7da01461048d576101c4565b8063379607f511610160578063379607f5146102f257806342842e0e146103055780634c89b86c146103255780636352211e14610345578063647846a51461036557806370a082311461037a578063715018a61461039a5780637e26de6c146103af5780638da5cb5b146103c4576101c4565b806301ffc9a7146101c957806303a02818146101ff57806306fdde0314610221578063081812fc14610243578063095ea7b31461027057806311fda6d11461029257806315cce224146102b257806323b872dd146102d2576101c4565b366101c457005b600080fd5b3480156101d557600080fd5b506101e96101e43660046121ec565b6105ac565b6040516101f691906123a6565b60405180910390f35b34801561020b57600080fd5b506102146105f4565b6040516101f69190612b16565b34801561022d57600080fd5b506102366105fa565b6040516101f691906123b1565b34801561024f57600080fd5b5061026361025e36600461226a565b61068c565b6040516101f691906122dd565b34801561027c57600080fd5b5061029061028b36600461218b565b6106d8565b005b34801561029e57600080fd5b506102906102ad36600461226a565b610770565b3480156102be57600080fd5b506102906102cd366004612055565b6107fe565b3480156102de57600080fd5b506102906102ed3660046120a1565b6108b6565b61029061030036600461226a565b6108ee565b34801561031157600080fd5b506102906103203660046120a1565b610b5c565b34801561033157600080fd5b50610290610340366004612055565b610b77565b34801561035157600080fd5b5061026361036036600461226a565b610c2e565b34801561037157600080fd5b50610263610c63565b34801561038657600080fd5b50610214610395366004612055565b610c72565b3480156103a657600080fd5b50610290610cb6565b3480156103bb57600080fd5b50610214610d01565b3480156103d057600080fd5b50610263610d07565b3480156103e557600080fd5b506102906103f4366004612224565b610d16565b34801561040557600080fd5b50610236610d98565b34801561041a57600080fd5b50610214610da7565b34801561042f57600080fd5b5061029061043e366004612155565b610dad565b34801561044f57600080fd5b50610214610e7b565b34801561046457600080fd5b506102906104733660046121b4565b610e81565b34801561048457600080fd5b50610214610efe565b34801561049957600080fd5b50610263610f05565b3480156104ae57600080fd5b506102906104bd3660046120dc565b610f15565b3480156104ce57600080fd5b50610214610f54565b3480156104e357600080fd5b506102906104f236600461226a565b610f5a565b34801561050357600080fd5b5061023661051236600461226a565b610fdd565b34801561052357600080fd5b50610290610532366004612055565b610fe8565b34801561054357600080fd5b506102146110c8565b34801561055857600080fd5b5061029061056736600461226a565b6110ce565b34801561057857600080fd5b506101e961058736600461206f565b611142565b34801561059857600080fd5b506102906105a7366004612055565b611170565b60006001600160e01b031982166380ac58cd60e01b14806105dd57506001600160e01b03198216635b5e139f60e01b145b806105ec57506105ec82611361565b90505b919050565b600a5481565b60606001805461060990612bc4565b80601f016020809104026020016040519081016040528092919081815260200182805461063590612bc4565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050905090565b60006106978261137a565b6106bc5760405162461bcd60e51b81526004016106b39061286f565b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b60006106e382610c2e565b9050806001600160a01b0316836001600160a01b031614156107175760405162461bcd60e51b81526004016106b390612988565b806001600160a01b0316610729611397565b6001600160a01b03161480610745575061074581610587611397565b6107615760405162461bcd60e51b81526004016106b3906125ea565b61076b838361139b565b505050565b610778611397565b6001600160a01b0316610789610d07565b6001600160a01b0316146107af5760405162461bcd60e51b81526004016106b3906128bb565b6101f48111156107be57600080fd5b60098190556040517f9b9826675f87ef4acb070bc292046fe3284c879eb08e7581ea25b70a04625061906107f3908390612b16565b60405180910390a150565b610806611397565b6001600160a01b0316610817610d07565b6001600160a01b03161461083d5760405162461bcd60e51b81526004016106b3906128bb565b600c546001600160a01b038281169116141561086b5760405162461bcd60e51b81526004016106b390612aaf565b600c80546001600160a01b0319166001600160a01b0383161790556040517fbd4032c1c91da2791730ea1bbc82c6b6f857da7c0a8318143d19ef74e62cd913906107f39083906122dd565b6108c76108c1611397565b82611409565b6108e35760405162461bcd60e51b81526004016106b3906129f8565b61076b838383611486565b600e5460ff16801561090357506108ae600d54105b61091f5760405162461bcd60e51b81526004016106b3906129c9565b600260085414156109425760405162461bcd60e51b81526004016106b390612adf565b6002600855806109645760405162461bcd60e51b81526004016106b390612a49565b6108be548111156109875760405162461bcd60e51b81526004016106b390612a78565b6108c0546001600160a01b031633146109f8576009548111156109bc5760405162461bcd60e51b81526004016106b39061275a565b600a543360009081526108bf60205260409020546109da9083611348565b11156109f85760405162461bcd60e51b81526004016106b3906127a1565b600b54600090610a0890836115b3565b600c549091506001600160a01b0316610a7b5780341015610a3b5760405162461bcd60e51b81526004016106b390612416565b80341115610a7b57336108fc610a518334612b6a565b6040518115909202916000818181858888f19350505050158015610a79573d6000803e3d6000fd5b505b610a84826115bf565b6108be5460005b83811015610b11576000610a9f8583611875565b9050610aab33826119c3565b610abd81610ab8836111e1565b611304565b600d54610acb906001611348565b600d553360009081526108bf60205260408120805491610aea83612bff565b91905055508280610afa90612bad565b935050508080610b0990612bff565b915050610a8b565b506108be8190556040517fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a90610b4a9033908690612352565b60405180910390a15050600160085550565b61076b83838360405180602001604052806000815250610f15565b610b7f611397565b6001600160a01b0316610b90610d07565b6001600160a01b031614610bb65760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b038116610bdc5760405162461bcd60e51b81526004016106b390612642565b6108c1546001600160a01b0382811691161415610c0b5760405162461bcd60e51b81526004016106b390612aaf565b6108c080546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600360205260408120546001600160a01b0316806105ec5760405162461bcd60e51b81526004016106b3906126c3565b600c546001600160a01b031681565b60006001600160a01b038216610c9a5760405162461bcd60e51b81526004016106b390612679565b506001600160a01b031660009081526004602052604090205490565b610cbe611397565b6001600160a01b0316610ccf610d07565b6001600160a01b031614610cf55760405162461bcd60e51b81526004016106b3906128bb565b610cff60006119e1565b565b6108ae81565b6000546001600160a01b031690565b610d1e611397565b6001600160a01b0316610d2f610d07565b6001600160a01b031614610d555760405162461bcd60e51b81526004016106b3906128bb565b8051610d6890600f906020840190611f35565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad816040516107f391906123b1565b60606002805461060990612bc4565b600b5490565b610db5611397565b6001600160a01b0316826001600160a01b03161415610de65760405162461bcd60e51b81526004016106b39061256b565b8060066000610df3611397565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610e37611397565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610e6f91906123a6565b60405180910390a35050565b600d5481565b610e89611397565b6001600160a01b0316610e9a610d07565b6001600160a01b031614610ec05760405162461bcd60e51b81526004016106b3906128bb565b600e805460ff19168215151790556040517f8939c08109a5d8d76bb72a1a22bd59c7ba7e81fe6dcfd41644887fc9ab07d828906107f39083906123a6565b6108be5490565b6108c0546001600160a01b031681565b610f26610f20611397565b83611409565b610f425760405162461bcd60e51b81526004016106b3906129f8565b610f4e84848484611a31565b50505050565b600b5481565b610f62611397565b6001600160a01b0316610f73610d07565b6001600160a01b031614610f995760405162461bcd60e51b81526004016106b3906128bb565b6101f4811115610fa857600080fd5b600a8190556040517f764ff695884be16cb59c81839f71b2897b6e0ad3bacb74a973f9345195785247906107f3908390612b16565b60606105ec82611a64565b610ff0611397565b6001600160a01b0316611001610d07565b6001600160a01b0316146110275760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b03811661104d5760405162461bcd60e51b81526004016106b390612642565b6108c1546001600160a01b038281169116141561107c5760405162461bcd60e51b81526004016106b390612aaf565b6108c180546001600160a01b0319166001600160a01b0383161790556040517f34830ecd12aee38e030de8db2aab7662959ba614a8af53e095041d13deced11d906107f39083906122dd565b60095481565b6110d6611397565b6001600160a01b03166110e7610d07565b6001600160a01b03161461110d5760405162461bcd60e51b81526004016106b3906128bb565b600b8190556040517f66cbca4f3c64fecf1dcb9ce094abcf7f68c3450a1d4e3a8e917dd621edb4ebe0906107f3908390612b16565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b611178611397565b6001600160a01b0316611189610d07565b6001600160a01b0316146111af5760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b0381166111d55760405162461bcd60e51b81526004016106b3906124aa565b6111de816119e1565b50565b60608161120657506040805180820190915260018152600360fc1b60208201526105ef565b8160005b8115611230578061121a81612bff565b91506112299050600a83612b37565b915061120a565b60008167ffffffffffffffff81111561125957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611283576020820181803683370190505b5090505b84156112fc57611298600183612b6a565b91506112a5600a86612c1a565b6112b0906030612b1f565b60f81b8183815181106112d357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506112f5600a86612b37565b9450611287565b949350505050565b61130d8261137a565b6113295760405162461bcd60e51b81526004016106b39061270c565b6000828152600760209081526040909120825161076b92840190611f35565b60006113548284612b1f565b9392505050565b3b151590565b6001600160e01b031981166301ffc9a760e01b14919050565b6000908152600360205260409020546001600160a01b0316151590565b3390565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906113d082610c2e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006114148261137a565b6114305760405162461bcd60e51b81526004016106b39061259e565b600061143b83610c2e565b9050806001600160a01b0316846001600160a01b031614806114765750836001600160a01b031661146b8461068c565b6001600160a01b0316145b806112fc57506112fc8185611142565b826001600160a01b031661149982610c2e565b6001600160a01b0316146114bf5760405162461bcd60e51b81526004016106b3906128f0565b6001600160a01b0382166114e55760405162461bcd60e51b81526004016106b390612527565b6114f083838361076b565b6114fb60008261139b565b6001600160a01b0383166000908152600460205260408120805460019290611524908490612b6a565b90915550506001600160a01b0382166000908152600460205260408120805460019290611552908490612b1f565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006113548284612b4b565b6108c2546108c3548110156115f8576108c154600b546115f2916001600160a01b0316906115ed90856115b3565b611b7d565b506111de565b6108c3548290805b8381101561184f578261161657505050506111de565b60006116916108c2838154811061163d57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060030201600201546108c2848154811061167157634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160010154611c6b90919063ffffffff16565b905083811115611771576116ea6108c283815481106116c057634e487b7160e01b600052603260045260246000fd5b6000918252602090912060039091020154600b546001600160a01b03909116906115ed90876115b3565b611730846108c2848154811061171057634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016002015461134890919063ffffffff16565b6108c2838154811061175257634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016002018190555050505050506111de565b6117c06108c2838154811061179657634e487b7160e01b600052603260045260246000fd5b6000918252602090912060039091020154600b546001600160a01b03909116906115ed90846115b3565b6117e6816108c2848154811061171057634e487b7160e01b600052603260045260246000fd5b6108c2838154811061180857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260039092020101556118268482611c6b565b6108c354909450611838906001611348565b6108c355508061184781612bff565b915050611600565b508115610f4e576108c154600b54610f4e916001600160a01b0316906115ed90856115b3565b600080333a4342611887600183612b6a565b4088886040516020016118a0979695949392919061236b565b6040516020818303038152906040528051906020012060001c905060006108be54826118cc9190612c1a565b905060006010826108ae81106118f257634e487b7160e01b600052603260045260246000fd5b01549050600081611904575081611907565b50805b600060016108be546119199190612b6a565b90508084146119a15760006010826108ae811061194657634e487b7160e01b600052603260045260246000fd5b015490508061197957816010866108ae811061197257634e487b7160e01b600052603260045260246000fd5b015561199f565b806010866108ae811061199c57634e487b7160e01b600052603260045260246000fd5b01555b505b6108be80549060006119b283612bad565b909155509198975050505050505050565b6119dd828260405180602001604052806000815250611c77565b5050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611a3c848484611486565b611a4884848484611caa565b610f4e5760405162461bcd60e51b81526004016106b3906123c4565b6060611a6f8261137a565b611a8b5760405162461bcd60e51b81526004016106b39061281e565b60008281526007602052604081208054611aa490612bc4565b80601f0160208091040260200160405190810160405280929190818152602001828054611ad090612bc4565b8015611b1d5780601f10611af257610100808354040283529160200191611b1d565b820191906000526020600020905b815481529060010190602001808311611b0057829003601f168201915b505050505090506000611b2e611dc5565b9050805160001415611b42575090506105ef565b815115611b74578082604051602001611b5c9291906122ae565b604051602081830303815290604052925050506105ef565b6112fc84611dd4565b600c546001600160a01b0316611bc9576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611bc3573d6000803e3d6000fd5b506119dd565b600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611bfd903390869086906004016122f1565b602060405180830381600087803b158015611c1757600080fd5b505af1158015611c2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4f91906121d0565b6119dd5760405162461bcd60e51b81526004016106b390612466565b60006113548284612b6a565b611c818383611e56565b611c8e6000848484611caa565b61076b5760405162461bcd60e51b81526004016106b3906123c4565b6000611cbe846001600160a01b031661135b565b15611dba57836001600160a01b031663150b7a02611cda611397565b8786866040518563ffffffff1660e01b8152600401611cfc9493929190612315565b602060405180830381600087803b158015611d1657600080fd5b505af1925050508015611d46575060408051601f3d908101601f19168201909252611d4391810190612208565b60015b611da0573d808015611d74576040519150601f19603f3d011682016040523d82523d6000602084013e611d79565b606091505b508051611d985760405162461bcd60e51b81526004016106b3906123c4565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506112fc565b506001949350505050565b6060600f805461060990612bc4565b6060611ddf8261137a565b611dfb5760405162461bcd60e51b81526004016106b390612939565b6000611e05611dc5565b90506000815111611e255760405180602001604052806000815250611354565b80611e2f846111e1565b604051602001611e409291906122ae565b6040516020818303038152906040529392505050565b6001600160a01b038216611e7c5760405162461bcd60e51b81526004016106b3906127e9565b611e858161137a565b15611ea25760405162461bcd60e51b81526004016106b3906124f0565b611eae6000838361076b565b6001600160a01b0382166000908152600460205260408120805460019290611ed7908490612b1f565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054611f4190612bc4565b90600052602060002090601f016020900481019282611f635760008555611fa9565b82601f10611f7c57805160ff1916838001178555611fa9565b82800160010185558215611fa9579182015b82811115611fa9578251825591602001919060010190611f8e565b50611fb5929150611fb9565b5090565b5b80821115611fb55760008155600101611fba565b600067ffffffffffffffff80841115611fe957611fe9612c5a565b604051601f8501601f19168101602001828111828210171561200d5761200d612c5a565b60405284815291508183850186101561202557600080fd5b8484602083013760006020868301015250509392505050565b80356001600160a01b03811681146105ef57600080fd5b600060208284031215612066578081fd5b6113548261203e565b60008060408385031215612081578081fd5b61208a8361203e565b91506120986020840161203e565b90509250929050565b6000806000606084860312156120b5578081fd5b6120be8461203e565b92506120cc6020850161203e565b9150604084013590509250925092565b600080600080608085870312156120f1578081fd5b6120fa8561203e565b93506121086020860161203e565b925060408501359150606085013567ffffffffffffffff81111561212a578182fd5b8501601f8101871361213a578182fd5b61214987823560208401611fce565b91505092959194509250565b60008060408385031215612167578182fd5b6121708361203e565b9150602083013561218081612c70565b809150509250929050565b6000806040838503121561219d578182fd5b6121a68361203e565b946020939093013593505050565b6000602082840312156121c5578081fd5b813561135481612c70565b6000602082840312156121e1578081fd5b815161135481612c70565b6000602082840312156121fd578081fd5b813561135481612c7e565b600060208284031215612219578081fd5b815161135481612c7e565b600060208284031215612235578081fd5b813567ffffffffffffffff81111561224b578182fd5b8201601f8101841361225b578182fd5b6112fc84823560208401611fce565b60006020828403121561227b578081fd5b5035919050565b6000815180845261229a816020860160208601612b81565b601f01601f19169290920160200192915050565b600083516122c0818460208801612b81565b8351908301906122d4818360208801612b81565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061234890830184612282565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b901515815260200190565b6000602082526113546020830184612282565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526030908201527f4472697050616e64613a20546f6f206c6974746c652073656e742c20706c656160408201526f0e6ca40e6cadcc840dadee4ca40cae8d60831b606082015260800190565b60208082526024908201527f4472697050616e64613a206661696c656420746f207472616e7366657220746f6040820152636b656e7360e01b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776040820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606082015260800190565b6020808252601a908201527f4472697050616e64613a20496e76616c69642061646472657373000000000000604082015260600190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526029908201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460408201526832b73a103a37b5b2b760b91b606082015260800190565b6020808252602e908201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60408201526d32bc34b9ba32b73a103a37b5b2b760911b606082015260800190565b60208082526027908201527f4472697050616e64613a206578636565646564206d6178206c696d69742070656040820152667220636c61696d60c81b606082015260800190565b60208082526028908201527f4472697050616e64613a206578636565646564206d6178206c696d69742070656040820152671c881dd85b1b195d60c21b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526031908201527f45524337323155524953746f726167653a2055524920717565727920666f72206040820152703737b732bc34b9ba32b73a103a37b5b2b760791b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b6020808252601590820152744472697050616e64613a206e6f742061637469766560581b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b602080825260159082015274111c9a5c14185b99184e881e995c9bc818dbdd5b9d605a1b604082015260600190565b6020808252601b908201527f4472697050616e64613a206e6f7420656e6f7567682070616e64610000000000604082015260600190565b602080825260169082015275111c9a5c14185b99184e88185b1c9958591e481cd95d60521b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b90815260200190565b60008219821115612b3257612b32612c2e565b500190565b600082612b4657612b46612c44565b500490565b6000816000190483118215151615612b6557612b65612c2e565b500290565b600082821015612b7c57612b7c612c2e565b500390565b60005b83811015612b9c578181015183820152602001612b84565b83811115610f4e5750506000910152565b600081612bbc57612bbc612c2e565b506000190190565b600281046001821680612bd857607f821691505b60208210811415612bf957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612c1357612c13612c2e565b5060010190565b600082612c2957612c29612c44565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146111de57600080fd5b6001600160e01b0319811681146111de57600080fdfea2646970667358221220dde492a5c54f58362735b16611607aefb0e188dedfbcf6700757b94eaf4c4c4864736f6c63430008000033

Deployed Bytecode

0x6080604052600436106101bd5760003560e01c80638ef79e91116100ed578063b88d4fde11610090578063b88d4fde146104a2578063c05fde7b146104c2578063c280a767146104d7578063c87b56dd146104f7578063d0d41fe114610517578063d8fee6bf14610537578063e87aad011461054c578063e985e9c51461056c578063f2fde38b1461058c576101c4565b80638ef79e91146103d957806395d89b41146103f9578063a035b1fe1461040e578063a22cb46514610423578063a2309ff814610443578063acec338a14610458578063af0adce114610478578063b77e7da01461048d576101c4565b8063379607f511610160578063379607f5146102f257806342842e0e146103055780634c89b86c146103255780636352211e14610345578063647846a51461036557806370a082311461037a578063715018a61461039a5780637e26de6c146103af5780638da5cb5b146103c4576101c4565b806301ffc9a7146101c957806303a02818146101ff57806306fdde0314610221578063081812fc14610243578063095ea7b31461027057806311fda6d11461029257806315cce224146102b257806323b872dd146102d2576101c4565b366101c457005b600080fd5b3480156101d557600080fd5b506101e96101e43660046121ec565b6105ac565b6040516101f691906123a6565b60405180910390f35b34801561020b57600080fd5b506102146105f4565b6040516101f69190612b16565b34801561022d57600080fd5b506102366105fa565b6040516101f691906123b1565b34801561024f57600080fd5b5061026361025e36600461226a565b61068c565b6040516101f691906122dd565b34801561027c57600080fd5b5061029061028b36600461218b565b6106d8565b005b34801561029e57600080fd5b506102906102ad36600461226a565b610770565b3480156102be57600080fd5b506102906102cd366004612055565b6107fe565b3480156102de57600080fd5b506102906102ed3660046120a1565b6108b6565b61029061030036600461226a565b6108ee565b34801561031157600080fd5b506102906103203660046120a1565b610b5c565b34801561033157600080fd5b50610290610340366004612055565b610b77565b34801561035157600080fd5b5061026361036036600461226a565b610c2e565b34801561037157600080fd5b50610263610c63565b34801561038657600080fd5b50610214610395366004612055565b610c72565b3480156103a657600080fd5b50610290610cb6565b3480156103bb57600080fd5b50610214610d01565b3480156103d057600080fd5b50610263610d07565b3480156103e557600080fd5b506102906103f4366004612224565b610d16565b34801561040557600080fd5b50610236610d98565b34801561041a57600080fd5b50610214610da7565b34801561042f57600080fd5b5061029061043e366004612155565b610dad565b34801561044f57600080fd5b50610214610e7b565b34801561046457600080fd5b506102906104733660046121b4565b610e81565b34801561048457600080fd5b50610214610efe565b34801561049957600080fd5b50610263610f05565b3480156104ae57600080fd5b506102906104bd3660046120dc565b610f15565b3480156104ce57600080fd5b50610214610f54565b3480156104e357600080fd5b506102906104f236600461226a565b610f5a565b34801561050357600080fd5b5061023661051236600461226a565b610fdd565b34801561052357600080fd5b50610290610532366004612055565b610fe8565b34801561054357600080fd5b506102146110c8565b34801561055857600080fd5b5061029061056736600461226a565b6110ce565b34801561057857600080fd5b506101e961058736600461206f565b611142565b34801561059857600080fd5b506102906105a7366004612055565b611170565b60006001600160e01b031982166380ac58cd60e01b14806105dd57506001600160e01b03198216635b5e139f60e01b145b806105ec57506105ec82611361565b90505b919050565b600a5481565b60606001805461060990612bc4565b80601f016020809104026020016040519081016040528092919081815260200182805461063590612bc4565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050905090565b60006106978261137a565b6106bc5760405162461bcd60e51b81526004016106b39061286f565b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b60006106e382610c2e565b9050806001600160a01b0316836001600160a01b031614156107175760405162461bcd60e51b81526004016106b390612988565b806001600160a01b0316610729611397565b6001600160a01b03161480610745575061074581610587611397565b6107615760405162461bcd60e51b81526004016106b3906125ea565b61076b838361139b565b505050565b610778611397565b6001600160a01b0316610789610d07565b6001600160a01b0316146107af5760405162461bcd60e51b81526004016106b3906128bb565b6101f48111156107be57600080fd5b60098190556040517f9b9826675f87ef4acb070bc292046fe3284c879eb08e7581ea25b70a04625061906107f3908390612b16565b60405180910390a150565b610806611397565b6001600160a01b0316610817610d07565b6001600160a01b03161461083d5760405162461bcd60e51b81526004016106b3906128bb565b600c546001600160a01b038281169116141561086b5760405162461bcd60e51b81526004016106b390612aaf565b600c80546001600160a01b0319166001600160a01b0383161790556040517fbd4032c1c91da2791730ea1bbc82c6b6f857da7c0a8318143d19ef74e62cd913906107f39083906122dd565b6108c76108c1611397565b82611409565b6108e35760405162461bcd60e51b81526004016106b3906129f8565b61076b838383611486565b600e5460ff16801561090357506108ae600d54105b61091f5760405162461bcd60e51b81526004016106b3906129c9565b600260085414156109425760405162461bcd60e51b81526004016106b390612adf565b6002600855806109645760405162461bcd60e51b81526004016106b390612a49565b6108be548111156109875760405162461bcd60e51b81526004016106b390612a78565b6108c0546001600160a01b031633146109f8576009548111156109bc5760405162461bcd60e51b81526004016106b39061275a565b600a543360009081526108bf60205260409020546109da9083611348565b11156109f85760405162461bcd60e51b81526004016106b3906127a1565b600b54600090610a0890836115b3565b600c549091506001600160a01b0316610a7b5780341015610a3b5760405162461bcd60e51b81526004016106b390612416565b80341115610a7b57336108fc610a518334612b6a565b6040518115909202916000818181858888f19350505050158015610a79573d6000803e3d6000fd5b505b610a84826115bf565b6108be5460005b83811015610b11576000610a9f8583611875565b9050610aab33826119c3565b610abd81610ab8836111e1565b611304565b600d54610acb906001611348565b600d553360009081526108bf60205260408120805491610aea83612bff565b91905055508280610afa90612bad565b935050508080610b0990612bff565b915050610a8b565b506108be8190556040517fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a90610b4a9033908690612352565b60405180910390a15050600160085550565b61076b83838360405180602001604052806000815250610f15565b610b7f611397565b6001600160a01b0316610b90610d07565b6001600160a01b031614610bb65760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b038116610bdc5760405162461bcd60e51b81526004016106b390612642565b6108c1546001600160a01b0382811691161415610c0b5760405162461bcd60e51b81526004016106b390612aaf565b6108c080546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600360205260408120546001600160a01b0316806105ec5760405162461bcd60e51b81526004016106b3906126c3565b600c546001600160a01b031681565b60006001600160a01b038216610c9a5760405162461bcd60e51b81526004016106b390612679565b506001600160a01b031660009081526004602052604090205490565b610cbe611397565b6001600160a01b0316610ccf610d07565b6001600160a01b031614610cf55760405162461bcd60e51b81526004016106b3906128bb565b610cff60006119e1565b565b6108ae81565b6000546001600160a01b031690565b610d1e611397565b6001600160a01b0316610d2f610d07565b6001600160a01b031614610d555760405162461bcd60e51b81526004016106b3906128bb565b8051610d6890600f906020840190611f35565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad816040516107f391906123b1565b60606002805461060990612bc4565b600b5490565b610db5611397565b6001600160a01b0316826001600160a01b03161415610de65760405162461bcd60e51b81526004016106b39061256b565b8060066000610df3611397565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610e37611397565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610e6f91906123a6565b60405180910390a35050565b600d5481565b610e89611397565b6001600160a01b0316610e9a610d07565b6001600160a01b031614610ec05760405162461bcd60e51b81526004016106b3906128bb565b600e805460ff19168215151790556040517f8939c08109a5d8d76bb72a1a22bd59c7ba7e81fe6dcfd41644887fc9ab07d828906107f39083906123a6565b6108be5490565b6108c0546001600160a01b031681565b610f26610f20611397565b83611409565b610f425760405162461bcd60e51b81526004016106b3906129f8565b610f4e84848484611a31565b50505050565b600b5481565b610f62611397565b6001600160a01b0316610f73610d07565b6001600160a01b031614610f995760405162461bcd60e51b81526004016106b3906128bb565b6101f4811115610fa857600080fd5b600a8190556040517f764ff695884be16cb59c81839f71b2897b6e0ad3bacb74a973f9345195785247906107f3908390612b16565b60606105ec82611a64565b610ff0611397565b6001600160a01b0316611001610d07565b6001600160a01b0316146110275760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b03811661104d5760405162461bcd60e51b81526004016106b390612642565b6108c1546001600160a01b038281169116141561107c5760405162461bcd60e51b81526004016106b390612aaf565b6108c180546001600160a01b0319166001600160a01b0383161790556040517f34830ecd12aee38e030de8db2aab7662959ba614a8af53e095041d13deced11d906107f39083906122dd565b60095481565b6110d6611397565b6001600160a01b03166110e7610d07565b6001600160a01b03161461110d5760405162461bcd60e51b81526004016106b3906128bb565b600b8190556040517f66cbca4f3c64fecf1dcb9ce094abcf7f68c3450a1d4e3a8e917dd621edb4ebe0906107f3908390612b16565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b611178611397565b6001600160a01b0316611189610d07565b6001600160a01b0316146111af5760405162461bcd60e51b81526004016106b3906128bb565b6001600160a01b0381166111d55760405162461bcd60e51b81526004016106b3906124aa565b6111de816119e1565b50565b60608161120657506040805180820190915260018152600360fc1b60208201526105ef565b8160005b8115611230578061121a81612bff565b91506112299050600a83612b37565b915061120a565b60008167ffffffffffffffff81111561125957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611283576020820181803683370190505b5090505b84156112fc57611298600183612b6a565b91506112a5600a86612c1a565b6112b0906030612b1f565b60f81b8183815181106112d357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506112f5600a86612b37565b9450611287565b949350505050565b61130d8261137a565b6113295760405162461bcd60e51b81526004016106b39061270c565b6000828152600760209081526040909120825161076b92840190611f35565b60006113548284612b1f565b9392505050565b3b151590565b6001600160e01b031981166301ffc9a760e01b14919050565b6000908152600360205260409020546001600160a01b0316151590565b3390565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906113d082610c2e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006114148261137a565b6114305760405162461bcd60e51b81526004016106b39061259e565b600061143b83610c2e565b9050806001600160a01b0316846001600160a01b031614806114765750836001600160a01b031661146b8461068c565b6001600160a01b0316145b806112fc57506112fc8185611142565b826001600160a01b031661149982610c2e565b6001600160a01b0316146114bf5760405162461bcd60e51b81526004016106b3906128f0565b6001600160a01b0382166114e55760405162461bcd60e51b81526004016106b390612527565b6114f083838361076b565b6114fb60008261139b565b6001600160a01b0383166000908152600460205260408120805460019290611524908490612b6a565b90915550506001600160a01b0382166000908152600460205260408120805460019290611552908490612b1f565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006113548284612b4b565b6108c2546108c3548110156115f8576108c154600b546115f2916001600160a01b0316906115ed90856115b3565b611b7d565b506111de565b6108c3548290805b8381101561184f578261161657505050506111de565b60006116916108c2838154811061163d57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060030201600201546108c2848154811061167157634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160010154611c6b90919063ffffffff16565b905083811115611771576116ea6108c283815481106116c057634e487b7160e01b600052603260045260246000fd5b6000918252602090912060039091020154600b546001600160a01b03909116906115ed90876115b3565b611730846108c2848154811061171057634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016002015461134890919063ffffffff16565b6108c2838154811061175257634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302016002018190555050505050506111de565b6117c06108c2838154811061179657634e487b7160e01b600052603260045260246000fd5b6000918252602090912060039091020154600b546001600160a01b03909116906115ed90846115b3565b6117e6816108c2848154811061171057634e487b7160e01b600052603260045260246000fd5b6108c2838154811061180857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600260039092020101556118268482611c6b565b6108c354909450611838906001611348565b6108c355508061184781612bff565b915050611600565b508115610f4e576108c154600b54610f4e916001600160a01b0316906115ed90856115b3565b600080333a4342611887600183612b6a565b4088886040516020016118a0979695949392919061236b565b6040516020818303038152906040528051906020012060001c905060006108be54826118cc9190612c1a565b905060006010826108ae81106118f257634e487b7160e01b600052603260045260246000fd5b01549050600081611904575081611907565b50805b600060016108be546119199190612b6a565b90508084146119a15760006010826108ae811061194657634e487b7160e01b600052603260045260246000fd5b015490508061197957816010866108ae811061197257634e487b7160e01b600052603260045260246000fd5b015561199f565b806010866108ae811061199c57634e487b7160e01b600052603260045260246000fd5b01555b505b6108be80549060006119b283612bad565b909155509198975050505050505050565b6119dd828260405180602001604052806000815250611c77565b5050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611a3c848484611486565b611a4884848484611caa565b610f4e5760405162461bcd60e51b81526004016106b3906123c4565b6060611a6f8261137a565b611a8b5760405162461bcd60e51b81526004016106b39061281e565b60008281526007602052604081208054611aa490612bc4565b80601f0160208091040260200160405190810160405280929190818152602001828054611ad090612bc4565b8015611b1d5780601f10611af257610100808354040283529160200191611b1d565b820191906000526020600020905b815481529060010190602001808311611b0057829003601f168201915b505050505090506000611b2e611dc5565b9050805160001415611b42575090506105ef565b815115611b74578082604051602001611b5c9291906122ae565b604051602081830303815290604052925050506105ef565b6112fc84611dd4565b600c546001600160a01b0316611bc9576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611bc3573d6000803e3d6000fd5b506119dd565b600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611bfd903390869086906004016122f1565b602060405180830381600087803b158015611c1757600080fd5b505af1158015611c2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4f91906121d0565b6119dd5760405162461bcd60e51b81526004016106b390612466565b60006113548284612b6a565b611c818383611e56565b611c8e6000848484611caa565b61076b5760405162461bcd60e51b81526004016106b3906123c4565b6000611cbe846001600160a01b031661135b565b15611dba57836001600160a01b031663150b7a02611cda611397565b8786866040518563ffffffff1660e01b8152600401611cfc9493929190612315565b602060405180830381600087803b158015611d1657600080fd5b505af1925050508015611d46575060408051601f3d908101601f19168201909252611d4391810190612208565b60015b611da0573d808015611d74576040519150601f19603f3d011682016040523d82523d6000602084013e611d79565b606091505b508051611d985760405162461bcd60e51b81526004016106b3906123c4565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506112fc565b506001949350505050565b6060600f805461060990612bc4565b6060611ddf8261137a565b611dfb5760405162461bcd60e51b81526004016106b390612939565b6000611e05611dc5565b90506000815111611e255760405180602001604052806000815250611354565b80611e2f846111e1565b604051602001611e409291906122ae565b6040516020818303038152906040529392505050565b6001600160a01b038216611e7c5760405162461bcd60e51b81526004016106b3906127e9565b611e858161137a565b15611ea25760405162461bcd60e51b81526004016106b3906124f0565b611eae6000838361076b565b6001600160a01b0382166000908152600460205260408120805460019290611ed7908490612b1f565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054611f4190612bc4565b90600052602060002090601f016020900481019282611f635760008555611fa9565b82601f10611f7c57805160ff1916838001178555611fa9565b82800160010185558215611fa9579182015b82811115611fa9578251825591602001919060010190611f8e565b50611fb5929150611fb9565b5090565b5b80821115611fb55760008155600101611fba565b600067ffffffffffffffff80841115611fe957611fe9612c5a565b604051601f8501601f19168101602001828111828210171561200d5761200d612c5a565b60405284815291508183850186101561202557600080fd5b8484602083013760006020868301015250509392505050565b80356001600160a01b03811681146105ef57600080fd5b600060208284031215612066578081fd5b6113548261203e565b60008060408385031215612081578081fd5b61208a8361203e565b91506120986020840161203e565b90509250929050565b6000806000606084860312156120b5578081fd5b6120be8461203e565b92506120cc6020850161203e565b9150604084013590509250925092565b600080600080608085870312156120f1578081fd5b6120fa8561203e565b93506121086020860161203e565b925060408501359150606085013567ffffffffffffffff81111561212a578182fd5b8501601f8101871361213a578182fd5b61214987823560208401611fce565b91505092959194509250565b60008060408385031215612167578182fd5b6121708361203e565b9150602083013561218081612c70565b809150509250929050565b6000806040838503121561219d578182fd5b6121a68361203e565b946020939093013593505050565b6000602082840312156121c5578081fd5b813561135481612c70565b6000602082840312156121e1578081fd5b815161135481612c70565b6000602082840312156121fd578081fd5b813561135481612c7e565b600060208284031215612219578081fd5b815161135481612c7e565b600060208284031215612235578081fd5b813567ffffffffffffffff81111561224b578182fd5b8201601f8101841361225b578182fd5b6112fc84823560208401611fce565b60006020828403121561227b578081fd5b5035919050565b6000815180845261229a816020860160208601612b81565b601f01601f19169290920160200192915050565b600083516122c0818460208801612b81565b8351908301906122d4818360208801612b81565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061234890830184612282565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b901515815260200190565b6000602082526113546020830184612282565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526030908201527f4472697050616e64613a20546f6f206c6974746c652073656e742c20706c656160408201526f0e6ca40e6cadcc840dadee4ca40cae8d60831b606082015260800190565b60208082526024908201527f4472697050616e64613a206661696c656420746f207472616e7366657220746f6040820152636b656e7360e01b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776040820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606082015260800190565b6020808252601a908201527f4472697050616e64613a20496e76616c69642061646472657373000000000000604082015260600190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526029908201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460408201526832b73a103a37b5b2b760b91b606082015260800190565b6020808252602e908201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60408201526d32bc34b9ba32b73a103a37b5b2b760911b606082015260800190565b60208082526027908201527f4472697050616e64613a206578636565646564206d6178206c696d69742070656040820152667220636c61696d60c81b606082015260800190565b60208082526028908201527f4472697050616e64613a206578636565646564206d6178206c696d69742070656040820152671c881dd85b1b195d60c21b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526031908201527f45524337323155524953746f726167653a2055524920717565727920666f72206040820152703737b732bc34b9ba32b73a103a37b5b2b760791b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b6020808252601590820152744472697050616e64613a206e6f742061637469766560581b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b602080825260159082015274111c9a5c14185b99184e881e995c9bc818dbdd5b9d605a1b604082015260600190565b6020808252601b908201527f4472697050616e64613a206e6f7420656e6f7567682070616e64610000000000604082015260600190565b602080825260169082015275111c9a5c14185b99184e88185b1c9958591e481cd95d60521b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b90815260200190565b60008219821115612b3257612b32612c2e565b500190565b600082612b4657612b46612c44565b500490565b6000816000190483118215151615612b6557612b65612c2e565b500290565b600082821015612b7c57612b7c612c2e565b500390565b60005b83811015612b9c578181015183820152602001612b84565b83811115610f4e5750506000910152565b600081612bbc57612bbc612c2e565b506000190190565b600281046001821680612bd857607f821691505b60208210811415612bf957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612c1357612c13612c2e565b5060010190565b600082612c2957612c29612c44565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146111de57600080fd5b6001600160e01b0319811681146111de57600080fdfea2646970667358221220dde492a5c54f58362735b16611607aefb0e188dedfbcf6700757b94eaf4c4c4864736f6c63430008000033

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.