ETH Price: $3,983.20 (-0.37%)

Token

Onchain Ninja (ONN)
 

Overview

Max Total Supply

114 ONN

Holders

98

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 ONN
0xe10786ed6c8b7363ac502de7270cd8b9f8cd248a
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:
Ninja

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 99 runs

Other Settings:
default evmVersion
File 1 of 5 : ninja.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "erc721a/contracts/ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";



contract Ninja is ERC721A, Ownable {
    uint256 private _tokenPrice = 10000000000000000; //0.01 ETH
    uint256 private _curLimit = 1111;
    uint256 private _perWallet = 20;
    bool private _isPublicSaleActive = true;
    bool private _isPublicClaimActive = false;

    mapping(address => uint) public claimed;
    mapping(address => bool) public freeClaimed;

    function toString(uint256 value) internal pure returns (string memory) {
        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);
    }

    function toString(int256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        int256 temp = value >= 0 ? value : -value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        if (value < 0) {
            digits++;
        }
        bytes memory buffer = new bytes(digits);
        if (value < 0) {
            //digits -= 1;
            value = -value;
            buffer[0] = bytes1(uint8(45));
        }
        
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        
        return string(buffer);
    }

    constructor() ERC721A("Onchain Ninja", "ONN") {}

    function setPrice(uint256 price) public onlyOwner {
        _tokenPrice = price;
    }
    
    function setPerWallet(uint256 amount) public onlyOwner {
        _perWallet = amount;
    }
   
    function setLimit(uint256 amount) public onlyOwner {
        _curLimit = amount;
    }

    function flipPublicSaleState() public onlyOwner {
        _isPublicSaleActive = !_isPublicSaleActive;
    }

    function flipPublicClaimState() public onlyOwner {
        _isPublicClaimActive = !_isPublicClaimActive;
    }

    function random(string memory input) internal pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(input)));
    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        string memory output;
        uint256 rand = random(string(abi.encodePacked('fff',toString(tokenId))));
        uint16 i;
        uint8 pet_type;
        uint8 palette;
        
        string[23] memory bg = [
            '0d1924',
            '0d1924',
            '091a0d',
            '240101',
            '663154',
            '171717',
            '544538',
            '1f0208',
            '121212',
            'edebeb',
            'Cat',
            'Rabbit',
            'Bear',
            'Cyber blue',
            'Neon warrior',
            'Matrix',
            'Fire Fury',
            'Sakura flower',
            'Moonlight',
            'Cardboard hero',
            'Purple Menace',
            'Nightmare',
            'Manga'
        ];


        uint240[3] memory phsl = [
            305030209050992040673040706720209983786990509920905099208060994080609940,
            101051071051071051020030020010020051030101071051070100070200,
            250250170150050070031021031150010030011040250250041200180170
            ];
        uint8 hsl1;
        uint8 hsl2;
        uint8 r1;
        uint8 r2;

        string[35] memory data = [
            '1408,535L-222,884L1408,535z M1125,643L-334,952L1125,643z M1080,581L-42,821L1080,581z M80,328l-384,81L80,328zM1089,114L-38,354L1089,114z M1143,81l-1245,263L1143,81z',
            '1128-72L-114,192L1128-72z',
            '235,117l-575,122L235,117z',
            '1508-102L-273,278L1508-102z',
            '-394,701l279-59L-394,701z',
            '-177,687L1049,427L-177,687z',
            '-269,674l1358-286L-269,674z',
            '895-106L-581,208l94,442l2343-499c0,0,40,159,34,160s-2386,508-2386,508l52,246L1510,649',
            '386,702c0,0,81-84,195-64c114,19,102-49,80-34c-24,16,0,21-148,11',
            '431,373c0,0,108-135,62,2',
            '332,419c0,0,77-136,51-31',
            '432,373c0,0,132-137,174-100c38,34-93,18-114,101',
            '386,702c0,0,51-53,129-65c42,27,22-40-2-21',
            '332,420c0,0,124-191,190-158c39,22-82,30-124,120',
            '386,702c0,0,51-53,129-65c42,27,22-40-2-21',
            '340,411c-19-53,79-92,57-28',
            '436,371c-8-56,120-71,57,5',
            '589,681L774,640L589,681z M550,599L817,533L550,599zM689,609L749,597L689,609z M655,521L831,477L655,521z M671,393l79-16L671,393zM518,313l252-53L518,313z',
            '606,480l29-211c0,0,32,26,27,68c-4,41-29,149-29,149',
            '620,483l21-124L620,483z',
            '636,509c0,0,46-15-17-25s-24,17-24,17l-65,5',
            '599,533c-30-36,21-42,32-29c45,51-87,42-105,72c-17,30-12,60-12,60s77,39,60,56c-17,17-87-10-120,1c-32,11,5,61-12,56c-17-5-59-15-57-73c4-101-9-11-55-40c0,0,8-78,43-81l31,38',
            '388,698c0,0,43-118,69-139',
            '386,651l30-86L386,651z',
            '412,453c0,0,25,22,22-14',
            '343,466c0,0,2,28,15,3',
            '485,417c0,0,19,7,50-3s58-17,58-17l-6-23l-54,21l27-38l-25-8l-15,40',
            '325,469c0,0-35-47,73-85c108-38,136,26,136,26s51,61-40,127c-92,65-159-10-159-10',
            '325,469c0,0,4,10,7,29c3,18-4,29,7,25s15-35,38-39c23-3,79,34,113-24C535,385,350,383,325,469z',
            '398,460l53-35L398,460z',
            '365,470l-25-6L365,470z',
            '1012,661l-1122,239L1012,661z',
            '1978,530l-2634,562L1978,530z',
            '1488-27l-1710,364L1488-27z',
            '1686,18l-2800,600L1686,18z'
        ];


        pet_type = uint8(rand % 3);
        palette = uint8((rand>>3) % 50);
        if (palette > 9)
            palette = palette % 9;

       
        output = string(abi.encodePacked('<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000">',
        '<style type="text/css" media="screen">',
        '<![CDATA[',
        'svg {margin: 0;background: #',bg[palette],';height: 100vh;width: 100%;}',
        'path {fill: none;stroke-dasharray: 80 700;animation: 4s ease-in infinite alternate draw;}',
        '@keyframes draw {to {stroke-dasharray: 1200 1900;}}',
        ']]>',
        '</style>'
            ));

        if (palette < 9) {
            hsl1 = uint8((phsl[0] / (100**(palette*4)))%100);
            hsl2 = uint8((phsl[0] / (100**(palette*4+1)))%100);
        } else {
            hsl1 = 20;
            hsl2 = 0;
        }

        r1 = uint8((phsl[1] / (1000**(palette*2)))%1000);
        r2 = uint8((phsl[2] / (1000**(palette*2)))%1000);
        for(i=0;i<=7;i++) {
            output = string(abi.encodePacked(output,
                '<path opacity="0.1" stroke="hsl(',
                toString(int((rand>>i)%r1) +  int((r2%10==1?int(uint(r2)):-int(uint(r2))))),
                ',',toString(hsl2),'%,',toString(hsl1),'%)" d="M',
                data[i]
                ));

            output = string(abi.encodePacked(output,
                '" stroke-width="',
                toString(465 + (rand>>i)%100),
                '"/>'
                ));
        }
        if (palette < 9) {
            hsl1 = uint8((phsl[0] / (100**(palette*4+2)))%100);
            hsl2 = uint8((phsl[0] / (100**(palette*4+3)))%100);
        } else {
            hsl1 = 10;
            hsl2 = 0; 
        }
        r1 = uint8((phsl[1] / (1000**(palette*2+1)))%1000);
        r2 = uint8((phsl[2] / (1000**(palette*2+1)))%1000);

        for(i=8+pet_type*3;i<=10+pet_type*3;i++) {
            output = string(abi.encodePacked(output,
                '<path stroke="hsl(',
                toString(int((rand>>i)%r1) +  int((r2%10==1?int(uint(r2)):-int(uint(r2))))),

                ',',toString(hsl2),'%,',toString(hsl1),'%)" d="M',
                data[i]
                ));
            output = string(abi.encodePacked(output,
                '" stroke-width="',
                toString(5 +(rand>>i)%5),
                '"/>'
                ));
            }
        
        for(i=17;i<35;i++) {
            output = string(abi.encodePacked(output,
                '<path stroke="hsl(',
                toString(int((rand>>i)%r1) +  int((r2%10==1?int(uint(r2)):-int(uint(r2))))),
                ',',toString(hsl2),'%,',toString(hsl1),'%)" d="M',
                data[i]
                ));
            output = string(abi.encodePacked(output,
                '" stroke-width="',
                toString(5 +(rand>>i)%5),
                '" opacity ="',((i==17||i>30)?'0.22':'1'),'" />'
                ));
            }


        output = string(abi.encodePacked(output,
        '</svg>'
        ));
        
        string memory strparams;

        strparams = string(abi.encodePacked('[{ "trait_type": "Pet", "value": "',bg[pet_type+10],'" }, { "trait_type": "Palette", "value": "',bg[palette+13],'" }, { "trait_type": "Genome", "value": "',toString(rand%100000000),'" }]'));


        output = Base64.encode(bytes(string(abi.encodePacked('{"name": "OnChain Ninja", "description": "Fast, dangerous, completely generated OnChain.","attributes":', strparams, ', "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}'))));
        output = string(abi.encodePacked('data:application/json;base64,', output));

        return output;
    }
    
    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    function buy(uint amount) public payable {
        require(amount > 0, "Wrong amount");
        require(_isPublicSaleActive, "Later");
        require(totalSupply() + amount < _curLimit, "Sale finished");
        require(_tokenPrice * amount <= msg.value, "Need more ETH");
       require(claimed[msg.sender] + amount <= _perWallet, "Tokens done");

        _safeMint(msg.sender, amount);
        claimed[msg.sender] += amount;
    }

    function mint() public {
        require(_isPublicClaimActive, "Later");
        require(totalSupply() < 111, "Claim finished");
        require(freeClaimed[msg.sender] == false, "Done");

        _safeMint(msg.sender, 1);
        freeClaimed[msg.sender] = true;
    }

    function drop(address _address, uint256 amount) public onlyOwner {
        require(totalSupply() + amount < _curLimit, "Sale finished");

        _safeMint(_address, amount);
    }
}



