ETH Price: $3,382.00 (+3.80%)

Token

BoovsBODY (KABB)
 

Overview

Max Total Supply

50 KABB

Holders

31

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
yadgen.eth
Balance
1 KABB
0x8118547d2f70f36e86c92aeba3c3fac4518d313c
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:
KassionaBody

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
No with 200 runs

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

//   _  __             _                    
//  | |/ /__ _ ___ ___(_) ___  _ __   __ _  
//  | ' // _` / __/ __| |/ _ \| '_ \ / _` | 
//  | . \ (_| \__ \__ \ | (_) | | | | (_| | 
//  |_|\_\__,_|___/___/_|\___/|_| |_|\__,_| 



pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";

contract KassionaBody is ERC721Enumerable,ERC721Burnable, Ownable {

    enum Rarity { Legendary,Epic,Rare,Common }
    enum Property { Ubinooa,Kiwanna,Busterra }

    uint256 public constant maxTokenSupply = 7779;
    uint256 public constant legedarySupplyPerProperty = 3;
    uint256 public constant epicSupplyPerProperty = 130;
    uint256 public constant rareSupplyPerProperty = 700;
    uint256 public constant commonSupplyPerProperty = 1760;

    address public admin; 

    string private _baseURIextended;

    // variable for weighted fisher–yates shuffle algorithm
    mapping(Rarity => mapping(uint => uint)) private _availableTokensOfRarity;
    mapping(Rarity =>uint) private _remainSupplyOfRarity;
    mapping(Rarity =>uint[]) private _randomWeight;
    mapping(Rarity =>uint[]) private _randomWeightSum;
    mapping(Rarity =>uint) private _randomWeightTotal;

    constructor() ERC721("BoovsBODY", "KABB") {
        _remainSupplyOfRarity[Rarity.Legendary] = 9;
        _remainSupplyOfRarity[Rarity.Epic] = 390;
        _remainSupplyOfRarity[Rarity.Rare] = 2100;
        _remainSupplyOfRarity[Rarity.Common] = 5280;

        _randomWeight[Rarity.Legendary] = [20,10,5,1];
        _randomWeight[Rarity.Epic] = [15,8,4,1];
        _randomWeight[Rarity.Rare] = [8,4,2,1];
        _randomWeight[Rarity.Common] = [1,1,1,1];

        _randomWeightSum[Rarity.Legendary] = [_randomWeight[Rarity.Legendary][0]*legedarySupplyPerProperty*3,_randomWeight[Rarity.Legendary][1]*epicSupplyPerProperty*3,_randomWeight[Rarity.Legendary][2]*rareSupplyPerProperty*3,_randomWeight[Rarity.Legendary][3]*commonSupplyPerProperty*3];
        _randomWeightSum[Rarity.Epic] = [_randomWeight[Rarity.Epic][0]*legedarySupplyPerProperty*3,_randomWeight[Rarity.Epic][1]*epicSupplyPerProperty*3,_randomWeight[Rarity.Epic][2]*rareSupplyPerProperty*3,_randomWeight[Rarity.Epic][3]*commonSupplyPerProperty*3];
        _randomWeightSum[Rarity.Rare] = [_randomWeight[Rarity.Rare][0]*legedarySupplyPerProperty*3,_randomWeight[Rarity.Rare][1]*epicSupplyPerProperty*3,_randomWeight[Rarity.Rare][2]*rareSupplyPerProperty*3,_randomWeight[Rarity.Rare][3]*commonSupplyPerProperty*3];
        _randomWeightSum[Rarity.Common] = [_randomWeight[Rarity.Common][0]*legedarySupplyPerProperty*3,_randomWeight[Rarity.Common][1]*epicSupplyPerProperty*3,_randomWeight[Rarity.Common][2]*rareSupplyPerProperty*3,_randomWeight[Rarity.Common][3]*commonSupplyPerProperty*3];
        
        _randomWeightTotal[Rarity.Legendary] = _randomWeightSum[Rarity.Legendary][0]+_randomWeightSum[Rarity.Legendary][1]+_randomWeightSum[Rarity.Legendary][2]+_randomWeightSum[Rarity.Legendary][3];
        _randomWeightTotal[Rarity.Epic] = _randomWeightSum[Rarity.Epic][0]+_randomWeightSum[Rarity.Epic][1]+_randomWeightSum[Rarity.Epic][2]+_randomWeightSum[Rarity.Epic][3];
        _randomWeightTotal[Rarity.Rare] = _randomWeightSum[Rarity.Rare][0]+_randomWeightSum[Rarity.Rare][1]+_randomWeightSum[Rarity.Rare][2]+_randomWeightSum[Rarity.Rare][3];
        _randomWeightTotal[Rarity.Common] = _randomWeightSum[Rarity.Common][0]+_randomWeightSum[Rarity.Common][1]+_randomWeightSum[Rarity.Common][2]+_randomWeightSum[Rarity.Common][3];
    }

    function ownerMint(uint256 tokenId) external onlyOwner {
        _safeMint(_msgSender(),tokenId);

        Rarity rarity = _tokenRarity(tokenId);
        _remainSupplyOfRarity[rarity] -= 1;
        uint256 lastValInArray = _availableTokensOfRarity[rarity][_remainSupplyOfRarity[rarity]];
        for(uint i=0;i<4;i++) {
            _randomWeightSum[Rarity(i)][uint(rarity)] -= _randomWeight[Rarity(i)][uint(rarity)];
            _randomWeightTotal[Rarity(i)] -= _randomWeight[Rarity(i)][uint(rarity)];
        }
        if (lastValInArray == 0) {
                _availableTokensOfRarity[rarity][_getRarityIndexByTokenId(tokenId)] = _remainSupplyOfRarity[rarity];
            } else {
                _availableTokensOfRarity[rarity][_getRarityIndexByTokenId(tokenId)] = lastValInArray;
            }
    }

    function mint(address addr,uint8 rarity) external {
        require(_msgSender() == admin || _msgSender() == owner(),"only admin or owner can mint");
        require(totalSupply() + 1 <= maxTokenSupply, "Cannot exceed total supply");
        _safeMint(addr,_getRandomTokenToMint(Rarity(rarity)));
    }

    function setAdmin(address admin_) external onlyOwner{
        admin = admin_;
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    function setBaseURI(string memory baseURI_) external onlyOwner() {
        _baseURIextended = baseURI_;
    }

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

    function isApprovedForAll(address account, address operator) public override(ERC721,IERC721) view returns (bool) {
        if (operator == admin) {
            return true;
        }

        return super.isApprovedForAll(account, operator);
    }

    function tokenProperty(uint256 tokenId) external pure returns (uint8){
        if(tokenId>=1 && tokenId<=2593) {
            return uint8(Property.Ubinooa);
        }else if(tokenId<=5186){
            return uint8(Property.Kiwanna);
        }else{
            return uint8(Property.Busterra);
        }
    }

    function tokenRarity(uint256 tokenId) external pure returns (uint8){
        uint256 propertyIndex = (tokenId-1)%2593 + 1;
        if(propertyIndex>=1 && propertyIndex<=3) {
            return uint8(Rarity.Legendary);
        }else if(propertyIndex<=133){
            return uint8(Rarity.Epic);
        }else if(propertyIndex<=833){
            return uint8(Rarity.Rare);
        }else{
            return uint8(Rarity.Common);
        }
    }

    function _tokenRarity(uint256 tokenId) internal  pure returns (Rarity){
        uint256 propertyIndex = (tokenId-1)%2593 + 1;
        if(propertyIndex>=1 && propertyIndex<=3) {
            return Rarity.Legendary;
        }else if(propertyIndex<=133){
            return Rarity.Epic;
        }else if(propertyIndex<=833){
            return Rarity.Rare;
        }else{
            return Rarity.Common;
        }
    }

    function tokenURIsOfOwner(address owner) public view  returns (string[] memory) {
        uint balance = balanceOf(owner); 
        string[] memory ret = new string[](balance);
        for(uint i=0;i<balance;i++) {
            ret[i] = tokenURI(tokenOfOwnerByIndex(owner, i));
        }
        return ret;
    }

    function tokenIdsOfOwner(address owner) public view  returns (uint256[] memory) {
        uint balance = balanceOf(owner); 
        uint256[] memory ret = new uint256[](balance);
        for(uint i=0;i<balance;i++) {
            ret[i] = tokenOfOwnerByIndex(owner, i);
        }
        return ret;
    }

    function _random(uint256 nonce) private view returns (uint256){
        return uint256(keccak256(abi.encodePacked(block.timestamp,block.difficulty,nonce)));
    }


    // weighted fisher–yates shuffle algorithm
    function _getRandomTokenToMint(Rarity rarity) private returns (uint256) {
        uint256 rd = _random(_randomWeightTotal[rarity])%_randomWeightTotal[rarity];
        Rarity randomRarity;

        for(uint i=0;i<4;i++) {
            if(rd<_randomWeightSum[rarity][i]) {
                randomRarity = Rarity(i);
                break;
            }else{
                rd -= _randomWeightSum[rarity][i];
            }
        }

        uint256 indexToUse = _random(_remainSupplyOfRarity[randomRarity])%_remainSupplyOfRarity[randomRarity];

        _remainSupplyOfRarity[randomRarity] -= 1;
        for(uint i=0;i<4;i++) {
            _randomWeightSum[Rarity(i)][uint(randomRarity)] -= _randomWeight[Rarity(i)][uint(randomRarity)];
            _randomWeightTotal[Rarity(i)] -= _randomWeight[Rarity(i)][uint(randomRarity)];
        }

        uint256 valAtIndex = _availableTokensOfRarity[randomRarity][indexToUse];
        if(valAtIndex==0) {
            valAtIndex = indexToUse;
        }

        uint256 lastIndex = _remainSupplyOfRarity[randomRarity];

        if(indexToUse!=lastIndex) {
            uint256 lastValInArray = _availableTokensOfRarity[randomRarity][lastIndex];
            if (lastValInArray == 0) {
                _availableTokensOfRarity[randomRarity][indexToUse] = lastIndex;
            } else {
                _availableTokensOfRarity[randomRarity][indexToUse] = lastValInArray;
            }
        }

        return _getTokenIdByRarityIndex(randomRarity,valAtIndex);
    }

    function _getTokenIdByRarityIndex(Rarity rarity,uint256 index) internal pure returns (uint256) {
        if(rarity == Rarity.Legendary) {
            return index%3+(index/3)*2593+1;
        }else if(rarity == Rarity.Epic) {
            return index%130+3+(index/130)*2593+1;
        }else if(rarity == Rarity.Rare) {
            return index%700+133+(index/700)*2593+1;
        }else{
            return index%1760+833+(index/1760)*2593+1;
        }
    }

    function _getRarityIndexByTokenId(uint256 tokenId) internal pure returns (uint256) {
        Rarity rarity = _tokenRarity(tokenId);
        if(rarity == Rarity.Legendary) {
            return (tokenId-1)/2593*3+(tokenId-1)%2593;
        }else if(rarity == Rarity.Epic) {
            return (tokenId-1)/2593*130+(tokenId-1)%2593-3;
        }else if(rarity == Rarity.Rare) {
            return (tokenId-1)/2593*700+(tokenId-1)%2593-133;
        }else{
            return (tokenId-1)/2593*1760+(tokenId-1)%2593-833;
        }
    }
}

File 2 of 14 : ERC721Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol)

