编译器
0.8.16+commit.07a7930e
文件 1 的 19:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 19:BoringOwnable.sol
pragma solidity ^0.8.0;
contract BoringOwnableData {
address public owner;
address public pendingOwner;
}
contract BoringOwnable is BoringOwnableData {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
function transferOwnership(
address newOwner,
bool direct,
bool renounce
) public onlyOwner {
if (direct) {
require(newOwner != address(0) || renounce, "Ownable: zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
pendingOwner = address(0);
} else {
pendingOwner = newOwner;
}
}
function claimOwnership() public {
address _pendingOwner = pendingOwner;
require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");
emit OwnershipTransferred(owner, _pendingOwner);
owner = _pendingOwner;
pendingOwner = address(0);
}
modifier onlyOwner() {
require(msg.sender == owner, "Ownable: caller is not the owner");
_;
}
}
文件 3 的 19:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 19:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 19:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 6 的 19:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 7 的 19:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 8 的 19:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 19:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 10 的 19:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 11 的 19:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 12 的 19: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);
}
文件 13 的 19:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 14 的 19:JanisMasterchef.sol
pragma solidity 0.8.16;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../libraries/BoringOwnable.sol";
import "../minting/MintableERC20.sol";
import "../minting/JanisMinter.sol";
library ERC20FactoryLib {
function createERC20(string memory name_, string memory symbol_, uint8 decimals) external returns(address)
{
ERC20 token = new MintableERC20(name_, symbol_, decimals);
return address(token);
}
}
interface IAbilityNFT {
function getAbility(uint tokenId) external view returns(uint);
}
contract JanisMasterChef is BoringOwnable, IERC721Receiver, ReentrancyGuard {
using SafeERC20 for ERC20;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
struct UserInfo {
uint amount;
uint rewardDebtJanis;
uint rewardDebtYieldToken;
}
struct PoolInfo {
ERC20 lpToken;
bool isNFT;
uint endTime;
bool usesPremint;
uint totalLocked;
uint allocPointJanis;
uint allocPointYieldToken;
uint lastRewardTime;
uint accJanisPerShare;
uint accYieldTokenPerShare;
uint depositFeeBPOrNFTETHFee;
address receiptToken;
bool isExtinctionPool;
}
struct NFTSlot {
address slot1;
uint tokenId1;
address slot2;
uint tokenId2;
address slot3;
uint tokenId3;
address slot4;
uint tokenId4;
address slot5;
uint tokenId5;
}
JanisMinter public janisMinter;
ERC20 public Janis;
uint public JanisPerSecond;
ERC20 public yieldToken;
uint public yieldTokenPerSecond;
address public reserveFund;
PoolInfo[] public poolInfo;
mapping(uint => mapping(address => UserInfo)) public userInfo;
mapping(address => bool) public isWhitelistedBoosterNFT;
mapping(address => bool) public isNFTAbilityEnabled;
mapping(address => uint) public nftAbilityBaseBoost;
mapping(address => uint) public nftAbilityBoostScalar;
mapping(address => uint) public nonAbilityBoost;
uint public totalAllocPointJanis;
uint public totalAllocPointYieldToken;
uint public immutable globalStartTime;
mapping(ERC20 => bool) public poolExistence;
mapping(address => mapping(uint => NFTSlot)) public userDepositedNFTMap;
event Deposit(address indexed user, uint indexed pid, uint amount);
event Withdraw(address indexed user, uint indexed pid, uint amount);
event EmergencyWithdraw(address indexed user, uint indexed pid, uint amount);
event UpdateJanisEmissionRate(address indexed user, uint JanisPerSecond);
event UpdateYieldTokenEmissionRate(address indexed user, uint yieldTokenPerSecond);
event UpdateBoosterNFTWhitelist(address indexed user, address indexed _nft, bool enabled, uint _boostRate, bool isAbilityEnabled, uint abilityNFTBaseBoost, uint _nftAbilityBoostScalar);
event UpdateNewReserveFund(address newReserveFund);
uint public MAX_NFT_COUNT = 150;
mapping(address => mapping(uint => uint)) public userStakeCounts;
function hasUserStakedNFT(address _user, address _series, uint _tokenId) external view returns (bool) {
return userStakedMap[_user][_series][_tokenId];
}
mapping(address => mapping(address => mapping(uint => bool))) public userStakedMap;
mapping(address => mapping(address => EnumerableSet.UintSet)) private userNftIdsMapArray;
function onERC721Received(
address,
address,
uint,
bytes calldata
) external override returns(bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
constructor(
address _Janis,
address _JanisMinter,
uint _JanisPerSecond,
ERC20 _yieldToken,
uint _yieldTokenPerSecond,
uint _globalSartTime
) {
require(_Janis != address(0), "_Janis!=0");
require(_JanisMinter != address(0), "_JanisMinter!=0");
Janis = ERC20(_Janis);
janisMinter = JanisMinter(_JanisMinter);
JanisPerSecond = _JanisPerSecond;
yieldToken = _yieldToken;
yieldTokenPerSecond = _yieldTokenPerSecond;
totalAllocPointJanis = 0;
totalAllocPointYieldToken = 0;
globalStartTime = _globalSartTime;
reserveFund = msg.sender;
}
modifier nonDuplicated(ERC20 _lpToken) {
require(poolExistence[_lpToken] == false, "nonDuplicated: duplicated");
_;
}
function getBoostRateJanis(address _nft, uint _nftId) public view returns (uint) {
if (isNFTAbilityEnabled[_nft]) {
return nftAbilityBaseBoost[_nft] + nftAbilityBoostScalar[_nft] * IAbilityNFT(_nft).getAbility(_nftId) / 1e4;
} else
return nonAbilityBoost[_nft];
}
function getBoostJanis(address _account, uint _pid) public view returns (uint) {
NFTSlot memory slot = userDepositedNFTMap[_account][_pid];
uint boost1 = getBoostRateJanis(slot.slot1, slot.tokenId1);
uint boost2 = getBoostRateJanis(slot.slot2, slot.tokenId2);
uint boost3 = getBoostRateJanis(slot.slot3, slot.tokenId3);
uint boost4 = getBoostRateJanis(slot.slot4, slot.tokenId4);
uint boost5 = getBoostRateJanis(slot.slot5, slot.tokenId5);
uint boost = boost1 + boost2 + boost3 + boost4 + boost5;
return boost;
}
function getSlots(address _account, uint _pid) external view returns (address, address, address, address, address) {
NFTSlot memory slot = userDepositedNFTMap[_account][_pid];
return (slot.slot1, slot.slot2, slot.slot3, slot.slot4, slot.slot5);
}
function getTokenIds(address _account, uint _pid) external view returns (uint, uint, uint, uint, uint) {
NFTSlot memory slot = userDepositedNFTMap[_account][_pid];
return (slot.tokenId1, slot.tokenId2, slot.tokenId3, slot.tokenId4, slot.tokenId5);
}
function poolLength() external view returns (uint) {
return poolInfo.length;
}
function getMultiplier(uint _from, uint _to) internal pure returns (uint) {
return _to - _from;
}
function pendingJanis(uint _pid, address _user) external view returns (uint) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint accJanisPerShare = pool.accJanisPerShare;
uint lpSupply = pool.totalLocked;
if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {
uint multiplier = getMultiplier(pool.lastRewardTime, block.timestamp);
uint JanisReward = multiplier * JanisPerSecond * pool.allocPointJanis / totalAllocPointJanis;
accJanisPerShare = accJanisPerShare + (JanisReward * 1e24 / lpSupply);
}
return (user.amount * accJanisPerShare / 1e24) - user.rewardDebtJanis;
}
function pendingYieldToken(uint _pid, address _user) external view returns (uint) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint accYieldTokenPerShare = pool.accYieldTokenPerShare;
uint lpSupply = pool.totalLocked;
if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {
uint multiplier = getMultiplier(pool.lastRewardTime, block.timestamp);
uint yieldTokenReward = multiplier * yieldTokenPerSecond * pool.allocPointYieldToken / totalAllocPointYieldToken;
accYieldTokenPerShare = accYieldTokenPerShare + (yieldTokenReward * 1e24 / lpSupply);
}
return (user.amount * accYieldTokenPerShare / 1e24) - user.rewardDebtYieldToken;
}
function add(bool _isExtinctionPool, bool _isNFT, uint _startTime, uint _endTime, bool _usesPremint, uint _allocPointJanis, uint _allocPointYieldToken, ERC20 _lpToken, uint _depositFeeBPOrNFTETHFee, bool _withMassUpdate) external onlyOwner nonDuplicated(_lpToken) {
require(_startTime == 0 || _startTime > block.timestamp, "invalid startTime!");
require(_endTime == 0 || (_startTime == 0 && _endTime > block.timestamp + 20) || (_startTime > block.timestamp && _endTime > _startTime + 20), "invalid endTime!");
require(_depositFeeBPOrNFTETHFee <= 1000, "too high fee");
_lpToken.balanceOf(address(this));
bool isReallyAnfNFT = false;
try ERC721(address(_lpToken)).supportsInterface(0x80ac58cd) returns (bool supportsNFT) {
isReallyAnfNFT = supportsNFT;
} catch {}
if (isReallyAnfNFT != _isNFT) {
if (_isNFT) {
revert("NFT address isn't and NFT Address!");
} else {
revert("ERC20 address isn't and ERC20 Address!");
}
}
if (_isNFT) {
_isExtinctionPool = false;
}
if (_withMassUpdate) {
massUpdatePools();
}
uint lastRewardTime = _startTime == 0 ? (block.timestamp > globalStartTime ? block.timestamp : globalStartTime) : _startTime;
totalAllocPointJanis = totalAllocPointJanis + _allocPointJanis;
totalAllocPointYieldToken = totalAllocPointYieldToken + _allocPointYieldToken;
poolExistence[_lpToken] = true;
poolInfo.push(PoolInfo({
isNFT: _isNFT,
endTime: _endTime,
usesPremint: _usesPremint,
lpToken : _lpToken,
allocPointJanis : _allocPointJanis,
allocPointYieldToken : _allocPointYieldToken,
lastRewardTime : lastRewardTime,
accJanisPerShare : 0,
accYieldTokenPerShare : 0,
depositFeeBPOrNFTETHFee: _depositFeeBPOrNFTETHFee,
totalLocked: 0,
receiptToken: address(0),
isExtinctionPool: _isExtinctionPool
}));
if (!_isExtinctionPool && !_isNFT) {
string memory receiptName = string.concat("J: ", _lpToken.name());
string memory receiptSymbol = string.concat("J: ", _lpToken.symbol());
poolInfo[poolInfo.length - 1].receiptToken = ERC20FactoryLib.createERC20(receiptName, receiptSymbol, _lpToken.decimals());
}
}
function set(uint _pid, uint _startTime, uint _endTime, bool _usesPremint, uint _allocPointJanis, uint _allocPointYieldToken, uint _depositFeeBPOrNFTETHFee, bool _withMassUpdate) external onlyOwner {
require(_startTime == 0 || _startTime > block.timestamp, "invalid startTime!");
require(_endTime == 0 || (_startTime == 0 && _endTime > block.timestamp + 20) || (_startTime > block.timestamp && _endTime > _startTime + 20), "invalid endTime!");
require(_depositFeeBPOrNFTETHFee <= 1000, "too high fee");
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
totalAllocPointJanis = (totalAllocPointJanis - poolInfo[_pid].allocPointJanis) + _allocPointJanis;
totalAllocPointYieldToken = (totalAllocPointYieldToken - poolInfo[_pid].allocPointYieldToken) + _allocPointYieldToken;
uint lastRewardTime = _startTime == 0 ? (block.timestamp > globalStartTime ? block.timestamp : globalStartTime) : _startTime;
poolInfo[_pid].lastRewardTime = lastRewardTime;
poolInfo[_pid].endTime = _endTime;
poolInfo[_pid].usesPremint = _usesPremint;
poolInfo[_pid].allocPointJanis = _allocPointJanis;
poolInfo[_pid].allocPointYieldToken = _allocPointYieldToken;
poolInfo[_pid].depositFeeBPOrNFTETHFee = _depositFeeBPOrNFTETHFee;
}
function setUsePremintOnly(uint _pid, bool _usesPremint) external onlyOwner {
poolInfo[_pid].usesPremint = _usesPremint;
}
function setAllocationPointsOnly(uint _pid, uint _allocPointJanis, uint _allocPointYieldToken, bool _withMassUpdate) external onlyOwner {
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
totalAllocPointJanis = (totalAllocPointJanis - poolInfo[_pid].allocPointJanis) + _allocPointJanis;
totalAllocPointYieldToken = (totalAllocPointYieldToken - poolInfo[_pid].allocPointYieldToken) + _allocPointYieldToken;
poolInfo[_pid].allocPointJanis = _allocPointJanis;
poolInfo[_pid].allocPointYieldToken = _allocPointYieldToken;
}
function setDepositFeeOnly(uint _pid, uint _depositFeeBPOrNFTETHFee, bool _withMassUpdate) external onlyOwner {
require(_depositFeeBPOrNFTETHFee <= 1000, "too high fee");
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
poolInfo[_pid].depositFeeBPOrNFTETHFee = _depositFeeBPOrNFTETHFee;
}
function setPoolScheduleKeepMultipliers(uint _pid, uint _startTime, uint _endTime, bool _withMassUpdate) external onlyOwner {
require(_startTime == 0 || _startTime > block.timestamp, "invalid startTime!");
require(_endTime == 0 || (_startTime == 0 && _endTime > block.timestamp + 20) || (_startTime > block.timestamp && _endTime > _startTime + 20), "invalid endTime!");
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
uint lastRewardTime = _startTime == 0 ? (block.timestamp > globalStartTime ? block.timestamp : globalStartTime) : _startTime;
poolInfo[_pid].lastRewardTime = lastRewardTime;
poolInfo[_pid].endTime = _endTime;
}
function setPoolScheduleAndMultipliers(uint _pid, uint _startTime, uint _endTime, uint _allocPointJanis, uint _allocPointYieldToken, bool _withMassUpdate) external onlyOwner {
require(_startTime == 0 || _startTime > block.timestamp, "invalid startTime!");
require(_endTime == 0 || (_startTime == 0 && _endTime > block.timestamp + 20) || (_startTime > block.timestamp && _endTime > _startTime + 20), "invalid endTime!");
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
uint lastRewardTime = _startTime == 0 ? (block.timestamp > globalStartTime ? block.timestamp : globalStartTime) : _startTime;
poolInfo[_pid].lastRewardTime = lastRewardTime;
poolInfo[_pid].endTime = _endTime;
totalAllocPointJanis = (totalAllocPointJanis - poolInfo[_pid].allocPointJanis) + _allocPointJanis;
totalAllocPointYieldToken = (totalAllocPointYieldToken - poolInfo[_pid].allocPointYieldToken) + _allocPointYieldToken;
poolInfo[_pid].allocPointJanis = _allocPointJanis;
poolInfo[_pid].allocPointYieldToken = _allocPointYieldToken;
}
function disablePoolKeepMultipliers(uint _pid, bool _withMassUpdate) external onlyOwner {
if (_withMassUpdate) {
massUpdatePools();
} else {
updatePool(_pid);
}
uint lastRewardTime = block.timestamp > globalStartTime ? block.timestamp : globalStartTime;
poolInfo[_pid].lastRewardTime = lastRewardTime;
poolInfo[_pid].endTime = lastRewardTime;
}
function zeroEndedMultipliersAndDecreaseEmissionVariables(uint startPid, uint endPid, bool _withMassUpdate) external onlyOwner {
require(startPid < poolInfo.length, "startPid too high!");
require(endPid < poolInfo.length, "endPid too high!");
if (_withMassUpdate) {
massUpdatePools();
}
uint janisAllocPointsEliminated = 0;
uint yieldTokenllocPointsEliminated = 0;
for (uint i = startPid;i<=endPid;i++) {
if (poolInfo[i].lastRewardTime >= poolInfo[i].endTime) {
janisAllocPointsEliminated += poolInfo[i].allocPointJanis;
yieldTokenllocPointsEliminated += poolInfo[i].allocPointYieldToken;
poolInfo[i].allocPointJanis = 0;
poolInfo[i].allocPointYieldToken = 0;
}
}
JanisPerSecond -= JanisPerSecond * janisAllocPointsEliminated / totalAllocPointJanis;
yieldTokenPerSecond -= yieldTokenPerSecond * yieldTokenllocPointsEliminated / totalAllocPointYieldToken;
totalAllocPointJanis -= janisAllocPointsEliminated;
totalAllocPointYieldToken -= yieldTokenllocPointsEliminated;
}
function depositNFT(address _nft, uint _tokenId, uint _slot, uint _pid) external nonReentrant {
require(_slot != 0 && _slot <= 5, "slot out of range 1-5!");
require(isWhitelistedBoosterNFT[_nft], "only approved NFTs");
require(ERC721(_nft).balanceOf(msg.sender) > 0, "user does not have specified NFT");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
transferPendingRewards(_pid);
user.rewardDebtJanis = user.amount * pool.accJanisPerShare / 1e24;
user.rewardDebtYieldToken = user.amount * pool.accYieldTokenPerShare / 1e24;
NFTSlot memory slot = userDepositedNFTMap[msg.sender][_pid];
address existingNFT;
if (_slot == 1) existingNFT = slot.slot1;
else if (_slot == 2) existingNFT = slot.slot2;
else if (_slot == 3) existingNFT = slot.slot3;
else if (_slot == 4) existingNFT = slot.slot4;
else if (_slot == 5) existingNFT = slot.slot5;
require(existingNFT == address(0), "you must empty this slot before depositing a new nft here!");
if (_slot == 1) slot.slot1 = _nft;
else if (_slot == 2) slot.slot2 = _nft;
else if (_slot == 3) slot.slot3 = _nft;
else if (_slot == 4) slot.slot4 = _nft;
else if (_slot == 5) slot.slot5 = _nft;
if (_slot == 1) slot.tokenId1 = _tokenId;
else if (_slot == 2) slot.tokenId2 = _tokenId;
else if (_slot == 3) slot.tokenId3 = _tokenId;
else if (_slot == 4) slot.tokenId4 = _tokenId;
else if (_slot == 5) slot.tokenId5 = _tokenId;
userDepositedNFTMap[msg.sender][_pid] = slot;
ERC721(_nft).transferFrom(msg.sender, address(this), _tokenId);
}
function withdrawNFT(uint _slot, uint _pid) external nonReentrant {
address _nft;
uint _tokenId;
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
transferPendingRewards(_pid);
user.rewardDebtJanis = user.amount * pool.accJanisPerShare / 1e24;
user.rewardDebtYieldToken = user.amount * pool.accYieldTokenPerShare / 1e24;
NFTSlot memory slot = userDepositedNFTMap[msg.sender][_pid];
if (_slot == 1) _nft = slot.slot1;
else if (_slot == 2) _nft = slot.slot2;
else if (_slot == 3) _nft = slot.slot3;
else if (_slot == 4) _nft = slot.slot4;
else if (_slot == 5) _nft = slot.slot5;
if (_slot == 1) _tokenId = slot.tokenId1;
else if (_slot == 2) _tokenId = slot.tokenId2;
else if (_slot == 3) _tokenId = slot.tokenId3;
else if (_slot == 4) _tokenId = slot.tokenId4;
else if (_slot == 5) _tokenId = slot.tokenId5;
if (_slot == 1) slot.slot1 = address(0);
else if (_slot == 2) slot.slot2 = address(0);
else if (_slot == 3) slot.slot3 = address(0);
else if (_slot == 4) slot.slot4 = address(0);
else if (_slot == 5) slot.slot5 = address(0);
if (_slot == 1) slot.tokenId1 = uint(0);
else if (_slot == 2) slot.tokenId2 = uint(0);
else if (_slot == 3) slot.tokenId3 = uint(0);
else if (_slot == 4) slot.tokenId4 = uint(0);
else if (_slot == 5) slot.tokenId5 = uint(0);
userDepositedNFTMap[msg.sender][_pid] = slot;
ERC721(_nft).transferFrom(address(this), msg.sender, _tokenId);
}
function massUpdatePools() public {
uint length = poolInfo.length;
for (uint pid = 0; pid < length; ++pid) {
updatePool(pid);
}
}
function updatePool(uint _pid) public {
PoolInfo storage pool = poolInfo[_pid];
if (block.timestamp <= pool.lastRewardTime) {
return;
}
if (pool.endTime != 0 && pool.lastRewardTime >= pool.endTime) {
pool.lastRewardTime = block.timestamp;
return;
}
uint lpSupply = pool.totalLocked;
if (lpSupply == 0) {
pool.lastRewardTime = block.timestamp;
return;
}
uint currentTimeOrEndOfPoolTime = pool.endTime == 0 ? block.timestamp : pool.endTime;
uint multiplier = getMultiplier(pool.lastRewardTime, currentTimeOrEndOfPoolTime);
if (pool.allocPointJanis > 0) {
uint JanisReward = multiplier * JanisPerSecond * pool.allocPointJanis / totalAllocPointJanis;
if (JanisReward > 0) {
if (!pool.usesPremint)
janisMinter.operatorMint(address(this), JanisReward);
else
janisMinter.operatorFetchOrMint(address(this), JanisReward);
pool.accJanisPerShare = pool.accJanisPerShare + (JanisReward * 1e24 / lpSupply);
}
}
if (pool.allocPointYieldToken > 0) {
uint yieldTokenReward = multiplier * yieldTokenPerSecond * pool.allocPointYieldToken / totalAllocPointYieldToken;
if (yieldTokenReward > 0) {
pool.accYieldTokenPerShare = pool.accYieldTokenPerShare + (yieldTokenReward * 1e24 / lpSupply);
}
}
pool.lastRewardTime = block.timestamp;
}
function transferPendingRewards(uint _pid) internal {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
if (user.amount > 0) {
uint pendingJanisToPay = (user.amount * pool.accJanisPerShare / 1e24) - user.rewardDebtJanis;
if (pendingJanisToPay > 0) {
safeJanisTransfer(msg.sender, pendingJanisToPay, _pid);
}
uint pendingYieldTokenToPay = (user.amount * pool.accYieldTokenPerShare / 1e24) - user.rewardDebtYieldToken;
if (pendingYieldTokenToPay > 0) {
safeYieldTokenTransfer(msg.sender, pendingYieldTokenToPay);
}
}
}
function deposit(uint _pid, uint _amountOrId, bool isNFTHarvest, address _referrer) public payable nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
transferPendingRewards(_pid);
janisMinter.recordReferral(msg.sender, _referrer);
if (!isNFTHarvest && pool.isNFT) {
require(msg.value >= pool.depositFeeBPOrNFTETHFee, "ETH deposit fee too low!");
if (pool.depositFeeBPOrNFTETHFee > 0) {
(bool transferSuccess, ) = payable(reserveFund).call{
value: payable(address(this)).balance
}("");
require(transferSuccess, "Fee Transfer Failed!");
}
address series = address(pool.lpToken);
userStakeCounts[msg.sender][_pid]++;
require(userStakeCounts[msg.sender][_pid] <= MAX_NFT_COUNT,
"you have aleady reached the maximum amount of NFTs you can stake in this pool");
IERC721(series).safeTransferFrom(msg.sender, address(this), _amountOrId);
userStakedMap[msg.sender][series][_amountOrId] = true;
userNftIdsMapArray[msg.sender][series].add(_amountOrId);
user.amount = user.amount + 1;
pool.totalLocked = pool.totalLocked + 1;
} else if (!pool.isNFT && _amountOrId > 0) {
if (_amountOrId > 0) {
uint lpBalanceBefore = pool.lpToken.balanceOf(address(this));
pool.lpToken.safeTransferFrom(msg.sender, address(this), _amountOrId);
_amountOrId = pool.lpToken.balanceOf(address(this)) - lpBalanceBefore;
require(_amountOrId > 0, "No tokens received, high transfer tax?");
uint userPoolBalanceBefore = user.amount;
if (pool.isExtinctionPool) {
pool.lpToken.safeTransfer(reserveFund, _amountOrId);
user.amount += _amountOrId;
pool.totalLocked += _amountOrId;
} else if (pool.depositFeeBPOrNFTETHFee > 0) {
uint _depositFee = _amountOrId * pool.depositFeeBPOrNFTETHFee / 1e4;
pool.lpToken.safeTransfer(reserveFund, _depositFee);
user.amount = (user.amount + _amountOrId) - _depositFee;
pool.totalLocked = (pool.totalLocked + _amountOrId) - _depositFee;
} else {
user.amount += _amountOrId;
pool.totalLocked += _amountOrId;
}
uint userPoolBalanceGained = user.amount - userPoolBalanceBefore;
require(userPoolBalanceGained > 0, "Zero deposit gained, depositing small wei?");
if (!pool.isExtinctionPool)
MintableERC20(pool.receiptToken).mint(msg.sender, userPoolBalanceGained);
}
}
user.rewardDebtJanis = user.amount * pool.accJanisPerShare / 1e24;
user.rewardDebtYieldToken = user.amount * pool.accYieldTokenPerShare / 1e24;
emit Deposit(msg.sender, _pid, _amountOrId);
}
function withdraw(uint _pid, uint _amountOrId) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
require(!pool.isExtinctionPool, "can't withdraw from extinction pools!");
UserInfo storage user = userInfo[_pid][msg.sender];
require(pool.isNFT || user.amount >= _amountOrId, "withdraw: not good");
updatePool(_pid);
transferPendingRewards(_pid);
uint256 withdrawQuantity = 0;
address tokenAddress = address(pool.lpToken);
if (pool.isNFT) {
require(userStakedMap[msg.sender][tokenAddress][_amountOrId], "nft not staked");
userStakeCounts[msg.sender][_pid]--;
userStakedMap[msg.sender][tokenAddress][_amountOrId] = false;
userNftIdsMapArray[msg.sender][tokenAddress].remove(_amountOrId);
withdrawQuantity = 1;
} else if (_amountOrId > 0) {
MintableERC20(pool.receiptToken).burn(msg.sender, _amountOrId);
pool.lpToken.safeTransfer(msg.sender, _amountOrId);
withdrawQuantity = _amountOrId;
}
user.amount -= withdrawQuantity;
pool.totalLocked -= withdrawQuantity;
user.rewardDebtJanis = user.amount * pool.accJanisPerShare / 1e24;
user.rewardDebtYieldToken = user.amount * pool.accYieldTokenPerShare / 1e24;
if (pool.isNFT)
IERC721(tokenAddress).safeTransferFrom(address(this), msg.sender, _amountOrId);
emit Withdraw(msg.sender, _pid, _amountOrId);
}
function emergencyWithdraw(uint _pid) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
require(!pool.isExtinctionPool, "can't withdraw from extinction pools!");
UserInfo storage user = userInfo[_pid][msg.sender];
uint amount = user.amount;
user.amount = 0;
user.rewardDebtJanis = 0;
user.rewardDebtYieldToken = 0;
userStakeCounts[msg.sender][_pid] = 0;
if (pool.totalLocked >= amount)
pool.totalLocked = pool.totalLocked - amount;
else
pool.totalLocked = 0;
if (pool.isNFT) {
address series = address(pool.lpToken);
EnumerableSet.UintSet storage nftStakedCollection = userNftIdsMapArray[msg.sender][series];
for (uint j = 0;j < nftStakedCollection.length();j++) {
uint nftId = nftStakedCollection.at(j);
userStakedMap[msg.sender][series][nftId] = false;
IERC721(series).safeTransferFrom(address(this), msg.sender, nftId);
}
delete userNftIdsMapArray[msg.sender][series];
} else {
MintableERC20(pool.receiptToken).burn(msg.sender, amount);
pool.lpToken.safeTransfer(msg.sender, amount);
}
emit EmergencyWithdraw(msg.sender, _pid, amount);
}
function viewStakerUserNFTs(address _series, address userAddress) external view returns (uint[] memory){
EnumerableSet.UintSet storage nftStakedCollection = userNftIdsMapArray[userAddress][_series];
uint[] memory nftStakedArray = new uint[](nftStakedCollection.length());
for (uint i = 0;i < nftStakedCollection.length();i++)
nftStakedArray[i] = nftStakedCollection.at(i);
return nftStakedArray;
}
function safeJanisTransfer(address _to, uint _amount, uint _pid) internal {
uint boost = 0;
Janis.transfer(_to, _amount);
boost = getBoostJanis(_to, _pid) * _amount / 1e4;
uint total = _amount + boost;
if (boost > 0) janisMinter.operatorMint(_to, boost);
janisMinter.mintReferralsOnly(_to, total);
janisMinter.mintDaoShare(total);
}
function safeYieldTokenTransfer(address _to, uint _amount) internal {
uint currentYieldTokenBalance = yieldToken.balanceOf(address(this));
if (currentYieldTokenBalance < _amount)
yieldToken.safeTransfer(_to, currentYieldTokenBalance);
else
yieldToken.safeTransfer(_to, _amount);
}
function updateJanisEmissionRate(uint _JanisPerSecond) external onlyOwner {
require(_JanisPerSecond < 1e22, "emissions too high!");
massUpdatePools();
JanisPerSecond = _JanisPerSecond;
emit UpdateJanisEmissionRate(msg.sender, _JanisPerSecond);
}
function updateYieldTokenEmissionRate(uint _yieldTokenPerSecond) external onlyOwner {
require(_yieldTokenPerSecond < 1e22, "emissions too high!");
massUpdatePools();
yieldTokenPerSecond = _yieldTokenPerSecond;
emit UpdateYieldTokenEmissionRate(msg.sender, _yieldTokenPerSecond);
}
function set_MAX_NFT_COUNT(uint new_MAX_NFT_COUNT) external onlyOwner {
require(new_MAX_NFT_COUNT >= 20, "MAX_NFT_COUNT must be greater than 0");
require(new_MAX_NFT_COUNT <= 150, "MAX_NFT_COUNT must be less than 150");
MAX_NFT_COUNT = new_MAX_NFT_COUNT;
}
function setBoosterNFTWhitelist(address _nft, bool enabled, uint _nonAbilityBoost, bool isAbilityEnabled, uint abilityNFTBaseBoost, uint _nftAbilityBoostScalar) external onlyOwner {
require(_nft != address(0), "_nft!=0");
require(enabled || (!enabled && !isAbilityEnabled), "Can't disable and also enable for ability boost!");
require(_nonAbilityBoost <= 500, "Max non-abilitu boost is 5%!");
require(abilityNFTBaseBoost<= 500, "Max ability base boost is 5%!");
require(_nftAbilityBoostScalar<= 500, "Max ability scalar boost is 5%!");
isWhitelistedBoosterNFT[_nft] = enabled;
isNFTAbilityEnabled[_nft] = isAbilityEnabled;
if (enabled && !isAbilityEnabled)
nonAbilityBoost[_nft] = _nonAbilityBoost;
else if (!enabled)
nonAbilityBoost[_nft] = 0;
if (isNFTAbilityEnabled[_nft]) {
nftAbilityBaseBoost[_nft] = abilityNFTBaseBoost;
nftAbilityBoostScalar[_nft] = _nftAbilityBoostScalar;
} else {
nftAbilityBaseBoost[_nft] = 0;
nftAbilityBoostScalar[_nft] = 0;
}
emit UpdateBoosterNFTWhitelist(msg.sender, _nft, enabled, nonAbilityBoost[_nft], isAbilityEnabled, nftAbilityBaseBoost[_nft], nftAbilityBoostScalar[_nft]);
}
function setReserveFund(address newReserveFund) external onlyOwner {
reserveFund = newReserveFund;
emit UpdateNewReserveFund(newReserveFund);
}
function harvestAllRewards() external {
uint length = poolInfo.length;
for (uint pid = 0; pid < length; ++pid) {
if (userInfo[pid][msg.sender].amount > 0) {
deposit(pid, 0, true, address(0));
}
}
}
}
文件 15 的 19:JanisMinter.sol
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../libraries/BoringOwnable.sol";
import "./MintableERC20.sol";
contract JanisMinter is BoringOwnable {
using SafeERC20 for IERC20;
using SafeERC20 for MintableERC20;
MintableERC20 public JanisToken;
address public daoAddress;
uint public constant MAX_BONUS = 500;
uint public referralBonusE4 = 300;
uint public refereeBonusE4 = 200;
uint public constant MAX_DAO_SHARE = 2500;
uint public daoShareE4 = 1200;
mapping(address => bool) public operators;
mapping(address => address) public referrers;
mapping(address => uint) public referralsCount;
mapping(address => uint) public totalReferralCommission;
mapping(address => mapping(address => uint)) public totalReferralCommissionPerUser;
mapping(address => uint) public totalRefereeReward;
mapping(address => mapping(address => uint)) public totalRefereeRewardPerReferrer;
event ReferralRecorded(address indexed user, address indexed oldReferrer, address indexed newReferrer);
event ReferralCommissionRecorded(address indexed referrer, address indexed user, uint commission);
event HasRefereeRewardRecorded(address indexed user, address indexed referrer, uint reward);
event JanisMinted(address indexed destination, uint amount);
event ReferralBonusUpdated(uint oldBonus, uint newBonus);
event RefereeBonusUpdated(uint oldBonus, uint newBonus);
event JanisTokenUpdated(address oldJanisToken, address janisToken);
event DaoAddressUpdated(address oldDaoAddress, address daoAddress);
event OperatorUpdated(address indexed operator, bool indexed status);
modifier onlyOperator {
require(operators[msg.sender], "Operator: caller is not the operator");
_;
}
constructor(
address _JanisToken,
address _DaoAddress
) {
require(_JanisToken != address(0), "_JanisToken!=0");
require(_DaoAddress != address(0), "_DaoAddress!=0");
JanisToken = MintableERC20(_JanisToken);
daoAddress = _DaoAddress;
operators[msg.sender] = true;
}
function recordReferral(address _user, address _referrer) external onlyOperator {
if (_user != address(0)
&& _referrer != address(0)
&& _user != _referrer
&& referrers[_user] != _referrer
) {
address oldReferrer = address(0);
if (referrers[_user] != address(0)) {
oldReferrer = referrers[_user];
referralsCount[oldReferrer] -= 1;
}
referralsCount[_referrer] += 1;
referrers[_user] = _referrer;
emit ReferralRecorded(_user, oldReferrer, _referrer);
}
}
function operatorMint(address _destination, uint _minting) external onlyOperator {
mintWithoutReferrals(_destination, _minting);
}
function operatorMintForReserves(uint _minting) external onlyOperator {
mintWithoutReferrals(address(this), _minting);
}
function operatorFetchOrMint(address _destination, uint _minting) external onlyOperator {
uint currentJanisBalance = JanisToken.balanceOf(address(this));
if (currentJanisBalance < _minting) {
JanisToken.mint(address(this), _minting - currentJanisBalance);
emit JanisMinted(address(this), _minting);
}
JanisToken.safeTransfer(_destination, _minting);
}
function mintWithReferrals(address _user, uint _minting) external onlyOperator {
mintWithoutReferrals(_user, _minting);
mintReferralsOnly(_user, _minting);
}
function mintWithoutReferrals(address _user, uint _minting) public onlyOperator {
if (_user != address(0) && _minting > 0) {
JanisToken.mint(_user, _minting);
emit JanisMinted(_user, _minting);
}
}
function mintReferralsOnly(address _user, uint _minting) public onlyOperator {
uint commission = _minting * referralBonusE4 / 1e4;
uint reward = _minting * refereeBonusE4 / 1e4;
address referrer = referrers[_user];
if (referrer != address(0) && _user != address(0) && commission > 0) {
totalReferralCommission[referrer] += commission;
totalReferralCommissionPerUser[referrer][_user] += commission;
JanisToken.mint(referrer, commission);
emit JanisMinted(referrer, commission);
emit ReferralCommissionRecorded(referrer, _user, commission);
}
if (_user != address(0) && referrer != address(0) && reward > 0) {
totalRefereeReward[_user] += reward;
totalRefereeRewardPerReferrer[_user][referrer] += reward;
JanisToken.mint(_user, reward);
emit JanisMinted(_user, reward);
emit ReferralCommissionRecorded(_user, referrer, reward);
}
}
function mintDaoShare(uint _minting) public onlyOperator {
uint daoShare = _minting * daoShareE4 / 1e4;
JanisToken.mint(daoAddress, daoShare);
emit JanisMinted(daoAddress, daoShare);
}
function getReferrer(address _user) external view returns (address) {
return referrers[_user];
}
function updateReferralBonus(uint _bonus) external onlyOwner {
require(_bonus <= MAX_BONUS, "Max bonus is 5%");
uint oldBonus = referralBonusE4;
referralBonusE4 = _bonus;
emit ReferralBonusUpdated(oldBonus, referralBonusE4);
}
function updateRefereeBonus(uint _bonus) external onlyOwner {
require(_bonus <= MAX_BONUS, "Max bonus is 5%");
uint oldBonus = refereeBonusE4;
refereeBonusE4 = _bonus;
emit ReferralBonusUpdated(oldBonus, refereeBonusE4);
}
function updateDaoShare(uint _perc) external onlyOwner {
require(_perc <= MAX_DAO_SHARE, "Max bonus is 25%");
uint oldPerc = daoShareE4;
daoShareE4 = _perc;
emit ReferralBonusUpdated(oldPerc, daoShareE4);
}
function setJanisToken(address _JanisToken) external onlyOwner {
require(_JanisToken != address(0), "_JanisToken!=0");
address oldJanisToken = address(JanisToken);
JanisToken = MintableERC20(_JanisToken);
emit JanisTokenUpdated(oldJanisToken, _JanisToken);
}
function setDaoAddress(address _DaoAddress) external onlyOwner {
require(_DaoAddress != address(0), "_DaoAddress!=0");
address oldDaoAddress = daoAddress;
daoAddress = _DaoAddress;
emit DaoAddressUpdated(oldDaoAddress, daoAddress);
}
function updateOperator(address _operator, bool _status) external onlyOwner {
operators[_operator] = _status;
emit OperatorUpdated(_operator, _status);
}
function drainERC20Token(IERC20 _token, uint _amount, address _to) external onlyOwner {
_token.safeTransfer(_to, _amount);
}
}
文件 16 的 19:MintableERC20.sol
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../libraries/BoringOwnable.sol";
contract MintableERC20 is ERC20, BoringOwnable {
uint8 public immutable decimalsToUse;
mapping(address => bool) public operators;
event OperatorUpdated(address indexed operator, bool indexed status);
modifier onlyOperatorOrOwner {
require(owner == msg.sender || operators[msg.sender], "Operator: caller is not the operator");
_;
}
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
decimalsToUse = decimals_;
operators[msg.sender] = true;
}
function mint(address account, uint256 amount) external onlyOperatorOrOwner {
_mint(account, amount);
}
function burn(address account, uint256 amount) external onlyOperatorOrOwner {
_burn(account, amount);
}
function decimals() public view override returns (uint8){
return decimalsToUse;
}
function updateOperator(address _operator, bool _status) external onlyOwner {
operators[_operator] = _status;
emit OperatorUpdated(_operator, _status);
}
}
文件 17 的 19:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 18 的 19:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 19 的 19:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
{
"compilationTarget": {
"contracts/janis-contracts/protocols/sushiswap/contracts/farm/JanisMasterchef.sol": "JanisMasterChef"
},
"evmVersion": "london",
"libraries": {
"contracts/janis-contracts/protocols/sushiswap/contracts/farm/JanisMasterchef.sol:ERC20FactoryLib": "0x33267e44e354d925885ef16d21b0872e185d3871"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_Janis","type":"address"},{"internalType":"address","name":"_JanisMinter","type":"address"},{"internalType":"uint256","name":"_JanisPerSecond","type":"uint256"},{"internalType":"contract ERC20","name":"_yieldToken","type":"address"},{"internalType":"uint256","name":"_yieldTokenPerSecond","type":"uint256"},{"internalType":"uint256","name":"_globalSartTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","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":"amount","type":"uint256"}],"name":"EmergencyWithdraw","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":"user","type":"address"},{"indexed":true,"internalType":"address","name":"_nft","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_boostRate","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isAbilityEnabled","type":"bool"},{"indexed":false,"internalType":"uint256","name":"abilityNFTBaseBoost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nftAbilityBoostScalar","type":"uint256"}],"name":"UpdateBoosterNFTWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"JanisPerSecond","type":"uint256"}],"name":"UpdateJanisEmissionRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newReserveFund","type":"address"}],"name":"UpdateNewReserveFund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"yieldTokenPerSecond","type":"uint256"}],"name":"UpdateYieldTokenEmissionRate","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":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"Janis","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"JanisPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NFT_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isExtinctionPool","type":"bool"},{"internalType":"bool","name":"_isNFT","type":"bool"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"bool","name":"_usesPremint","type":"bool"},{"internalType":"uint256","name":"_allocPointJanis","type":"uint256"},{"internalType":"uint256","name":"_allocPointYieldToken","type":"uint256"},{"internalType":"contract ERC20","name":"_lpToken","type":"address"},{"internalType":"uint256","name":"_depositFeeBPOrNFTETHFee","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amountOrId","type":"uint256"},{"internalType":"bool","name":"isNFTHarvest","type":"bool"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_nft","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_slot","type":"uint256"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"depositNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"disablePoolKeepMultipliers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getBoostJanis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nft","type":"address"},{"internalType":"uint256","name":"_nftId","type":"uint256"}],"name":"getBoostRateJanis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getSlots","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestAllRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_series","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"hasUserStakedNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isNFTAbilityEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelistedBoosterNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"janisMinter","outputs":[{"internalType":"contract JanisMinter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nftAbilityBaseBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nftAbilityBoostScalar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonAbilityBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingJanis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingYieldToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"name":"poolExistence","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract ERC20","name":"lpToken","type":"address"},{"internalType":"bool","name":"isNFT","type":"bool"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"usesPremint","type":"bool"},{"internalType":"uint256","name":"totalLocked","type":"uint256"},{"internalType":"uint256","name":"allocPointJanis","type":"uint256"},{"internalType":"uint256","name":"allocPointYieldToken","type":"uint256"},{"internalType":"uint256","name":"lastRewardTime","type":"uint256"},{"internalType":"uint256","name":"accJanisPerShare","type":"uint256"},{"internalType":"uint256","name":"accYieldTokenPerShare","type":"uint256"},{"internalType":"uint256","name":"depositFeeBPOrNFTETHFee","type":"uint256"},{"internalType":"address","name":"receiptToken","type":"address"},{"internalType":"bool","name":"isExtinctionPool","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"bool","name":"_usesPremint","type":"bool"},{"internalType":"uint256","name":"_allocPointJanis","type":"uint256"},{"internalType":"uint256","name":"_allocPointYieldToken","type":"uint256"},{"internalType":"uint256","name":"_depositFeeBPOrNFTETHFee","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPointJanis","type":"uint256"},{"internalType":"uint256","name":"_allocPointYieldToken","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"setAllocationPointsOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nft","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"uint256","name":"_nonAbilityBoost","type":"uint256"},{"internalType":"bool","name":"isAbilityEnabled","type":"bool"},{"internalType":"uint256","name":"abilityNFTBaseBoost","type":"uint256"},{"internalType":"uint256","name":"_nftAbilityBoostScalar","type":"uint256"}],"name":"setBoosterNFTWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_depositFeeBPOrNFTETHFee","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"setDepositFeeOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"uint256","name":"_allocPointJanis","type":"uint256"},{"internalType":"uint256","name":"_allocPointYieldToken","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"setPoolScheduleAndMultipliers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"setPoolScheduleKeepMultipliers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newReserveFund","type":"address"}],"name":"setReserveFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"bool","name":"_usesPremint","type":"bool"}],"name":"setUsePremintOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"new_MAX_NFT_COUNT","type":"uint256"}],"name":"set_MAX_NFT_COUNT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocPointJanis","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPointYieldToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"bool","name":"direct","type":"bool"},{"internalType":"bool","name":"renounce","type":"bool"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_JanisPerSecond","type":"uint256"}],"name":"updateJanisEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_yieldTokenPerSecond","type":"uint256"}],"name":"updateYieldTokenEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userDepositedNFTMap","outputs":[{"internalType":"address","name":"slot1","type":"address"},{"internalType":"uint256","name":"tokenId1","type":"uint256"},{"internalType":"address","name":"slot2","type":"address"},{"internalType":"uint256","name":"tokenId2","type":"uint256"},{"internalType":"address","name":"slot3","type":"address"},{"internalType":"uint256","name":"tokenId3","type":"uint256"},{"internalType":"address","name":"slot4","type":"address"},{"internalType":"uint256","name":"tokenId4","type":"uint256"},{"internalType":"address","name":"slot5","type":"address"},{"internalType":"uint256","name":"tokenId5","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebtJanis","type":"uint256"},{"internalType":"uint256","name":"rewardDebtYieldToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakeCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakedMap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_series","type":"address"},{"internalType":"address","name":"userAddress","type":"address"}],"name":"viewStakerUserNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amountOrId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slot","type":"uint256"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"withdrawNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yieldToken","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldTokenPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startPid","type":"uint256"},{"internalType":"uint256","name":"endPid","type":"uint256"},{"internalType":"bool","name":"_withMassUpdate","type":"bool"}],"name":"zeroEndedMultipliersAndDecreaseEmissionVariables","outputs":[],"stateMutability":"nonpayable","type":"function"}]