/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
    bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /// @notice Encodes some bytes to the base64 representation
    function encode(bytes memory data) internal pure returns (string memory) {
        uint256 len = data.length;
        if (len == 0) return "";

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((len + 2) / 3);

        // Add some extra buffer at the end
        bytes memory result = new bytes(encodedLen + 32);

        bytes memory table = TABLE;

        assembly {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 32)

            for {
                let i := 0
            } lt(i, len) {

            } {
                i := add(i, 3)
                let input := and(mload(add(data, i)), 0xffffff)

                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
                out := shl(224, out)

                mstore(resultPtr, out)

                resultPtr := add(resultPtr, 4)
            }

            switch mod(len, 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }

            mstore(result, encodedLen)
        }

        return string(result);
    }
}

File 2 of 5 : 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 5 : ERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import './IERC721A.sol';

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

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

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

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

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

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
    }

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

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

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

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

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

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

    /**
     * Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr)
                if (curr < _currentIndex) {
                    uint256 packed = _packedOwnerships[curr];
                    // If not burned.
                    if (packed & _BITMASK_BURNED == 0) {
                        // Invariant:
                        // There will always be an initialized ownership slot
                        // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                        // before an unintialized ownership slot
                        // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                        // Hence, `curr` will not underflow.
                        //
                        // We can directly compare the packed value.
                        // If the address is zero, packed will be zero.
                        while (packed == 0) {
                            packed = _packedOwnerships[--curr];
                        }
                        return packed;
                    }
                }
        }
        revert OwnerQueryForNonexistentToken();
    }

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

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

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

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

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * 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) public payable virtual override {
        address owner = ownerOf(tokenId);

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

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

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

        return _tokenApprovals[tokenId].value;
    }

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom}
     * for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex && // If within bounds,
            _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.
    }

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

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

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

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

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

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

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

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

        _beforeTokenTransfers(from, to, tokenId, 1);

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // We can directly increment and decrement the balances.
            --_packedAddressData[from]; // Updates: `balance -= 1`.
            ++_packedAddressData[to]; // Updates: `balance += 1`.

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                revert TransferToNonERC721ReceiverImplementer();
            }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token IDs
     * are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

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

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

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) revert MintZeroQuantity();

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

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

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

            uint256 toMasked;
            uint256 end = startTokenId + quantity;

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

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

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

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

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

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

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

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

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

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * See {_mint}.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal virtual {
        _mint(to, quantity);

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

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

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

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

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

        address from = address(uint160(prevOwnershipPacked));

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

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

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

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

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

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

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

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

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

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

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

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

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

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

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

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

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

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

File 4 of 5 : IERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 5 of 5 : 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;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"drop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipPublicClaimState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipPublicSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"freeClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052662386f26fc10000600955610457600a556014600b55600c805461ffff191660011790553480156200003557600080fd5b506040518060400160405280600d81526020016c4f6e636861696e204e696e6a6160981b8152506040518060400160405280600381526020016227a72760e91b8152508160029081620000899190620001a7565b506003620000988282620001a7565b50506000805550620000aa33620000b0565b62000273565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200012d57607f821691505b6020821081036200014e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001a257600081815260208120601f850160051c810160208610156200017d5750805b601f850160051c820191505b818110156200019e5782815560010162000189565b5050505b505050565b81516001600160401b03811115620001c357620001c362000102565b620001db81620001d4845462000118565b8462000154565b602080601f831160018114620002135760008415620001fa5750858301515b600019600386901b1c1916600185901b1785556200019e565b600085815260208120601f198616915b82811015620002445788860151825594840194600190910190840162000223565b5085821015620002635787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61395480620002836000396000f3fe6080604052600436106101775760003560e01c80638d0f8cef116100cc578063c87b56dd1161007a578063c87b56dd146103ea578063c884ef831461040a578063cf00b56314610437578063d3896e5714610457578063d96a094a1461046c578063e985e9c51461047f578063f2fde38b1461049f57600080fd5b80638d0f8cef146103385780638da5cb5b1461035857806391b7f5ed1461036d57806395d89b411461038d578063a10866ef146103a2578063a22cb465146103b7578063b88d4fde146103d757600080fd5b806327ea6f2b1161012957806327ea6f2b1461026b5780633ccfd60b1461028b57806342842e0e146102a057806361c0b6a0146102b35780636352211e146102e357806370a0823114610303578063715018a61461032357600080fd5b806301ffc9a71461017c57806306fdde03146101b1578063081812fc146101d3578063095ea7b31461020b5780631249c58b1461022057806318160ddd1461023557806323b872dd14610258575b600080fd5b34801561018857600080fd5b5061019c6101973660046126e4565b6104bf565b60405190151581526020015b60405180910390f35b3480156101bd57600080fd5b506101c6610511565b6040516101a89190612751565b3480156101df57600080fd5b506101f36101ee366004612764565b6105a3565b6040516001600160a01b0390911681526020016101a8565b61021e610219366004612799565b6105e7565b005b34801561022c57600080fd5b5061021e610687565b34801561024157600080fd5b50600154600054035b6040519081526020016101a8565b61021e6102663660046127c3565b610774565b34801561027757600080fd5b5061021e610286366004612764565b6108fa565b34801561029757600080fd5b5061021e61092e565b61021e6102ae3660046127c3565b610990565b3480156102bf57600080fd5b5061019c6102ce3660046127ff565b600e6020526000908152604090205460ff1681565b3480156102ef57600080fd5b506101f36102fe366004612764565b6109b0565b34801561030f57600080fd5b5061024a61031e3660046127ff565b6109bb565b34801561032f57600080fd5b5061021e610a0a565b34801561034457600080fd5b5061021e610353366004612799565b610a45565b34801561036457600080fd5b506101f3610ab6565b34801561037957600080fd5b5061021e610388366004612764565b610ac5565b34801561039957600080fd5b506101c6610af9565b3480156103ae57600080fd5b5061021e610b08565b3480156103c357600080fd5b5061021e6103d236600461281a565b610b4b565b61021e6103e536600461286c565b610bb7565b3480156103f657600080fd5b506101c6610405366004612764565b610c01565b34801561041657600080fd5b5061024a6104253660046127ff565b600d6020526000908152604090205481565b34801561044357600080fd5b5061021e610452366004612764565b611cc9565b34801561046357600080fd5b5061021e611cfd565b61021e61047a366004612764565b611d49565b34801561048b57600080fd5b5061019c61049a366004612948565b611eba565b3480156104ab57600080fd5b5061021e6104ba3660046127ff565b611ee8565b60006301ffc9a760e01b6001600160e01b0319831614806104f057506380ac58cd60e01b6001600160e01b03198316145b8061050b5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546105209061297b565b80601f016020809104026020016040519081016040528092919081815260200182805461054c9061297b565b80156105995780601f1061056e57610100808354040283529160200191610599565b820191906000526020600020905b81548152906001019060200180831161057c57829003601f168201915b5050505050905090565b60006105ae82611f88565b6105cb576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006105f2826109b0565b9050336001600160a01b0382161461062b5761060e8133611eba565b61062b576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600c54610100900460ff166106b75760405162461bcd60e51b81526004016106ae906129b5565b60405180910390fd5b606f6106c66001546000540390565b106107045760405162461bcd60e51b815260206004820152600e60248201526d10db185a5b48199a5b9a5cda195960921b60448201526064016106ae565b336000908152600e602052604090205460ff161561074d5760405162461bcd60e51b81526004016106ae90602080825260049082015263446f6e6560e01b604082015260600190565b610758336001611faf565b336000908152600e60205260409020805460ff19166001179055565b600061077f82611fc9565b9050836001600160a01b0316816001600160a01b0316146107b25760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b038816909114176107ff576107e28633611eba565b6107ff57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03851661082657604051633a954ecd60e21b815260040160405180910390fd5b801561083157600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b841690036108c3576001840160008181526004602052604081205490036108c15760005481146108c15760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b031660008051602061376c83398151915260405160405180910390a4505050505050565b33610903610ab6565b6001600160a01b0316146109295760405162461bcd60e51b81526004016106ae906129d4565b600a55565b33610937610ab6565b6001600160a01b03161461095d5760405162461bcd60e51b81526004016106ae906129d4565b6040514790339082156108fc029083906000818181858888f1935050505015801561098c573d6000803e3d6000fd5b5050565b6109ab83838360405180602001604052806000815250610bb7565b505050565b600061050b82611fc9565b60006001600160a01b0382166109e4576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b33610a13610ab6565b6001600160a01b031614610a395760405162461bcd60e51b81526004016106ae906129d4565b610a436000612037565b565b33610a4e610ab6565b6001600160a01b031614610a745760405162461bcd60e51b81526004016106ae906129d4565b600a5481610a856001546000540390565b610a8f9190612a1f565b10610aac5760405162461bcd60e51b81526004016106ae90612a32565b61098c8282611faf565b6008546001600160a01b031690565b33610ace610ab6565b6001600160a01b031614610af45760405162461bcd60e51b81526004016106ae906129d4565b600955565b6060600380546105209061297b565b33610b11610ab6565b6001600160a01b031614610b375760405162461bcd60e51b81526004016106ae906129d4565b600c805460ff19811660ff90911615179055565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610bc2848484610774565b6001600160a01b0383163b15610bfb57610bde84848484612089565b610bfb576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060806000610c36610c1285612175565b604051602001610c229190612a59565b604051602081830303815290604052612276565b604080516103208101825260066102e08201818152650c190c4e4c8d60d21b6103008401819052908352835180850185528281526020818101929092528184015283518085018552828152650c0e4c584c1960d21b8183015283850152835180850185528281526532343031303160d01b8183015260608085019190915284518086018652838152650d8d8ccc4d4d60d21b818401526080850152845180860186528381526531373137313760d01b8184015260a0850152845180860186528381526506a68686a66760d31b8184015260c08501528451808601865283815265062cc606460760d31b8184015260e0850152845180860186528381526518991899189960d11b81840152610100850152845180860186528381526532b232b132b160d11b8184015261012085015284518086018652600381526210d85d60ea1b818401526101408501528451808601865283815265149858989a5d60d21b818401526101608501528451808601865260048152632132b0b960e11b8184015261018085015284518086018652600a815269437962657220626c756560b01b818401526101a085015284518086018652600c81526b2732b7b7103bb0b93934b7b960a11b818401526101c0850152845180860186529283526509ac2e8e4d2f60d31b838301526101e08401929092528351808501855260098082526846697265204675727960b81b8284015261020085019190915284518086018652600d8082526c29b0b5bab93090333637bbb2b960991b828501526102208601919091528551808701875282815268135bdbdb9b1a59da1d60ba1b8185015261024086015285518087018752600e81526d43617264626f617264206865726f60901b81850152610260860152855180870187529081526c507572706c65204d656e61636560981b8184015261028085015284518086018652908152684e696768746d61726560b81b818301526102a08401528351808501855260058152644d616e676160d81b818301526102c0840152835191820184527d2c323303b959a29e41a08175b8551b8e38a975d7222487d40ef44b16169482527810192e689f507af3cee8f18999a5305fecf245508b366ddf38908201527827ddfdaf78bc2ae0a8042bee29d9fc66e39605a62a51437bca818401528251610540810190935260a3610460840181815294955060009485948594939285928392839283928392918291906136c96104808401398152602001604051806040016040528060198152602001781898991c169b99261698989a16189c99261898991c169b993d60391b81525081526020016040518060400160405280601981526020017819199a9618989bb6169a9b9a961899192619199a9618989bbd60391b81525081526020016040518060400160405280601b81526020017f313530382d3130324c2d3237332c3237384c313530382d3130327a000000000081525081526020016040518060400160405280601981526020017816999c9a161b9818b6191b9c969a9ca616999c9a161b9818bd60391b81525081526020016040518060400160405280601b81526020017f2d3137372c3638374c313034392c3432374c2d3137372c3638377a000000000081525081526020016040518060400160405280601b81526020017f2d3236392c3637346c313335382d3238364c2d3236392c3637347a000000000081525081526020016040518060800160405280605581526020016137da6055913981526020016040518060600160405280603f81526020016135a8603f91398152602001604051806040016040528060188152602001771a199896199b99b19816181618981c1698999a961b19161960411b8152508152602001604051806040016040528060188152602001773333322c34313963302c302c37372d3133362c35312d333160401b81525081526020016040518060600160405280602f8152602001613619602f913981526020016040518060600160405280602981526020016134d66029913981526020016040518060600160405280602f815260200161347d602f913981526020016040518060600160405280602981526020016134d66029913981526020016040518060400160405280601a815260200179066686058686262c65a62725a6a66586e725a7264586a6e5a64760331b8152508152602001604051806040016040528060198152602001783433362c333731632d382d35362c3132302d37312c35372c3560381b81525081526020016040518060c001604052806095815260200161382f6095913981526020016040518060600160405280603281526020016135e7603291398152602001604051806040016040528060178152602001761b1918161a1c19b619189698991a261b1918161a1c19bd60491b81525081526020016040518060600160405280602a81526020016134ac602a913981526020016040518060e0016040528060a981526020016134ff60a991398152602001604051806040016040528060198152602001783338382c36393863302c302c34332d3131382c36392d31333960381b815250815260200160405180604001604052806016815260200175199c1b161b1a98b61998169c1b26199c1b161b1a98bd60511b8152508152602001604051806040016040528060178152602001760d0c4c8b0d0d4cd8cc0b0c0b0c8d4b0c8c8b0c8c8b4c4d604a1b8152508152602001604051806040016040528060158152602001743334332c34363663302c302c322c32382c31352c3360581b81525081526020016040518060800160405280604181526020016136886041913981526020016040518060800160405280604e815260200161378c604e913981526020016040518060800160405280605b81526020016138c4605b9139815260200160405180604001604052806016815260200175199c9c161a1b18361a9996999aa6199c9c161a1b183d60511b815250815260200160405180604001604052806016815260200175199b1a961a1b983616991a969b26199b1a961a1b983d60511b81525081526020016040518060400160405280601c81526020017f313031322c3636316c2d313132322c3233394c313031322c3636317a0000000081525081526020016040518060400160405280601c81526020017f313937382c3533306c2d323633342c3536324c313937382c3533307a0000000081525081526020016040518060400160405280601a815260200179189a1c1c16991bb616989b989816199b1a26189a1c1c16991bbd60311b81525081526020016040518060400160405280601a815260200179189b1c1b16189c3616991c1818161b181826189b1c1b16189c3d60311b815250815250905060038b6115da9190612a9a565b98506115eb603260038d901c612a9a565b975060098860ff16111561160757611604600989612aae565b97505b868860ff166017811061161c5761161c612ad0565b60200201516040516020016116319190612ae6565b6040516020818303038152906040529b5060098860ff1610156116d057606461165b896004612cfc565b611666906064612e05565b875161167b91906001600160f01b0316612e14565b6116859190612a9a565b94506064611694896004612cfc565b61169f906001612e28565b6116aa906064612e05565b87516116bf91906001600160f01b0316612e14565b6116c99190612a9a565b93506116d9565b60149450600093505b6103e86116e7896002612cfc565b6116f3906103e8612e05565b602088015161170b91906001600160f01b0316612e14565b6117159190612a9a565b92506103e8611725896002612cfc565b611731906103e8612e05565b604088015161174991906001600160f01b0316612e14565b6117539190612a9a565b9150600099505b60078a61ffff161161186f578b6117ba611775600a85612aae565b60ff166001146117905761178b60ff8516612e41565b611795565b8360ff165b8560ff168d61ffff168f901c6117ab9190612a9a565b6117b59190612e5d565b6122a7565b6117c68660ff16612175565b6117d28860ff16612175565b848e61ffff16602381106117e8576117e8612ad0565b6020020151604051602001611801959493929190612e85565b60408051601f198184030181529190529b508b61183a611829606461ffff8e168f901c612a9a565b611835906101d1612a1f565b612175565b60405160200161184b929190612f4e565b6040516020818303038152906040529b50898061186790612fa9565b9a505061175a565b60098860ff161015611908576064611888896004612cfc565b611893906002612e28565b61189e906064612e05565b87516118b391906001600160f01b0316612e14565b6118bd9190612a9a565b945060646118cc896004612cfc565b6118d7906003612e28565b6118e2906064612e05565b87516118f791906001600160f01b0316612e14565b6119019190612a9a565b9350611911565b600a9450600093505b6103e861191f896002612cfc565b61192a906001612e28565b611936906103e8612e05565b602088015161194e91906001600160f01b0316612e14565b6119589190612a9a565b92506103e8611968896002612cfc565b611973906001612e28565b61197f906103e8612e05565b604088015161199791906001600160f01b0316612e14565b6119a19190612a9a565b91506119ae896003612cfc565b6119b9906008612e28565b60ff1699505b6119ca896003612cfc565b6119d590600a612e28565b60ff168a61ffff1611611aa0578b6119f1611775600a85612aae565b6119fd8660ff16612175565b611a098860ff16612175565b848e61ffff1660238110611a1f57611a1f612ad0565b6020020151604051602001611a38959493929190612fca565b60408051601f198184030181529190529b508b611a6b611a60600561ffff8e168f901c612a9a565b611835906005612a1f565b604051602001611a7c929190612f4e565b6040516020818303038152906040529b508980611a9890612fa9565b9a50506119bf565b601199505b60238a61ffff161015611bbe578b611ac1611775600a85612aae565b611acd8660ff16612175565b611ad98860ff16612175565b848e61ffff1660238110611aef57611aef612ad0565b6020020151604051602001611b08959493929190612fca565b60408051601f198184030181529190529b508b611b30611a60600561ffff8e168f901c612a9a565b8b61ffff1660111480611b475750601e8c61ffff16115b611b6a57604051806040016040528060018152602001603160f81b815250611b88565b604051806040016040528060048152602001631817191960e11b8152505b604051602001611b9a9392919061308c565b6040516020818303038152906040529b508980611bb690612fa9565b9a5050611aa5565b8b604051602001611bcf9190613116565b60408051601f198184030181529190529b50606087611bef8b600a612e28565b60ff1660178110611c0257611c02612ad0565b602002015188611c138b600d612e28565b60ff1660178110611c2657611c26612ad0565b6020020151611c3e6305f5e1008f6118359190612a9a565b604051602001611c5093929190613140565b6040516020818303038152906040529050611c9381611c6e8f61241d565b604051602001611c7f929190613241565b60405160208183030381529060405261241d565b9c508c604051602001611ca6919061333c565b60408051601f198184030181529190529f9e505050505050505050505050505050565b33611cd2610ab6565b6001600160a01b031614611cf85760405162461bcd60e51b81526004016106ae906129d4565b600b55565b33611d06610ab6565b6001600160a01b031614611d2c5760405162461bcd60e51b81526004016106ae906129d4565b600c805461ff001981166101009182900460ff1615909102179055565b60008111611d885760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c8185b5bdd5b9d60a21b60448201526064016106ae565b600c5460ff16611daa5760405162461bcd60e51b81526004016106ae906129b5565b600a5481611dbb6001546000540390565b611dc59190612a1f565b10611de25760405162461bcd60e51b81526004016106ae90612a32565b3481600954611df19190613381565b1115611e2f5760405162461bcd60e51b815260206004820152600d60248201526c09ccacac840dadee4ca408aa89609b1b60448201526064016106ae565b600b54336000908152600d6020526040902054611e4d908390612a1f565b1115611e895760405162461bcd60e51b815260206004820152600b60248201526a546f6b656e7320646f6e6560a81b60448201526064016106ae565b611e933382611faf565b336000908152600d602052604081208054839290611eb2908490612a1f565b909155505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b33611ef1610ab6565b6001600160a01b031614611f175760405162461bcd60e51b81526004016106ae906129d4565b6001600160a01b038116611f7c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106ae565b611f8581612037565b50565b600080548210801561050b575050600090815260046020526040902054600160e01b161590565b61098c828260405180602001604052806000815250612587565b60008160005481101561201e5760008181526004602052604081205490600160e01b8216900361201c575b80600003612015575060001901600081815260046020526040902054611ff4565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906120be903390899088908890600401613398565b6020604051808303816000875af19250505080156120f9575060408051601f3d908101601f191682019092526120f6918101906133d5565b60015b612157573d808015612127576040519150601f19603f3d011682016040523d82523d6000602084013e61212c565b606091505b50805160000361214f576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608160000361219c5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156121c657806121b0816133f2565b91506121bf9050600a83612e14565b91506121a0565b60008167ffffffffffffffff8111156121e1576121e1612856565b6040519080825280601f01601f19166020018201604052801561220b576020820181803683370190505b5090505b841561216d5761222060018361340b565b915061222d600a86612a9a565b612238906030612a1f565b60f81b81838151811061224d5761224d612ad0565b60200101906001600160f81b031916908160001a90535061226f600a86612e14565b945061220f565b600081604051602001612289919061341e565b60408051601f19818403018152919052805160209091012092915050565b6060816000036122ce5750506040805180820190915260018152600360fc1b602082015290565b6000808312156122e6576122e183612e41565b6122e8565b825b905060005b811561231357806122fd816133f2565b915061230c9050600a8361343a565b91506122ed565b600084121561232a5780612326816133f2565b9150505b60008167ffffffffffffffff81111561234557612345612856565b6040519080825280601f01601f19166020018201604052801561236f576020820181803683370190505b50905060008512156123b65761238485612e41565b9450602d60f81b8160008151811061239e5761239e612ad0565b60200101906001600160f81b031916908160001a9053505b841561216d576123c760018361340b565b91506123d4600a86613468565b6123df906030612a1f565b60f81b8183815181106123f4576123f4612ad0565b60200101906001600160f81b031916908160001a905350612416600a8661343a565b94506123b6565b80516060906000819003612441575050604080516020810190915260008152919050565b60006003612450836002612a1f565b61245a9190612e14565b612465906004613381565b90506000612474826020612a1f565b67ffffffffffffffff81111561248c5761248c612856565b6040519080825280601f01601f1916602001820160405280156124b6576020820181803683370190505b5090506000604051806060016040528060408152602001613648604091399050600181016020830160005b86811015612542576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016124e1565b50600386066001811461255c576002811461256d57612579565b613d3d60f01b600119830152612579565b603d60f81b6000198301525b505050918152949350505050565b61259183836125f4565b6001600160a01b0383163b156109ab576000548281035b6125bb6000868380600101945086612089565b6125d8576040516368d2bf6b60e11b815260040160405180910390fd5b8181106125a85781600054146125ed57600080fd5b5050505050565b60008054908290036126195760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b1783179055828401908390839060008051602061376c8339815191528180a4600183015b8181146126a4578083600060008051602061376c833981519152600080a460010161267e565b50816000036126c557604051622e076360e81b815260040160405180910390fd5b60005550505050565b6001600160e01b031981168114611f8557600080fd5b6000602082840312156126f657600080fd5b8135612015816126ce565b60005b8381101561271c578181015183820152602001612704565b50506000910152565b6000815180845261273d816020860160208601612701565b601f01601f19169290920160200192915050565b6020815260006120156020830184612725565b60006020828403121561277657600080fd5b5035919050565b80356001600160a01b038116811461279457600080fd5b919050565b600080604083850312156127ac57600080fd5b6127b58361277d565b946020939093013593505050565b6000806000606084860312156127d857600080fd5b6127e18461277d565b92506127ef6020850161277d565b9150604084013590509250925092565b60006020828403121561281157600080fd5b6120158261277d565b6000806040838503121561282d57600080fd5b6128368361277d565b91506020830135801515811461284b57600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561288257600080fd5b61288b8561277d565b93506128996020860161277d565b925060408501359150606085013567ffffffffffffffff808211156128bd57600080fd5b818701915087601f8301126128d157600080fd5b8135818111156128e3576128e3612856565b604051601f8201601f19908116603f0116810190838211818310171561290b5761290b612856565b816040528281528a602084870101111561292457600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561295b57600080fd5b6129648361277d565b91506129726020840161277d565b90509250929050565b600181811c9082168061298f57607f821691505b6020821081036129af57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600590820152642630ba32b960d91b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082018082111561050b5761050b612a09565b6020808252600d908201526c14d85b1948199a5b9a5cda1959609a1b604082015260600190565b6233333360e91b815260008251612a77816003850160208701612701565b9190910160030192915050565b634e487b7160e01b600052601260045260246000fd5b600082612aa957612aa9612a84565b500690565b600060ff831680612ac157612ac1612a84565b8060ff84160691505092915050565b634e487b7160e01b600052603260045260246000fd5b7f3c7376672076657273696f6e3d22312e302220786d6c6e733d22687474703a2f81527f2f7777772e77332e6f72672f323030302f737667222077696474683d2231303060208201527f3022206865696768743d2231303030222076696577426f783d2230203020313060408201526818181018981818111f60b91b60608201527f3c7374796c6520747970653d22746578742f63737322206d656469613d2273636069820152653932b2b7111f60d11b6089820152683c215b43444154415b60b81b608f8201527f737667207b6d617267696e3a20303b6261636b67726f756e643a202300000000609882015260008251612be98160b4850160208701612701565b7f3b6865696768743a2031303076683b77696474683a20313030253b7d0000000060b49184019182015261216d612ce8612cd9612c9460d085017f70617468207b66696c6c3a206e6f6e653b7374726f6b652d646173686172726181527f793a203830203730303b616e696d6174696f6e3a20347320656173652d696e20602082015278696e66696e69746520616c7465726e61746520647261773b7d60381b604082015260590190565b7f406b65796672616d65732064726177207b746f207b7374726f6b652d6461736881527261727261793a203132303020313930303b7d7d60681b602082015260330190565b622eae9f60e91b815260030190565b671e17b9ba3cb6329f60c11b815260080190565b60ff8181168382160290811690818114612d1857612d18612a09565b5092915050565b600181600019825b80861115612d5b57828204831115612d4157612d41612a09565b80861615612d4e57928202925b94851c9491800291612d27565b50509250929050565b600082612d735750600161050b565b81612d805750600061050b565b8160018114612d965760028114612da057612dbc565b600191505061050b565b60ff841115612db157612db1612a09565b50506001821b61050b565b5060208310610133831016604e8410600b8410161715612ddf575081810a61050b565b612de98383612d1f565b8060001904821115612dfd57612dfd612a09565b029392505050565b600061201560ff841683612d64565b600082612e2357612e23612a84565b500490565b60ff818116838216019081111561050b5761050b612a09565b6000600160ff1b8201612e5657612e56612a09565b5060000390565b8082018281126000831280158216821582161715612e7d57612e7d612a09565b505092915050565b600086516020612e988285838c01612701565b7f3c70617468206f7061636974793d22302e3122207374726f6b653d2268736c289184019182528751612ed081838501848c01612701565b600b60fa1b9201818101929092528651612ef081602185018a8501612701565b61094b60f21b602193909101928301528551612f128160238501848a01612701565b6725292220643d224d60c01b6003939091018201928301528451612f3c81600b8501888501612701565b909101600b0198975050505050505050565b60008351612f60818460208801612701565b6f111039ba3937b5b296bbb4b23a341e9160811b9083019081528351612f8d816010840160208801612701565b6211179f60e91b60109290910191820152601301949350505050565b600061ffff808316818103612fc057612fc0612a09565b6001019392505050565b60008651612fdc818460208b01612701565b71078e0c2e8d040e6e8e4ded6ca7a44d0e6d8560731b908301908152865161300b816012840160208b01612701565b600b60fa1b60129290910191820152855161302d816013840160208a01612701565b61094b60f21b601392909101918201528451613050816015840160208901612701565b6012818301019150506725292220643d224d60c01b6003820152835161307d81600b840160208801612701565b01600b01979650505050505050565b6000845161309e818460208901612701565b6f111039ba3937b5b296bbb4b23a341e9160811b90830190815284516130cb816010840160208901612701565b6b111037b830b1b4ba3c901e9160a11b6010929091019182015283516130f881601c840160208801612701565b631110179f60e11b601c929091019182015260200195945050505050565b60008251613128818460208701612701565b651e17b9bb339f60d11b920191825250600601919050565b7f5b7b202274726169745f74797065223a2022506574222c202276616c7565223a815261101160f11b602082015260008451613183816022850160208901612701565b7f22207d2c207b202274726169745f74797065223a202250616c65747465222c2060229184019182015269113b30b63ab2911d101160b11b604282015284516131d381604c840160208901612701565b7f22207d2c207b202274726169745f74797065223a202247656e6f6d65222c2022604c9290910191820152683b30b63ab2911d101160b91b606c8201528351613223816075840160208801612701565b6322207d5d60e01b6075929091019182015260790195945050505050565b7f7b226e616d65223a20224f6e436861696e204e696e6a61222c2022646573637281527f697074696f6e223a2022466173742c2064616e6765726f75732c20636f6d706c60208201527f6574656c792067656e657261746564204f6e436861696e2e222c226174747269604082015266313aba32b9911d60c91b6060820152600083516132d5816067850160208801612701565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260679184019182015265185cd94d8d0b60d21b6087820152835161332181608d840160208801612701565b61227d60f01b608d9290910191820152608f01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161337481601d850160208701612701565b91909101601d0192915050565b808202811582820484141761050b5761050b612a09565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133cb90830184612725565b9695505050505050565b6000602082840312156133e757600080fd5b8151612015816126ce565b60006001820161340457613404612a09565b5060010190565b8181038181111561050b5761050b612a09565b60008251613430818460208701612701565b9190910192915050565b60008261344957613449612a84565b600160ff1b82146000198414161561346357613463612a09565b500590565b60008261347757613477612a84565b50079056fe3333322c34323063302c302c3132342d3139312c3139302d3135386333392c32322d38322c33302d3132342c3132303633362c35303963302c302c34362d31352d31372d3235732d32342c31372d32342c31376c2d36352c353338362c37303263302c302c35312d35332c3132392d36356334322c32372c32322d34302d322d32313539392c353333632d33302d33362c32312d34322c33322d32396334352c35312d38372c34322d3130352c3732632d31372c33302d31322c36302d31322c36307337372c33392c36302c3536632d31372c31372d38372d31302d3132302c31632d33322c31312c352c36312d31322c3536632d31372d352d35392d31352d35372d373363342d3130312d392d31312d35352d343063302c302c382d37382c34332d38316c33312c33383338362c37303263302c302c38312d38342c3139352d3634633131342c31392c3130322d34392c38302d3334632d32342c31362c302c32312d3134382c31313630362c3438306c32392d32313163302c302c33322c32362c32372c3638632d342c34312d32392c3134392d32392c3134393433322c33373363302c302c3133322d3133372c3137342d3130306333382c33342d39332c31382d3131342c3130314142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f3438352c34313763302c302c31392c372c35302d337335382d31372c35382d31376c2d362d32336c2d35342c32316c32372d33386c2d32352d386c2d31352c3430313430382c3533354c2d3232322c3838344c313430382c3533357a204d313132352c3634334c2d3333342c3935324c313132352c3634337a204d313038302c3538314c2d34322c3832314c313038302c3538317a204d38302c3332386c2d3338342c38314c38302c3332387a4d313038392c3131344c2d33382c3335344c313038392c3131347a204d313134332c38316c2d313234352c3236334c313134332c38317addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef3332352c34363963302c302d33352d34372c37332d3835633130382d33382c3133362c32362c3133362c32367335312c36312d34302c313237632d39322c36352d3135392d31302d3135392d31303839352d3130364c2d3538312c3230386c39342c3434326c323334332d34393963302c302c34302c3135392c33342c313630732d323338362c3530382d323338362c3530386c35322c3234364c313531302c3634393538392c3638314c3737342c3634304c3538392c3638317a204d3535302c3539394c3831372c3533334c3535302c3539397a4d3638392c3630394c3734392c3539374c3638392c3630397a204d3635352c3532314c3833312c3437374c3635352c3532317a204d3637312c3339336c37392d31364c3637312c3339337a4d3531382c3331336c3235322d35334c3531382c3331337a3332352c34363963302c302c342c31302c372c323963332c31382d342c32392c372c32357331352d33352c33382d33396332332d332c37392c33342c3131332d3234433533352c3338352c3335302c3338332c3332352c3436397aa26469706673582212204072a36a42e125884984809ba46f69d9076e6fbb6d1ef05c01fe0caf378b0ba964736f6c63430008110033

Deployed Bytecode

0x6080604052600436106101775760003560e01c80638d0f8cef116100cc578063c87b56dd1161007a578063c87b56dd146103ea578063c884ef831461040a578063cf00b56314610437578063d3896e5714610457578063d96a094a1461046c578063e985e9c51461047f578063f2fde38b1461049f57600080fd5b80638d0f8cef146103385780638da5cb5b1461035857806391b7f5ed1461036d57806395d89b411461038d578063a10866ef146103a2578063a22cb465146103b7578063b88d4fde146103d757600080fd5b806327ea6f2b1161012957806327ea6f2b1461026b5780633ccfd60b1461028b57806342842e0e146102a057806361c0b6a0146102b35780636352211e146102e357806370a0823114610303578063715018a61461032357600080fd5b806301ffc9a71461017c57806306fdde03146101b1578063081812fc146101d3578063095ea7b31461020b5780631249c58b1461022057806318160ddd1461023557806323b872dd14610258575b600080fd5b34801561018857600080fd5b5061019c6101973660046126e4565b6104bf565b60405190151581526020015b60405180910390f35b3480156101bd57600080fd5b506101c6610511565b6040516101a89190612751565b3480156101df57600080fd5b506101f36101ee366004612764565b6105a3565b6040516001600160a01b0390911681526020016101a8565b61021e610219366004612799565b6105e7565b005b34801561022c57600080fd5b5061021e610687565b34801561024157600080fd5b50600154600054035b6040519081526020016101a8565b61021e6102663660046127c3565b610774565b34801561027757600080fd5b5061021e610286366004612764565b6108fa565b34801561029757600080fd5b5061021e61092e565b61021e6102ae3660046127c3565b610990565b3480156102bf57600080fd5b5061019c6102ce3660046127ff565b600e6020526000908152604090205460ff1681565b3480156102ef57600080fd5b506101f36102fe366004612764565b6109b0565b34801561030f57600080fd5b5061024a61031e3660046127ff565b6109bb565b34801561032f57600080fd5b5061021e610a0a565b34801561034457600080fd5b5061021e610353366004612799565b610a45565b34801561036457600080fd5b506101f3610ab6565b34801561037957600080fd5b5061021e610388366004612764565b610ac5565b34801561039957600080fd5b506101c6610af9565b3480156103ae57600080fd5b5061021e610b08565b3480156103c357600080fd5b5061021e6103d236600461281a565b610b4b565b61021e6103e536600461286c565b610bb7565b3480156103f657600080fd5b506101c6610405366004612764565b610c01565b34801561041657600080fd5b5061024a6104253660046127ff565b600d6020526000908152604090205481565b34801561044357600080fd5b5061021e610452366004612764565b611cc9565b34801561046357600080fd5b5061021e611cfd565b61021e61047a366004612764565b611d49565b34801561048b57600080fd5b5061019c61049a366004612948565b611eba565b3480156104ab57600080fd5b5061021e6104ba3660046127ff565b611ee8565b60006301ffc9a760e01b6001600160e01b0319831614806104f057506380ac58cd60e01b6001600160e01b03198316145b8061050b5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546105209061297b565b80601f016020809104026020016040519081016040528092919081815260200182805461054c9061297b565b80156105995780601f1061056e57610100808354040283529160200191610599565b820191906000526020600020905b81548152906001019060200180831161057c57829003601f168201915b5050505050905090565b60006105ae82611f88565b6105cb576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006105f2826109b0565b9050336001600160a01b0382161461062b5761060e8133611eba565b61062b576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600c54610100900460ff166106b75760405162461bcd60e51b81526004016106ae906129b5565b60405180910390fd5b606f6106c66001546000540390565b106107045760405162461bcd60e51b815260206004820152600e60248201526d10db185a5b48199a5b9a5cda195960921b60448201526064016106ae565b336000908152600e602052604090205460ff161561074d5760405162461bcd60e51b81526004016106ae90602080825260049082015263446f6e6560e01b604082015260600190565b610758336001611faf565b336000908152600e60205260409020805460ff19166001179055565b600061077f82611fc9565b9050836001600160a01b0316816001600160a01b0316146107b25760405162a1148160e81b815260040160405180910390fd5b60008281526006602052604090208054338082146001600160a01b038816909114176107ff576107e28633611eba565b6107ff57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03851661082657604051633a954ecd60e21b815260040160405180910390fd5b801561083157600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b841690036108c3576001840160008181526004602052604081205490036108c15760005481146108c15760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b031660008051602061376c83398151915260405160405180910390a4505050505050565b33610903610ab6565b6001600160a01b0316146109295760405162461bcd60e51b81526004016106ae906129d4565b600a55565b33610937610ab6565b6001600160a01b03161461095d5760405162461bcd60e51b81526004016106ae906129d4565b6040514790339082156108fc029083906000818181858888f1935050505015801561098c573d6000803e3d6000fd5b5050565b6109ab83838360405180602001604052806000815250610bb7565b505050565b600061050b82611fc9565b60006001600160a01b0382166109e4576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b33610a13610ab6565b6001600160a01b031614610a395760405162461bcd60e51b81526004016106ae906129d4565b610a436000612037565b565b33610a4e610ab6565b6001600160a01b031614610a745760405162461bcd60e51b81526004016106ae906129d4565b600a5481610a856001546000540390565b610a8f9190612a1f565b10610aac5760405162461bcd60e51b81526004016106ae90612a32565b61098c8282611faf565b6008546001600160a01b031690565b33610ace610ab6565b6001600160a01b031614610af45760405162461bcd60e51b81526004016106ae906129d4565b600955565b6060600380546105209061297b565b33610b11610ab6565b6001600160a01b031614610b375760405162461bcd60e51b81526004016106ae906129d4565b600c805460ff19811660ff90911615179055565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610bc2848484610774565b6001600160a01b0383163b15610bfb57610bde84848484612089565b610bfb576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060806000610c36610c1285612175565b604051602001610c229190612a59565b604051602081830303815290604052612276565b604080516103208101825260066102e08201818152650c190c4e4c8d60d21b6103008401819052908352835180850185528281526020818101929092528184015283518085018552828152650c0e4c584c1960d21b8183015283850152835180850185528281526532343031303160d01b8183015260608085019190915284518086018652838152650d8d8ccc4d4d60d21b818401526080850152845180860186528381526531373137313760d01b8184015260a0850152845180860186528381526506a68686a66760d31b8184015260c08501528451808601865283815265062cc606460760d31b8184015260e0850152845180860186528381526518991899189960d11b81840152610100850152845180860186528381526532b232b132b160d11b8184015261012085015284518086018652600381526210d85d60ea1b818401526101408501528451808601865283815265149858989a5d60d21b818401526101608501528451808601865260048152632132b0b960e11b8184015261018085015284518086018652600a815269437962657220626c756560b01b818401526101a085015284518086018652600c81526b2732b7b7103bb0b93934b7b960a11b818401526101c0850152845180860186529283526509ac2e8e4d2f60d31b838301526101e08401929092528351808501855260098082526846697265204675727960b81b8284015261020085019190915284518086018652600d8082526c29b0b5bab93090333637bbb2b960991b828501526102208601919091528551808701875282815268135bdbdb9b1a59da1d60ba1b8185015261024086015285518087018752600e81526d43617264626f617264206865726f60901b81850152610260860152855180870187529081526c507572706c65204d656e61636560981b8184015261028085015284518086018652908152684e696768746d61726560b81b818301526102a08401528351808501855260058152644d616e676160d81b818301526102c0840152835191820184527d2c323303b959a29e41a08175b8551b8e38a975d7222487d40ef44b16169482527810192e689f507af3cee8f18999a5305fecf245508b366ddf38908201527827ddfdaf78bc2ae0a8042bee29d9fc66e39605a62a51437bca818401528251610540810190935260a3610460840181815294955060009485948594939285928392839283928392918291906136c96104808401398152602001604051806040016040528060198152602001781898991c169b99261698989a16189c99261898991c169b993d60391b81525081526020016040518060400160405280601981526020017819199a9618989bb6169a9b9a961899192619199a9618989bbd60391b81525081526020016040518060400160405280601b81526020017f313530382d3130324c2d3237332c3237384c313530382d3130327a000000000081525081526020016040518060400160405280601981526020017816999c9a161b9818b6191b9c969a9ca616999c9a161b9818bd60391b81525081526020016040518060400160405280601b81526020017f2d3137372c3638374c313034392c3432374c2d3137372c3638377a000000000081525081526020016040518060400160405280601b81526020017f2d3236392c3637346c313335382d3238364c2d3236392c3637347a000000000081525081526020016040518060800160405280605581526020016137da6055913981526020016040518060600160405280603f81526020016135a8603f91398152602001604051806040016040528060188152602001771a199896199b99b19816181618981c1698999a961b19161960411b8152508152602001604051806040016040528060188152602001773333322c34313963302c302c37372d3133362c35312d333160401b81525081526020016040518060600160405280602f8152602001613619602f913981526020016040518060600160405280602981526020016134d66029913981526020016040518060600160405280602f815260200161347d602f913981526020016040518060600160405280602981526020016134d66029913981526020016040518060400160405280601a815260200179066686058686262c65a62725a6a66586e725a7264586a6e5a64760331b8152508152602001604051806040016040528060198152602001783433362c333731632d382d35362c3132302d37312c35372c3560381b81525081526020016040518060c001604052806095815260200161382f6095913981526020016040518060600160405280603281526020016135e7603291398152602001604051806040016040528060178152602001761b1918161a1c19b619189698991a261b1918161a1c19bd60491b81525081526020016040518060600160405280602a81526020016134ac602a913981526020016040518060e0016040528060a981526020016134ff60a991398152602001604051806040016040528060198152602001783338382c36393863302c302c34332d3131382c36392d31333960381b815250815260200160405180604001604052806016815260200175199c1b161b1a98b61998169c1b26199c1b161b1a98bd60511b8152508152602001604051806040016040528060178152602001760d0c4c8b0d0d4cd8cc0b0c0b0c8d4b0c8c8b0c8c8b4c4d604a1b8152508152602001604051806040016040528060158152602001743334332c34363663302c302c322c32382c31352c3360581b81525081526020016040518060800160405280604181526020016136886041913981526020016040518060800160405280604e815260200161378c604e913981526020016040518060800160405280605b81526020016138c4605b9139815260200160405180604001604052806016815260200175199c9c161a1b18361a9996999aa6199c9c161a1b183d60511b815250815260200160405180604001604052806016815260200175199b1a961a1b983616991a969b26199b1a961a1b983d60511b81525081526020016040518060400160405280601c81526020017f313031322c3636316c2d313132322c3233394c313031322c3636317a0000000081525081526020016040518060400160405280601c81526020017f313937382c3533306c2d323633342c3536324c313937382c3533307a0000000081525081526020016040518060400160405280601a815260200179189a1c1c16991bb616989b989816199b1a26189a1c1c16991bbd60311b81525081526020016040518060400160405280601a815260200179189b1c1b16189c3616991c1818161b181826189b1c1b16189c3d60311b815250815250905060038b6115da9190612a9a565b98506115eb603260038d901c612a9a565b975060098860ff16111561160757611604600989612aae565b97505b868860ff166017811061161c5761161c612ad0565b60200201516040516020016116319190612ae6565b6040516020818303038152906040529b5060098860ff1610156116d057606461165b896004612cfc565b611666906064612e05565b875161167b91906001600160f01b0316612e14565b6116859190612a9a565b94506064611694896004612cfc565b61169f906001612e28565b6116aa906064612e05565b87516116bf91906001600160f01b0316612e14565b6116c99190612a9a565b93506116d9565b60149450600093505b6103e86116e7896002612cfc565b6116f3906103e8612e05565b602088015161170b91906001600160f01b0316612e14565b6117159190612a9a565b92506103e8611725896002612cfc565b611731906103e8612e05565b604088015161174991906001600160f01b0316612e14565b6117539190612a9a565b9150600099505b60078a61ffff161161186f578b6117ba611775600a85612aae565b60ff166001146117905761178b60ff8516612e41565b611795565b8360ff165b8560ff168d61ffff168f901c6117ab9190612a9a565b6117b59190612e5d565b6122a7565b6117c68660ff16612175565b6117d28860ff16612175565b848e61ffff16602381106117e8576117e8612ad0565b6020020151604051602001611801959493929190612e85565b60408051601f198184030181529190529b508b61183a611829606461ffff8e168f901c612a9a565b611835906101d1612a1f565b612175565b60405160200161184b929190612f4e565b6040516020818303038152906040529b50898061186790612fa9565b9a505061175a565b60098860ff161015611908576064611888896004612cfc565b611893906002612e28565b61189e906064612e05565b87516118b391906001600160f01b0316612e14565b6118bd9190612a9a565b945060646118cc896004612cfc565b6118d7906003612e28565b6118e2906064612e05565b87516118f791906001600160f01b0316612e14565b6119019190612a9a565b9350611911565b600a9450600093505b6103e861191f896002612cfc565b61192a906001612e28565b611936906103e8612e05565b602088015161194e91906001600160f01b0316612e14565b6119589190612a9a565b92506103e8611968896002612cfc565b611973906001612e28565b61197f906103e8612e05565b604088015161199791906001600160f01b0316612e14565b6119a19190612a9a565b91506119ae896003612cfc565b6119b9906008612e28565b60ff1699505b6119ca896003612cfc565b6119d590600a612e28565b60ff168a61ffff1611611aa0578b6119f1611775600a85612aae565b6119fd8660ff16612175565b611a098860ff16612175565b848e61ffff1660238110611a1f57611a1f612ad0565b6020020151604051602001611a38959493929190612fca565b60408051601f198184030181529190529b508b611a6b611a60600561ffff8e168f901c612a9a565b611835906005612a1f565b604051602001611a7c929190612f4e565b6040516020818303038152906040529b508980611a9890612fa9565b9a50506119bf565b601199505b60238a61ffff161015611bbe578b611ac1611775600a85612aae565b611acd8660ff16612175565b611ad98860ff16612175565b848e61ffff1660238110611aef57611aef612ad0565b6020020151604051602001611b08959493929190612fca565b60408051601f198184030181529190529b508b611b30611a60600561ffff8e168f901c612a9a565b8b61ffff1660111480611b475750601e8c61ffff16115b611b6a57604051806040016040528060018152602001603160f81b815250611b88565b604051806040016040528060048152602001631817191960e11b8152505b604051602001611b9a9392919061308c565b6040516020818303038152906040529b508980611bb690612fa9565b9a5050611aa5565b8b604051602001611bcf9190613116565b60408051601f198184030181529190529b50606087611bef8b600a612e28565b60ff1660178110611c0257611c02612ad0565b602002015188611c138b600d612e28565b60ff1660178110611c2657611c26612ad0565b6020020151611c3e6305f5e1008f6118359190612a9a565b604051602001611c5093929190613140565b6040516020818303038152906040529050611c9381611c6e8f61241d565b604051602001611c7f929190613241565b60405160208183030381529060405261241d565b9c508c604051602001611ca6919061333c565b60408051601f198184030181529190529f9e505050505050505050505050505050565b33611cd2610ab6565b6001600160a01b031614611cf85760405162461bcd60e51b81526004016106ae906129d4565b600b55565b33611d06610ab6565b6001600160a01b031614611d2c5760405162461bcd60e51b81526004016106ae906129d4565b600c805461ff001981166101009182900460ff1615909102179055565b60008111611d885760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c8185b5bdd5b9d60a21b60448201526064016106ae565b600c5460ff16611daa5760405162461bcd60e51b81526004016106ae906129b5565b600a5481611dbb6001546000540390565b611dc59190612a1f565b10611de25760405162461bcd60e51b81526004016106ae90612a32565b3481600954611df19190613381565b1115611e2f5760405162461bcd60e51b815260206004820152600d60248201526c09ccacac840dadee4ca408aa89609b1b60448201526064016106ae565b600b54336000908152600d6020526040902054611e4d908390612a1f565b1115611e895760405162461bcd60e51b815260206004820152600b60248201526a546f6b656e7320646f6e6560a81b60448201526064016106ae565b611e933382611faf565b336000908152600d602052604081208054839290611eb2908490612a1f565b909155505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b33611ef1610ab6565b6001600160a01b031614611f175760405162461bcd60e51b81526004016106ae906129d4565b6001600160a01b038116611f7c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106ae565b611f8581612037565b50565b600080548210801561050b575050600090815260046020526040902054600160e01b161590565b61098c828260405180602001604052806000815250612587565b60008160005481101561201e5760008181526004602052604081205490600160e01b8216900361201c575b80600003612015575060001901600081815260046020526040902054611ff4565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906120be903390899088908890600401613398565b6020604051808303816000875af19250505080156120f9575060408051601f3d908101601f191682019092526120f6918101906133d5565b60015b612157573d808015612127576040519150601f19603f3d011682016040523d82523d6000602084013e61212c565b606091505b50805160000361214f576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608160000361219c5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156121c657806121b0816133f2565b91506121bf9050600a83612e14565b91506121a0565b60008167ffffffffffffffff8111156121e1576121e1612856565b6040519080825280601f01601f19166020018201604052801561220b576020820181803683370190505b5090505b841561216d5761222060018361340b565b915061222d600a86612a9a565b612238906030612a1f565b60f81b81838151811061224d5761224d612ad0565b60200101906001600160f81b031916908160001a90535061226f600a86612e14565b945061220f565b600081604051602001612289919061341e565b60408051601f19818403018152919052805160209091012092915050565b6060816000036122ce5750506040805180820190915260018152600360fc1b602082015290565b6000808312156122e6576122e183612e41565b6122e8565b825b905060005b811561231357806122fd816133f2565b915061230c9050600a8361343a565b91506122ed565b600084121561232a5780612326816133f2565b9150505b60008167ffffffffffffffff81111561234557612345612856565b6040519080825280601f01601f19166020018201604052801561236f576020820181803683370190505b50905060008512156123b65761238485612e41565b9450602d60f81b8160008151811061239e5761239e612ad0565b60200101906001600160f81b031916908160001a9053505b841561216d576123c760018361340b565b91506123d4600a86613468565b6123df906030612a1f565b60f81b8183815181106123f4576123f4612ad0565b60200101906001600160f81b031916908160001a905350612416600a8661343a565b94506123b6565b80516060906000819003612441575050604080516020810190915260008152919050565b60006003612450836002612a1f565b61245a9190612e14565b612465906004613381565b90506000612474826020612a1f565b67ffffffffffffffff81111561248c5761248c612856565b6040519080825280601f01601f1916602001820160405280156124b6576020820181803683370190505b5090506000604051806060016040528060408152602001613648604091399050600181016020830160005b86811015612542576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016124e1565b50600386066001811461255c576002811461256d57612579565b613d3d60f01b600119830152612579565b603d60f81b6000198301525b505050918152949350505050565b61259183836125f4565b6001600160a01b0383163b156109ab576000548281035b6125bb6000868380600101945086612089565b6125d8576040516368d2bf6b60e11b815260040160405180910390fd5b8181106125a85781600054146125ed57600080fd5b5050505050565b60008054908290036126195760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b1783179055828401908390839060008051602061376c8339815191528180a4600183015b8181146126a4578083600060008051602061376c833981519152600080a460010161267e565b50816000036126c557604051622e076360e81b815260040160405180910390fd5b60005550505050565b6001600160e01b031981168114611f8557600080fd5b6000602082840312156126f657600080fd5b8135612015816126ce565b60005b8381101561271c578181015183820152602001612704565b50506000910152565b6000815180845261273d816020860160208601612701565b601f01601f19169290920160200192915050565b6020815260006120156020830184612725565b60006020828403121561277657600080fd5b5035919050565b80356001600160a01b038116811461279457600080fd5b919050565b600080604083850312156127ac57600080fd5b6127b58361277d565b946020939093013593505050565b6000806000606084860312156127d857600080fd5b6127e18461277d565b92506127ef6020850161277d565b9150604084013590509250925092565b60006020828403121561281157600080fd5b6120158261277d565b6000806040838503121561282d57600080fd5b6128368361277d565b91506020830135801515811461284b57600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561288257600080fd5b61288b8561277d565b93506128996020860161277d565b925060408501359150606085013567ffffffffffffffff808211156128bd57600080fd5b818701915087601f8301126128d157600080fd5b8135818111156128e3576128e3612856565b604051601f8201601f19908116603f0116810190838211818310171561290b5761290b612856565b816040528281528a602084870101111561292457600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561295b57600080fd5b6129648361277d565b91506129726020840161277d565b90509250929050565b600181811c9082168061298f57607f821691505b6020821081036129af57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600590820152642630ba32b960d91b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082018082111561050b5761050b612a09565b6020808252600d908201526c14d85b1948199a5b9a5cda1959609a1b604082015260600190565b6233333360e91b815260008251612a77816003850160208701612701565b9190910160030192915050565b634e487b7160e01b600052601260045260246000fd5b600082612aa957612aa9612a84565b500690565b600060ff831680612ac157612ac1612a84565b8060ff84160691505092915050565b634e487b7160e01b600052603260045260246000fd5b7f3c7376672076657273696f6e3d22312e302220786d6c6e733d22687474703a2f81527f2f7777772e77332e6f72672f323030302f737667222077696474683d2231303060208201527f3022206865696768743d2231303030222076696577426f783d2230203020313060408201526818181018981818111f60b91b60608201527f3c7374796c6520747970653d22746578742f63737322206d656469613d2273636069820152653932b2b7111f60d11b6089820152683c215b43444154415b60b81b608f8201527f737667207b6d617267696e3a20303b6261636b67726f756e643a202300000000609882015260008251612be98160b4850160208701612701565b7f3b6865696768743a2031303076683b77696474683a20313030253b7d0000000060b49184019182015261216d612ce8612cd9612c9460d085017f70617468207b66696c6c3a206e6f6e653b7374726f6b652d646173686172726181527f793a203830203730303b616e696d6174696f6e3a20347320656173652d696e20602082015278696e66696e69746520616c7465726e61746520647261773b7d60381b604082015260590190565b7f406b65796672616d65732064726177207b746f207b7374726f6b652d6461736881527261727261793a203132303020313930303b7d7d60681b602082015260330190565b622eae9f60e91b815260030190565b671e17b9ba3cb6329f60c11b815260080190565b60ff8181168382160290811690818114612d1857612d18612a09565b5092915050565b600181600019825b80861115612d5b57828204831115612d4157612d41612a09565b80861615612d4e57928202925b94851c9491800291612d27565b50509250929050565b600082612d735750600161050b565b81612d805750600061050b565b8160018114612d965760028114612da057612dbc565b600191505061050b565b60ff841115612db157612db1612a09565b50506001821b61050b565b5060208310610133831016604e8410600b8410161715612ddf575081810a61050b565b612de98383612d1f565b8060001904821115612dfd57612dfd612a09565b029392505050565b600061201560ff841683612d64565b600082612e2357612e23612a84565b500490565b60ff818116838216019081111561050b5761050b612a09565b6000600160ff1b8201612e5657612e56612a09565b5060000390565b8082018281126000831280158216821582161715612e7d57612e7d612a09565b505092915050565b600086516020612e988285838c01612701565b7f3c70617468206f7061636974793d22302e3122207374726f6b653d2268736c289184019182528751612ed081838501848c01612701565b600b60fa1b9201818101929092528651612ef081602185018a8501612701565b61094b60f21b602193909101928301528551612f128160238501848a01612701565b6725292220643d224d60c01b6003939091018201928301528451612f3c81600b8501888501612701565b909101600b0198975050505050505050565b60008351612f60818460208801612701565b6f111039ba3937b5b296bbb4b23a341e9160811b9083019081528351612f8d816010840160208801612701565b6211179f60e91b60109290910191820152601301949350505050565b600061ffff808316818103612fc057612fc0612a09565b6001019392505050565b60008651612fdc818460208b01612701565b71078e0c2e8d040e6e8e4ded6ca7a44d0e6d8560731b908301908152865161300b816012840160208b01612701565b600b60fa1b60129290910191820152855161302d816013840160208a01612701565b61094b60f21b601392909101918201528451613050816015840160208901612701565b6012818301019150506725292220643d224d60c01b6003820152835161307d81600b840160208801612701565b01600b01979650505050505050565b6000845161309e818460208901612701565b6f111039ba3937b5b296bbb4b23a341e9160811b90830190815284516130cb816010840160208901612701565b6b111037b830b1b4ba3c901e9160a11b6010929091019182015283516130f881601c840160208801612701565b631110179f60e11b601c929091019182015260200195945050505050565b60008251613128818460208701612701565b651e17b9bb339f60d11b920191825250600601919050565b7f5b7b202274726169745f74797065223a2022506574222c202276616c7565223a815261101160f11b602082015260008451613183816022850160208901612701565b7f22207d2c207b202274726169745f74797065223a202250616c65747465222c2060229184019182015269113b30b63ab2911d101160b11b604282015284516131d381604c840160208901612701565b7f22207d2c207b202274726169745f74797065223a202247656e6f6d65222c2022604c9290910191820152683b30b63ab2911d101160b91b606c8201528351613223816075840160208801612701565b6322207d5d60e01b6075929091019182015260790195945050505050565b7f7b226e616d65223a20224f6e436861696e204e696e6a61222c2022646573637281527f697074696f6e223a2022466173742c2064616e6765726f75732c20636f6d706c60208201527f6574656c792067656e657261746564204f6e436861696e2e222c226174747269604082015266313aba32b9911d60c91b6060820152600083516132d5816067850160208801612701565b7f2c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6260679184019182015265185cd94d8d0b60d21b6087820152835161332181608d840160208801612701565b61227d60f01b608d9290910191820152608f01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161337481601d850160208701612701565b91909101601d0192915050565b808202811582820484141761050b5761050b612a09565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906133cb90830184612725565b9695505050505050565b6000602082840312156133e757600080fd5b8151612015816126ce565b60006001820161340457613404612a09565b5060010190565b8181038181111561050b5761050b612a09565b60008251613430818460208701612701565b9190910192915050565b60008261344957613449612a84565b600160ff1b82146000198414161561346357613463612a09565b500590565b60008261347757613477612a84565b50079056fe3333322c34323063302c302c3132342d3139312c3139302d3135386333392c32322d38322c33302d3132342c3132303633362c35303963302c302c34362d31352d31372d3235732d32342c31372d32342c31376c2d36352c353338362c37303263302c302c35312d35332c3132392d36356334322c32372c32322d34302d322d32313539392c353333632d33302d33362c32312d34322c33322d32396334352c35312d38372c34322d3130352c3732632d31372c33302d31322c36302d31322c36307337372c33392c36302c3536632d31372c31372d38372d31302d3132302c31632d33322c31312c352c36312d31322c3536632d31372d352d35392d31352d35372d373363342d3130312d392d31312d35352d343063302c302c382d37382c34332d38316c33312c33383338362c37303263302c302c38312d38342c3139352d3634633131342c31392c3130322d34392c38302d3334632d32342c31362c302c32312d3134382c31313630362c3438306c32392d32313163302c302c33322c32362c32372c3638632d342c34312d32392c3134392d32392c3134393433322c33373363302c302c3133322d3133372c3137342d3130306333382c33342d39332c31382d3131342c3130314142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f3438352c34313763302c302c31392c372c35302d337335382d31372c35382d31376c2d362d32336c2d35342c32316c32372d33386c2d32352d386c2d31352c3430313430382c3533354c2d3232322c3838344c313430382c3533357a204d313132352c3634334c2d3333342c3935324c313132352c3634337a204d313038302c3538314c2d34322c3832314c313038302c3538317a204d38302c3332386c2d3338342c38314c38302c3332387a4d313038392c3131344c2d33382c3335344c313038392c3131347a204d313134332c38316c2d313234352c3236334c313134332c38317addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef3332352c34363963302c302d33352d34372c37332d3835633130382d33382c3133362c32362c3133362c32367335312c36312d34302c313237632d39322c36352d3135392d31302d3135392d31303839352d3130364c2d3538312c3230386c39342c3434326c323334332d34393963302c302c34302c3135392c33342c313630732d323338362c3530382d323338362c3530386c35322c3234364c313531302c3634393538392c3638314c3737342c3634304c3538392c3638317a204d3535302c3539394c3831372c3533334c3535302c3539397a4d3638392c3630394c3734392c3539374c3638392c3630397a204d3635352c3532314c3833312c3437374c3635352c3532317a204d3637312c3339336c37392d31364c3637312c3339337a4d3531382c3331336c3235322d35334c3531382c3331337a3332352c34363963302c302c342c31302c372c323963332c31382d342c32392c372c32357331352d33352c33382d33396332332d332c37392c33342c3131332d3234433533352c3338352c3335302c3338332c3332352c3436397aa26469706673582212204072a36a42e125884984809ba46f69d9076e6fbb6d1ef05c01fe0caf378b0ba964736f6c63430008110033

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.