编译器
0.8.18+commit.87f61d96
文件 1 的 22: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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 22:Consts.sol
pragma solidity ^0.8.18;
enum Rarity {
OneStar,
TwoStar,
ThreeStar,
FourStar,
FiveStar
}
enum Rank { S, A, B, C, D }
enum NFTType { Explorer, Tool, Team }
enum NFTSubType { Type1, Type2, Type3 }
文件 3 的 22: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;
}
}
文件 4 的 22: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;
}
}
文件 5 的 22: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: address zero is not a valid owner");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
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) {
_requireMinted(tokenId);
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 token owner or approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
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: caller is not token owner or 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: caller is not token owner or 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 _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
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, 1);
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
owner = ERC721.ownerOf(tokenId);
delete _tokenApprovals[tokenId];
unchecked {
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
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, 1);
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
delete _tokenApprovals[tokenId];
unchecked {
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
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 _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
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 firstTokenId,
uint256 batchSize
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}
文件 6 的 22: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 firstTokenId,
uint256 batchSize
) internal virtual override {
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
if (batchSize > 1) {
revert("ERC721Enumerable: consecutive transfers not supported");
}
uint256 tokenId = firstTokenId;
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 的 22:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 8 的 22:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
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);
}
文件 9 的 22: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,
bytes calldata data
) external;
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 setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 10 的 22: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);
}
文件 11 的 22: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);
}
文件 12 的 22:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 13 的 22:IOracleGame.sol
pragma solidity ^0.8.18;
import "./Consts.sol";
interface IOracleGame {
function requestRandomness(uint256 min, uint256 max) external returns (uint256);
function fetchRandomNumber(uint256 requestId) external returns (uint256);
function getRarityAndPower(uint256 requestId) external returns (Rarity, uint256);
function getMaxTools(Rarity rarity) external pure returns (uint256);
function getExplorerPower(Rarity rarity, uint256 requestId) external returns (uint256);
function calculateSuccessRate(Rank teamRank, uint256 excavationLevel) external pure returns (uint256);
function calculateRewardIncrease(uint256 teamLevel) external view returns (uint256);
function getRewardsByExcavationLevel(uint256 excavationLevel) external view returns (uint256);
function getConvertedRewardsInToken(uint256 excavationLevel) external view returns (uint256);
function getRequiredExplorerPoints(uint256 excavationLevel) external pure returns (uint256);
function getNextLevelExperience(uint256 level) external view returns (uint256);
function getExperiencePointsEarned() external pure returns (uint256);
function calcTotalRewards(uint256 experiencePoints, uint256 excavationLevel) external view returns (uint256);
}
文件 14 的 22:IOraclePrice.sol
pragma solidity ^0.8.18;
interface IOraclePrice {
enum NFTType { Explorer, Tool }
function setExplorerPrice(uint256 dollarPrice) external;
function setToolPrice(uint256 dollarPrice) external;
function getPriceInTokensForQtity(IOraclePrice.NFTType nftType, uint256 quantity) external view returns (uint256);
function getUSDCAddress() external view returns (address);
function getTokensPerUSDC() external view returns(uint256);
function getContractPrice(uint256 period) external view returns (uint256);
function getContractPriceInTokens(uint256 period, uint256 numWorkers) external view returns (uint256);
}
文件 15 的 22:IRegistry.sol
pragma solidity ^0.8.18;
interface IRegistry {
function setNFTManager(address _nftManager) external;
function setExcavationManager(address _excavationManager) external;
function setMarketplace(address _marketplace) external;
function setOraclePrice(address _oraclePrice) external;
function setOracleGame(address _oracleGame) external;
function setReserve(address _reserve) external;
function setERC20(address _erc20) external;
function setUSDC(address _usdc) external;
function setUniswapRouter(address _uniswapRouter) external;
function setFeeRecipient(address _feeRecipient) external;
function setTokenETHPair(address _tokenETHPair) external;
function setETHUSDCPair(address _ETHUSDCPair) external;
function setTokenAddress(address _tokenAddress) external;
function setETHAddress(address _ETHAddress) external;
function getNFTManager() external view returns (address);
function getExcavationManager() external view returns (address);
function getMarketplace() external view returns (address);
function getOraclePrice() external view returns (address);
function getOracleGame() external view returns (address);
function getReserve() external view returns (address);
function getUSDC() external view returns (address);
function getUniswapRouter() external view returns (address);
function getFeeRecipient() external view returns (address);
function getTokenETHPair() external view returns (address);
function getETHUSDCPair() external view returns (address);
function getTokenAddress() external view returns (address);
function getETHAddress() external view returns (address);
}
文件 16 的 22:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
文件 17 的 22:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 18 的 22:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 19 的 22:NFTManager.sol
pragma solidity ^0.8.18;
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./oracle/IOraclePrice.sol";
import "./oracle/IOracleGame.sol";
import "./oracle/Consts.sol";
import "./IRegistry.sol";
contract NFTManager is ERC721Enumerable, Ownable, ReentrancyGuard {
struct ExplorerDetail {
uint256 maxTools;
bool revealed;
Rarity rarity;
}
struct ToolDetail {
uint256 explorerPower;
bool revealed;
Rarity rarity;
}
struct TeamDetail {
uint256[] explorerIds;
uint256[] toolIds;
}
struct NFTDetail {
NFTType nftType;
ExplorerDetail explorerDetail;
ToolDetail toolDetail;
TeamDetail teamDetail;
uint256 requestId;
}
struct Team {
string name;
uint256 miningPower;
Rank rank;
uint256 level;
uint256 experience;
uint256 numExplorers;
uint256 numTools;
uint256 contractDays;
uint256 contractStartDate;
uint256 totalRewards;
uint256 firstExcavationDay;
uint256 lastExcavationDay;
uint256 maxTools;
}
struct RewardInfo {
uint256 totalRewards;
uint256 lastExplorationDay;
}
IRegistry public registry;
mapping(uint256 => Team) public teams;
mapping(address => RewardInfo) public rewardInfos;
mapping(uint256 => NFTDetail) public nftDetails;
mapping(address => uint256) public firstExcavationTime;
uint256 private nonce;
uint256 private nftCounter;
uint256 public refundPercentage;
bool internal _paused;
event NFTMinted(address indexed owner, uint256 indexed tokenId, NFTType nftType);
event NFTRevealed(address indexed owner, uint256 indexed tokenId, NFTType nftType);
event TeamCreated(address indexed owner, uint256 indexed teamId, string name, uint256 totalPower, Rank teamRank);
event TeamDisassembled(address indexed owner, uint256 indexed teamId);
event ContractDaysSet(address indexed owner, uint256 indexed teamId, uint256 contractDays, uint256 totalCost);
event RewardsWithdrawn(address indexed owner, uint256 indexed teamId, uint256 amount, uint256 fee);
event AllRewardsWithdrawn(address indexed owner, uint256 totalAmount);
bool public swap;
constructor(
address registry_
) ERC721("MyNFTCollection", "MNFT") {
registry = IRegistry(registry_);
refundPercentage = 20;
swap = true;
}
modifier onlyTokenOwner(uint256 tokenId) {
require(ownerOf(tokenId) == msg.sender, "You must own the team");
_;
}
modifier isExists(uint256 teamId) {
require(_exists(teamId), "token does not exist");
_;
}
function setSwap(bool val) external onlyOwner{
swap = val;
}
function updateFirstExcavationTime( address user, uint256 teamId, uint256 time) external {
require(msg.sender == registry.getExcavationManager(), "Not allowed");
Team storage team = teams[teamId];
team.firstExcavationDay = time;
firstExcavationTime[user] = time;
}
function updateLastExcavationTime(uint256 teamId, uint256 time) external {
require(msg.sender == registry.getExcavationManager(), "Not allowed");
Team storage team = teams[teamId];
team.lastExcavationDay = time;
}
function getWithdrawalFee(address user) public view returns (uint256) {
if (firstExcavationTime[user] == 0) {
return 30;
}
uint256 daysSinceFirstExcavation = (block.timestamp - firstExcavationTime[user]) / 1 days;
if (daysSinceFirstExcavation == 0) {
return 30;
}
uint256 feeReduction = daysSinceFirstExcavation * 2;
if (feeReduction >= 30) {
return 0;
}
return 30 - feeReduction;
}
function updateTeamStats(
uint256 teamId,
uint256 reward,
uint256 experience,
uint256 level
) external {
require(msg.sender == registry.getExcavationManager(), "Not allowed");
Team storage team = teams[teamId];
team.totalRewards += reward;
team.experience = experience;
team.level = level;
}
function mintNFT(NFTType nftType, uint256 quantity) external {
require(quantity > 0 && quantity <= 20, "Wrong quantity");
uint256 totalPrice;
IOraclePrice oraclePrice = IOraclePrice(registry.getOraclePrice());
IERC20 paymentToken = IERC20(registry.getTokenAddress());
address reserve = registry.getReserve();
if (swap) {
if (nftType == NFTType.Explorer) {
totalPrice = oraclePrice.getPriceInTokensForQtity(IOraclePrice.NFTType.Explorer, quantity);
} else if (nftType == NFTType.Tool) {
totalPrice = oraclePrice.getPriceInTokensForQtity(IOraclePrice.NFTType.Tool, quantity);
} else {
revert("Invalid NFT");
}
} else {
totalPrice = quantity;
}
require(paymentToken.transferFrom(msg.sender, reserve, totalPrice), "Payment failed");
for (uint256 i = 0; i < quantity; i++) {
uint256 tokenId = nftCounter;
nftCounter++;
_mint(msg.sender, tokenId);
uint256 requestId = IOracleGame(registry.getOracleGame()).requestRandomness(1, 100);
if (nftType == NFTType.Explorer) {
nftDetails[tokenId] = NFTDetail(
NFTType.Explorer,
ExplorerDetail(0, false, Rarity.OneStar),
ToolDetail(0, false, Rarity.OneStar),
TeamDetail(new uint256[](0) , new uint256[](0)),
requestId
);
} else {
nftDetails[tokenId] = NFTDetail(
NFTType.Tool,
ExplorerDetail(0, false, Rarity.OneStar),
ToolDetail(0, false, Rarity.OneStar),
TeamDetail(new uint256[](0) , new uint256[](0)),
requestId
);
}
emit NFTMinted(msg.sender, tokenId, nftType);
}
}
function revealNFT(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Token not owned");
IOracleGame oracleGame = IOracleGame(registry.getOracleGame());
NFTType nftType = nftDetails[tokenId].nftType;
uint256 requestId = nftDetails[tokenId].requestId;
if (nftType == NFTType.Explorer) {
require(!nftDetails[tokenId].explorerDetail.revealed, "Explorer already revealed");
(Rarity rarity, ) = oracleGame.getRarityAndPower(requestId);
nftDetails[tokenId].explorerDetail.rarity = rarity;
nftDetails[tokenId].explorerDetail.maxTools = oracleGame.getMaxTools(rarity);
nftDetails[tokenId].explorerDetail.revealed = true;
} else if (nftType == NFTType.Tool) {
require(!nftDetails[tokenId].toolDetail.revealed, "Tool already revealed");
(Rarity rarity, uint256 explorerPower) = oracleGame.getRarityAndPower(requestId);
nftDetails[tokenId].toolDetail.rarity = rarity;
nftDetails[tokenId].toolDetail.explorerPower = explorerPower;
nftDetails[tokenId].toolDetail.revealed = true;
} else {
revert("Invalid NFT");
}
emit NFTRevealed(msg.sender, tokenId, nftType);
}
function createTeam(string memory teamName, uint256[] memory explorerIds, uint256[] memory toolIds) external {
require(bytes(teamName).length >= 3 && bytes(teamName).length <= 15, "Name must be between 3 and 15 characters");
require(explorerIds.length <= 10, "Cannot have more than 10 explorers");
uint256 totalPower = 0;
uint256 numExplorers = explorerIds.length;
uint256 numTools = toolIds.length;
uint256 teamId = nftCounter;
nftCounter++;
uint256 maxTools = 0;
uint256[] memory rarityCounts = new uint256[](5);
uint256[] memory explorerToolCount = new uint256[](explorerIds.length);
for (uint256 i = 0; i < explorerIds.length; i++) {
processExplorer(explorerIds[i], rarityCounts, explorerToolCount, i);
maxTools += nftDetails[explorerIds[i]].explorerDetail.maxTools;
_burn(explorerIds[i]);
}
for (uint256 i = 0; i < toolIds.length; i++) {
totalPower = processTool(toolIds[i], explorerIds, explorerToolCount, totalPower);
_burn(toolIds[i]);
}
require(totalPower >= 100, "Total power must be at least 100");
_mint(msg.sender, teamId);
teams[teamId] = Team({
name: teamName,
miningPower: totalPower,
rank: determineRank(rarityCounts),
level: 1,
experience: 0,
numExplorers: numExplorers,
numTools: numTools,
contractDays: 0,
contractStartDate: 0,
totalRewards: 0,
firstExcavationDay: 0,
lastExcavationDay: 0,
maxTools: maxTools
});
nftDetails[teamId] = NFTDetail(
NFTType.Team,
ExplorerDetail(0, false, Rarity.OneStar),
ToolDetail(0, false, Rarity.OneStar),
TeamDetail(explorerIds, toolIds),
0
);
emit TeamCreated(msg.sender, teamId, teamName, totalPower, determineRank(rarityCounts));
}
function burnNFT(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "You must own the NFT to burn it");
_burn(tokenId);
}
function disassembleTeam(uint256 teamId) onlyTokenOwner(teamId) external {
require(getRemainingContractTime(teamId) == 0, "Team is contracted");
uint256[] memory explorers = nftDetails[teamId].teamDetail.explorerIds;
uint256[] memory tools = nftDetails[teamId].teamDetail.toolIds;
for (uint256 i = 0; i < explorers.length; i++) {
uint256 oldExplorerId = explorers[i];
uint256 newExplorerId = nftCounter;
nftCounter++;
nftDetails[newExplorerId] = NFTDetail({
nftType: NFTType.Explorer,
explorerDetail: nftDetails[oldExplorerId].explorerDetail,
toolDetail: ToolDetail(0, false, Rarity.OneStar),
teamDetail: TeamDetail(new uint256[](0) , new uint256[](0)),
requestId: 0
});
_mint(msg.sender, newExplorerId);
}
for (uint256 i = 0; i < tools.length; i++) {
uint256 oldToolId = tools[i];
uint256 newToolId = nftCounter;
nftCounter++;
nftDetails[newToolId] = NFTDetail({
nftType: NFTType.Tool,
explorerDetail: ExplorerDetail(0, false, Rarity.OneStar),
toolDetail: nftDetails[oldToolId].toolDetail,
teamDetail: TeamDetail(new uint256[](0) , new uint256[](0)),
requestId: 0
});
_mint(msg.sender, newToolId);
}
_burn(teamId);
delete teams[teamId];
emit TeamDisassembled(msg.sender, teamId);
}
function setContractDays(uint256 teamId, uint256 contractDays) onlyTokenOwner(teamId) external {
Team storage team = teams[teamId];
require(!isTeamContractActive(teamId), "Team is already contracted");
uint256 totalCostInTokens = IOraclePrice(registry.getOraclePrice()).getContractPriceInTokens(contractDays, team.numTools);
require(totalCostInTokens > 0, "Invalid contract duration");
if (swap) {
address usdcAddress = registry.getUSDC();
IERC20 USDC = IERC20(usdcAddress);
IUniswapV2Router02 router = IUniswapV2Router02(registry.getUniswapRouter());
IERC20 paymentToken = IERC20(registry.getTokenAddress());
address[] memory path = new address[](3);
path[0] = address(paymentToken);
path[1] = router.WETH();
path[2] = usdcAddress;
require(paymentToken.transferFrom(msg.sender, address(this), totalCostInTokens), "Payment failed");
paymentToken.approve(address(router), totalCostInTokens);
router.swapExactTokensForTokens(
paymentToken.balanceOf(address(this)),
0,
path,
address(this),
block.timestamp
);
uint256 usdcBalance = USDC.balanceOf(address(this));
require(usdcBalance > 0, "Swap failed: no USDC received");
require(USDC.transfer(registry.getFeeRecipient(), usdcBalance), "USDC transfer to fee recipient failed");
}
team.contractDays = contractDays;
team.contractStartDate = block.timestamp;
emit ContractDaysSet(msg.sender, teamId, contractDays, totalCostInTokens);
}
function withdrawAllRewards() external nonReentrant {
IERC20 paymentToken = IERC20(registry.getTokenAddress());
uint256 withdrawalFee = getWithdrawalFee(msg.sender);
uint256[] memory userTeamIds = getTeamTokenIdsByOwner(msg.sender);
uint256 totalAmount = 0;
for (uint256 i = 0; i < userTeamIds.length; i++) {
uint256 teamId = userTeamIds[i];
Team storage team = teams[teamId];
uint256 fee = (team.totalRewards * withdrawalFee) / 100;
require(team.totalRewards >= fee, "Fee exceeds total rewards");
uint256 amountToTransfer = team.totalRewards - fee;
require(paymentToken.transferFrom(registry.getReserve(), ownerOf(teamId), amountToTransfer), "Reward transfer failed");
emit RewardsWithdrawn(ownerOf(teamId), teamId, amountToTransfer, fee);
totalAmount += amountToTransfer;
team.totalRewards = 0;
}
emit AllRewardsWithdrawn(msg.sender, totalAmount);
}
function setPause(bool val) external onlyOwner {
_paused = val;
}
function setRefundPercentage(uint256 val) external onlyOwner {
refundPercentage = val;
}
function emergencyWithdrawalTokens(address tokenAddress) external onlyOwner {
require(IERC20(tokenAddress).transfer(owner(), IERC20(tokenAddress).balanceOf(address(this))), "Transfer failed");
}
function paused() public view returns(bool){
return _paused;
}
function getUserRewardsAndPenalties(address user) external view returns (uint256 totalRewards, uint256 averagePenalty) {
uint256[] memory userTeamIds = getTeamTokenIdsByOwner(user);
uint256 totalPenalty = 0;
uint256 teamCount = userTeamIds.length;
for (uint256 i = 0; i < teamCount; i++) {
uint256 teamId = userTeamIds[i];
Team storage team = teams[teamId];
totalRewards += team.totalRewards;
}
if (teamCount > 0) {
averagePenalty = totalPenalty / teamCount;
} else {
averagePenalty = 0;
}
}
function getTeamTokenIdsByOwner(address owner) public view returns (uint256[] memory) {
uint256 tokenCount = balanceOf(owner);
uint256[] memory teamTokenIds = new uint256[](tokenCount);
uint256 teamCount = 0;
for (uint256 i = 0; i < tokenCount; i++) {
uint256 tokenId = tokenOfOwnerByIndex(owner, i);
if (nftDetails[tokenId].nftType == NFTType.Team) {
teamTokenIds[teamCount] = tokenId;
teamCount++;
}
}
bytes memory encoded = abi.encode(teamTokenIds);
assembly { mstore(add(encoded, 0x40), teamCount) }
return abi.decode(encoded, (uint256[]));
}
function isTeamContractActive(uint256 teamId) isExists(teamId) public view returns (bool) {
Team memory team = teams[teamId];
if (team.contractDays == 0) {
return false;
}
uint256 contractEndDate = team.contractStartDate + (team.contractDays * 1 days);
return block.timestamp <= contractEndDate;
}
function getRemainingContractTime(uint256 teamId) isExists(teamId) public view returns (uint256) {
Team memory team = teams[teamId];
if (team.contractDays == 0 || team.contractStartDate == 0) {
return 0;
}
uint256 contractEndDate = team.contractStartDate + (team.contractDays * 1 days);
if (block.timestamp > contractEndDate) {
return 0;
}
return contractEndDate - block.timestamp;
}
function getNFTDetail(uint256 tokenId) isExists(tokenId) external view returns (NFTType, ExplorerDetail memory, ToolDetail memory, TeamDetail memory) {
return (nftDetails[tokenId].nftType, nftDetails[tokenId].explorerDetail, nftDetails[tokenId].toolDetail, nftDetails[tokenId].teamDetail);
}
function getTeamDetails(uint256 teamId) external view returns (
string memory name,
uint256 miningPower,
Rank rank,
uint256 level,
uint256 experience,
uint256 numExplorers,
uint256 numTools,
uint256 contractDays,
uint256 contractStartDate,
uint256 totalRewards,
uint256 firstExcavationDay,
uint256 lastExacavationDay,
uint256 maxTools
) {
Team memory team = teams[teamId];
return (
team.name,
team.miningPower,
team.rank,
team.level,
team.experience,
team.numExplorers,
team.numTools,
team.contractDays,
team.contractStartDate,
team.totalRewards,
team.firstExcavationDay,
team.lastExcavationDay,
team.maxTools
);
}
function getTokenIdsByAddr(address addr, bool isRevealed, bool isExplorer) external view returns (uint256[] memory) {
uint256 tokenCount = balanceOf(addr);
uint256[] memory tokenIds = new uint256[](tokenCount);
uint256 count = 0;
for (uint256 i = 0; i < tokenCount; i++) {
uint256 tokenId = tokenOfOwnerByIndex(addr, i);
if (isExplorer) {
if (nftDetails[tokenId].nftType == NFTType.Explorer && nftDetails[tokenId].explorerDetail.revealed == isRevealed) {
tokenIds[count] = tokenId;
count++;
}
} else {
if (nftDetails[tokenId].nftType == NFTType.Tool && nftDetails[tokenId].toolDetail.revealed == isRevealed) {
tokenIds[count] = tokenId;
count++;
}
}
}
bytes memory encoded = abi.encode(tokenIds);
assembly { mstore(add(encoded, 0x40), count) }
return abi.decode(encoded, (uint256[]));
}
function getMaxToolsForOwner(address owner) external view returns (uint256) {
uint256 tokenCount = balanceOf(owner);
uint256 totalMaxTools = 0;
for (uint256 i = 0; i < tokenCount; i++) {
uint256 tokenId = tokenOfOwnerByIndex(owner, i);
if (nftDetails[tokenId].nftType == NFTType.Explorer) {
totalMaxTools += nftDetails[tokenId].explorerDetail.maxTools;
}
}
return totalMaxTools;
}
function getMaxToolsForTeam(uint256 teamId) isExists(teamId) external view returns (uint256) {
return teams[teamId].maxTools;
}
function calculateMaxToolsForExplorers(uint256[] memory explorerIds) external view returns (uint256) {
uint256 totalMaxTools = 0;
for (uint256 i = 0; i < explorerIds.length; i++) {
NFTDetail storage detail = nftDetails[explorerIds[i]];
require(detail.nftType == NFTType.Explorer, "Invalid explorer NFT ID");
totalMaxTools += detail.explorerDetail.maxTools;
}
return totalMaxTools;
}
function calculateExplorerPower(uint256[] memory toolIds) external view returns (uint256) {
uint256 totalExplorerPower = 0;
for (uint256 i = 0; i < toolIds.length; i++) {
NFTDetail storage detail = nftDetails[toolIds[i]];
require(detail.nftType == NFTType.Tool, "Invalid tool NFT ID");
totalExplorerPower += detail.toolDetail.explorerPower;
}
return totalExplorerPower;
}
function getMajorityRarityOfExplorers(uint256[] memory explorerIds) public view returns (uint256) {
uint256[] memory rarityCounts = new uint256[](5);
for (uint256 i = 0; i < explorerIds.length; i++) {
uint256 explorerId = explorerIds[i];
require(nftDetails[explorerId].nftType == NFTType.Explorer, "Invalid explorer NFT ID");
uint256 rarityIndex = uint256(nftDetails[explorerId].explorerDetail.rarity);
require(rarityIndex >= 1 && rarityIndex <= 5, "Invalid rarity index");
rarityCounts[rarityIndex - 1]++;
}
uint256 majorityRarity = 0;
uint256 maxCount = 0;
for (uint256 i = 0; i < rarityCounts.length; i++) {
if (rarityCounts[i] > maxCount) {
majorityRarity = i + 1;
maxCount = rarityCounts[i];
}
}
return majorityRarity;
}
function getMaxEPForAddr(address addr) external view returns (uint256) {
uint256 tokenCount = balanceOf(addr);
uint256 totalExplorerPower = 0;
for (uint256 i = 0; i < tokenCount; i++) {
uint256 tokenId = tokenOfOwnerByIndex(addr, i);
if (nftDetails[tokenId].nftType == NFTType.Tool) {
totalExplorerPower += nftDetails[tokenId].toolDetail.explorerPower;
}
}
return totalExplorerPower;
}
function getfirstExcavationDaysByAddress(address owner) external view returns (uint256[] memory) {
uint256[] memory teamIds = getTeamTokenIdsByOwner(owner);
uint256[] memory lastDays = new uint256[](teamIds.length);
for (uint256 i = 0; i < teamIds.length; i++) {
lastDays[i] = teams[teamIds[i]].firstExcavationDay;
}
return lastDays;
}
function getRewards(address user) external view returns (uint256 totalRewards, uint256 lastExplorationDay) {
return (rewardInfos[user].totalRewards, rewardInfos[user].lastExplorationDay);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal override {
require(
from == address(0) ||
to == address(0) ||
from == owner() ||
msg.sender == registry.getMarketplace() ||
to == address(this) ||
to == registry.getMarketplace(),
"Transfer not allowed"
);
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}
function convertRank(Rank rank) internal pure returns (Rank) {
if (rank == Rank.S) return Rank.S;
if (rank == Rank.A) return Rank.A;
if (rank == Rank.B) return Rank.B;
if (rank == Rank.C) return Rank.C;
if (rank == Rank.D) return Rank.D;
revert("Invalid Rank");
}
function getMajorityRarity(uint256[] memory rarityCounts) internal pure returns (uint256) {
uint256 majorityRarity = 0;
uint256 maxCount = 0;
for (uint256 i = 0; i < rarityCounts.length; i++) {
if (rarityCounts[i] > maxCount) {
majorityRarity = i;
maxCount = rarityCounts[i];
}
}
return majorityRarity;
}
function processExplorer(
uint256 explorerId,
uint256[] memory rarityCounts,
uint256[] memory explorerToolCount,
uint256 index
) internal view {
require(ownerOf(explorerId) == msg.sender, "You must own the explorer");
require(nftDetails[explorerId].nftType == NFTType.Explorer, "Invalid explorer NFT");
require(nftDetails[explorerId].explorerDetail.revealed, "Explorer must be revealed");
uint256 rarityIndex = uint256(nftDetails[explorerId].explorerDetail.rarity);
require(rarityIndex >= 0 && rarityIndex < 5, "Invalid rarity index");
rarityCounts[rarityIndex]++;
explorerToolCount[index] = 0;
}
function processTool(
uint256 toolId,
uint256[] memory explorerIds,
uint256[] memory explorerToolCount,
uint256 totalPower
) internal view returns (uint256) {
require(ownerOf(toolId) == msg.sender, "You must own the tool");
require(nftDetails[toolId].nftType == NFTType.Tool, "Invalid tool");
require(nftDetails[toolId].toolDetail.revealed, "Tool must be revealed");
bool assigned = false;
for (uint256 j = 0; j < explorerIds.length; j++) {
if (explorerToolCount[j] < nftDetails[explorerIds[j]].explorerDetail.maxTools) {
explorerToolCount[j]++;
assigned = true;
break;
}
}
require(assigned, "Too many tools for available explorers");
totalPower += nftDetails[toolId].toolDetail.explorerPower;
return totalPower;
}
function determineRank(uint256[] memory rarityCounts) internal pure returns (Rank) {
uint256 majorityRarity = getMajorityRarity(rarityCounts);
if (majorityRarity == uint256(Rarity.FiveStar)) {
return Rank.S;
} else if (majorityRarity == uint256(Rarity.FourStar)) {
return Rank.A;
} else if (majorityRarity == uint256(Rarity.ThreeStar)) {
return Rank.B;
} else if (majorityRarity == uint256(Rarity.TwoStar)) {
return Rank.C;
} else {
return Rank.D;
}
}
}
文件 20 的 22: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());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
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);
}
}
文件 21 的 22: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() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
}
文件 22 的 22:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
{
"compilationTarget": {
"contracts/NFTManager.sol": "NFTManager"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"registry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"AllRewardsWithdrawn","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":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"contractDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalCost","type":"uint256"}],"name":"ContractDaysSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"enum NFTType","name":"nftType","type":"uint8"}],"name":"NFTMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"enum NFTType","name":"nftType","type":"uint8"}],"name":"NFTRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"RewardsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"totalPower","type":"uint256"},{"indexed":false,"internalType":"enum Rank","name":"teamRank","type":"uint8"}],"name":"TeamCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"TeamDisassembled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burnNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toolIds","type":"uint256[]"}],"name":"calculateExplorerPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"explorerIds","type":"uint256[]"}],"name":"calculateMaxToolsForExplorers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"teamName","type":"string"},{"internalType":"uint256[]","name":"explorerIds","type":"uint256[]"},{"internalType":"uint256[]","name":"toolIds","type":"uint256[]"}],"name":"createTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"disassembleTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"emergencyWithdrawalTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"firstExcavationTime","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":"explorerIds","type":"uint256[]"}],"name":"getMajorityRarityOfExplorers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getMaxEPForAddr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getMaxToolsForOwner","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"getMaxToolsForTeam","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getNFTDetail","outputs":[{"internalType":"enum NFTType","name":"","type":"uint8"},{"components":[{"internalType":"uint256","name":"maxTools","type":"uint256"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"enum Rarity","name":"rarity","type":"uint8"}],"internalType":"struct NFTManager.ExplorerDetail","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"explorerPower","type":"uint256"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"enum Rarity","name":"rarity","type":"uint8"}],"internalType":"struct NFTManager.ToolDetail","name":"","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"explorerIds","type":"uint256[]"},{"internalType":"uint256[]","name":"toolIds","type":"uint256[]"}],"internalType":"struct NFTManager.TeamDetail","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"getRemainingContractTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint256","name":"lastExplorationDay","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"getTeamDetails","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"miningPower","type":"uint256"},{"internalType":"enum Rank","name":"rank","type":"uint8"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"numExplorers","type":"uint256"},{"internalType":"uint256","name":"numTools","type":"uint256"},{"internalType":"uint256","name":"contractDays","type":"uint256"},{"internalType":"uint256","name":"contractStartDate","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint256","name":"firstExcavationDay","type":"uint256"},{"internalType":"uint256","name":"lastExacavationDay","type":"uint256"},{"internalType":"uint256","name":"maxTools","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getTeamTokenIdsByOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isRevealed","type":"bool"},{"internalType":"bool","name":"isExplorer","type":"bool"}],"name":"getTokenIdsByAddr","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserRewardsAndPenalties","outputs":[{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint256","name":"averagePenalty","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getWithdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getfirstExcavationDaysByAddress","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":"teamId","type":"uint256"}],"name":"isTeamContractActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum NFTType","name":"nftType","type":"uint8"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftDetails","outputs":[{"internalType":"enum NFTType","name":"nftType","type":"uint8"},{"components":[{"internalType":"uint256","name":"maxTools","type":"uint256"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"enum Rarity","name":"rarity","type":"uint8"}],"internalType":"struct NFTManager.ExplorerDetail","name":"explorerDetail","type":"tuple"},{"components":[{"internalType":"uint256","name":"explorerPower","type":"uint256"},{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"enum Rarity","name":"rarity","type":"uint8"}],"internalType":"struct NFTManager.ToolDetail","name":"toolDetail","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"explorerIds","type":"uint256[]"},{"internalType":"uint256[]","name":"toolIds","type":"uint256[]"}],"internalType":"struct NFTManager.TeamDetail","name":"teamDetail","type":"tuple"},{"internalType":"uint256","name":"requestId","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":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"revealNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardInfos","outputs":[{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint256","name":"lastExplorationDay","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":"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":"uint256","name":"teamId","type":"uint256"},{"internalType":"uint256","name":"contractDays","type":"uint256"}],"name":"setContractDays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"val","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setRefundPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"val","type":"bool"}],"name":"setSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swap","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":"","type":"uint256"}],"name":"teams","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"miningPower","type":"uint256"},{"internalType":"enum Rank","name":"rank","type":"uint8"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"numExplorers","type":"uint256"},{"internalType":"uint256","name":"numTools","type":"uint256"},{"internalType":"uint256","name":"contractDays","type":"uint256"},{"internalType":"uint256","name":"contractStartDate","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"uint256","name":"firstExcavationDay","type":"uint256"},{"internalType":"uint256","name":"lastExcavationDay","type":"uint256"},{"internalType":"uint256","name":"maxTools","type":"uint256"}],"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":"address","name":"user","type":"address"},{"internalType":"uint256","name":"teamId","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"updateFirstExcavationTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"updateLastExcavationTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"teamId","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"}],"name":"updateTeamStats","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAllRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]