pragma solidity ^0.8.0;

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

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
        _burn(tokenId);
    }
}

File 3 of 14 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

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

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

File 4 of 14 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

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() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        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 {
        _transferOwnership(address(0));
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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

pragma solidity ^0.8.0;

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

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

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

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

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

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

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

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

        _afterTokenTransfer(address(0), to, tokenId);
    }

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

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

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

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

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

        _afterTokenTransfer(owner, address(0), tokenId);
    }

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

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

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

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

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

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

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 6 of 14 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 9 of 14 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

File 10 of 14 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 11 of 14 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

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

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

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

File 12 of 14 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 13 of 14 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

    /**
     * @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 have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

pragma solidity ^0.8.0;

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":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":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commonSupplyPerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epicSupplyPerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legedarySupplyPerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokenSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint8","name":"rarity","type":"uint8"}],"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":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rareSupplyPerProperty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin_","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokenIdsOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenProperty","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenRarity","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokenURIsOfOwner","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280600981526020017f426f6f7673424f445900000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f4b414242000000000000000000000000000000000000000000000000000000008152508160009080519060200190620000969291906200158d565b508060019080519060200190620000af9291906200158d565b505050620000d2620000c6620014bf60201b60201c565b620014c760201b60201c565b6009600e6000806003811115620000ee57620000ed620016e6565b5b6003811115620001035762000102620016e6565b5b815260200190815260200160002081905550610186600e600060016003811115620001335762000132620016e6565b5b6003811115620001485762000147620016e6565b5b815260200190815260200160002081905550610834600e600060026003811115620001785762000177620016e6565b5b60038111156200018d576200018c620016e6565b5b8152602001908152602001600020819055506114a0600e6000600380811115620001bc57620001bb620016e6565b5b6003811115620001d157620001d0620016e6565b5b8152602001908152602001600020819055506040518060800160405280601460ff168152602001600a60ff168152602001600560ff168152602001600160ff16815250600f60008060038111156200022e576200022d620016e6565b5b6003811115620002435762000242620016e6565b5b8152602001908152602001600020906004620002619291906200161e565b506040518060800160405280600f60ff168152602001600860ff168152602001600460ff168152602001600160ff16815250600f600060016003811115620002ae57620002ad620016e6565b5b6003811115620002c357620002c2620016e6565b5b8152602001908152602001600020906004620002e19291906200161e565b506040518060800160405280600860ff168152602001600460ff168152602001600260ff168152602001600160ff16815250600f6000600260038111156200032e576200032d620016e6565b5b6003811115620003435762000342620016e6565b5b8152602001908152602001600020906004620003619291906200161e565b506040518060800160405280600160ff168152602001600160ff168152602001600160ff168152602001600160ff16815250600f6000600380811115620003ad57620003ac620016e6565b5b6003811115620003c257620003c1620016e6565b5b8152602001908152602001600020906004620003e09291906200161e565b506040518060800160405280600380600f6000806003811115620004095762000408620016e6565b5b60038111156200041e576200041d620016e6565b5b815260200190815260200160002060008154811062000442576200044162001715565b5b90600052602060002001546200045991906200177d565b6200046591906200177d565b815260200160036082600f6000806003811115620004885762000487620016e6565b5b60038111156200049d576200049c620016e6565b5b8152602001908152602001600020600181548110620004c157620004c062001715565b5b9060005260206000200154620004d891906200177d565b620004e491906200177d565b815260200160036102bc600f6000806003811115620005085762000507620016e6565b5b60038111156200051d576200051c620016e6565b5b815260200190815260200160002060028154811062000541576200054062001715565b5b90600052602060002001546200055891906200177d565b6200056491906200177d565b815260200160036106e0600f6000806003811115620005885762000587620016e6565b5b60038111156200059d576200059c620016e6565b5b8152602001908152602001600020600381548110620005c157620005c062001715565b5b9060005260206000200154620005d891906200177d565b620005e491906200177d565b81525060106000806003811115620006015762000600620016e6565b5b6003811115620006165762000615620016e6565b5b81526020019081526020016000209060046200063492919062001675565b506040518060800160405280600380600f6000600160038111156200065e576200065d620016e6565b5b6003811115620006735762000672620016e6565b5b815260200190815260200160002060008154811062000697576200069662001715565b5b9060005260206000200154620006ae91906200177d565b620006ba91906200177d565b815260200160036082600f600060016003811115620006de57620006dd620016e6565b5b6003811115620006f357620006f2620016e6565b5b815260200190815260200160002060018154811062000717576200071662001715565b5b90600052602060002001546200072e91906200177d565b6200073a91906200177d565b815260200160036102bc600f6000600160038111156200075f576200075e620016e6565b5b6003811115620007745762000773620016e6565b5b815260200190815260200160002060028154811062000798576200079762001715565b5b9060005260206000200154620007af91906200177d565b620007bb91906200177d565b815260200160036106e0600f600060016003811115620007e057620007df620016e6565b5b6003811115620007f557620007f4620016e6565b5b815260200190815260200160002060038154811062000819576200081862001715565b5b90600052602060002001546200083091906200177d565b6200083c91906200177d565b81525060106000600160038111156200085a5762000859620016e6565b5b60038111156200086f576200086e620016e6565b5b81526020019081526020016000209060046200088d92919062001675565b506040518060800160405280600380600f600060026003811115620008b757620008b6620016e6565b5b6003811115620008cc57620008cb620016e6565b5b8152602001908152602001600020600081548110620008f057620008ef62001715565b5b90600052602060002001546200090791906200177d565b6200091391906200177d565b815260200160036082600f600060026003811115620009375762000936620016e6565b5b60038111156200094c576200094b620016e6565b5b815260200190815260200160002060018154811062000970576200096f62001715565b5b90600052602060002001546200098791906200177d565b6200099391906200177d565b815260200160036102bc600f600060026003811115620009b857620009b7620016e6565b5b6003811115620009cd57620009cc620016e6565b5b8152602001908152602001600020600281548110620009f157620009f062001715565b5b906000526020600020015462000a0891906200177d565b62000a1491906200177d565b815260200160036106e0600f60006002600381111562000a395762000a38620016e6565b5b600381111562000a4e5762000a4d620016e6565b5b815260200190815260200160002060038154811062000a725762000a7162001715565b5b906000526020600020015462000a8991906200177d565b62000a9591906200177d565b815250601060006002600381111562000ab35762000ab2620016e6565b5b600381111562000ac85762000ac7620016e6565b5b815260200190815260200160002090600462000ae692919062001675565b506040518060800160405280600380600f600060038081111562000b0f5762000b0e620016e6565b5b600381111562000b245762000b23620016e6565b5b815260200190815260200160002060008154811062000b485762000b4762001715565b5b906000526020600020015462000b5f91906200177d565b62000b6b91906200177d565b815260200160036082600f600060038081111562000b8e5762000b8d620016e6565b5b600381111562000ba35762000ba2620016e6565b5b815260200190815260200160002060018154811062000bc75762000bc662001715565b5b906000526020600020015462000bde91906200177d565b62000bea91906200177d565b815260200160036102bc600f600060038081111562000c0e5762000c0d620016e6565b5b600381111562000c235762000c22620016e6565b5b815260200190815260200160002060028154811062000c475762000c4662001715565b5b906000526020600020015462000c5e91906200177d565b62000c6a91906200177d565b815260200160036106e0600f600060038081111562000c8e5762000c8d620016e6565b5b600381111562000ca35762000ca2620016e6565b5b815260200190815260200160002060038154811062000cc75762000cc662001715565b5b906000526020600020015462000cde91906200177d565b62000cea91906200177d565b8152506010600060038081111562000d075762000d06620016e6565b5b600381111562000d1c5762000d1b620016e6565b5b815260200190815260200160002090600462000d3a92919062001675565b506010600080600381111562000d555762000d54620016e6565b5b600381111562000d6a5762000d69620016e6565b5b815260200190815260200160002060038154811062000d8e5762000d8d62001715565b5b90600052602060002001546010600080600381111562000db35762000db2620016e6565b5b600381111562000dc85762000dc7620016e6565b5b815260200190815260200160002060028154811062000dec5762000deb62001715565b5b90600052602060002001546010600080600381111562000e115762000e10620016e6565b5b600381111562000e265762000e25620016e6565b5b815260200190815260200160002060018154811062000e4a5762000e4962001715565b5b90600052602060002001546010600080600381111562000e6f5762000e6e620016e6565b5b600381111562000e845762000e83620016e6565b5b815260200190815260200160002060008154811062000ea85762000ea762001715565b5b906000526020600020015462000ebf9190620017de565b62000ecb9190620017de565b62000ed79190620017de565b6011600080600381111562000ef15762000ef0620016e6565b5b600381111562000f065762000f05620016e6565b5b815260200190815260200160002081905550601060006001600381111562000f335762000f32620016e6565b5b600381111562000f485762000f47620016e6565b5b815260200190815260200160002060038154811062000f6c5762000f6b62001715565b5b9060005260206000200154601060006001600381111562000f925762000f91620016e6565b5b600381111562000fa75762000fa6620016e6565b5b815260200190815260200160002060028154811062000fcb5762000fca62001715565b5b9060005260206000200154601060006001600381111562000ff15762000ff0620016e6565b5b6003811115620010065762001005620016e6565b5b81526020019081526020016000206001815481106200102a576200102962001715565b5b9060005260206000200154601060006001600381111562001050576200104f620016e6565b5b6003811115620010655762001064620016e6565b5b815260200190815260200160002060008154811062001089576200108862001715565b5b9060005260206000200154620010a09190620017de565b620010ac9190620017de565b620010b89190620017de565b6011600060016003811115620010d357620010d2620016e6565b5b6003811115620010e857620010e7620016e6565b5b8152602001908152602001600020819055506010600060026003811115620011155762001114620016e6565b5b60038111156200112a5762001129620016e6565b5b81526020019081526020016000206003815481106200114e576200114d62001715565b5b90600052602060002001546010600060026003811115620011745762001173620016e6565b5b6003811115620011895762001188620016e6565b5b8152602001908152602001600020600281548110620011ad57620011ac62001715565b5b90600052602060002001546010600060026003811115620011d357620011d2620016e6565b5b6003811115620011e857620011e7620016e6565b5b81526020019081526020016000206001815481106200120c576200120b62001715565b5b90600052602060002001546010600060026003811115620012325762001231620016e6565b5b6003811115620012475762001246620016e6565b5b81526020019081526020016000206000815481106200126b576200126a62001715565b5b9060005260206000200154620012829190620017de565b6200128e9190620017de565b6200129a9190620017de565b6011600060026003811115620012b557620012b4620016e6565b5b6003811115620012ca57620012c9620016e6565b5b81526020019081526020016000208190555060106000600380811115620012f657620012f5620016e6565b5b60038111156200130b576200130a620016e6565b5b81526020019081526020016000206003815481106200132f576200132e62001715565b5b906000526020600020015460106000600380811115620013545762001353620016e6565b5b6003811115620013695762001368620016e6565b5b81526020019081526020016000206002815481106200138d576200138c62001715565b5b906000526020600020015460106000600380811115620013b257620013b1620016e6565b5b6003811115620013c757620013c6620016e6565b5b8152602001908152602001600020600181548110620013eb57620013ea62001715565b5b90600052602060002001546010600060038081111562001410576200140f620016e6565b5b6003811115620014255762001424620016e6565b5b815260200190815260200160002060008154811062001449576200144862001715565b5b9060005260206000200154620014609190620017de565b6200146c9190620017de565b620014789190620017de565b60116000600380811115620014925762001491620016e6565b5b6003811115620014a757620014a6620016e6565b5b8152602001908152602001600020819055506200189f565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8280546200159b906200186a565b90600052602060002090601f016020900481019282620015bf57600085556200160b565b82601f10620015da57805160ff19168380011785556200160b565b828001600101855582156200160b579182015b828111156200160a578251825591602001919060010190620015ed565b5b5090506200161a9190620016c7565b5090565b82805482825590600052602060002090810192821562001662579160200282015b8281111562001661578251829060ff169055916020019190600101906200163f565b5b509050620016719190620016c7565b5090565b828054828255906000526020600020908101928215620016b4579160200282015b82811115620016b357825182559160200191906001019062001696565b5b509050620016c39190620016c7565b5090565b5b80821115620016e2576000816000905550600101620016c8565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200178a8262001744565b9150620017978362001744565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620017d357620017d26200174e565b5b828202905092915050565b6000620017eb8262001744565b9150620017f88362001744565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111562001830576200182f6200174e565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200188357607f821691505b6020821081036200189957620018986200183b565b5b50919050565b614e3980620018af6000396000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c8063715018a61161011a578063c0faf790116100ad578063e985e9c51161007c578063e985e9c514610611578063ec2737e314610641578063f19e75d41461065f578063f2fde38b1461067b578063f851a4401461069757610206565b8063c0faf79014610587578063c30a9bb8146105a5578063c59e5f8a146105c3578063c87b56dd146105e157610206565b8063a0e939e9116100e9578063a0e939e9146104ef578063a22cb4651461051f578063afb0a3691461053b578063b88d4fde1461056b57610206565b8063715018a6146104795780638da5cb5b1461048357806395d89b41146104a15780639e59e598146104bf57610206565b806342842e0e1161019d57806355f804b31161016c57806355f804b3146103c55780636352211e146103e1578063691562a014610411578063704b6c021461042d57806370a082311461044957610206565b806342842e0e1461033f57806342966c681461035b5780634f6ccce71461037757806350f7c204146103a757610206565b8063095ea7b3116101d9578063095ea7b3146102b957806318160ddd146102d557806323b872dd146102f35780632f745c591461030f57610206565b806301ffc9a71461020b57806306fdde031461023b578063081812fc1461025957806308c243aa14610289575b600080fd5b610225600480360381019061022091906137ef565b6106b5565b6040516102329190613837565b60405180910390f35b6102436106c7565b60405161025091906138eb565b60405180910390f35b610273600480360381019061026e9190613943565b610759565b60405161028091906139b1565b60405180910390f35b6102a3600480360381019061029e9190613943565b61079f565b6040516102b091906139e8565b60405180910390f35b6102d360048036038101906102ce9190613a2f565b610813565b005b6102dd61092a565b6040516102ea9190613a7e565b60405180910390f35b61030d60048036038101906103089190613a99565b610937565b005b61032960048036038101906103249190613a2f565b610997565b6040516103369190613a7e565b60405180910390f35b61035960048036038101906103549190613a99565b610a3c565b005b61037560048036038101906103709190613943565b610a5c565b005b610391600480360381019061038c9190613943565b610ab8565b60405161039e9190613a7e565b60405180910390f35b6103af610b29565b6040516103bc9190613a7e565b60405180910390f35b6103df60048036038101906103da9190613c21565b610b2f565b005b6103fb60048036038101906103f69190613943565b610b51565b60405161040891906139b1565b60405180910390f35b61042b60048036038101906104269190613c96565b610c02565b005b61044760048036038101906104429190613cd6565b610d60565b005b610463600480360381019061045e9190613cd6565b610dac565b6040516104709190613a7e565b60405180910390f35b610481610e63565b005b61048b610e77565b60405161049891906139b1565b60405180910390f35b6104a9610ea1565b6040516104b691906138eb565b60405180910390f35b6104d960048036038101906104d49190613cd6565b610f33565b6040516104e69190613dc1565b60405180910390f35b61050960048036038101906105049190613cd6565b610fe1565b6040516105169190613eef565b60405180910390f35b61053960048036038101906105349190613f3d565b61109b565b005b61055560048036038101906105509190613943565b6110b1565b60405161056291906139e8565b60405180910390f35b6105856004803603810190610580919061401e565b611174565b005b61058f6111d6565b60405161059c9190613a7e565b60405180910390f35b6105ad6111db565b6040516105ba9190613a7e565b60405180910390f35b6105cb6111e0565b6040516105d89190613a7e565b60405180910390f35b6105fb60048036038101906105f69190613943565b6111e6565b60405161060891906138eb565b60405180910390f35b61062b600480360381019061062691906140a1565b61124e565b6040516106389190613837565b60405180910390f35b6106496112c1565b6040516106569190613a7e565b60405180910390f35b61067960048036038101906106749190613943565b6112c7565b005b61069560048036038101906106909190613cd6565b6116b0565b005b61069f611733565b6040516106ac91906139b1565b60405180910390f35b60006106c082611759565b9050919050565b6060600080546106d690614110565b80601f016020809104026020016040519081016040528092919081815260200182805461070290614110565b801561074f5780601f106107245761010080835404028352916020019161074f565b820191906000526020600020905b81548152906001019060200180831161073257829003601f168201915b5050505050905090565b6000610764826117d3565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600182101580156107b45750610a218211155b156107d457600060028111156107cd576107cc614141565b5b905061080e565b61144282116107f857600160028111156107f1576107f0614141565b5b905061080e565b60028081111561080b5761080a614141565b5b90505b919050565b600061081e82610b51565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361088e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610885906141e2565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166108ad61181e565b73ffffffffffffffffffffffffffffffffffffffff1614806108dc57506108db816108d661181e565b61124e565b5b61091b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091290614274565b60405180910390fd5b6109258383611826565b505050565b6000600880549050905090565b61094861094261181e565b826118df565b610987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097e90614306565b60405180910390fd5b610992838383611974565b505050565b60006109a283610dac565b82106109e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da90614398565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610a5783838360405180602001604052806000815250611174565b505050565b610a6d610a6761181e565b826118df565b610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390614306565b60405180910390fd5b610ab581611bda565b50565b6000610ac261092a565b8210610b03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afa9061442a565b60405180910390fd5b60088281548110610b1757610b1661444a565b5b90600052602060002001549050919050565b611e6381565b610b37611cf7565b80600c9080519060200190610b4d9291906136e0565b5050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf0906144c5565b60405180910390fd5b80915050919050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610c4361181e565b73ffffffffffffffffffffffffffffffffffffffff161480610c9e5750610c68610e77565b73ffffffffffffffffffffffffffffffffffffffff16610c8661181e565b73ffffffffffffffffffffffffffffffffffffffff16145b610cdd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd490614531565b60405180910390fd5b611e636001610cea61092a565b610cf49190614580565b1115610d35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2c90614622565b60405180910390fd5b610d5c82610d578360ff166003811115610d5257610d51614141565b5b611d75565b612371565b5050565b610d68611cf7565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e13906146b4565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610e6b611cf7565b610e75600061238f565b565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054610eb090614110565b80601f0160208091040260200160405190810160405280929190818152602001828054610edc90614110565b8015610f295780601f10610efe57610100808354040283529160200191610f29565b820191906000526020600020905b815481529060010190602001808311610f0c57829003601f168201915b5050505050905090565b60606000610f4083610dac565b905060008167ffffffffffffffff811115610f5e57610f5d613af6565b5b604051908082528060200260200182016040528015610f8c5781602001602082028036833780820191505090505b50905060005b82811015610fd657610fa48582610997565b828281518110610fb757610fb661444a565b5b6020026020010181815250508080610fce906146d4565b915050610f92565b508092505050919050565b60606000610fee83610dac565b905060008167ffffffffffffffff81111561100c5761100b613af6565b5b60405190808252806020026020018201604052801561103f57816020015b606081526020019060019003908161102a5790505b50905060005b828110156110905761105f61105a8683610997565b6111e6565b8282815181106110725761107161444a565b5b60200260200101819052508080611088906146d4565b915050611045565b508092505050919050565b6110ad6110a661181e565b8383612455565b5050565b6000806001610a216001856110c6919061471c565b6110d0919061477f565b6110da9190614580565b9050600181101580156110ee575060038111155b1561110f576000600381111561110757611106614141565b5b91505061116f565b60858111611133576001600381111561112b5761112a614141565b5b91505061116f565b610341811161115857600260038111156111505761114f614141565b5b91505061116f565b60038081111561116b5761116a614141565b5b9150505b919050565b61118561117f61181e565b836118df565b6111c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bb90614306565b60405180910390fd5b6111d0848484846125c1565b50505050565b608281565b600381565b6106e081565b60606111f1826117d3565b60006111fb61261d565b9050600081511161121b5760405180602001604052806000815250611246565b80611225846126af565b6040516020016112369291906147ec565b6040516020818303038152906040525b915050919050565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112ae57600190506112bb565b6112b8838361280f565b90505b92915050565b6102bc81565b6112cf611cf7565b6112e06112da61181e565b82612371565b60006112eb826128a3565b90506001600e600083600381111561130657611305614141565b5b600381111561131857611317614141565b5b81526020019081526020016000206000828254611335919061471c565b925050819055506000600d600083600381111561135557611354614141565b5b600381111561136757611366614141565b5b81526020019081526020016000206000600e600085600381111561138e5761138d614141565b5b60038111156113a05761139f614141565b5b815260200190815260200160002054815260200190815260200160002054905060005b60048110156115bb57600f60008260038111156113e3576113e2614141565b5b60038111156113f5576113f4614141565b5b600381111561140757611406614141565b5b815260200190815260200160002083600381111561142857611427614141565b5b815481106114395761143861444a565b5b90600052602060002001546010600083600381111561145b5761145a614141565b5b600381111561146d5761146c614141565b5b600381111561147f5761147e614141565b5b81526020019081526020016000208460038111156114a05761149f614141565b5b815481106114b1576114b061444a565b5b9060005260206000200160008282546114ca919061471c565b92505081905550600f60008260038111156114e8576114e7614141565b5b60038111156114fa576114f9614141565b5b600381111561150c5761150b614141565b5b815260200190815260200160002083600381111561152d5761152c614141565b5b8154811061153e5761153d61444a565b5b9060005260206000200154601160008360038111156115605761155f614141565b5b600381111561157257611571614141565b5b600381111561158457611583614141565b5b815260200190815260200160002060008282546115a1919061471c565b9250508190555080806115b3906146d4565b9150506113c3565b506000810361165557600e60008360038111156115db576115da614141565b5b60038111156115ed576115ec614141565b5b815260200190815260200160002054600d600084600381111561161357611612614141565b5b600381111561162557611624614141565b5b8152602001908152602001600020600061163e8661291f565b8152602001908152602001600020819055506116ab565b80600d600084600381111561166d5761166c614141565b5b600381111561167f5761167e614141565b5b815260200190815260200160002060006116988661291f565b8152602001908152602001600020819055505b505050565b6116b8611cf7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161171e90614882565b60405180910390fd5b6117308161238f565b50565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806117cc57506117cb82612b21565b5b9050919050565b6117dc81612c03565b61181b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611812906144c5565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661189983610b51565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806118eb83610b51565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061192d575061192c818561124e565b5b8061196b57508373ffffffffffffffffffffffffffffffffffffffff1661195384610759565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661199482610b51565b73ffffffffffffffffffffffffffffffffffffffff16146119ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e190614914565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a50906149a6565b60405180910390fd5b611a64838383612c6f565b611a6f600082611826565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611abf919061471c565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611b169190614580565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611bd5838383612c7f565b505050565b6000611be582610b51565b9050611bf381600084612c6f565b611bfe600083611826565b6001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611c4e919061471c565b925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611cf381600084612c7f565b5050565b611cff61181e565b73ffffffffffffffffffffffffffffffffffffffff16611d1d610e77565b73ffffffffffffffffffffffffffffffffffffffff1614611d73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d6a90614a12565b60405180910390fd5b565b60008060116000846003811115611d8f57611d8e614141565b5b6003811115611da157611da0614141565b5b815260200190815260200160002054611df060116000866003811115611dca57611dc9614141565b5b6003811115611ddc57611ddb614141565b5b815260200190815260200160002054612c84565b611dfa919061477f565b9050600080600090505b6004811015611ef65760106000866003811115611e2457611e23614141565b5b6003811115611e3657611e35614141565b5b81526020019081526020016000208181548110611e5657611e5561444a565b5b9060005260206000200154831015611e8257806003811115611e7b57611e7a614141565b5b9150611ef6565b60106000866003811115611e9957611e98614141565b5b6003811115611eab57611eaa614141565b5b81526020019081526020016000208181548110611ecb57611eca61444a565b5b906000526020600020015483611ee1919061471c565b92508080611eee906146d4565b915050611e04565b506000600e6000836003811115611f1057611f0f614141565b5b6003811115611f2257611f21614141565b5b815260200190815260200160002054611f71600e6000856003811115611f4b57611f4a614141565b5b6003811115611f5d57611f5c614141565b5b815260200190815260200160002054612c84565b611f7b919061477f565b90506001600e6000846003811115611f9657611f95614141565b5b6003811115611fa857611fa7614141565b5b81526020019081526020016000206000828254611fc5919061471c565b9250508190555060005b60048110156121c757600f6000826003811115611fef57611fee614141565b5b600381111561200157612000614141565b5b600381111561201357612012614141565b5b815260200190815260200160002083600381111561203457612033614141565b5b815481106120455761204461444a565b5b90600052602060002001546010600083600381111561206757612066614141565b5b600381111561207957612078614141565b5b600381111561208b5761208a614141565b5b81526020019081526020016000208460038111156120ac576120ab614141565b5b815481106120bd576120bc61444a565b5b9060005260206000200160008282546120d6919061471c565b92505081905550600f60008260038111156120f4576120f3614141565b5b600381111561210657612105614141565b5b600381111561211857612117614141565b5b815260200190815260200160002083600381111561213957612138614141565b5b8154811061214a5761214961444a565b5b90600052602060002001546011600083600381111561216c5761216b614141565b5b600381111561217e5761217d614141565b5b60038111156121905761218f614141565b5b815260200190815260200160002060008282546121ad919061471c565b9250508190555080806121bf906146d4565b915050611fcf565b506000600d60008460038111156121e1576121e0614141565b5b60038111156121f3576121f2614141565b5b8152602001908152602001600020600083815260200190815260200160002054905060008103612221578190505b6000600e600085600381111561223a57612239614141565b5b600381111561224c5761224b614141565b5b815260200190815260200160002054905080831461235b576000600d600086600381111561227d5761227c614141565b5b600381111561228f5761228e614141565b5b815260200190815260200160002060008381526020019081526020016000205490506000810361230b5781600d60008760038111156122d1576122d0614141565b5b60038111156122e3576122e2614141565b5b8152602001908152602001600020600086815260200190815260200160002081905550612359565b80600d600087600381111561232357612322614141565b5b600381111561233557612334614141565b5b81526020019081526020016000206000868152602001908152602001600020819055505b505b6123658483612cbb565b95505050505050919050565b61238b828260405180602001604052806000815250612e7b565b5050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ba90614a7e565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125b49190613837565b60405180910390a3505050565b6125cc848484611974565b6125d884848484612ed6565b612617576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161260e90614b10565b60405180910390fd5b50505050565b6060600c805461262c90614110565b80601f016020809104026020016040519081016040528092919081815260200182805461265890614110565b80156126a55780601f1061267a576101008083540402835291602001916126a5565b820191906000526020600020905b81548152906001019060200180831161268857829003601f168201915b5050505050905090565b6060600082036126f6576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061280a565b600082905060005b60008214612728578080612711906146d4565b915050600a826127219190614b30565b91506126fe565b60008167ffffffffffffffff81111561274457612743613af6565b5b6040519080825280601f01601f1916602001820160405280156127765781602001600182028036833780820191505090505b5090505b600085146128035760018261278f919061471c565b9150600a8561279e919061477f565b60306127aa9190614580565b60f81b8183815181106127c0576127bf61444a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a856127fc9190614b30565b945061277a565b8093505050505b919050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000806001610a216001856128b8919061471c565b6128c2919061477f565b6128cc9190614580565b9050600181101580156128e0575060038111155b156128ef57600091505061291a565b6085811161290157600191505061291a565b610341811161291457600291505061291a565b60039150505b919050565b60008061292b836128a3565b90506000600381111561294157612940614141565b5b81600381111561295457612953614141565b5b036129ab57610a21600184612969919061471c565b612973919061477f565b6003610a21600186612985919061471c565b61298f9190614b30565b6129999190614b61565b6129a39190614580565b915050612b1c565b600160038111156129bf576129be614141565b5b8160038111156129d2576129d1614141565b5b03612a35576003610a216001856129e9919061471c565b6129f3919061477f565b6082610a21600187612a05919061471c565b612a0f9190614b30565b612a199190614b61565b612a239190614580565b612a2d919061471c565b915050612b1c565b60026003811115612a4957612a48614141565b5b816003811115612a5c57612a5b614141565b5b03612ac0576085610a21600185612a73919061471c565b612a7d919061477f565b6102bc610a21600187612a90919061471c565b612a9a9190614b30565b612aa49190614b61565b612aae9190614580565b612ab8919061471c565b915050612b1c565b610341610a21600185612ad3919061471c565b612add919061477f565b6106e0610a21600187612af0919061471c565b612afa9190614b30565b612b049190614b61565b612b0e9190614580565b612b18919061471c565b9150505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612bec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612bfc5750612bfb8261305d565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b612c7a8383836130c7565b505050565b505050565b6000424483604051602001612c9b93929190614bdc565b6040516020818303038152906040528051906020012060001c9050919050565b6000806003811115612cd057612ccf614141565b5b836003811115612ce357612ce2614141565b5b03612d2c576001610a21600384612cfa9190614b30565b612d049190614b61565b600384612d11919061477f565b612d1b9190614580565b612d259190614580565b9050612e75565b60016003811115612d4057612d3f614141565b5b836003811115612d5357612d52614141565b5b03612da8576001610a21608284612d6a9190614b30565b612d749190614b61565b6003608285612d83919061477f565b612d8d9190614580565b612d979190614580565b612da19190614580565b9050612e75565b60026003811115612dbc57612dbb614141565b5b836003811115612dcf57612dce614141565b5b03612e26576001610a216102bc84612de79190614b30565b612df19190614b61565b60856102bc85612e01919061477f565b612e0b9190614580565b612e159190614580565b612e1f9190614580565b9050612e75565b6001610a216106e084612e399190614b30565b612e439190614b61565b6103416106e085612e54919061477f565b612e5e9190614580565b612e689190614580565b612e729190614580565b90505b92915050565b612e8583836131d9565b612e926000848484612ed6565b612ed1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ec890614b10565b60405180910390fd5b505050565b6000612ef78473ffffffffffffffffffffffffffffffffffffffff166133b2565b15613050578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612f2061181e565b8786866040518563ffffffff1660e01b8152600401612f429493929190614c6e565b6020604051808303816000875af1925050508015612f7e57506040513d601f19601f82011682018060405250810190612f7b9190614ccf565b60015b613000573d8060008114612fae576040519150601f19603f3d011682016040523d82523d6000602084013e612fb3565b606091505b506000815103612ff8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fef90614b10565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613055565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6130d28383836133d5565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036131145761310f816133da565b613153565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613152576131518382613423565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036131955761319081613590565b6131d4565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146131d3576131d28282613661565b5b5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323f90614d48565b60405180910390fd5b61325181612c03565b15613291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328890614db4565b60405180910390fd5b61329d60008383612c6f565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546132ed9190614580565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46133ae60008383612c7f565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161343084610dac565b61343a919061471c565b905060006007600084815260200190815260200160002054905081811461351f576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b600060016008805490506135a4919061471c565b90506000600960008481526020019081526020016000205490506000600883815481106135d4576135d361444a565b5b9060005260206000200154905080600883815481106135f6576135f561444a565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061364557613644614dd4565b5b6001900381819060005260206000200160009055905550505050565b600061366c83610dac565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b8280546136ec90614110565b90600052602060002090601f01602090048101928261370e5760008555613755565b82601f1061372757805160ff1916838001178555613755565b82800160010185558215613755579182015b82811115613754578251825591602001919060010190613739565b5b5090506137629190613766565b5090565b5b8082111561377f576000816000905550600101613767565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6137cc81613797565b81146137d757600080fd5b50565b6000813590506137e9816137c3565b92915050565b6000602082840312156138055761380461378d565b5b6000613813848285016137da565b91505092915050565b60008115159050919050565b6138318161381c565b82525050565b600060208201905061384c6000830184613828565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561388c578082015181840152602081019050613871565b8381111561389b576000848401525b50505050565b6000601f19601f8301169050919050565b60006138bd82613852565b6138c7818561385d565b93506138d781856020860161386e565b6138e0816138a1565b840191505092915050565b6000602082019050818103600083015261390581846138b2565b905092915050565b6000819050919050565b6139208161390d565b811461392b57600080fd5b50565b60008135905061393d81613917565b92915050565b6000602082840312156139595761395861378d565b5b60006139678482850161392e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061399b82613970565b9050919050565b6139ab81613990565b82525050565b60006020820190506139c660008301846139a2565b92915050565b600060ff82169050919050565b6139e2816139cc565b82525050565b60006020820190506139fd60008301846139d9565b92915050565b613a0c81613990565b8114613a1757600080fd5b50565b600081359050613a2981613a03565b92915050565b60008060408385031215613a4657613a4561378d565b5b6000613a5485828601613a1a565b9250506020613a658582860161392e565b9150509250929050565b613a788161390d565b82525050565b6000602082019050613a936000830184613a6f565b92915050565b600080600060608486031215613ab257613ab161378d565b5b6000613ac086828701613a1a565b9350506020613ad186828701613a1a565b9250506040613ae28682870161392e565b9150509250925092565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b2e826138a1565b810181811067ffffffffffffffff82111715613b4d57613b4c613af6565b5b80604052505050565b6000613b60613783565b9050613b6c8282613b25565b919050565b600067ffffffffffffffff821115613b8c57613b8b613af6565b5b613b95826138a1565b9050602081019050919050565b82818337600083830152505050565b6000613bc4613bbf84613b71565b613b56565b905082815260208101848484011115613be057613bdf613af1565b5b613beb848285613ba2565b509392505050565b600082601f830112613c0857613c07613aec565b5b8135613c18848260208601613bb1565b91505092915050565b600060208284031215613c3757613c3661378d565b5b600082013567ffffffffffffffff811115613c5557613c54613792565b5b613c6184828501613bf3565b91505092915050565b613c73816139cc565b8114613c7e57600080fd5b50565b600081359050613c9081613c6a565b92915050565b60008060408385031215613cad57613cac61378d565b5b6000613cbb85828601613a1a565b9250506020613ccc85828601613c81565b9150509250929050565b600060208284031215613cec57613ceb61378d565b5b6000613cfa84828501613a1a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613d388161390d565b82525050565b6000613d4a8383613d2f565b60208301905092915050565b6000602082019050919050565b6000613d6e82613d03565b613d788185613d0e565b9350613d8383613d1f565b8060005b83811015613db4578151613d9b8882613d3e565b9750613da683613d56565b925050600181019050613d87565b5085935050505092915050565b60006020820190508181036000830152613ddb8184613d63565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000613e2b82613852565b613e358185613e0f565b9350613e4581856020860161386e565b613e4e816138a1565b840191505092915050565b6000613e658383613e20565b905092915050565b6000602082019050919050565b6000613e8582613de3565b613e8f8185613dee565b935083602082028501613ea185613dff565b8060005b85811015613edd5784840389528151613ebe8582613e59565b9450613ec983613e6d565b925060208a01995050600181019050613ea5565b50829750879550505050505092915050565b60006020820190508181036000830152613f098184613e7a565b905092915050565b613f1a8161381c565b8114613f2557600080fd5b50565b600081359050613f3781613f11565b92915050565b60008060408385031215613f5457613f5361378d565b5b6000613f6285828601613a1a565b9250506020613f7385828601613f28565b9150509250929050565b600067ffffffffffffffff821115613f9857613f97613af6565b5b613fa1826138a1565b9050602081019050919050565b6000613fc1613fbc84613f7d565b613b56565b905082815260208101848484011115613fdd57613fdc613af1565b5b613fe8848285613ba2565b509392505050565b600082601f83011261400557614004613aec565b5b8135614015848260208601613fae565b91505092915050565b600080600080608085870312156140385761403761378d565b5b600061404687828801613a1a565b945050602061405787828801613a1a565b93505060406140688782880161392e565b925050606085013567ffffffffffffffff81111561408957614088613792565b5b61409587828801613ff0565b91505092959194509250565b600080604083850312156140b8576140b761378d565b5b60006140c685828601613a1a565b92505060206140d785828601613a1a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061412857607f821691505b60208210810361413b5761413a6140e1565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006141cc60218361385d565b91506141d782614170565b604082019050919050565b600060208201905081810360008301526141fb816141bf565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c0000602082015250565b600061425e603e8361385d565b915061426982614202565b604082019050919050565b6000602082019050818103600083015261428d81614251565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206e6f7220617070726f766564000000000000000000000000000000000000602082015250565b60006142f0602e8361385d565b91506142fb82614294565b604082019050919050565b6000602082019050818103600083015261431f816142e3565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614382602b8361385d565b915061438d82614326565b604082019050919050565b600060208201905081810360008301526143b181614375565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614414602c8361385d565b915061441f826143b8565b604082019050919050565b6000602082019050818103600083015261444381614407565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b60006144af60188361385d565b91506144ba82614479565b602082019050919050565b600060208201905081810360008301526144de816144a2565b9050919050565b7f6f6e6c792061646d696e206f72206f776e65722063616e206d696e7400000000600082015250565b600061451b601c8361385d565b9150614526826144e5565b602082019050919050565b6000602082019050818103600083015261454a8161450e565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061458b8261390d565b91506145968361390d565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156145cb576145ca614551565b5b828201905092915050565b7f43616e6e6f742065786365656420746f74616c20737570706c79000000000000600082015250565b600061460c601a8361385d565b9150614617826145d6565b602082019050919050565b6000602082019050818103600083015261463b816145ff565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061469e60298361385d565b91506146a982614642565b604082019050919050565b600060208201905081810360008301526146cd81614691565b9050919050565b60006146df8261390d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361471157614710614551565b5b600182019050919050565b60006147278261390d565b91506147328361390d565b92508282101561474557614744614551565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061478a8261390d565b91506147958361390d565b9250826147a5576147a4614750565b5b828206905092915050565b600081905092915050565b60006147c682613852565b6147d081856147b0565b93506147e081856020860161386e565b80840191505092915050565b60006147f882856147bb565b915061480482846147bb565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061486c60268361385d565b915061487782614810565b604082019050919050565b6000602082019050818103600083015261489b8161485f565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148fe60258361385d565b9150614909826148a2565b604082019050919050565b6000602082019050818103600083015261492d816148f1565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061499060248361385d565b915061499b82614934565b604082019050919050565b600060208201905081810360008301526149bf81614983565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149fc60208361385d565b9150614a07826149c6565b602082019050919050565b60006020820190508181036000830152614a2b816149ef565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614a6860198361385d565b9150614a7382614a32565b602082019050919050565b60006020820190508181036000830152614a9781614a5b565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614afa60328361385d565b9150614b0582614a9e565b604082019050919050565b60006020820190508181036000830152614b2981614aed565b9050919050565b6000614b3b8261390d565b9150614b468361390d565b925082614b5657614b55614750565b5b828204905092915050565b6000614b6c8261390d565b9150614b778361390d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614bb057614baf614551565b5b828202905092915050565b6000819050919050565b614bd6614bd18261390d565b614bbb565b82525050565b6000614be88286614bc5565b602082019150614bf88285614bc5565b602082019150614c088284614bc5565b602082019150819050949350505050565b600081519050919050565b600082825260208201905092915050565b6000614c4082614c19565b614c4a8185614c24565b9350614c5a81856020860161386e565b614c63816138a1565b840191505092915050565b6000608082019050614c8360008301876139a2565b614c9060208301866139a2565b614c9d6040830185613a6f565b8181036060830152614caf8184614c35565b905095945050505050565b600081519050614cc9816137c3565b92915050565b600060208284031215614ce557614ce461378d565b5b6000614cf384828501614cba565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614d3260208361385d565b9150614d3d82614cfc565b602082019050919050565b60006020820190508181036000830152614d6181614d25565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614d9e601c8361385d565b9150614da982614d68565b602082019050919050565b60006020820190508181036000830152614dcd81614d91565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220827c629e6c9e6f6fd600db865693cb50fd8942534cd1f4b3ef6fd52559e17c4164736f6c634300080d0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102065760003560e01c8063715018a61161011a578063c0faf790116100ad578063e985e9c51161007c578063e985e9c514610611578063ec2737e314610641578063f19e75d41461065f578063f2fde38b1461067b578063f851a4401461069757610206565b8063c0faf79014610587578063c30a9bb8146105a5578063c59e5f8a146105c3578063c87b56dd146105e157610206565b8063a0e939e9116100e9578063a0e939e9146104ef578063a22cb4651461051f578063afb0a3691461053b578063b88d4fde1461056b57610206565b8063715018a6146104795780638da5cb5b1461048357806395d89b41146104a15780639e59e598146104bf57610206565b806342842e0e1161019d57806355f804b31161016c57806355f804b3146103c55780636352211e146103e1578063691562a014610411578063704b6c021461042d57806370a082311461044957610206565b806342842e0e1461033f57806342966c681461035b5780634f6ccce71461037757806350f7c204146103a757610206565b8063095ea7b3116101d9578063095ea7b3146102b957806318160ddd146102d557806323b872dd146102f35780632f745c591461030f57610206565b806301ffc9a71461020b57806306fdde031461023b578063081812fc1461025957806308c243aa14610289575b600080fd5b610225600480360381019061022091906137ef565b6106b5565b6040516102329190613837565b60405180910390f35b6102436106c7565b60405161025091906138eb565b60405180910390f35b610273600480360381019061026e9190613943565b610759565b60405161028091906139b1565b60405180910390f35b6102a3600480360381019061029e9190613943565b61079f565b6040516102b091906139e8565b60405180910390f35b6102d360048036038101906102ce9190613a2f565b610813565b005b6102dd61092a565b6040516102ea9190613a7e565b60405180910390f35b61030d60048036038101906103089190613a99565b610937565b005b61032960048036038101906103249190613a2f565b610997565b6040516103369190613a7e565b60405180910390f35b61035960048036038101906103549190613a99565b610a3c565b005b61037560048036038101906103709190613943565b610a5c565b005b610391600480360381019061038c9190613943565b610ab8565b60405161039e9190613a7e565b60405180910390f35b6103af610b29565b6040516103bc9190613a7e565b60405180910390f35b6103df60048036038101906103da9190613c21565b610b2f565b005b6103fb60048036038101906103f69190613943565b610b51565b60405161040891906139b1565b60405180910390f35b61042b60048036038101906104269190613c96565b610c02565b005b61044760048036038101906104429190613cd6565b610d60565b005b610463600480360381019061045e9190613cd6565b610dac565b6040516104709190613a7e565b60405180910390f35b610481610e63565b005b61048b610e77565b60405161049891906139b1565b60405180910390f35b6104a9610ea1565b6040516104b691906138eb565b60405180910390f35b6104d960048036038101906104d49190613cd6565b610f33565b6040516104e69190613dc1565b60405180910390f35b61050960048036038101906105049190613cd6565b610fe1565b6040516105169190613eef565b60405180910390f35b61053960048036038101906105349190613f3d565b61109b565b005b61055560048036038101906105509190613943565b6110b1565b60405161056291906139e8565b60405180910390f35b6105856004803603810190610580919061401e565b611174565b005b61058f6111d6565b60405161059c9190613a7e565b60405180910390f35b6105ad6111db565b6040516105ba9190613a7e565b60405180910390f35b6105cb6111e0565b6040516105d89190613a7e565b60405180910390f35b6105fb60048036038101906105f69190613943565b6111e6565b60405161060891906138eb565b60405180910390f35b61062b600480360381019061062691906140a1565b61124e565b6040516106389190613837565b60405180910390f35b6106496112c1565b6040516106569190613a7e565b60405180910390f35b61067960048036038101906106749190613943565b6112c7565b005b61069560048036038101906106909190613cd6565b6116b0565b005b61069f611733565b6040516106ac91906139b1565b60405180910390f35b60006106c082611759565b9050919050565b6060600080546106d690614110565b80601f016020809104026020016040519081016040528092919081815260200182805461070290614110565b801561074f5780601f106107245761010080835404028352916020019161074f565b820191906000526020600020905b81548152906001019060200180831161073257829003601f168201915b5050505050905090565b6000610764826117d3565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600182101580156107b45750610a218211155b156107d457600060028111156107cd576107cc614141565b5b905061080e565b61144282116107f857600160028111156107f1576107f0614141565b5b905061080e565b60028081111561080b5761080a614141565b5b90505b919050565b600061081e82610b51565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361088e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610885906141e2565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166108ad61181e565b73ffffffffffffffffffffffffffffffffffffffff1614806108dc57506108db816108d661181e565b61124e565b5b61091b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091290614274565b60405180910390fd5b6109258383611826565b505050565b6000600880549050905090565b61094861094261181e565b826118df565b610987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097e90614306565b60405180910390fd5b610992838383611974565b505050565b60006109a283610dac565b82106109e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da90614398565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610a5783838360405180602001604052806000815250611174565b505050565b610a6d610a6761181e565b826118df565b610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390614306565b60405180910390fd5b610ab581611bda565b50565b6000610ac261092a565b8210610b03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afa9061442a565b60405180910390fd5b60088281548110610b1757610b1661444a565b5b90600052602060002001549050919050565b611e6381565b610b37611cf7565b80600c9080519060200190610b4d9291906136e0565b5050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf0906144c5565b60405180910390fd5b80915050919050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610c4361181e565b73ffffffffffffffffffffffffffffffffffffffff161480610c9e5750610c68610e77565b73ffffffffffffffffffffffffffffffffffffffff16610c8661181e565b73ffffffffffffffffffffffffffffffffffffffff16145b610cdd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd490614531565b60405180910390fd5b611e636001610cea61092a565b610cf49190614580565b1115610d35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2c90614622565b60405180910390fd5b610d5c82610d578360ff166003811115610d5257610d51614141565b5b611d75565b612371565b5050565b610d68611cf7565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e13906146b4565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610e6b611cf7565b610e75600061238f565b565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054610eb090614110565b80601f0160208091040260200160405190810160405280929190818152602001828054610edc90614110565b8015610f295780601f10610efe57610100808354040283529160200191610f29565b820191906000526020600020905b815481529060010190602001808311610f0c57829003601f168201915b5050505050905090565b60606000610f4083610dac565b905060008167ffffffffffffffff811115610f5e57610f5d613af6565b5b604051908082528060200260200182016040528015610f8c5781602001602082028036833780820191505090505b50905060005b82811015610fd657610fa48582610997565b828281518110610fb757610fb661444a565b5b6020026020010181815250508080610fce906146d4565b915050610f92565b508092505050919050565b60606000610fee83610dac565b905060008167ffffffffffffffff81111561100c5761100b613af6565b5b60405190808252806020026020018201604052801561103f57816020015b606081526020019060019003908161102a5790505b50905060005b828110156110905761105f61105a8683610997565b6111e6565b8282815181106110725761107161444a565b5b60200260200101819052508080611088906146d4565b915050611045565b508092505050919050565b6110ad6110a661181e565b8383612455565b5050565b6000806001610a216001856110c6919061471c565b6110d0919061477f565b6110da9190614580565b9050600181101580156110ee575060038111155b1561110f576000600381111561110757611106614141565b5b91505061116f565b60858111611133576001600381111561112b5761112a614141565b5b91505061116f565b610341811161115857600260038111156111505761114f614141565b5b91505061116f565b60038081111561116b5761116a614141565b5b9150505b919050565b61118561117f61181e565b836118df565b6111c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bb90614306565b60405180910390fd5b6111d0848484846125c1565b50505050565b608281565b600381565b6106e081565b60606111f1826117d3565b60006111fb61261d565b9050600081511161121b5760405180602001604052806000815250611246565b80611225846126af565b6040516020016112369291906147ec565b6040516020818303038152906040525b915050919050565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112ae57600190506112bb565b6112b8838361280f565b90505b92915050565b6102bc81565b6112cf611cf7565b6112e06112da61181e565b82612371565b60006112eb826128a3565b90506001600e600083600381111561130657611305614141565b5b600381111561131857611317614141565b5b81526020019081526020016000206000828254611335919061471c565b925050819055506000600d600083600381111561135557611354614141565b5b600381111561136757611366614141565b5b81526020019081526020016000206000600e600085600381111561138e5761138d614141565b5b60038111156113a05761139f614141565b5b815260200190815260200160002054815260200190815260200160002054905060005b60048110156115bb57600f60008260038111156113e3576113e2614141565b5b60038111156113f5576113f4614141565b5b600381111561140757611406614141565b5b815260200190815260200160002083600381111561142857611427614141565b5b815481106114395761143861444a565b5b90600052602060002001546010600083600381111561145b5761145a614141565b5b600381111561146d5761146c614141565b5b600381111561147f5761147e614141565b5b81526020019081526020016000208460038111156114a05761149f614141565b5b815481106114b1576114b061444a565b5b9060005260206000200160008282546114ca919061471c565b92505081905550600f60008260038111156114e8576114e7614141565b5b60038111156114fa576114f9614141565b5b600381111561150c5761150b614141565b5b815260200190815260200160002083600381111561152d5761152c614141565b5b8154811061153e5761153d61444a565b5b9060005260206000200154601160008360038111156115605761155f614141565b5b600381111561157257611571614141565b5b600381111561158457611583614141565b5b815260200190815260200160002060008282546115a1919061471c565b9250508190555080806115b3906146d4565b9150506113c3565b506000810361165557600e60008360038111156115db576115da614141565b5b60038111156115ed576115ec614141565b5b815260200190815260200160002054600d600084600381111561161357611612614141565b5b600381111561162557611624614141565b5b8152602001908152602001600020600061163e8661291f565b8152602001908152602001600020819055506116ab565b80600d600084600381111561166d5761166c614141565b5b600381111561167f5761167e614141565b5b815260200190815260200160002060006116988661291f565b8152602001908152602001600020819055505b505050565b6116b8611cf7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161171e90614882565b60405180910390fd5b6117308161238f565b50565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806117cc57506117cb82612b21565b5b9050919050565b6117dc81612c03565b61181b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611812906144c5565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661189983610b51565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806118eb83610b51565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061192d575061192c818561124e565b5b8061196b57508373ffffffffffffffffffffffffffffffffffffffff1661195384610759565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661199482610b51565b73ffffffffffffffffffffffffffffffffffffffff16146119ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e190614914565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a59576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a50906149a6565b60405180910390fd5b611a64838383612c6f565b611a6f600082611826565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611abf919061471c565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611b169190614580565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611bd5838383612c7f565b505050565b6000611be582610b51565b9050611bf381600084612c6f565b611bfe600083611826565b6001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611c4e919061471c565b925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611cf381600084612c7f565b5050565b611cff61181e565b73ffffffffffffffffffffffffffffffffffffffff16611d1d610e77565b73ffffffffffffffffffffffffffffffffffffffff1614611d73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d6a90614a12565b60405180910390fd5b565b60008060116000846003811115611d8f57611d8e614141565b5b6003811115611da157611da0614141565b5b815260200190815260200160002054611df060116000866003811115611dca57611dc9614141565b5b6003811115611ddc57611ddb614141565b5b815260200190815260200160002054612c84565b611dfa919061477f565b9050600080600090505b6004811015611ef65760106000866003811115611e2457611e23614141565b5b6003811115611e3657611e35614141565b5b81526020019081526020016000208181548110611e5657611e5561444a565b5b9060005260206000200154831015611e8257806003811115611e7b57611e7a614141565b5b9150611ef6565b60106000866003811115611e9957611e98614141565b5b6003811115611eab57611eaa614141565b5b81526020019081526020016000208181548110611ecb57611eca61444a565b5b906000526020600020015483611ee1919061471c565b92508080611eee906146d4565b915050611e04565b506000600e6000836003811115611f1057611f0f614141565b5b6003811115611f2257611f21614141565b5b815260200190815260200160002054611f71600e6000856003811115611f4b57611f4a614141565b5b6003811115611f5d57611f5c614141565b5b815260200190815260200160002054612c84565b611f7b919061477f565b90506001600e6000846003811115611f9657611f95614141565b5b6003811115611fa857611fa7614141565b5b81526020019081526020016000206000828254611fc5919061471c565b9250508190555060005b60048110156121c757600f6000826003811115611fef57611fee614141565b5b600381111561200157612000614141565b5b600381111561201357612012614141565b5b815260200190815260200160002083600381111561203457612033614141565b5b815481106120455761204461444a565b5b90600052602060002001546010600083600381111561206757612066614141565b5b600381111561207957612078614141565b5b600381111561208b5761208a614141565b5b81526020019081526020016000208460038111156120ac576120ab614141565b5b815481106120bd576120bc61444a565b5b9060005260206000200160008282546120d6919061471c565b92505081905550600f60008260038111156120f4576120f3614141565b5b600381111561210657612105614141565b5b600381111561211857612117614141565b5b815260200190815260200160002083600381111561213957612138614141565b5b8154811061214a5761214961444a565b5b90600052602060002001546011600083600381111561216c5761216b614141565b5b600381111561217e5761217d614141565b5b60038111156121905761218f614141565b5b815260200190815260200160002060008282546121ad919061471c565b9250508190555080806121bf906146d4565b915050611fcf565b506000600d60008460038111156121e1576121e0614141565b5b60038111156121f3576121f2614141565b5b8152602001908152602001600020600083815260200190815260200160002054905060008103612221578190505b6000600e600085600381111561223a57612239614141565b5b600381111561224c5761224b614141565b5b815260200190815260200160002054905080831461235b576000600d600086600381111561227d5761227c614141565b5b600381111561228f5761228e614141565b5b815260200190815260200160002060008381526020019081526020016000205490506000810361230b5781600d60008760038111156122d1576122d0614141565b5b60038111156122e3576122e2614141565b5b8152602001908152602001600020600086815260200190815260200160002081905550612359565b80600d600087600381111561232357612322614141565b5b600381111561233557612334614141565b5b81526020019081526020016000206000868152602001908152602001600020819055505b505b6123658483612cbb565b95505050505050919050565b61238b828260405180602001604052806000815250612e7b565b5050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124ba90614a7e565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125b49190613837565b60405180910390a3505050565b6125cc848484611974565b6125d884848484612ed6565b612617576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161260e90614b10565b60405180910390fd5b50505050565b6060600c805461262c90614110565b80601f016020809104026020016040519081016040528092919081815260200182805461265890614110565b80156126a55780601f1061267a576101008083540402835291602001916126a5565b820191906000526020600020905b81548152906001019060200180831161268857829003601f168201915b5050505050905090565b6060600082036126f6576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061280a565b600082905060005b60008214612728578080612711906146d4565b915050600a826127219190614b30565b91506126fe565b60008167ffffffffffffffff81111561274457612743613af6565b5b6040519080825280601f01601f1916602001820160405280156127765781602001600182028036833780820191505090505b5090505b600085146128035760018261278f919061471c565b9150600a8561279e919061477f565b60306127aa9190614580565b60f81b8183815181106127c0576127bf61444a565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a856127fc9190614b30565b945061277a565b8093505050505b919050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000806001610a216001856128b8919061471c565b6128c2919061477f565b6128cc9190614580565b9050600181101580156128e0575060038111155b156128ef57600091505061291a565b6085811161290157600191505061291a565b610341811161291457600291505061291a565b60039150505b919050565b60008061292b836128a3565b90506000600381111561294157612940614141565b5b81600381111561295457612953614141565b5b036129ab57610a21600184612969919061471c565b612973919061477f565b6003610a21600186612985919061471c565b61298f9190614b30565b6129999190614b61565b6129a39190614580565b915050612b1c565b600160038111156129bf576129be614141565b5b8160038111156129d2576129d1614141565b5b03612a35576003610a216001856129e9919061471c565b6129f3919061477f565b6082610a21600187612a05919061471c565b612a0f9190614b30565b612a199190614b61565b612a239190614580565b612a2d919061471c565b915050612b1c565b60026003811115612a4957612a48614141565b5b816003811115612a5c57612a5b614141565b5b03612ac0576085610a21600185612a73919061471c565b612a7d919061477f565b6102bc610a21600187612a90919061471c565b612a9a9190614b30565b612aa49190614b61565b612aae9190614580565b612ab8919061471c565b915050612b1c565b610341610a21600185612ad3919061471c565b612add919061477f565b6106e0610a21600187612af0919061471c565b612afa9190614b30565b612b049190614b61565b612b0e9190614580565b612b18919061471c565b9150505b919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612bec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612bfc5750612bfb8261305d565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b612c7a8383836130c7565b505050565b505050565b6000424483604051602001612c9b93929190614bdc565b6040516020818303038152906040528051906020012060001c9050919050565b6000806003811115612cd057612ccf614141565b5b836003811115612ce357612ce2614141565b5b03612d2c576001610a21600384612cfa9190614b30565b612d049190614b61565b600384612d11919061477f565b612d1b9190614580565b612d259190614580565b9050612e75565b60016003811115612d4057612d3f614141565b5b836003811115612d5357612d52614141565b5b03612da8576001610a21608284612d6a9190614b30565b612d749190614b61565b6003608285612d83919061477f565b612d8d9190614580565b612d979190614580565b612da19190614580565b9050612e75565b60026003811115612dbc57612dbb614141565b5b836003811115612dcf57612dce614141565b5b03612e26576001610a216102bc84612de79190614b30565b612df19190614b61565b60856102bc85612e01919061477f565b612e0b9190614580565b612e159190614580565b612e1f9190614580565b9050612e75565b6001610a216106e084612e399190614b30565b612e439190614b61565b6103416106e085612e54919061477f565b612e5e9190614580565b612e689190614580565b612e729190614580565b90505b92915050565b612e8583836131d9565b612e926000848484612ed6565b612ed1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ec890614b10565b60405180910390fd5b505050565b6000612ef78473ffffffffffffffffffffffffffffffffffffffff166133b2565b15613050578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612f2061181e565b8786866040518563ffffffff1660e01b8152600401612f429493929190614c6e565b6020604051808303816000875af1925050508015612f7e57506040513d601f19601f82011682018060405250810190612f7b9190614ccf565b60015b613000573d8060008114612fae576040519150601f19603f3d011682016040523d82523d6000602084013e612fb3565b606091505b506000815103612ff8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fef90614b10565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613055565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6130d28383836133d5565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036131145761310f816133da565b613153565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613152576131518382613423565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036131955761319081613590565b6131d4565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146131d3576131d28282613661565b5b5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323f90614d48565b60405180910390fd5b61325181612c03565b15613291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328890614db4565b60405180910390fd5b61329d60008383612c6f565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546132ed9190614580565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46133ae60008383612c7f565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161343084610dac565b61343a919061471c565b905060006007600084815260200190815260200160002054905081811461351f576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b600060016008805490506135a4919061471c565b90506000600960008481526020019081526020016000205490506000600883815481106135d4576135d361444a565b5b9060005260206000200154905080600883815481106135f6576135f561444a565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061364557613644614dd4565b5b6001900381819060005260206000200160009055905550505050565b600061366c83610dac565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b8280546136ec90614110565b90600052602060002090601f01602090048101928261370e5760008555613755565b82601f1061372757805160ff1916838001178555613755565b82800160010185558215613755579182015b82811115613754578251825591602001919060010190613739565b5b5090506137629190613766565b5090565b5b8082111561377f576000816000905550600101613767565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6137cc81613797565b81146137d757600080fd5b50565b6000813590506137e9816137c3565b92915050565b6000602082840312156138055761380461378d565b5b6000613813848285016137da565b91505092915050565b60008115159050919050565b6138318161381c565b82525050565b600060208201905061384c6000830184613828565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561388c578082015181840152602081019050613871565b8381111561389b576000848401525b50505050565b6000601f19601f8301169050919050565b60006138bd82613852565b6138c7818561385d565b93506138d781856020860161386e565b6138e0816138a1565b840191505092915050565b6000602082019050818103600083015261390581846138b2565b905092915050565b6000819050919050565b6139208161390d565b811461392b57600080fd5b50565b60008135905061393d81613917565b92915050565b6000602082840312156139595761395861378d565b5b60006139678482850161392e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061399b82613970565b9050919050565b6139ab81613990565b82525050565b60006020820190506139c660008301846139a2565b92915050565b600060ff82169050919050565b6139e2816139cc565b82525050565b60006020820190506139fd60008301846139d9565b92915050565b613a0c81613990565b8114613a1757600080fd5b50565b600081359050613a2981613a03565b92915050565b60008060408385031215613a4657613a4561378d565b5b6000613a5485828601613a1a565b9250506020613a658582860161392e565b9150509250929050565b613a788161390d565b82525050565b6000602082019050613a936000830184613a6f565b92915050565b600080600060608486031215613ab257613ab161378d565b5b6000613ac086828701613a1a565b9350506020613ad186828701613a1a565b9250506040613ae28682870161392e565b9150509250925092565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b2e826138a1565b810181811067ffffffffffffffff82111715613b4d57613b4c613af6565b5b80604052505050565b6000613b60613783565b9050613b6c8282613b25565b919050565b600067ffffffffffffffff821115613b8c57613b8b613af6565b5b613b95826138a1565b9050602081019050919050565b82818337600083830152505050565b6000613bc4613bbf84613b71565b613b56565b905082815260208101848484011115613be057613bdf613af1565b5b613beb848285613ba2565b509392505050565b600082601f830112613c0857613c07613aec565b5b8135613c18848260208601613bb1565b91505092915050565b600060208284031215613c3757613c3661378d565b5b600082013567ffffffffffffffff811115613c5557613c54613792565b5b613c6184828501613bf3565b91505092915050565b613c73816139cc565b8114613c7e57600080fd5b50565b600081359050613c9081613c6a565b92915050565b60008060408385031215613cad57613cac61378d565b5b6000613cbb85828601613a1a565b9250506020613ccc85828601613c81565b9150509250929050565b600060208284031215613cec57613ceb61378d565b5b6000613cfa84828501613a1a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613d388161390d565b82525050565b6000613d4a8383613d2f565b60208301905092915050565b6000602082019050919050565b6000613d6e82613d03565b613d788185613d0e565b9350613d8383613d1f565b8060005b83811015613db4578151613d9b8882613d3e565b9750613da683613d56565b925050600181019050613d87565b5085935050505092915050565b60006020820190508181036000830152613ddb8184613d63565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000613e2b82613852565b613e358185613e0f565b9350613e4581856020860161386e565b613e4e816138a1565b840191505092915050565b6000613e658383613e20565b905092915050565b6000602082019050919050565b6000613e8582613de3565b613e8f8185613dee565b935083602082028501613ea185613dff565b8060005b85811015613edd5784840389528151613ebe8582613e59565b9450613ec983613e6d565b925060208a01995050600181019050613ea5565b50829750879550505050505092915050565b60006020820190508181036000830152613f098184613e7a565b905092915050565b613f1a8161381c565b8114613f2557600080fd5b50565b600081359050613f3781613f11565b92915050565b60008060408385031215613f5457613f5361378d565b5b6000613f6285828601613a1a565b9250506020613f7385828601613f28565b9150509250929050565b600067ffffffffffffffff821115613f9857613f97613af6565b5b613fa1826138a1565b9050602081019050919050565b6000613fc1613fbc84613f7d565b613b56565b905082815260208101848484011115613fdd57613fdc613af1565b5b613fe8848285613ba2565b509392505050565b600082601f83011261400557614004613aec565b5b8135614015848260208601613fae565b91505092915050565b600080600080608085870312156140385761403761378d565b5b600061404687828801613a1a565b945050602061405787828801613a1a565b93505060406140688782880161392e565b925050606085013567ffffffffffffffff81111561408957614088613792565b5b61409587828801613ff0565b91505092959194509250565b600080604083850312156140b8576140b761378d565b5b60006140c685828601613a1a565b92505060206140d785828601613a1a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061412857607f821691505b60208210810361413b5761413a6140e1565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006141cc60218361385d565b91506141d782614170565b604082019050919050565b600060208201905081810360008301526141fb816141bf565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c0000602082015250565b600061425e603e8361385d565b915061426982614202565b604082019050919050565b6000602082019050818103600083015261428d81614251565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206e6f7220617070726f766564000000000000000000000000000000000000602082015250565b60006142f0602e8361385d565b91506142fb82614294565b604082019050919050565b6000602082019050818103600083015261431f816142e3565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614382602b8361385d565b915061438d82614326565b604082019050919050565b600060208201905081810360008301526143b181614375565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000614414602c8361385d565b915061441f826143b8565b604082019050919050565b6000602082019050818103600083015261444381614407565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b60006144af60188361385d565b91506144ba82614479565b602082019050919050565b600060208201905081810360008301526144de816144a2565b9050919050565b7f6f6e6c792061646d696e206f72206f776e65722063616e206d696e7400000000600082015250565b600061451b601c8361385d565b9150614526826144e5565b602082019050919050565b6000602082019050818103600083015261454a8161450e565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061458b8261390d565b91506145968361390d565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156145cb576145ca614551565b5b828201905092915050565b7f43616e6e6f742065786365656420746f74616c20737570706c79000000000000600082015250565b600061460c601a8361385d565b9150614617826145d6565b602082019050919050565b6000602082019050818103600083015261463b816145ff565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061469e60298361385d565b91506146a982614642565b604082019050919050565b600060208201905081810360008301526146cd81614691565b9050919050565b60006146df8261390d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361471157614710614551565b5b600182019050919050565b60006147278261390d565b91506147328361390d565b92508282101561474557614744614551565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061478a8261390d565b91506147958361390d565b9250826147a5576147a4614750565b5b828206905092915050565b600081905092915050565b60006147c682613852565b6147d081856147b0565b93506147e081856020860161386e565b80840191505092915050565b60006147f882856147bb565b915061480482846147bb565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061486c60268361385d565b915061487782614810565b604082019050919050565b6000602082019050818103600083015261489b8161485f565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148fe60258361385d565b9150614909826148a2565b604082019050919050565b6000602082019050818103600083015261492d816148f1565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061499060248361385d565b915061499b82614934565b604082019050919050565b600060208201905081810360008301526149bf81614983565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149fc60208361385d565b9150614a07826149c6565b602082019050919050565b60006020820190508181036000830152614a2b816149ef565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614a6860198361385d565b9150614a7382614a32565b602082019050919050565b60006020820190508181036000830152614a9781614a5b565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614afa60328361385d565b9150614b0582614a9e565b604082019050919050565b60006020820190508181036000830152614b2981614aed565b9050919050565b6000614b3b8261390d565b9150614b468361390d565b925082614b5657614b55614750565b5b828204905092915050565b6000614b6c8261390d565b9150614b778361390d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614bb057614baf614551565b5b828202905092915050565b6000819050919050565b614bd6614bd18261390d565b614bbb565b82525050565b6000614be88286614bc5565b602082019150614bf88285614bc5565b602082019150614c088284614bc5565b602082019150819050949350505050565b600081519050919050565b600082825260208201905092915050565b6000614c4082614c19565b614c4a8185614c24565b9350614c5a81856020860161386e565b614c63816138a1565b840191505092915050565b6000608082019050614c8360008301876139a2565b614c9060208301866139a2565b614c9d6040830185613a6f565b8181036060830152614caf8184614c35565b905095945050505050565b600081519050614cc9816137c3565b92915050565b600060208284031215614ce557614ce461378d565b5b6000614cf384828501614cba565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614d3260208361385d565b9150614d3d82614cfc565b602082019050919050565b60006020820190508181036000830152614d6181614d25565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614d9e601c8361385d565b9150614da982614d68565b602082019050919050565b60006020820190508181036000830152614dcd81614d91565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220827c629e6c9e6f6fd600db865693cb50fd8942534cd1f4b3ef6fd52559e17c4164736f6c634300080d0033

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.