pragma solidity ^0.8.0;










contract OkayHumans is ReentrancyGuard, Pausable, ERC721Enumerable, Ownable, IERC721Receiver {
    using Counters for Counters.Counter;
    using Strings for uint256;
    using EnumerableSet for EnumerableSet.UintSet;

    /* ------------------------ NFT Minting ------------------------- */
    address payable private _PaymentAddress;
    address payable private _DevAddress;

    uint256 public MAX_SUPPLY = 3333;
    uint256 public FREE_SUPPLY = 888;
    uint256 public PUBLIC_PRICE = 0.033 ether;
    
    uint256 public PRESALE_MINT_LIMIT = 1;
    uint256 public PUBLIC_MINT_LIMIT = 20;
    
    bytes32 public _whitelistRoot;
    mapping (address => bool) public MAP_WHITELIST;
    mapping(address => uint256) public MAP_PRESALE_MINT_COUNT;
    mapping(address => uint256) public MAP_PUBLIC_MINT_COUNT;

    uint256 public SALE_STEP = 0; // 0: NONE, 1: PRSALE, 2: PUBLIC
    bool public _revealEnabled = false;
    
    string private _tokenBaseURI = "";
    string private _unrevealURI = "";
    
    Counters.Counter internal _publicCounter;

    /* ------------------------ NFT Staking ------------------------- */
    struct UserInfo {
        uint256 balance;
        uint256 rewards;
        uint256 lastUpdated;
    }
    mapping(address => UserInfo) public userInfo;
    mapping(address => EnumerableSet.UintSet) private userBlanaces;
    address[] public stakerList;

    IERC20 public rewardToken;
    uint256 public dailyTokenRewards = 0.5 ether;
    uint256 public minterTokenRewards = 300 ether;
    /* --------------------------------------------------------------------------------- */
    
    constructor(address _rewardToken, address _paymentAddress) ERC721("Okay Humans NFT", "OKHM") {
        _PaymentAddress = payable(_paymentAddress);
        _DevAddress = payable(msg.sender);
        rewardToken = IERC20(_rewardToken);
    }

    function setPaymentAddress(address paymentAddress) external onlyOwner {
        _PaymentAddress = payable(paymentAddress);
    }

    function setRewardToken(address rewardTokenAddress) external onlyOwner {
        rewardToken = IERC20(rewardTokenAddress);
    }

    function setRewardsAmount(uint256 dailyRewards, uint256 minterRewards) external onlyOwner {
        dailyTokenRewards = dailyRewards;
        minterTokenRewards = minterRewards;
    }

    function setSaleStep(uint256 _saleStep) external onlyOwner {
        SALE_STEP = _saleStep;
    }

    function setRevealEnabled(bool bEnable) external onlyOwner {
        _revealEnabled = bEnable;
    }

    function setWhiteListRoot(bytes32 root) external onlyOwner {
        _whitelistRoot = root;
    }

    function setWhiteList(address[] memory airdropAddress, bool bFlag) external onlyOwner {
        for (uint256 k = 0; k < airdropAddress.length; k++) {
            MAP_WHITELIST[airdropAddress[k]] = bFlag;
        }
    }

    // Verify that a given leaf is in the tree.
    function isWhiteListed(bytes32 _leafNode, bytes32[] memory proof) internal view returns (bool) {
        return MerkleProof.verify(proof, _whitelistRoot, _leafNode);
    }

    // Generate the leaf node (just the hash of tokenID concatenated with the account address)
    function toLeaf(address account, uint256 index, uint256 amount) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(index, account, amount));
    }

    function setMintPrice(uint256 publicMintPrice) external onlyOwner {
        PUBLIC_PRICE = publicMintPrice;
    }

    function setMaxSupply(uint256 maxSupply, uint256 freeSupply) external onlyOwner {
        MAX_SUPPLY = maxSupply;
        FREE_SUPPLY = freeSupply;
    }

    function setMintLimit(uint256 presaleMintLimit, uint256 publicMintLimit) external onlyOwner {
        PRESALE_MINT_LIMIT = presaleMintLimit;
        PUBLIC_MINT_LIMIT = publicMintLimit;
    }

    function setUnrevealURI(string memory unrevealURI) external onlyOwner {
        _unrevealURI = unrevealURI;
    }

    function setBaseURI(string memory baseURI) external onlyOwner {
        _tokenBaseURI = baseURI;
    }

    function airdrop(address[] memory airdropAddress, uint256 numberOfTokens) external onlyOwner {
        require(_publicCounter.current() + airdropAddress.length * numberOfTokens <= MAX_SUPPLY,"Purchase would exceed MAX_SUPPLY");

        for (uint256 k = 0; k < airdropAddress.length; k++) {
            for (uint256 i = 0; i < numberOfTokens; i++) {
                uint256 tokenId = _publicCounter.current();
                _publicCounter.increment();
                if (!_exists(tokenId)) {
                    _safeMint(airdropAddress[k], tokenId);
                }
            }
        }
    }

    function purchase(uint256 numberOfTokens) external payable {
        require(_publicCounter.current() + numberOfTokens <= MAX_SUPPLY,"Purchase would exceed MAX_SUPPLY");

        require(SALE_STEP == 2,"Public Mint is not activated.");

        require(PUBLIC_PRICE * numberOfTokens <= msg.value,"ETH amount is not sufficient");

        MAP_PUBLIC_MINT_COUNT[_msgSender()] = MAP_PUBLIC_MINT_COUNT[_msgSender()] + numberOfTokens;
        
        require(MAP_PUBLIC_MINT_COUNT[_msgSender()] <= PUBLIC_MINT_LIMIT,"Overflow for PUBLIC_MINT_LIMIT");

        uint256 devFee = msg.value / 20;
        _DevAddress.transfer(devFee);
        _PaymentAddress.transfer(msg.value - devFee);
        
        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 tokenId = _publicCounter.current();
            _publicCounter.increment();
            if (!_exists(tokenId)) {
                _safeMint(_msgSender(), tokenId);
            }
        }

        rewardToken.transfer(_msgSender(), numberOfTokens * minterTokenRewards);
    }

    function presale(uint256 numberOfTokens, uint256 index, uint256 amount, bytes32[] calldata proof) external {
        require(_publicCounter.current() + numberOfTokens <= FREE_SUPPLY,"Purchase would exceed FREE_SUPPLY");

        require(isWhiteListed(toLeaf(_msgSender(), index, amount), proof) || MAP_WHITELIST[_msgSender()], "Invalid proof");

        require(SALE_STEP == 1,"Presale Round is not activated.");

        MAP_PRESALE_MINT_COUNT[_msgSender()] = MAP_PRESALE_MINT_COUNT[_msgSender()] + numberOfTokens;
        
        require(MAP_PRESALE_MINT_COUNT[_msgSender()] <= PRESALE_MINT_LIMIT,"Overflow for PRESALE_MINT_LIMIT");

        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 tokenId = _publicCounter.current();
            _publicCounter.increment();
            if (!_exists(tokenId)) {
                _safeMint(_msgSender(), tokenId);
            }
        }

        rewardToken.transfer(_msgSender(), numberOfTokens * minterTokenRewards);
    }

    function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory) {
        require(_exists(tokenId), "Token does not exist");

        if (_revealEnabled) {
            return string(abi.encodePacked(_tokenBaseURI, tokenId.toString()));
        }

        return _unrevealURI;
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        payable(_msgSender()).transfer(balance);
    }

    function withdrawToken() external onlyOwner {
        uint256 balance = rewardToken.balanceOf(address(this));
        rewardToken.transfer(_msgSender(), balance);
    }

    function userHoldNFTs(address _owner) public view returns(uint256[] memory){
        uint256 tokenCount = balanceOf(_owner);
        uint256[] memory result = new uint256[](tokenCount);
        for (uint256 index = 0; index < tokenCount; index++) {
            result[index] = tokenOfOwnerByIndex(_owner, index);
        }
        return result;
    }

    /* --------------------------------------------------------------------- */
    function addStakerList(address _user) internal{
        for (uint256 i = 0; i < stakerList.length; i++) {
            if (stakerList[i] == _user)
                return;
        }
        stakerList.push(_user);
    }

    function userStakeInfo(address _owner) external view returns(UserInfo memory){
         return userInfo[_owner];
    }
    
    function userStakedNFTs(address _owner) public view returns(uint256[] memory){
        uint256 tokenCount = userBlanaces[_owner].length();
        uint256[] memory result = new uint256[](tokenCount);
        for (uint256 index = 0; index < tokenCount; index++) {
            result[index] = userBlanaces[_owner].at(index);
        }
        return result;
    }

    function userStakedNFTCount(address _owner) public view returns(uint256){
         return userBlanaces[_owner].length();
    }

    function isStaked( address account ,uint256 tokenId) public view returns (bool) {
        return userBlanaces[account].contains(tokenId);
    }

    function earned(address account) public view returns (uint256) {
        uint256 blockTime = block.timestamp;

        UserInfo memory user = userInfo[account];

        uint256 amount = (blockTime - user.lastUpdated) * userStakedNFTCount(account) * dailyTokenRewards / 1 days;

        return user.rewards + amount;
    }

    function totalEarned() public view returns (uint256) {
        uint256 totalEarning = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            totalEarning += earned(stakerList[i]);
        }
        return totalEarning;
    }

    function totalStakedCount() public view returns (uint256) {
        uint256 totalCount = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            totalCount += userStakedNFTCount(stakerList[i]);
        }
        return totalCount;
    }

    function totalStakedMembers() public view returns (uint256) {
        uint256 totalMembers = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            if (userStakedNFTCount(stakerList[i]) > 0) totalMembers += 1;
        }
        return totalMembers;
    }

    function stake( uint256[] memory  tokenIdList) public nonReentrant whenNotPaused {
        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = earned(_msgSender());
        user.lastUpdated = block.timestamp;

        addStakerList(_msgSender());

        for (uint256 i = 0; i < tokenIdList.length; i++) {
            safeTransferFrom(_msgSender(), address(this), tokenIdList[i]);

            userBlanaces[_msgSender()].add(tokenIdList[i]);
        }
    }

    function unstake( uint256[] memory  tokenIdList) public nonReentrant {
        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = earned(_msgSender());
        user.lastUpdated = block.timestamp;

        for (uint256 i = 0; i < tokenIdList.length; i++) {

            require(isStaked(_msgSender(), tokenIdList[i]), "Not staked this nft");        

            _safeTransfer(address(this) , _msgSender(), tokenIdList[i], "");

            userBlanaces[_msgSender()].remove(tokenIdList[i]);
        }
    }

    function harvest() public nonReentrant {
        require(earned(_msgSender()) > 0, "Nothing Rewards");
        
        rewardToken.transfer(_msgSender(), earned(_msgSender()));

        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = 0;
        user.lastUpdated = block.timestamp;
    }

    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    receive() external payable {}
}
[{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_paymentAddress","type":"address"}],"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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"FREE_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_PRESALE_MINT_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_PUBLIC_MINT_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_WHITELIST","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRESALE_MINT_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_MINT_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_revealEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_whitelistRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"airdropAddress","type":"address[]"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","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":[],"name":"dailyTokenRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","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":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterTokenRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"presale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"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":"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":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"freeSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"presaleMintLimit","type":"uint256"},{"internalType":"uint256","name":"publicMintLimit","type":"uint256"}],"name":"setMintLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"publicMintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentAddress","type":"address"}],"name":"setPaymentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"bEnable","type":"bool"}],"name":"setRevealEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardTokenAddress","type":"address"}],"name":"setRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dailyRewards","type":"uint256"},{"internalType":"uint256","name":"minterRewards","type":"uint256"}],"name":"setRewardsAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_saleStep","type":"uint256"}],"name":"setSaleStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"unrevealURI","type":"string"}],"name":"setUnrevealURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"airdropAddress","type":"address[]"},{"internalType":"bool","name":"bFlag","type":"bool"}],"name":"setWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setWhiteListRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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"},{"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":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedMembers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userHoldNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakeInfo","outputs":[{"components":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"internalType":"struct OkayHumans.UserInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakedNFTCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakedNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]