编译器
0.8.20+commit.a1b79de6
文件 1 的 12: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 的 12: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 的 12:ERC721.sol
pragma solidity >=0.8.0;
abstract contract ERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory);
mapping(uint256 => address) internal _ownerOf;
mapping(address => uint256) internal _balanceOf;
function ownerOf(uint256 id) public view virtual returns (address owner) {
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
}
function balanceOf(address owner) public view virtual returns (uint256) {
require(owner != address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
function approve(address spender, uint256 id) public virtual {
address owner = _ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(
address from,
address to,
uint256 id
) public virtual {
require(from == _ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
"NOT_AUTHORIZED"
);
unchecked {
_balanceOf[from]--;
_balanceOf[to]++;
}
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes calldata data
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f;
}
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
unchecked {
_balanceOf[to]++;
}
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = _ownerOf[id];
require(owner != address(0), "NOT_MINTED");
unchecked {
_balanceOf[owner]--;
}
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(
address to,
uint256 id,
bytes memory data
) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
abstract contract ERC721TokenReceiver {
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external virtual returns (bytes4) {
return ERC721TokenReceiver.onERC721Received.selector;
}
}
文件 4 的 12: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);
function mint(address _to, uint256 _amount) external returns (bool);
function burn(uint256 _amount) external returns (bool);
}
文件 5 的 12:IUniswapV2Pair.sol
pragma solidity ^0.8.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
文件 6 的 12:IUniswapV2Router.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
文件 7 的 12: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, "Math: mulDiv overflow");
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 << 3) < value ? 1 : 0);
}
}
}
文件 8 的 12: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);
}
}
文件 9 的 12:PepeStudioNFT.sol
pragma solidity ^0.8.13;
import "solmate/tokens/ERC721.sol";
import "solmate/utils/ReentrancyGuard.sol";
import "openzeppelin-contracts/contracts/utils/Strings.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV2Router.sol";
import "./interfaces/IERC20.sol";
import "openzeppelin-contracts/contracts/utils/Address.sol";
import "openzeppelin-contracts/contracts/access/Ownable.sol";
error MintPriceNotPaid();
error NonExistentTokenURI();
error WithdrawTransfer();
error NotEnoughPepe();
error TransferStakedNFT();
contract PepeStudioNFT is ERC721, ReentrancyGuard, Ownable {
using Strings for uint256;
string public baseURI;
IERC20 public immutable pepeToken;
IERC20 public immutable pepeStudioToken;
IUniswapV2Pair public immutable uniswapV2Pair;
uint256 public currentTokenId;
uint256 public BASE_MINT_PRICE = 10_000_000 ether;
address public dev;
mapping(address => uint256) public referralRewards;
mapping(address => uint256) public nextWithdrawTime;
uint256 public constant EMISSION_RATE = 200_000 ether;
uint256 public totalStakedNFTs;
address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
enum RarityLevel {
COMMON,
RARE,
EPIC,
LEGENDARY
}
struct NFTMetadata {
uint256 stakedAt;
uint256 hashRate;
RarityLevel rarityLevel;
bool isStaked;
}
mapping(uint256 => NFTMetadata) public metadata;
struct UserInfo {
uint256 hashRate;
uint256 rewardDebt;
uint256[] stakedNFTs;
}
struct PoolInfo {
uint256 currentHashRate;
uint256 minimumHashRate;
uint256 maximumHashRate;
uint256 stakeTime;
uint256 allocPoint;
uint256 lastRewardBlock;
uint256 accPepeStudioPerShare;
}
PoolInfo[] public poolInfo;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
uint256 public totalAllocPoint = 0;
uint256 public startStakingBlock;
uint256 public startMintBlock;
event ReferralRegistered(address indexed referrer, address indexed referee, uint256 tokenId);
event WithdrawReferralReward(address indexed referrer, uint256 amount);
event Stake(uint256 indexed tokenId);
event Unstake(uint256 indexed tokenId, uint256 stakedAtTimestamp, uint256 removedFromStakeAtTimestamp);
event EmergencyUnstake(address indexed user, uint256 indexed pid, uint256[] nfts);
modifier notContract() {
require(!Address.isContract(msg.sender), "contract not allowed");
require(msg.sender == tx.origin, "proxy contract not allowed");
_;
}
modifier startMint() {
require(block.number >= startMintBlock, "minting has not started yet");
_;
}
modifier startStake() {
require(block.number >= startStakingBlock, "staking has not started yet");
_;
}
constructor(
string memory _name,
string memory _symbol,
string memory _baseURI,
address _pepeToken,
address _pepeStudioToken,
address _uniswapV2Factory,
uint256 _startStakingBlock,
uint256 _startMintBlock
) ERC721(_name, _symbol) Ownable() {
dev = msg.sender;
baseURI = _baseURI;
pepeToken = IERC20(_pepeToken);
pepeStudioToken = IERC20(_pepeStudioToken);
IUniswapV2Factory uniswapV2Factory = IUniswapV2Factory(_uniswapV2Factory);
uniswapV2Pair = IUniswapV2Pair(uniswapV2Factory.createPair(_pepeStudioToken, _pepeToken));
startStakingBlock = _startStakingBlock;
startMintBlock = _startMintBlock;
poolInfo.push(
PoolInfo({
currentHashRate: 0,
minimumHashRate: 0,
maximumHashRate: 0,
stakeTime: 0,
allocPoint: 0,
lastRewardBlock: _startStakingBlock,
accPepeStudioPerShare: 0
})
);
poolInfo.push(
PoolInfo({
currentHashRate: 0,
minimumHashRate: 0,
maximumHashRate: 100000,
stakeTime: 9 days,
allocPoint: 300,
lastRewardBlock: _startStakingBlock,
accPepeStudioPerShare: 0
})
);
poolInfo.push(
PoolInfo({
currentHashRate: 0,
minimumHashRate: 100000,
maximumHashRate: 200000,
stakeTime: 10 days,
allocPoint: 200,
lastRewardBlock: _startStakingBlock,
accPepeStudioPerShare: 0
})
);
poolInfo.push(
PoolInfo({
currentHashRate: 0,
minimumHashRate: 0,
maximumHashRate: 200000,
stakeTime: 7 days,
allocPoint: 500,
lastRewardBlock: _startStakingBlock,
accPepeStudioPerShare: 0
})
);
totalAllocPoint = 1000;
}
function calculateMintingPrice(uint256 _tokenId) internal view returns (uint256) {
return BASE_MINT_PRICE * (100 + (_tokenId / 1000) * 3) / 100;
}
function getMintingPrice() public view returns (uint256) {
return calculateMintingPrice(currentTokenId + 1);
}
function changeDev(address _dev) public {
require(msg.sender == dev, "Only dev can change dev address");
dev = _dev;
}
function randomInRange(uint256 min, uint256 max, uint256 nonce) internal view returns (uint256) {
return
uint256(
keccak256(
abi.encodePacked(block.timestamp, block.prevrandao, msg.sender, nonce)
)
) % (max - min) + min;
}
function mintUsingPEPE(address recipient, uint256 quantity, address referrer) public startMint notContract {
uint256 mintingPrice = calculateMintingPrice(currentTokenId + 1);
if(mintingPrice > BASE_MINT_PRICE) {
BASE_MINT_PRICE = mintingPrice;
}
pepeToken.transferFrom(msg.sender, address(this), mintingPrice * quantity);
if (referrer != address(0) && referrer != msg.sender) {
uint256 referrerReward = mintingPrice * quantity / 20;
referralRewards[referrer] += referrerReward;
}
for(uint256 i = 0; i < quantity; i++) {
uint256 newTokenId = ++currentTokenId;
uint256 randomNumber = randomInRange(0, 10000, newTokenId);
uint256 hashRate;
RarityLevel rarityLevel;
if (randomNumber < 6875) {
rarityLevel = RarityLevel.COMMON;
hashRate = randomInRange(10000, 100000, block.number * (i + 1));
} else if (randomNumber < 8700) {
rarityLevel = RarityLevel.RARE;
hashRate = randomInRange(20000, 100000, block.number * (i + 1));
} else if (randomNumber < 9800) {
rarityLevel = RarityLevel.EPIC;
hashRate = randomInRange(30000, 100000, block.number * (i + 1));
} else {
rarityLevel = RarityLevel.LEGENDARY;
hashRate = randomInRange(1, 200000, block.number * (i + 1));
}
metadata[newTokenId] = NFTMetadata({
rarityLevel: rarityLevel,
hashRate: hashRate,
stakedAt: 0,
isStaked: false
});
_safeMint(recipient, newTokenId);
emit ReferralRegistered(referrer, recipient, newTokenId);
}
}
function mintUsingPEPEStudio(address recipient, uint256 quantity) public startMint notContract {
uint256 mintingPrice = calculateMintingPrice(currentTokenId + 1);
if(mintingPrice > BASE_MINT_PRICE) {
BASE_MINT_PRICE = mintingPrice;
}
pepeStudioToken.transferFrom(msg.sender, address(this), mintingPrice * quantity);
pepeStudioToken.burn(mintingPrice * quantity);
for(uint256 i = 0; i < quantity; i++) {
uint256 newTokenId = ++currentTokenId;
uint256 randomNumber = randomInRange(0, 10000, newTokenId);
RarityLevel rarityLevel;
uint256 hashRate;
if (randomNumber < 5875) {
rarityLevel = RarityLevel.COMMON;
hashRate = randomInRange(10000, 100000, block.number * (i + 1));
} else if (randomNumber < 8300) {
rarityLevel = RarityLevel.RARE;
hashRate = randomInRange(20000, 100000, block.number * (i + 1));
} else if (randomNumber < 9625) {
rarityLevel = RarityLevel.EPIC;
hashRate = randomInRange(30000, 100000, block.number * (i + 1));
} else {
rarityLevel = RarityLevel.LEGENDARY;
hashRate = randomInRange(1, 200000, block.number * (i + 1));
}
metadata[newTokenId] = NFTMetadata({
rarityLevel: rarityLevel,
hashRate: hashRate,
stakedAt: 0,
isStaked: false
});
_safeMint(recipient, newTokenId);
}
}
function addLiquidity() public nonReentrant notContract returns (bool) {
pepeToken.transfer(dev, pepeToken.balanceOf(address(this)) * 2 / 100);
pepeToken.transfer(msg.sender, pepeToken.balanceOf(address(this)) * 3 / 1000);
uint256 amountB = pepeToken.balanceOf(address(this));
uint256 amountA;
if(uniswapV2Pair.totalSupply() == 0) {
amountA = amountB;
} else {
amountA = (amountB * pepeStudioToken.balanceOf(address(uniswapV2Pair))) /
pepeToken.balanceOf(address(uniswapV2Pair));
}
pepeStudioToken.mint(address(uniswapV2Pair), amountA);
pepeToken.transfer(address(uniswapV2Pair), amountB);
uniswapV2Pair.mint(address(this));
uniswapV2Pair.transfer(BURN_ADDRESS, uniswapV2Pair.balanceOf(address(this)));
return true;
}
function claimReferralRewards() public nonReentrant returns (bool) {
require(nextWithdrawTime[msg.sender] < block.timestamp, "You can only claim once every 3 days");
uint256 amount = referralRewards[msg.sender];
require(amount > 0, "No referral rewards to claim");
if(amount > pepeToken.balanceOf(address(this))) {
revert NotEnoughPepe();
}
referralRewards[msg.sender] = 0;
pepeToken.transfer(msg.sender, amount);
nextWithdrawTime[msg.sender] = block.timestamp + 3 days;
return true;
}
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
if(metadata[tokenId].isStaked) {
revert TransferStakedNFT();
}
super.transferFrom(from, to, tokenId);
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
if (ownerOf(tokenId) == address(0)) {
revert NonExistentTokenURI();
}
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: "";
}
function poolLength() external view returns (uint256) {
return poolInfo.length;
}
function getMultiplier(uint256 _from, uint256 _to) public pure returns (uint256) {
return (_to - _from);
}
function pendingPepeStudio(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 accPepeStudioPerShare = pool.accPepeStudioPerShare;
uint256 totalHashRate = pool.currentHashRate;
if (block.number > pool.lastRewardBlock && totalHashRate != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 pepeStudioReward = multiplier * EMISSION_RATE * pool.allocPoint / totalAllocPoint;
accPepeStudioPerShare = accPepeStudioPerShare + (pepeStudioReward * 1e12 / totalHashRate);
}
return (user.hashRate * accPepeStudioPerShare / 1e12) - user.rewardDebt;
}
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
}
}
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
if (block.number <= pool.lastRewardBlock) {
return;
}
uint256 totalHashRate = pool.currentHashRate;
if (totalHashRate == 0) {
pool.lastRewardBlock = block.number;
return;
}
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 pepeStudioReward = multiplier * EMISSION_RATE * pool.allocPoint / totalAllocPoint;
pepeStudioToken.mint(dev, pepeStudioReward / 30);
pepeStudioToken.mint(address(this), pepeStudioReward);
pool.accPepeStudioPerShare = pool.accPepeStudioPerShare + (pepeStudioReward * 1e12 / totalHashRate);
pool.lastRewardBlock = block.number;
}
function stake(uint256 _pid, uint256[] memory _nfts) public startStake {
require(_pid != 0, "deposit NFT by staking");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
if (user.hashRate > 0) {
uint256 pending = (user.hashRate * pool.accPepeStudioPerShare / 1e12) - user.rewardDebt;
if (pending > 0) {
safePepeStudioTransfer(msg.sender, pending);
}
}
for (uint256 i = 0; i < _nfts.length; i++) {
require(ownerOf(_nfts[i]) == msg.sender, "You are not the owner of this token");
require(!metadata[_nfts[i]].isStaked, "This token is already staked");
require(metadata[_nfts[i]].hashRate >= pool.minimumHashRate, "hash rate is too low");
require(metadata[_nfts[i]].hashRate <= pool.maximumHashRate, "hash rate is too high");
pool.currentHashRate += metadata[_nfts[i]].hashRate;
user.hashRate += metadata[_nfts[i]].hashRate;
user.stakedNFTs.push(_nfts[i]);
metadata[_nfts[i]].isStaked = true;
emit Stake(_nfts[i]);
}
user.rewardDebt = user.hashRate * pool.accPepeStudioPerShare / 1e12;
}
function unstake(uint256 _pid, uint256[] memory _nfts) public {
require(_pid != 0, "withdraw NFT by unstaking");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.hashRate > 0, "no hash rate");
require(user.stakedNFTs.length >= _nfts.length, "not enough nfts");
updatePool(_pid);
uint256 pending = (user.hashRate * pool.accPepeStudioPerShare / 1e12) - user.rewardDebt;
if (pending > 0) {
safePepeStudioTransfer(msg.sender, pending);
}
for (uint256 i = 0; i < _nfts.length; i++) {
require(ownerOf(_nfts[i]) == msg.sender, "You are not the owner of this token");
require(metadata[_nfts[i]].isStaked, "This token is not staked");
require(metadata[_nfts[i]].stakedAt + pool.stakeTime < block.timestamp, "You cannot withdraw this token yet");
pool.currentHashRate -= metadata[_nfts[i]].hashRate;
user.hashRate -= metadata[_nfts[i]].hashRate;
metadata[_nfts[i]].isStaked = false;
for (uint256 j = 0; j < user.stakedNFTs.length; j++) {
if (user.stakedNFTs[j] == _nfts[i]) {
user.stakedNFTs[j] = user.stakedNFTs[user.stakedNFTs.length - 1];
user.stakedNFTs.pop();
break;
}
}
emit Unstake(_nfts[i], metadata[_nfts[i]].stakedAt, block.timestamp);
}
user.rewardDebt = user.hashRate * pool.accPepeStudioPerShare / 1e12;
}
function emergencyUnstake(uint256 _pid, uint256[] memory _nfts) public {
require(_pid != 0, "emergency withdraw NFT by unstaking");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.hashRate > 0, "no hash rate");
require(user.stakedNFTs.length >= _nfts.length, "not enough nfts");
for (uint256 i = 0; i < _nfts.length; i++) {
require(ownerOf(_nfts[i]) == msg.sender, "You are not the owner of this token");
require(metadata[_nfts[i]].isStaked, "This token is not staked");
pool.currentHashRate -= metadata[_nfts[i]].hashRate;
user.hashRate -= metadata[_nfts[i]].hashRate;
metadata[_nfts[i]].isStaked = false;
for (uint256 j = 0; j < user.stakedNFTs.length; j++) {
if (user.stakedNFTs[j] == _nfts[i]) {
user.stakedNFTs[j] = user.stakedNFTs[user.stakedNFTs.length - 1];
user.stakedNFTs.pop();
break;
}
}
}
user.rewardDebt = user.hashRate * pool.accPepeStudioPerShare / 1e12;
emit EmergencyUnstake(msg.sender, _pid, _nfts);
}
function safePepeStudioTransfer(address _to, uint256 _amount) internal {
uint256 pepeStudioBal = pepeStudioToken.balanceOf(address(this));
if (_amount > pepeStudioBal) {
pepeStudioToken.transfer(_to, pepeStudioBal);
} else {
pepeStudioToken.transfer(_to, _amount);
}
}
function burnNFT(uint256 _tokenId) public {
require(ownerOf(_tokenId) == msg.sender, "You are not the owner of this token");
require(!metadata[_tokenId].isStaked, "This token is staked");
pepeToken.transfer(msg.sender, calculateMintingPrice(_tokenId) / 2);
_burn(_tokenId);
}
}
文件 10 的 12:ReentrancyGuard.sol
pragma solidity >=0.8.0;
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() virtual {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}
文件 11 的 12:SignedMath.sol
pragma solidity ^0.8.0;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 12 的 12:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.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 toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
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);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
{
"compilationTarget": {
"src/PepeStudioNFT.sol": "PepeStudioNFT"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":solmate/=lib/solmate/src/"
]
}
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"address","name":"_pepeToken","type":"address"},{"internalType":"address","name":"_pepeStudioToken","type":"address"},{"internalType":"address","name":"_uniswapV2Factory","type":"address"},{"internalType":"uint256","name":"_startStakingBlock","type":"uint256"},{"internalType":"uint256","name":"_startMintBlock","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NonExistentTokenURI","type":"error"},{"inputs":[],"name":"NotEnoughPepe","type":"error"},{"inputs":[],"name":"TransferStakedNFT","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"nfts","type":"uint256[]"}],"name":"EmergencyUnstake","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":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ReferralRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Stake","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakedAtTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"removedFromStakeAtTimestamp","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawReferralReward","type":"event"},{"inputs":[],"name":"BASE_MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addLiquidity","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burnNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dev","type":"address"}],"name":"changeDev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimReferralRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dev","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256[]","name":"_nfts","type":"uint256[]"}],"name":"emergencyUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintingPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"getMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"metadata","outputs":[{"internalType":"uint256","name":"stakedAt","type":"uint256"},{"internalType":"uint256","name":"hashRate","type":"uint256"},{"internalType":"enum PepeStudioNFT.RarityLevel","name":"rarityLevel","type":"uint8"},{"internalType":"bool","name":"isStaked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"mintUsingPEPE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintUsingPEPEStudio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nextWithdrawTime","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":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingPepeStudio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pepeStudioToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pepeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"uint256","name":"currentHashRate","type":"uint256"},{"internalType":"uint256","name":"minimumHashRate","type":"uint256"},{"internalType":"uint256","name":"maximumHashRate","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accPepeStudioPerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referralRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"id","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":"_pid","type":"uint256"},{"internalType":"uint256[]","name":"_nfts","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startMintBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startStakingBlock","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":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedNFTs","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":[],"name":"uniswapV2Pair","outputs":[{"internalType":"contract IUniswapV2Pair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256[]","name":"_nfts","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"hashRate","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"}]