编译器
0.8.15+commit.e14f2714
文件 1 的 19:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
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");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
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);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
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);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 19:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 19:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 4 的 19:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 5 的 19: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";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
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");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
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"
);
}
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);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
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);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
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);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 6 的 19:ERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
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];
}
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
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);
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId;
_ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId;
_allTokensIndex[lastTokenId] = tokenIndex;
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
文件 7 的 19:FarmerLandNFT.sol
pragma solidity ^0.8.15;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./WHEAT.sol";
contract FarmerLandNFT is ERC721Enumerable, Ownable, ReentrancyGuard {
using SafeERC20 for WHEAT;
mapping(address => uint) public userRoostingsCount;
uint public immutable MAX_ELEMENTS;
uint public maticPrice = 1e60;
uint public wheatPrice = 1e60;
WHEAT public immutable wheatToken;
mapping(address => bool) public admins;
address public constant founder = 0xC43f13A64fd351C8846660B5D02dB344829859b8;
bool public paused = true;
uint public startTime;
uint public constant MAX_CONCURRENT_MINT = 50;
uint public immutable MAX_LEVEL;
uint public constant MAX_ABILITY = 999e4;
uint public immutable ABILITY_SCALAR;
mapping(uint => uint) private level;
mapping(uint => uint) private ability;
uint public immutable nftType;
string public baseTokenURI;
mapping(uint => uint) public foreverRoostingTimer;
mapping(uint => uint) public startOfCurrentRoosting;
mapping(address => bool) public freeMintWhitelist;
event AbilitySet(uint tokenId, uint oldAbility, uint newAbility);
event LevelSet(uint tokenId, uint oldLevel, uint newLevel);
event WithdrawGas(address destination, uint gasBalance);
event WithdrawWHEAT(address destination, uint wheatBalance);
event AddToWhiteList(uint numberOfAllocations);
event BaseURISet(string oldURI, string newURI);
event Paused(bool currentPausedStatus);
event StartTimeChanged(uint newStartTime);
event WHEATPriceSet(uint price);
event MATICPriceSet(uint price);
event AdminSet(address admin, bool value);
event NFTRoosted(uint indexed id);
event NFTUnRoosted(uint indexed id);
event CreateFarmerLandNFT(uint indexed id);
constructor(uint _startTime, uint _nftType, uint _MAX_ELEMENTS, uint _MAX_LEVEL, uint _ABILITY_SCALAR, WHEAT _WHEAT, string memory name1, string memory name2) ERC721(name1, name2) {
require(_MAX_ELEMENTS%2 == 0, "max elements must be even");
require(_MAX_LEVEL <= 200, "_ABILITY_SCALAR out of range");
require(_ABILITY_SCALAR > 0 && _ABILITY_SCALAR <= 10, "_ABILITY_SCALAR out of range");
MAX_ELEMENTS = _MAX_ELEMENTS;
MAX_LEVEL =_MAX_LEVEL;
ABILITY_SCALAR = _ABILITY_SCALAR;
wheatToken = _WHEAT;
startTime = _startTime;
nftType = _nftType;
admins[founder] = true;
admins[msg.sender] = true;
}
mapping(uint256 => uint256) private _tokenIdsCache;
function availableSupply() public view returns (uint) {
return MAX_ELEMENTS - totalSupply();
}
function _getNextRandomNumber() private returns (uint256 index) {
uint _availableSupply = availableSupply();
require(_availableSupply > 0, "Invalid _remaining");
uint256 i = (MAX_ELEMENTS + uint(keccak256(abi.encode(block.timestamp, tx.origin, blockhash(block.number-1))))) %
_availableSupply;
index = _tokenIdsCache[i] == 0 ? i : _tokenIdsCache[i];
_tokenIdsCache[i] = _tokenIdsCache[_availableSupply - 1] == 0
? _availableSupply - 1
: _tokenIdsCache[_availableSupply - 1];
}
function getUsersNumberOfRoostings(address user) external view returns (uint) {
return userRoostingsCount[user];
}
function getAbility(uint tokenId) external view returns (uint) {
return ability[tokenId];
}
function setAbility(uint tokenId, uint _ability) external {
require(admins[msg.sender], "sender not admin!");
require(_ability <= MAX_ABILITY, "ability too high!");
uint oldAbility = ability[tokenId];
ability[tokenId] = _ability;
emit AbilitySet(tokenId, oldAbility, _ability);
}
function getLevel(uint tokenId) external view returns (uint) {
return level[tokenId];
}
function setLevel(uint tokenId, uint _level) external {
require(admins[msg.sender], "sender not admin!");
require(_level <= MAX_LEVEL, "level too high!");
uint oldLevel = level[tokenId];
level[tokenId] = _level;
emit LevelSet(tokenId, oldLevel, _level);
}
function mint(address _to, uint _count) external payable nonReentrant {
require(!paused, "Minting is paused!");
require(startTime < block.timestamp, "Minting not started yet!");
require(admins[msg.sender] || _count <= MAX_CONCURRENT_MINT, "Can only mint 50!");
uint total = totalSupply();
require(total + _count <= MAX_ELEMENTS, "Max limit");
if (!freeMintWhitelist[msg.sender]) {
require(msg.value >= getMATICPrice(_count) ||
admins[msg.sender], "Value below price");
if (!admins[msg.sender])
wheatToken.safeTransferFrom(msg.sender, address(this), getWHEATPrice(_count));
} else {
require(msg.value >= getMATICPrice(_count - 1) ||
admins[msg.sender], "Value below price");
if (!admins[msg.sender])
wheatToken.safeTransferFrom(msg.sender, address(this), getWHEATPrice(_count - 1));
freeMintWhitelist[msg.sender] = false;
}
for (uint i = 0; i < _count; i++) {
_mintAnElement(_to);
}
}
function _mintAnElement(address _to) private {
uint id = _getNextRandomNumber() + 1;
uint abilityRNG = uint(keccak256(abi.encode(id * MAX_ELEMENTS))) % 10;
if (abilityRNG == 0) {
ability[id] = 4e4;
} else if (abilityRNG <= 3) {
ability[id] = 3e4;
} else if (abilityRNG <= 6) {
ability[id] = 2e4;
} else {
ability[id] = 1e4;
}
ability[id] = ability[id] * ABILITY_SCALAR;
emit CreateFarmerLandNFT(id);
_mint(_to, id);
}
function getMATICPrice(uint _count) public view returns (uint) {
return maticPrice * _count;
}
function getWHEATPrice(uint _count) public view returns (uint) {
return wheatPrice * _count;
}
function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI;
}
function setBaseURI(string memory baseURI) external onlyOwner {
emit BaseURISet(baseTokenURI, baseURI);
baseTokenURI = baseURI;
}
function withdrawGas() public payable onlyOwner {
uint gasBalance = address(this).balance;
require(gasBalance > 0, "zero balance");
_withdraw(founder, gasBalance);
emit WithdrawGas(founder, gasBalance);
}
function withdrawWHEAT() public onlyOwner {
uint wheatBalance = wheatToken.balanceOf(address(this));
require(wheatBalance > 0, "zero balance");
wheatToken.safeTransfer(founder, wheatBalance);
emit WithdrawWHEAT(founder, wheatBalance);
}
function walletOfOwner(address _owner, uint startIndex, uint count) external view returns (uint[] memory) {
uint tokenCount = balanceOf(_owner);
uint[] memory tokensId = new uint[](tokenCount);
for (uint i = startIndex; i < tokenCount && i - startIndex < count; i++) {
tokensId[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokensId;
}
function _withdraw(address _address, uint _amount) private {
(bool success, ) = _address.call{value: _amount}("");
require(success, "Transfer failed.");
}
function _transfer(address from, address to, uint tokenId) internal override {
if (isNftIdRoosting(tokenId)) {
foreverRoostingTimer[tokenId]+= block.timestamp - startOfCurrentRoosting[tokenId];
startOfCurrentRoosting[tokenId] = 0;
userRoostingsCount[from]--;
emit NFTUnRoosted(tokenId);
}
super._transfer( from, to, tokenId );
}
function isNftIdRoosting(uint nftId) public view returns (bool) {
return startOfCurrentRoosting[nftId] > 0;
}
function isNftIdRoostingWithOwner(address owner, uint nftId) external view returns (bool) {
return ownerOf(nftId) == owner && startOfCurrentRoosting[nftId] > 0;
}
function roostNftId(uint nftId) external {
require(ownerOf(nftId) == msg.sender, "owner of NFT isn't sender!");
require(nftId <= MAX_ELEMENTS, "invalid NFTId!");
require(startOfCurrentRoosting[nftId] == 0, "nft is aready roosting!");
startOfCurrentRoosting[nftId] = block.timestamp;
userRoostingsCount[msg.sender]++;
emit NFTRoosted(nftId);
}
function unroostNftId(uint nftId) public {
require(ownerOf(nftId) == msg.sender, "owner of NFT isn't sender!");
require(nftId <= MAX_ELEMENTS, "invalid NFTId!");
require(startOfCurrentRoosting[nftId] > 0, "nft isnt currently roosting!");
foreverRoostingTimer[nftId]+= block.timestamp - startOfCurrentRoosting[nftId];
startOfCurrentRoosting[nftId] = 0;
userRoostingsCount[msg.sender]--;
emit NFTUnRoosted(nftId);
}
function addToWhiteList(address[] calldata participants) external onlyOwner {
for (uint i = 0;i<participants.length;i++) {
freeMintWhitelist[participants[i]] = true;
}
emit AddToWhiteList(participants.length);
}
function setMATICPrice(uint _newPrice) public onlyOwner {
maticPrice = _newPrice;
emit MATICPriceSet(maticPrice);
}
function setWHEATPrice(uint _newPrice) public onlyOwner {
wheatPrice = _newPrice;
emit WHEATPriceSet(wheatPrice);
}
function pause() external onlyOwner {
paused = !paused;
emit Paused(paused);
}
function setStartTime(uint _newStartTime) external onlyOwner {
require(startTime == 0 || block.timestamp < startTime, "Minting has already started!");
require(_newStartTime > startTime, "new start time must be in future!");
startTime = _newStartTime;
emit StartTimeChanged(_newStartTime);
}
function setAdmins(address _newAdmin, bool status) public onlyOwner {
admins[_newAdmin] = status;
emit AdminSet(_newAdmin, status);
}
}
文件 8 的 19:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 19:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 10 的 19:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 11 的 19:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 12 的 19:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 13 的 19:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 14 的 19:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 15 的 19:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 16 的 19:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 17 的 19:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 18 的 19:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function 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);
}
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);
}
}
文件 19 的 19:WHEAT.sol
pragma solidity ^0.8.15;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import { FarmerLandNFT } from "./FarmerLandNFT.sol";
contract WHEAT is ERC20, Ownable, ReentrancyGuard {
ERC20 public constant token_USDC = ERC20(0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9);
struct RoostInfo {
address series;
uint tokenId;
}
mapping(address => RoostInfo) public minotaurNFTRoost;
mapping(address => RoostInfo) public farmerNFTRoost;
mapping(address => RoostInfo) public landNFTRoost;
mapping(address => RoostInfo) public toolNFTRoost;
mapping(address => bool) public nftAddressAllowList;
mapping(address => uint256) public stakeCounts;
event PercentOfLobbyToBePooledChanged(uint oldPercent, uint newPercent);
event MCAddressSet(address oldAddress, address newAddress);
event DaoAddressSet(address oldAddress, address newAddress);
event LotteryShareSet(uint oldValue, uint newValue);
event DaoUSDCWHEATShares(uint oldUSDCShare, uint oldUWHEATShare, uint newUSDCShare, uint newWHEATShare);
event MCUSDCWHEATShares(uint oldUSDCShare, uint oldUWHEATShare, uint newUSDCShare, uint newWHEATShare);
event LastLobbySet(uint oldValue, uint newValue);
event DividensPoolCalDaysSet(uint oldValue, uint newValue);
event LoaningStatusSwitched(bool oldValue, bool newValue);
event VirtualBalanceEnteringSwitched(bool oldValue, bool newValue);
event StakeSellingStatusSwitched(bool oldValue, bool newValue);
event LottyPoolFlushed(address destination, uint amount);
event DevShareOfStakeSellsFlushed(address destination, uint amount);
event UserStake(address indexed addr, uint rawAmount, uint duration, uint stakeId);
event UserStakeCollect(address indexed addr, uint rawAmount, uint stakeId, uint bonusAmount);
event UserLobby(address indexed addr, uint rawAmount, uint extraAmount, address referrer);
event UserLobbyCollect(address indexed addr, uint rawAmount, uint day, uint boostedAmount, uint masterchefWHEATShare, uint daoWHEATShare, uint ref_bonus_NR, uint ref_bonus_NRR);
event StakeSellRequest(address indexed addr, uint price, uint rawAmount, uint stakeId);
event CancelStakeSellRequest(address indexed addr, uint stakeId);
event StakeBuyRequest(address indexed seller, uint sellerStakeId, address indexed buyer, uint buyerStakeId, uint tradeAmount);
event StakeLoanRequest(address indexed addr, uint rawAmount, uint returnAmount, uint duration, uint stakeId);
event CancelStakeLoanRequest(address indexed addr, uint stakeId);
event StakeLend(address indexed addr, uint lendId, address indexed loaner, uint stakeId, uint amount);
event StakeLoanFinished(address indexed lender, uint lendId, address indexed loaner, uint stakeId, uint amount);
event DayLobbyEntry(uint day, uint value);
event LotteryWinner(address indexed addr, uint amount, uint lastRecord);
event LotteryUpdate(uint newPool, uint lastRecord);
event WithdrawSoldStakeFunds(address indexed addr, uint amount);
event WithdrawLoanedFunds(address indexed addr, uint amount);
event NftAddressAllowListSet(address series, bool allowed);
event NFTRoosted(address series, uint tokenId, uint prevTokenId);
constructor(
uint launchTime
) ERC20("WHEAT", "WHEAT") {
LAUNCH_TIME = launchTime;
_mint(msg.sender, 89000 * 1e18);
_updatePercentOfLobbyToBePooled();
}
function set_nftMasterChefAddress(address _nftMasterChefAddress) external onlyOwner() {
require(_nftMasterChefAddress != address(0), "!0");
address oldNftMasterChefAddress = nftMasterChefAddress;
nftMasterChefAddress = _nftMasterChefAddress;
emit MCAddressSet(oldNftMasterChefAddress, _nftMasterChefAddress);
}
function changeDaoAddress(address _daoAddress) external onlyOwner() {
require(_daoAddress != address(0), "!0");
address oldDaoAddress = daoAddress;
daoAddress = _daoAddress;
emit DaoAddressSet(oldDaoAddress, _daoAddress);
}
address public nftMasterChefAddress;
address public daoAddress = 0x994aF05EB0eA1Bb37dfEBd2EA279133C8059ffa7;
uint public lottery_share_percentage = 200;
uint internal immutable LAUNCH_TIME;
uint public currentDay;
function _updatePercentOfLobbyToBePooled() private {
uint oldPercentOfLobbyToBePooled = percentOfLobbyToBePooled;
percentOfLobbyToBePooled = 10000 - (lottery_share_percentage + masterchefUSDCShare + daoUSDCShare);
emit PercentOfLobbyToBePooledChanged(oldPercentOfLobbyToBePooled, percentOfLobbyToBePooled);
}
function set_lottery_share_percentage(uint _lottery_share_percentage) external onlyOwner() {
require(_lottery_share_percentage <= 1000);
uint oldLotterySharePercentage = lottery_share_percentage;
lottery_share_percentage = _lottery_share_percentage;
_updatePercentOfLobbyToBePooled();
emit LotteryShareSet(oldLotterySharePercentage, _lottery_share_percentage);
}
function set_masterchefUSDCWHEATShare(uint _masterchefUSDCShare, uint _masterchefWHEATShare) external onlyOwner() {
require(_masterchefUSDCShare <= 1000 && _masterchefWHEATShare <= 1000);
uint oldMasterchefUSDCShare = masterchefUSDCShare;
uint oldMasterchefWHEATShare = masterchefWHEATShare;
masterchefUSDCShare = _masterchefUSDCShare;
masterchefWHEATShare = _masterchefWHEATShare;
_updatePercentOfLobbyToBePooled();
emit MCUSDCWHEATShares(oldMasterchefUSDCShare, oldMasterchefWHEATShare, _masterchefUSDCShare, _masterchefWHEATShare);
}
function set_daoUSDCWHEATShares(uint _daoUSDCShare, uint _daoWHEATShare) external onlyOwner() {
require(_daoUSDCShare <= 1000 && _daoWHEATShare <= 1000);
uint oldDaoUSDCShare = daoUSDCShare;
uint oldDaoWHEATShare = daoWHEATShare;
daoUSDCShare = _daoUSDCShare;
daoWHEATShare = _daoWHEATShare;
_updatePercentOfLobbyToBePooled();
emit DaoUSDCWHEATShares(oldDaoUSDCShare, oldDaoWHEATShare, _daoUSDCShare, _daoWHEATShare);
}
uint public masterchefUSDCShare = 500;
uint public masterchefWHEATShare = 1000;
uint public daoUSDCShare = 500;
uint public daoWHEATShare = 1000;
function set_lastLobbyPool(uint _lastLobbyPool) external onlyOwner() {
uint oldLastLobbyPool = lastLobbyPool;
lastLobbyPool = _lastLobbyPool;
emit LastLobbySet(oldLastLobbyPool, _lastLobbyPool);
}
mapping(uint => uint) public lobbyPool;
uint public lastLobbyPool = 5050505050505050505051;
uint internal constant lobby_pool_decrease_percentage = 100;
uint public percentOfLobbyToBePooled;
uint internal constant bonus_calc_ratio = 310;
uint public constant max_stake_days = 180;
uint public constant ref_bonus_NR = 300;
uint public constant ref_bonus_NRR = 200;
function set_dividendsPoolCapDays(uint _dividendsPoolCapDays) external onlyOwner() {
require(_dividendsPoolCapDays > 0 && _dividendsPoolCapDays <= 300);
uint oldDividendsPoolCapDays = dividendsPoolCapDays;
dividendsPoolCapDays = _dividendsPoolCapDays;
emit DividensPoolCalDaysSet(oldDividendsPoolCapDays, _dividendsPoolCapDays);
}
uint public dividendsPoolCapDays = 50;
bool public loaningIsPaused = false;
bool public stakeSellingIsPaused = false;
bool public virtualBalanceEnteringIsPaused = false;
mapping(address => address) public usersLastReferrer;
struct memberLobby_overallData {
uint overall_collectedTokens;
uint overall_lobbyEnteries;
uint overall_stakedTokens;
uint overall_collectedDivs;
}
uint public overall_lobbyEntry;
uint public overall_stakedTokens;
uint public overall_collectedTokens;
uint public overall_collectedDivs;
uint public overall_collectedBonusTokens;
mapping(address => uint) public referrerBonusesPaid;
mapping(uint => uint) public usersCountDaily;
uint public usersCount = 0;
uint public saveTotalToken;
struct memberLobby {
uint extraVirtualTokens;
uint entryAmount;
uint entryDay;
bool collected;
address referrer;
}
function getMapMemberLobbyEntryByDay(address user, uint day) external view returns (uint) {
return mapMemberLobby[user][day].entryAmount;
}
mapping(address => mapping(uint => memberLobby)) public mapMemberLobby;
mapping(uint => uint) public lobbyEntry;
struct memberStake {
address userAddress;
uint tokenValue;
uint startDay;
uint endDay;
uint stakeId;
uint price;
uint loansReturnAmount;
bool collected;
bool hasSold;
bool forSell;
bool hasLoan;
bool forLoan;
}
mapping(address => mapping(uint => memberStake)) public mapMemberStake;
function switchLoaningStatus() external onlyOwner() {
loaningIsPaused = !loaningIsPaused;
emit LoaningStatusSwitched(!loaningIsPaused, loaningIsPaused);
}
function switchVirtualBalanceEntering() external onlyOwner() {
virtualBalanceEnteringIsPaused = !virtualBalanceEnteringIsPaused;
emit VirtualBalanceEnteringSwitched(!virtualBalanceEnteringIsPaused, virtualBalanceEnteringIsPaused);
}
function switchStakeSellingStatus() external onlyOwner() {
stakeSellingIsPaused = !stakeSellingIsPaused;
emit StakeSellingStatusSwitched(!stakeSellingIsPaused, stakeSellingIsPaused);
}
function flushLottyPool() external onlyOwner() nonReentrant {
if (lottery_Pool > 0) {
uint256 amount = lottery_Pool;
lottery_Pool = 0;
token_USDC.transfer(daoAddress, amount);
emit LottyPoolFlushed(daoAddress, amount);
}
}
function flushDevShareOfStakeSells() external onlyOwner() nonReentrant {
require(devShareOfStakeSellsAndLoanFee > 0);
token_USDC.transfer(address(daoAddress), devShareOfStakeSellsAndLoanFee);
uint oldDevShareOfStakeSellsAndLoanFee = devShareOfStakeSellsAndLoanFee;
devShareOfStakeSellsAndLoanFee = 0;
emit DevShareOfStakeSellsFlushed(daoAddress, oldDevShareOfStakeSellsAndLoanFee);
}
function _clcDay() public view returns (uint) {
if (block.timestamp <= LAUNCH_TIME) return 0;
return (block.timestamp - LAUNCH_TIME) / 1 days;
}
function updateDaily() public {
uint _currentDay = _clcDay();
if (currentDay != _currentDay) {
if (currentDay < dividendsPoolCapDays) {
for (uint _day = currentDay + 1; _day <= (currentDay * 2 + 1); _day++) {
dayUSDCPool[_day] += currentDay > 0 ? (lobbyEntry[currentDay] * percentOfLobbyToBePooled) / ((currentDay + 1) * 10000) : 0;
}
} else {
for (uint _day = currentDay + 1; _day <= currentDay + dividendsPoolCapDays; _day++) {
dayUSDCPool[_day] += (lobbyEntry[currentDay] * percentOfLobbyToBePooled) / (dividendsPoolCapDays * 10000);
}
}
currentDay = _currentDay;
_updateLobbyPool();
lobbyPool[currentDay] = lastLobbyPool;
_sendShares();
checkLottery();
emit DayLobbyEntry(currentDay, lobbyEntry[currentDay - 1]);
}
}
function _updateLobbyPool() internal {
lastLobbyPool -= ((lastLobbyPool * lobby_pool_decrease_percentage) /10000);
}
function _sendShares() internal {
require(currentDay > 0);
if (daoAddress != address(0)) {
uint daoUSDCRawShare = (lobbyEntry[currentDay - 1] * daoUSDCShare) /10000;
token_USDC.transfer(address(daoAddress), daoUSDCRawShare);
}
if (nftMasterChefAddress != address(0)) {
uint masterchefUSDCRawShare = (lobbyEntry[currentDay - 1] * masterchefUSDCShare) /10000;
token_USDC.transfer(address(nftMasterChefAddress), masterchefUSDCRawShare);
}
}
function virtualBalanceEnteringLobby(address referrerAddr, uint stakeId) external nonReentrant {
require(virtualBalanceEnteringIsPaused == false, "paused");
require(mapMemberStake[msg.sender][stakeId].endDay <= currentDay, "Locked stake");
DoEndStake(stakeId, true);
uint profit = calcStakeCollecting(msg.sender, stakeId);
DoEnterLobby(referrerAddr, profit + ((profit * 10) /100), ((profit * 10) /100));
}
function EnterLobby(address referrerAddr, uint amount) external {
DoEnterLobby(referrerAddr, amount, 0);
}
function DoEnterLobby(
address referrerAddr,
uint amount,
uint virtualExtraAmount
) internal {
uint rawAmount = amount;
require(rawAmount > 0, "!0");
if (virtualExtraAmount == 0) {
token_USDC.transferFrom(msg.sender, address(this), amount);
}
updateDaily();
require(currentDay > 0, "lobby disabled on day 0!");
if (mapMemberLobby[msg.sender][currentDay].entryAmount == 0) {
usersCount++;
usersCountDaily[currentDay]++;
}
if (virtualExtraAmount > 0) {
lobbyEntry[currentDay] += (rawAmount - virtualExtraAmount);
overall_lobbyEntry += (rawAmount - virtualExtraAmount);
mapMemberLobby[msg.sender][currentDay].extraVirtualTokens += virtualExtraAmount;
} else {
lobbyEntry[currentDay] += rawAmount;
overall_lobbyEntry += rawAmount;
}
mapMemberLobby[msg.sender][currentDay].entryAmount += rawAmount;
if (mapMemberLobby[msg.sender][currentDay].entryAmount > lottery_topBuy_today) {
lottery_topBuy_today = mapMemberLobby[msg.sender][currentDay].entryAmount;
lottery_topBuyer_today = msg.sender;
}
mapMemberLobby[msg.sender][currentDay].entryDay = currentDay;
mapMemberLobby[msg.sender][currentDay].collected = false;
if ((referrerAddr == address(0) || referrerAddr == msg.sender) &&
usersLastReferrer[msg.sender] != address(0) && usersLastReferrer[msg.sender] != msg.sender) {
mapMemberLobby[msg.sender][currentDay].referrer = usersLastReferrer[msg.sender];
} else if (referrerAddr != msg.sender && referrerAddr != address(0)) {
usersLastReferrer[msg.sender] = referrerAddr;
mapMemberLobby[msg.sender][currentDay].referrer = referrerAddr;
}
emit UserLobby(msg.sender, rawAmount, virtualExtraAmount, mapMemberLobby[msg.sender][currentDay].referrer);
}
function setNftAddressAllowList(address _series, bool allowed) external onlyOwner() {
nftAddressAllowList[_series] = allowed;
emit NftAddressAllowListSet(_series, allowed);
}
function getNFTType(address series) internal view returns (uint) {
return FarmerLandNFT(series).nftType();
}
function setUserNFTRoostings(address series, uint tokenId) external nonReentrant {
require(nftAddressAllowList[series]);
require(tokenId == 0 || isNftIdRoostingWithOwner(msg.sender, series, tokenId), "!roosted");
uint nftType = getNFTType(series);
uint prevTokenId;
if (nftType == 1) {
prevTokenId = farmerNFTRoost[msg.sender].tokenId;
farmerNFTRoost[msg.sender].series = series;
farmerNFTRoost[msg.sender].tokenId = tokenId;
} else if (nftType == 2) {
prevTokenId = landNFTRoost[msg.sender].tokenId;
landNFTRoost[msg.sender].series = series;
landNFTRoost[msg.sender].tokenId = tokenId;
} else if (nftType == 3) {
prevTokenId = toolNFTRoost[msg.sender].tokenId;
toolNFTRoost[msg.sender].series = series;
toolNFTRoost[msg.sender].tokenId = tokenId;
} else if (nftType == 4) {
prevTokenId = minotaurNFTRoost[msg.sender].tokenId;
minotaurNFTRoost[msg.sender].series = series;
minotaurNFTRoost[msg.sender].tokenId = tokenId;
}
emit NFTRoosted(series, tokenId, prevTokenId);
}
function isNftIdRoostingWithOwner(address owner, address series, uint tokenId) internal view returns (bool) {
if (series != address(0))
return FarmerLandNFT(series).isNftIdRoostingWithOwner(owner, tokenId);
else
return false;
}
function getNFTAbility(address series, uint tokenId) internal view returns (uint) {
return FarmerLandNFT(series).getAbility(tokenId);
}
function _clcNFTBoost(uint amount, uint ability ) internal pure returns (uint) {
return (amount * (1e12 * 105 / 100 + (((1e12 * ability * 3) / 1000) / 1e4))) / 1e12;
}
function getNFTRoostingBoostedAmount(uint tokenAmount) public view returns (uint) {
if (isNftIdRoostingWithOwner(msg.sender, farmerNFTRoost[msg.sender].series, farmerNFTRoost[msg.sender].tokenId)) {
tokenAmount = _clcNFTBoost(
tokenAmount,
getNFTAbility(farmerNFTRoost[msg.sender].series, farmerNFTRoost[msg.sender].tokenId)
);
if (isNftIdRoostingWithOwner(msg.sender, toolNFTRoost[msg.sender].series, toolNFTRoost[msg.sender].tokenId)) {
tokenAmount = _clcNFTBoost(
tokenAmount,
getNFTAbility(toolNFTRoost[msg.sender].series, toolNFTRoost[msg.sender].tokenId)
);
}
}
if (isNftIdRoostingWithOwner(msg.sender, landNFTRoost[msg.sender].series, landNFTRoost[msg.sender].tokenId)) {
tokenAmount = _clcNFTBoost(
tokenAmount,
getNFTAbility(landNFTRoost[msg.sender].series, landNFTRoost[msg.sender].tokenId)
);
}
if (isNftIdRoostingWithOwner(msg.sender, minotaurNFTRoost[msg.sender].series, minotaurNFTRoost[msg.sender].tokenId)) {
tokenAmount = _clcNFTBoost(
tokenAmount,
getNFTAbility(minotaurNFTRoost[msg.sender].series, minotaurNFTRoost[msg.sender].tokenId)
);
}
return tokenAmount;
}
function ExitLobby(uint targetDay) external {
require(mapMemberLobby[msg.sender][targetDay].collected == false, "Already collected");
updateDaily();
require(targetDay < currentDay);
uint tokensToPay = clcTokenValue(msg.sender, targetDay);
uint exitLobbyWHEATAmount = getNFTRoostingBoostedAmount(tokensToPay);
mapMemberLobby[msg.sender][targetDay].collected = true;
overall_collectedTokens += exitLobbyWHEATAmount;
_mint(msg.sender, exitLobbyWHEATAmount);
if (nftMasterChefAddress != address(0) && exitLobbyWHEATAmount > 0 && masterchefWHEATShare > 0)
_mint(nftMasterChefAddress, (exitLobbyWHEATAmount * masterchefWHEATShare) /10000);
if (daoAddress != address(0) && exitLobbyWHEATAmount > 0 && daoWHEATShare > 0)
_mint(daoAddress, (exitLobbyWHEATAmount * daoWHEATShare) /10000);
address referrerAddress = mapMemberLobby[msg.sender][targetDay].referrer;
if (referrerAddress != address(0)) {
uint refBonus = (tokensToPay * ref_bonus_NR) /10000;
referrerBonusesPaid[referrerAddress] += refBonus;
_mint(referrerAddress, refBonus);
_mint(msg.sender, (tokensToPay * ref_bonus_NRR) /10000);
}
emit UserLobbyCollect(msg.sender, tokensToPay, targetDay, exitLobbyWHEATAmount, masterchefWHEATShare, daoWHEATShare, ref_bonus_NR, ref_bonus_NRR);
}
function clcTokenValue(address _address, uint _day) public view returns (uint) {
require(_day != 0, "lobby disabled on day 0!");
uint _tokenValue;
uint entryDay = mapMemberLobby[_address][_day].entryDay;
if (entryDay != 0 && entryDay < currentDay) {
_tokenValue = (lobbyPool[_day] * mapMemberLobby[_address][_day].entryAmount) / lobbyEntry[entryDay];
} else {
_tokenValue = 0;
}
return _tokenValue;
}
mapping(uint => uint) public dayUSDCPool;
mapping(uint => uint) public enterytokenMath;
mapping(uint => uint) public totalTokensInActiveStake;
function EnterStake(uint amount, uint stakingDays) external {
require(amount > 0, "Can't be zero wheat");
require(stakingDays >= 1, "Staking days < 1");
require(stakingDays <= max_stake_days, "Staking days > max_stake_days");
require(balanceOf(msg.sender) >= amount, "!userbalance");
_burn(msg.sender, amount);
updateDaily();
uint stakeId = stakeCounts[msg.sender];
stakeCounts[msg.sender]++;
overall_stakedTokens += amount;
mapMemberStake[msg.sender][stakeId].stakeId = stakeId;
mapMemberStake[msg.sender][stakeId].userAddress = msg.sender;
mapMemberStake[msg.sender][stakeId].tokenValue = amount;
mapMemberStake[msg.sender][stakeId].startDay = currentDay + 1;
mapMemberStake[msg.sender][stakeId].endDay = currentDay + 1 + stakingDays;
mapMemberStake[msg.sender][stakeId].collected = false;
mapMemberStake[msg.sender][stakeId].hasSold = false;
mapMemberStake[msg.sender][stakeId].hasLoan = false;
mapMemberStake[msg.sender][stakeId].forSell = false;
mapMemberStake[msg.sender][stakeId].forLoan = false;
for (uint i = currentDay + 1; i <= currentDay + stakingDays; i++) {
totalTokensInActiveStake[i] += amount;
}
saveTotalToken += amount;
emit UserStake(msg.sender, amount, stakingDays, stakeId);
}
function EndStake(uint stakeId) external nonReentrant {
DoEndStake(stakeId, false);
}
function DoEndStake(uint stakeId, bool doNotSendDivs) internal {
require(mapMemberStake[msg.sender][stakeId].endDay <= currentDay, "Locked stake");
require(mapMemberStake[msg.sender][stakeId].userAddress == msg.sender);
require(mapMemberStake[msg.sender][stakeId].collected == false);
require(mapMemberStake[msg.sender][stakeId].hasSold == false);
updateDaily();
mapMemberStake[msg.sender][stakeId].forSell = false;
mapMemberStake[msg.sender][stakeId].forLoan = false;
uint profit = calcStakeCollecting(msg.sender, stakeId);
overall_collectedDivs += profit;
mapMemberStake[msg.sender][stakeId].collected = true;
if (doNotSendDivs == false) {
token_USDC.transfer(address(msg.sender), profit);
}
if (mapMemberStake[msg.sender][stakeId].hasLoan == true) {
updateFinishedLoan(
mapRequestingLoans[msg.sender][stakeId].lenderAddress,
msg.sender,
mapRequestingLoans[msg.sender][stakeId].lenderLendId,
stakeId
);
}
uint stakeReturn = mapMemberStake[msg.sender][stakeId].tokenValue;
uint bonusAmount;
if (stakeReturn != 0) {
bonusAmount = calcBonusToken(mapMemberStake[msg.sender][stakeId].endDay - mapMemberStake[msg.sender][stakeId].startDay, stakeReturn);
bonusAmount = getNFTRoostingBoostedAmount(bonusAmount);
overall_collectedBonusTokens += bonusAmount;
uint endStakeWHEATMintAmount = stakeReturn + bonusAmount;
_mint(msg.sender, endStakeWHEATMintAmount);
if (nftMasterChefAddress != address(0) && bonusAmount > 0 && masterchefWHEATShare > 0)
_mint(nftMasterChefAddress, (bonusAmount * masterchefWHEATShare) /10000);
if (daoAddress != address(0) && bonusAmount > 0 && daoWHEATShare > 0)
_mint(daoAddress, (bonusAmount * daoWHEATShare) /10000);
}
emit UserStakeCollect(msg.sender, profit, stakeId, bonusAmount);
}
function calcStakeCollecting(address _address, uint _stakeId) public view returns (uint) {
uint userDivs;
uint _endDay = mapMemberStake[_address][_stakeId].endDay;
uint _startDay = mapMemberStake[_address][_stakeId].startDay;
uint _stakeValue = mapMemberStake[_address][_stakeId].tokenValue;
for (uint _day = _startDay; _day < _endDay && _day < currentDay; _day++) {
userDivs += (dayUSDCPool[_day] * _stakeValue * 1e6) / totalTokensInActiveStake[_day];
}
userDivs /= 1e6;
return (userDivs - mapMemberStake[_address][_stakeId].loansReturnAmount);
}
function calcBonusToken(uint StakeDuration, uint StakeAmount) public pure returns (uint) {
require(StakeDuration <= max_stake_days, "Staking days > max_stake_days");
uint _bonusAmount = (StakeAmount * (StakeDuration**2) * bonus_calc_ratio) / 1e7;
_bonusAmount+= (StakeAmount * (StakeDuration/30) * 150) / 1e4;
return _bonusAmount;
}
uint public devShareOfStakeSellsAndLoanFee;
uint public totalStakesSold;
uint public totalTradeAmount;
mapping(address => uint) public soldStakeFunds;
function sellStakeRequest(uint stakeId, uint price) external {
updateDaily();
require(stakeSellingIsPaused == false, "paused");
require(mapMemberStake[msg.sender][stakeId].userAddress == msg.sender, "!auth");
require(mapMemberStake[msg.sender][stakeId].hasLoan == false, "Has active loan");
require(mapMemberStake[msg.sender][stakeId].hasSold == false, "Stake sold");
require(mapMemberStake[msg.sender][stakeId].endDay > currentDay, "Has ended");
if (mapMemberStake[msg.sender][stakeId].forLoan == true) {
cancelStakeLoanRequest(stakeId);
}
require(mapMemberStake[msg.sender][stakeId].forLoan == false);
mapMemberStake[msg.sender][stakeId].forSell = true;
mapMemberStake[msg.sender][stakeId].price = price;
emit StakeSellRequest(msg.sender, price, mapMemberStake[msg.sender][stakeId].tokenValue, stakeId);
}
function sellStakeCancelRequest(uint stakeId) external {
updateDaily();
require(stakeSellingIsPaused == false, "paused");
cancelSellStakeRequest(stakeId);
}
function buyStakeRequest(
address sellerAddress,
uint stakeId,
uint amount
) external {
updateDaily();
require(stakeSellingIsPaused == false, "paused");
require(mapMemberStake[sellerAddress][stakeId].userAddress != msg.sender, "no self buy");
require(mapMemberStake[sellerAddress][stakeId].userAddress == sellerAddress, "!auth");
require(mapMemberStake[sellerAddress][stakeId].hasSold == false, "Stake sold");
require(mapMemberStake[sellerAddress][stakeId].forSell == true, "!for sell");
uint priceP = amount;
require(mapMemberStake[sellerAddress][stakeId].price == priceP, "!funds");
require(mapMemberStake[sellerAddress][stakeId].endDay > currentDay);
token_USDC.transferFrom(msg.sender, address(this), amount);
uint pc90 = (mapMemberStake[sellerAddress][stakeId].price * 90) /100;
uint pc10 = mapMemberStake[sellerAddress][stakeId].price - pc90;
uint pc2 = pc10 / 5;
lobbyEntry[currentDay] += pc10 - pc2;
devShareOfStakeSellsAndLoanFee += pc2;
soldStakeFunds[sellerAddress] += pc90;
mapMemberStake[sellerAddress][stakeId].hasSold = true;
mapMemberStake[sellerAddress][stakeId].forSell = false;
mapMemberStake[sellerAddress][stakeId].collected = true;
totalStakesSold += 1;
totalTradeAmount += priceP;
uint newStakeId = stakeCounts[msg.sender];
stakeCounts[msg.sender]++;
mapMemberStake[msg.sender][newStakeId].userAddress = msg.sender;
mapMemberStake[msg.sender][newStakeId].tokenValue = mapMemberStake[sellerAddress][stakeId].tokenValue;
mapMemberStake[msg.sender][newStakeId].startDay = mapMemberStake[sellerAddress][stakeId].startDay;
mapMemberStake[msg.sender][newStakeId].endDay = mapMemberStake[sellerAddress][stakeId].endDay;
mapMemberStake[msg.sender][newStakeId].loansReturnAmount = mapMemberStake[sellerAddress][stakeId].loansReturnAmount;
mapMemberStake[msg.sender][newStakeId].stakeId = newStakeId;
mapMemberStake[msg.sender][newStakeId].collected = false;
mapMemberStake[msg.sender][newStakeId].hasSold = false;
mapMemberStake[msg.sender][newStakeId].hasLoan = false;
mapMemberStake[msg.sender][newStakeId].forSell = false;
mapMemberStake[msg.sender][newStakeId].forLoan = false;
mapMemberStake[msg.sender][newStakeId].price = 0;
emit StakeBuyRequest(sellerAddress, stakeId, msg.sender, newStakeId, amount);
}
function withdrawSoldStakeFunds() external nonReentrant {
require(soldStakeFunds[msg.sender] > 0, "!funds");
uint toBeSend = soldStakeFunds[msg.sender];
soldStakeFunds[msg.sender] = 0;
token_USDC.transfer(address(msg.sender), toBeSend);
emit WithdrawSoldStakeFunds(msg.sender, toBeSend);
}
struct loanRequest {
address loanerAddress;
address lenderAddress;
uint stakeId;
uint lenderLendId;
uint loanAmount;
uint returnAmount;
uint duration;
uint lend_startDay;
uint lend_endDay;
bool hasLoan;
bool loanIsPaid;
}
struct lendInfo {
address lenderAddress;
address loanerAddress;
uint lenderLendId;
uint loanAmount;
uint returnAmount;
uint endDay;
bool loanIsPaid;
}
mapping(address => uint) public LoanedFunds;
mapping(address => uint) public LendedFunds;
uint public totalLoanedAmount;
uint public totalLoanedCount;
mapping(address => mapping(uint => loanRequest)) public mapRequestingLoans;
mapping(address => mapping(uint => lendInfo)) public mapLenderInfo;
mapping(address => uint) public lendersPaidAmount;
function getLoanOnStake(
uint stakeId,
uint loanAmount,
uint returnAmount,
uint loanDuration
) external {
updateDaily();
require(loaningIsPaused == false, "paused");
require(loanAmount < returnAmount, "need loanAmount < returnAmount");
require(mapMemberStake[msg.sender][stakeId].userAddress == msg.sender, "!auth");
require(mapMemberStake[msg.sender][stakeId].hasLoan == false, "Has active loan");
require(mapMemberStake[msg.sender][stakeId].hasSold == false, "Stake sold");
require(mapMemberStake[msg.sender][stakeId].endDay > currentDay + loanDuration);
uint stakeDivs = calcStakeCollecting(msg.sender, stakeId);
require(returnAmount <= stakeDivs);
if (mapMemberStake[msg.sender][stakeId].forSell == true) {
cancelSellStakeRequest(stakeId);
}
require(mapMemberStake[msg.sender][stakeId].forSell == false);
mapMemberStake[msg.sender][stakeId].forLoan = true;
mapRequestingLoans[msg.sender][stakeId].loanerAddress = msg.sender;
mapRequestingLoans[msg.sender][stakeId].stakeId = stakeId;
mapRequestingLoans[msg.sender][stakeId].loanAmount = loanAmount;
mapRequestingLoans[msg.sender][stakeId].returnAmount = returnAmount;
mapRequestingLoans[msg.sender][stakeId].duration = loanDuration;
mapRequestingLoans[msg.sender][stakeId].loanIsPaid = false;
emit StakeLoanRequest(msg.sender, loanAmount, returnAmount, loanDuration, stakeId);
}
function cancelStakeLoanRequest(uint stakeId) public {
require(mapMemberStake[msg.sender][stakeId].hasLoan == false);
mapMemberStake[msg.sender][stakeId].forLoan = false;
emit CancelStakeLoanRequest(msg.sender, stakeId);
}
function cancelSellStakeRequest(uint stakeId) internal {
require(mapMemberStake[msg.sender][stakeId].userAddress == msg.sender);
require(mapMemberStake[msg.sender][stakeId].forSell == true);
require(mapMemberStake[msg.sender][stakeId].hasSold == false);
mapMemberStake[msg.sender][stakeId].forSell = false;
emit CancelStakeSellRequest(msg.sender, stakeId);
}
function lendOnStake(
address loanerAddress,
uint stakeId,
uint amount
) external nonReentrant {
updateDaily();
require(loaningIsPaused == false, "paused");
require(mapMemberStake[loanerAddress][stakeId].userAddress != msg.sender, "no self lend");
require(mapMemberStake[loanerAddress][stakeId].hasLoan == false, "Has active loan");
require(mapMemberStake[loanerAddress][stakeId].forLoan == true, "!requesting a loan");
require(mapMemberStake[loanerAddress][stakeId].hasSold == false, "Stake is sold");
require(mapMemberStake[loanerAddress][stakeId].endDay > currentDay, "Stake finished");
uint loanAmount = mapRequestingLoans[loanerAddress][stakeId].loanAmount;
uint returnAmount = mapRequestingLoans[loanerAddress][stakeId].returnAmount;
uint rawAmount = amount;
require(rawAmount == mapRequestingLoans[loanerAddress][stakeId].loanAmount);
token_USDC.transferFrom(msg.sender, address(this), amount);
uint theLoanFee = (rawAmount * 2) /100;
devShareOfStakeSellsAndLoanFee += theLoanFee - (theLoanFee /2);
lobbyEntry[currentDay] += theLoanFee /2;
mapMemberStake[loanerAddress][stakeId].loansReturnAmount += returnAmount;
mapMemberStake[loanerAddress][stakeId].hasLoan = true;
mapMemberStake[loanerAddress][stakeId].forLoan = false;
uint lenderLendId = clcLenderLendId(msg.sender);
mapRequestingLoans[loanerAddress][stakeId].hasLoan = true;
mapRequestingLoans[loanerAddress][stakeId].loanIsPaid = false;
mapRequestingLoans[loanerAddress][stakeId].lenderAddress = msg.sender;
mapRequestingLoans[loanerAddress][stakeId].lenderLendId = lenderLendId;
mapRequestingLoans[loanerAddress][stakeId].lend_startDay = currentDay;
mapRequestingLoans[loanerAddress][stakeId].lend_endDay = currentDay + mapRequestingLoans[loanerAddress][stakeId].duration;
mapLenderInfo[msg.sender][lenderLendId].lenderAddress = msg.sender;
mapLenderInfo[msg.sender][lenderLendId].loanerAddress = loanerAddress;
mapLenderInfo[msg.sender][lenderLendId].lenderLendId = lenderLendId;
mapLenderInfo[msg.sender][lenderLendId].loanAmount = loanAmount;
mapLenderInfo[msg.sender][lenderLendId].returnAmount = returnAmount;
mapLenderInfo[msg.sender][lenderLendId].endDay = mapRequestingLoans[loanerAddress][stakeId].lend_endDay;
uint resultAmount = rawAmount - theLoanFee;
LoanedFunds[loanerAddress] += resultAmount;
LendedFunds[msg.sender] += resultAmount;
totalLoanedAmount += resultAmount;
totalLoanedCount += 1;
emit StakeLend(msg.sender, lenderLendId, loanerAddress, stakeId, rawAmount);
}
function withdrawLoanedFunds() external nonReentrant {
require(LoanedFunds[msg.sender] > 0, "!funds");
uint toBeSend = LoanedFunds[msg.sender];
LoanedFunds[msg.sender] = 0;
token_USDC.transfer(address(msg.sender), toBeSend);
emit WithdrawLoanedFunds(msg.sender, toBeSend);
}
function clcLenderLendId(address _address) public view returns (uint) {
uint stakeCount = 0;
for (uint i = 0; mapLenderInfo[_address][i].lenderAddress == _address; i++) {
stakeCount += 1;
}
return stakeCount;
}
function collectLendReturn(uint stakeId, uint lenderLendId) external nonReentrant {
updateFinishedLoan(msg.sender, mapLenderInfo[msg.sender][lenderLendId].loanerAddress, lenderLendId, stakeId);
}
function updateFinishedLoan(
address lenderAddress,
address loanerAddress,
uint lenderLendId,
uint stakeId
) internal {
updateDaily();
require(mapMemberStake[loanerAddress][stakeId].hasLoan == true, "Stake has no active loan");
require(currentDay >= mapRequestingLoans[loanerAddress][stakeId].lend_endDay, "Due date not yet reached");
require(mapLenderInfo[lenderAddress][lenderLendId].loanIsPaid == false);
require(mapRequestingLoans[loanerAddress][stakeId].loanIsPaid == false);
require(mapRequestingLoans[loanerAddress][stakeId].hasLoan == true);
require(mapRequestingLoans[loanerAddress][stakeId].lenderAddress == lenderAddress);
require(mapRequestingLoans[loanerAddress][stakeId].lenderLendId == lenderLendId);
mapMemberStake[loanerAddress][stakeId].hasLoan = false;
mapLenderInfo[lenderAddress][lenderLendId].loanIsPaid = true;
mapRequestingLoans[loanerAddress][stakeId].hasLoan = false;
mapRequestingLoans[loanerAddress][stakeId].loanIsPaid = true;
uint toBePaid = mapRequestingLoans[loanerAddress][stakeId].returnAmount;
lendersPaidAmount[lenderAddress] += toBePaid;
mapRequestingLoans[loanerAddress][stakeId].returnAmount = 0;
token_USDC.transfer(address(lenderAddress), toBePaid);
emit StakeLoanFinished(lenderAddress, lenderLendId, loanerAddress, stakeId, toBePaid);
}
uint public lottery_topBuy_today;
address public lottery_topBuyer_today;
uint public lottery_topBuy_latest;
uint public lottery_Pool;
function checkLottery() internal {
if (lottery_topBuy_today > lottery_topBuy_latest) {
lottery_topBuy_latest = lottery_topBuy_today;
if (currentDay >= 7) {
uint winnerAmount = (lottery_Pool * 50) /100;
lottery_Pool -= winnerAmount;
token_USDC.transfer(address(lottery_topBuyer_today), winnerAmount);
emit LotteryWinner(lottery_topBuyer_today, winnerAmount, lottery_topBuy_latest);
}
} else {
lottery_topBuy_latest -= (lottery_topBuy_latest * 200) /1000;
}
lottery_Pool += (lobbyEntry[currentDay - 1] * lottery_share_percentage) /10000;
lottery_topBuyer_today = address(0);
lottery_topBuy_today = 0;
emit LotteryUpdate(lottery_Pool, lottery_topBuy_latest);
}
}
{
"compilationTarget": {
"contracts/FarmerLandNFT.sol": "FarmerLandNFT"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_nftType","type":"uint256"},{"internalType":"uint256","name":"_MAX_ELEMENTS","type":"uint256"},{"internalType":"uint256","name":"_MAX_LEVEL","type":"uint256"},{"internalType":"uint256","name":"_ABILITY_SCALAR","type":"uint256"},{"internalType":"contract WHEAT","name":"_WHEAT","type":"address"},{"internalType":"string","name":"name1","type":"string"},{"internalType":"string","name":"name2","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldAbility","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAbility","type":"uint256"}],"name":"AbilitySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"numberOfAllocations","type":"uint256"}],"name":"AddToWhiteList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"AdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oldURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CreateFarmerLandNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldLevel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLevel","type":"uint256"}],"name":"LevelSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MATICPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"NFTRoosted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"NFTUnRoosted","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":"bool","name":"currentPausedStatus","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newStartTime","type":"uint256"}],"name":"StartTimeChanged","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":"uint256","name":"price","type":"uint256"}],"name":"WHEATPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasBalance","type":"uint256"}],"name":"WithdrawGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"wheatBalance","type":"uint256"}],"name":"WithdrawWHEAT","type":"event"},{"inputs":[],"name":"ABILITY_SCALAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ABILITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CONCURRENT_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ELEMENTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LEVEL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"participants","type":"address[]"}],"name":"addToWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"availableSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"foreverRoostingTimer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"founder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"freeMintWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getAbility","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":"uint256","name":"tokenId","type":"uint256"}],"name":"getLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"getMATICPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUsersNumberOfRoostings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"getWHEATPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"isNftIdRoosting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"isNftIdRoostingWithOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maticPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"roostNftId","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"_ability","type":"uint256"}],"name":"setAbility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAdmin","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setAdmins","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":"tokenId","type":"uint256"},{"internalType":"uint256","name":"_level","type":"uint256"}],"name":"setLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setMATICPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newStartTime","type":"uint256"}],"name":"setStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setWHEATPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"startOfCurrentRoosting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"nftId","type":"uint256"}],"name":"unroostNftId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRoostingsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"walletOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wheatPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wheatToken","outputs":[{"internalType":"contract WHEAT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawWHEAT","outputs":[],"stateMutability":"nonpayable","type":"function"}]