文件 1 的 14:Address.sol
pragma solidity ^0.8.7;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 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 的 14:CimoStaking.sol
pragma solidity ^0.8.7;
import "./../libs/Ownable.sol";
import "./../contracts/ReentrancyGuard.sol";
import "./../contracts/ERC721Holder.sol";
import "./../interfaces/IUniswapV2Router02.sol";
import "./../libs/SafeERC20.sol";
import "./../interfaces/ICimo.sol";
import "./../interfaces/INFT.sol";
contract CimoStaking is Ownable, ReentrancyGuard, ERC721Holder {
using SafeERC20 for IERC20;
struct UserInfo {
uint16 nftBoost;
uint16 lockTimeBoost;
uint32 lockedUntil;
uint96 claimableETH;
uint112 amount;
uint112 weightedBalance;
uint256 withdrawn;
uint112 ETHrewardDebt;
address[] NFTContracts;
uint256[] NFTTokenIDs;
}
struct PoolInfo {
IERC20 lpToken;
uint64 allocPoint;
uint64 lastRewardBlock;
uint112 accETHPerShare;
uint112 weightedBalance;
}
struct UsersNFTs {
address NFTContract;
uint256 TokenId;
}
uint16 public pointsPerNFT = 150;
uint256 constant ONE_DAY = 86400;
ICimo public Cimo;
address public router;
address public WETH;
mapping(address => bool) public isNFTContract;
address public TaxDistributor;
uint256 public ETHPerBlock;
uint256 public ETHLeftUnshared;
uint256 public ETHLeftUnclaimed;
uint256 public numdays;
PoolInfo[] public poolInfo;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
uint256 public totalAllocPoint;
uint256 public startBlock;
bool public isEmergency;
event Deposit(address indexed user, uint256 indexed pid, uint256 amount, uint256 lockTime);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(
address indexed user,
uint256 indexed pid,
uint256 amount
);
event UpdateEmissionRate(address indexed user, uint256 cimoRWTokenPerBlock);
event NFTStaked(
address indexed user,
address indexed NFTContract,
uint256 tokenID
);
event NFTWithdrawn(
address indexed user,
address indexed NFTContract,
uint256 tokenID
);
event TokensLocked(
address indexed user,
uint256 timestamp,
uint256 lockTime
);
event Emergency(uint256 timestamp, bool ifEmergency);
mapping(IERC20 => bool) public poolExistence;
modifier nonDuplicated(IERC20 _lpToken) {
require(poolExistence[_lpToken] == false, "nonDuplicated: LP Token already added");
_;
}
modifier onlyEmergency() {
require(isEmergency == true, "onlyEmergency: Emergency use only!");
_;
}
mapping(address => bool) public authorized;
modifier onlyAuthorized() {
require(authorized[msg.sender] == true, "onlyAuthorized: address not authorized");
_;
}
constructor(ICimo _cimo, address _router) {
Cimo = _cimo;
router = _router;
WETH = IUniswapV2Router02(router).WETH();
startBlock = type(uint256).max;
Cimo.approve(router, Cimo.totalSupply());
numdays = 8;
}
function poolLength() external view returns (uint256) {
return poolInfo.length;
}
function getMultiplier(uint256 _from, uint256 _to)
public
pure
returns (uint256)
{
return (_to - _from);
}
function pendingRewards(uint256 _pid, address _user) external view returns (uint256)
{
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 userWeightedAmount = user.weightedBalance;
uint256 accETHPerShare = pool.accETHPerShare;
uint256 weightedBalance = pool.weightedBalance;
uint256 PendingETH;
if (block.number > pool.lastRewardBlock && weightedBalance != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 ETHReward = multiplier * ETHPerBlock * pool.allocPoint / totalAllocPoint;
accETHPerShare = accETHPerShare + ETHReward * 1e12 / weightedBalance;
PendingETH = (userWeightedAmount * accETHPerShare / 1e12) - user.ETHrewardDebt + user.claimableETH;
}
return (PendingETH);
}
function getUsersNFTs(uint256 _pid, address _user)
public
view
returns (address[] memory, uint256[] memory)
{
UserInfo storage user = userInfo[_pid][_user];
uint256 nftCount = user.NFTContracts.length;
address[] memory _nftContracts = new address[](nftCount);
uint256[] memory _nftTokenIds = new uint256[](nftCount);
for (uint256 i = 0; i < nftCount; i++) {
_nftContracts[i] = user.NFTContracts[i];
_nftTokenIds[i] = user.NFTTokenIDs[i];
}
return (_nftContracts, _nftTokenIds);
}
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
}
}
fallback() external payable {
ETHLeftUnshared += msg.value;
updateETHRewards();
}
receive() external payable {
require(msg.sender != TaxDistributor);
}
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
if (block.number <= pool.lastRewardBlock) {
return;
}
uint256 lpSupply = pool.weightedBalance;
if (lpSupply == 0 || pool.allocPoint == 0) {
pool.lastRewardBlock = uint64(block.number);
return;
}
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
uint256 ETHReward = multiplier * ETHPerBlock * pool.allocPoint / totalAllocPoint;
ETHLeftUnclaimed = ETHLeftUnclaimed + ETHReward;
ETHLeftUnshared = ETHLeftUnshared - ETHReward;
pool.accETHPerShare = uint112(pool.accETHPerShare + ETHReward * 1e12 / lpSupply);
pool.lastRewardBlock = uint64(block.number);
}
function deposit(uint256 _pid, uint256 _amount, uint256 lockTime) public nonReentrant {
_deposit(msg.sender, _pid, _amount, lockTime);
}
function withdraw(uint32 _pid, uint256 _amount) public nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.lockedUntil < block.timestamp, "withdraw: Tokens locked, if you're trying to claim your rewards use the deposit function");
require(user.amount >= _amount && _amount > 0, "withdraw: not good");
updatePool(_pid);
if (user.weightedBalance > 0) {
_addToClaimable(_pid, msg.sender);
if (user.claimableETH > 0) {
safeETHTransfer(msg.sender, user.claimableETH);
user.withdrawn += user.claimableETH;
user.claimableETH = 0;
}
}
user.amount = uint112(user.amount - _amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
updateUserWeightedBalance(_pid, msg.sender);
emit Withdraw(msg.sender, _pid, _amount);
}
function emergencyWithdraw(uint256 _pid) public nonReentrant onlyEmergency {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
uint256 amount = user.amount;
pool.weightedBalance -= user.weightedBalance;
user.amount = 0;
user.weightedBalance = 0;
user.ETHrewardDebt = 0;
user.claimableETH = 0;
pool.lpToken.safeTransfer(address(msg.sender), amount);
emit EmergencyWithdraw(msg.sender, _pid, amount);
}
function addLiquidityNoFeeAndStake(uint256 amountTokensIn, uint256 amountETHMin, uint256 amountTokenMin, uint256 lockTime) public payable nonReentrant {
ICimo.LiquidityETHParams memory params;
UserInfo storage user = userInfo[0][msg.sender];
require(msg.value > 0);
require((lockTime >= 0 && lockTime <= 90 * ONE_DAY && user.lockedUntil <= lockTime + block.timestamp), "addLiquidityNoFeeAndStake : Lock out of range");
updatePool(0);
if (user.weightedBalance > 0) {
_addToClaimable(0, msg.sender);
}
Cimo.transferFrom(msg.sender, address(this), amountTokensIn);
params.pair = address(poolInfo[0].lpToken);
params.to = address(this);
params.amountTokenMin = amountTokenMin;
params.amountETHMin = amountETHMin;
params.amountTokenOrLP = amountTokensIn;
params.deadline = block.timestamp;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(router);
(, uint256 ETHUsed, uint256 numLiquidityAdded) = _uniswapV2Router.addLiquidityETH{value : msg.value}(
address(Cimo),
params.amountTokenOrLP,
params.amountTokenMin,
params.amountETHMin,
params.to,
block.timestamp
);
payable(msg.sender).transfer(msg.value - ETHUsed);
user.amount += uint112(numLiquidityAdded);
if (lockTime > 0) {
lockTokens(msg.sender, 0, lockTime);
} else {
updateUserWeightedBalance(0, msg.sender);
}
emit Deposit(msg.sender, 0, numLiquidityAdded, lockTime);
}
function reinvestETHRewards(uint256 amountOutMin) public nonReentrant {
UserInfo storage user = userInfo[1][msg.sender];
updatePool(1);
uint256 ETHPending = (user.weightedBalance * poolInfo[1].accETHPerShare / 1e12) - user.ETHrewardDebt + user.claimableETH;
require(ETHPending > 0);
address[] memory path = new address[](2);
path[0] = WETH;
path[1] = address(Cimo);
if (ETHPending > ETHLeftUnclaimed) {
ETHPending = ETHLeftUnclaimed;
}
uint256 balanceBefore = Cimo.balanceOf(address(this));
IUniswapV2Router02(router).swapExactETHForTokensSupportingFeeOnTransferTokens{value: ETHPending}(
amountOutMin,
path,
address(this),
block.timestamp
);
uint256 amountSwapped = Cimo.balanceOf(address(this)) - balanceBefore;
user.amount += uint112(amountSwapped);
user.claimableETH = 0;
user.withdrawn += ETHPending;
updateUserWeightedBalance(1, msg.sender);
emit Deposit(msg.sender, 1, amountSwapped, 0);
}
function withdrawNFT(uint256 _pid, address NFTContract, uint256 tokenID) public nonReentrant {
address sender = msg.sender;
uint256 NFTIndex;
bool tokenFound;
uint256 length = userInfo[_pid][sender].NFTContracts.length;
updatePool(_pid);
_addToClaimable(_pid, sender);
for (uint256 i; i < userInfo[_pid][sender].NFTContracts.length; i++) {
if (userInfo[_pid][sender].NFTContracts[i] == NFTContract) {
if (userInfo[_pid][sender].NFTTokenIDs[i] == tokenID) {
tokenFound = true;
NFTIndex = i;
break;
}
}
}
require(tokenFound == true, "withdrawNFT, token not found");
userInfo[_pid][sender].nftBoost -= uint16(pointsPerNFT);
userInfo[_pid][sender].NFTContracts[NFTIndex] = userInfo[_pid][sender].NFTContracts[length - 1];
userInfo[_pid][sender].NFTContracts.pop();
userInfo[_pid][sender].NFTTokenIDs[NFTIndex] = userInfo[_pid][sender].NFTTokenIDs[length - 1];
userInfo[_pid][sender].NFTTokenIDs.pop();
updateUserWeightedBalance(_pid, sender);
INFT(NFTContract).safeTransferFrom(address(this), sender, tokenID);
emit NFTWithdrawn(sender, NFTContract, tokenID);
}
function boostWithNFT(uint256 _pid, address NFTContract, uint256 tokenID) public nonReentrant {
require(msg.sender == tx.origin, "boostWithNFT : Deposit from contract disabled");
require(isNFTContract[NFTContract], "boostWithNFT: incorrect contract address");
require(userInfo[_pid][msg.sender].amount > 0, "boostWithNFT: Requires staked tokens");
updatePool(_pid);
_addToClaimable(_pid, msg.sender);
INFT(NFTContract).safeTransferFrom(msg.sender, address(this), tokenID);
userInfo[_pid][msg.sender].NFTContracts.push(NFTContract);
userInfo[_pid][msg.sender].NFTTokenIDs.push(tokenID);
userInfo[_pid][msg.sender].nftBoost += uint16(pointsPerNFT);
updateUserWeightedBalance(_pid, msg.sender);
emit NFTWithdrawn(msg.sender, NFTContract, tokenID);
}
function addToClaimable(uint256 _pid, address sender) public nonReentrant {
require(userInfo[_pid][sender].weightedBalance > 0);
updatePool(_pid);
_addToClaimable(_pid, sender);
}
function depositFor(address sender, uint256 _pid, uint256 amount, uint256 lockTime ) public onlyAuthorized {
_deposit(sender, _pid, amount, lockTime);
}
function add(uint64 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner nonDuplicated(_lpToken) {
if (_withUpdate) {
massUpdatePools();
}
uint64 lastRewardBlock = uint64(block.number > startBlock ? block.number : startBlock);
totalAllocPoint = totalAllocPoint + _allocPoint;
poolExistence[_lpToken] = true;
poolInfo.push(
PoolInfo({
lpToken : _lpToken,
allocPoint : _allocPoint,
lastRewardBlock : lastRewardBlock,
accETHPerShare : 0,
weightedBalance : 0
}));
}
function addNFTContract(address NFTcontract) public onlyOwner {
isNFTContract[NFTcontract] = true;
}
function setTaxDistributor(address _TaxDistributor) public onlyOwner {
TaxDistributor = _TaxDistributor;
}
function setRouter(address _router) public onlyOwner {
router = _router;
}
function rescueToken(address tokenAddress) public onlyOwner {
require(!poolExistence[IERC20(tokenAddress)], "rescueToken : wrong token address");
uint256 bal = IERC20(tokenAddress).balanceOf(address(this));
IERC20(tokenAddress).transfer(msg.sender, bal);
}
function set(uint256 _pid, uint64 _allocPoint, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
massUpdatePools();
}
totalAllocPoint = totalAllocPoint - poolInfo[_pid].allocPoint + _allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
}
function startRewards() public onlyOwner {
require(startBlock > block.number, "startRewards: rewards already started");
startBlock = block.number;
for (uint256 i; i < poolInfo.length; i++) {
poolInfo[i].lastRewardBlock = uint64(block.number);
}
}
function emergency(bool _isEmergency) public onlyOwner {
isEmergency = _isEmergency;
emit Emergency(block.timestamp, _isEmergency);
}
function authorize(address _address) public onlyOwner {
authorized[_address] = true;
}
function unauthorize(address _address) public onlyOwner {
authorized[_address] = false;
}
function setnumdays(uint256 _days) public onlyOwner {
require(_days > 0 && _days < 14);
numdays = _days;
}
function _deposit(address sender, uint256 _pid, uint256 _amount, uint256 lockTime) internal {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][sender];
updatePool(_pid);
if (user.weightedBalance > 0) {
if (_amount == 0 && lockTime == 0) {
uint256 ETHPending = (user.weightedBalance * pool.accETHPerShare / 1e12) - user.ETHrewardDebt + user.claimableETH;
if (ETHPending > 0) {
safeETHTransfer(sender, ETHPending);
user.withdrawn += ETHPending;
user.ETHrewardDebt = user.weightedBalance * pool.accETHPerShare / 1e12;
}
user.claimableETH = 0;
} else {
_addToClaimable(_pid, sender);
}
}
if (_amount > 0) {
require(
(lockTime >= 0 && lockTime <= 90 * ONE_DAY && user.lockedUntil <= lockTime + block.timestamp),
"deposit : Lock out of range or previously locked tokens are locked longer than new desired lock"
);
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
user.amount = uint112(user.amount + _amount);
if (lockTime == 0) {
updateUserWeightedBalance(_pid, sender);
}
}
if (lockTime > 0) {
lockTokens(sender, _pid, lockTime);
}
if (user.lockedUntil < block.timestamp) {
updateUserWeightedBalance(_pid, sender);
}
emit Deposit(sender, _pid, _amount, lockTime);
}
function lockTokens(address sender, uint256 _pid, uint256 lockTime) internal {
UserInfo storage user = userInfo[_pid][sender];
require(user.amount > 0, "lockTokens: No tokens to lock");
require(user.lockedUntil <= block.timestamp + lockTime, "lockTokens: Tokens already locked");
require(lockTime >= ONE_DAY, "lockTokens: Lock time too short");
require(lockTime <= 90 * ONE_DAY, "lockTokens: Lock time too long");
user.lockedUntil = uint32(block.timestamp + lockTime);
user.lockTimeBoost = uint16((2 * 1000 * lockTime) / (90 * ONE_DAY));
updateUserWeightedBalance(_pid, sender);
emit TokensLocked(sender, block.timestamp, lockTime);
}
function updateUserWeightedBalance(uint256 _pid, address _user) public {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 poolBalance = pool.weightedBalance - user.weightedBalance;
if (user.lockedUntil < block.timestamp) {
user.lockTimeBoost = 0;
}
user.weightedBalance = (user.amount * (1000 + user.lockTimeBoost + user.nftBoost) / 1000);
pool.weightedBalance = uint112(poolBalance + user.weightedBalance);
user.ETHrewardDebt = user.weightedBalance * pool.accETHPerShare / 1e12;
}
function updateETHRewards() internal {
massUpdatePools();
ETHPerBlock = ETHLeftUnshared / (6400 * numdays);
}
function _addToClaimable(uint256 _pid, address sender) internal {
UserInfo storage user = userInfo[_pid][sender];
PoolInfo storage pool = poolInfo[_pid];
uint256 ETHPending = (user.weightedBalance * pool.accETHPerShare / 1e12) - user.ETHrewardDebt;
if (ETHPending > 0) {
user.claimableETH += uint96(ETHPending);
user.ETHrewardDebt = user.weightedBalance * pool.accETHPerShare / 1e12;
}
}
function safeETHTransfer(address _to, uint256 _amount) internal {
if (_amount > ETHLeftUnclaimed) {
_amount = ETHLeftUnclaimed;
}
payable(_to).transfer(_amount);
ETHLeftUnclaimed -= _amount;
}
}
文件 3 的 14:Context.sol
pragma solidity ^0.8.7;
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 的 14:ERC721Holder.sol
pragma solidity ^0.8.7;
import "./../interfaces/IERC721Receiver.sol";
contract ERC721Holder is IERC721Receiver {
function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
文件 5 的 14:ICimo.sol
pragma solidity ^0.8.7;
import "./IERC20.sol";
interface ICimo is IERC20 {
struct LiquidityETHParams {
address pair;
address to;
uint256 amountTokenOrLP;
uint256 amountTokenMin;
uint256 amountETHMin;
uint256 deadline;
}
}
文件 6 的 14:IERC165.sol
pragma solidity ^0.8.7;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 14:IERC20.sol
pragma solidity ^0.8.7;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender,
address recipient,
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);
}
文件 8 的 14:IERC721.sol
pragma solidity ^0.8.7;
import "./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;
}
文件 9 的 14:IERC721Receiver.sol
pragma solidity ^0.8.7;
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
文件 10 的 14:INFT.sol
pragma solidity ^0.8.7;
import "./IERC721.sol";
interface INFT is IERC721 {
function getMultiplierForTokenID(uint256 _tokenID) external view returns (uint256);
}
文件 11 的 14:IUniswapV2Router02.sol
pragma solidity ^0.8.7;
interface IUniswapV2Router02 {
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
}
文件 12 的 14:Ownable.sol
pragma solidity ^0.8.7;
import "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 14:ReentrancyGuard.sol
pragma solidity ^0.8.7;
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;
}
}
文件 14 的 14:SafeERC20.sol
pragma solidity ^0.8.7;
import "./Address.sol";
import "./../interfaces/IERC20.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");
}
}
}
{
"compilationTarget": {
"CimoStaking.sol": "CimoStaking"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ICimo","name":"_cimo","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"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"},{"indexed":false,"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"bool","name":"ifEmergency","type":"bool"}],"name":"Emergency","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":"user","type":"address"},{"indexed":true,"internalType":"address","name":"NFTContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"NFTStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"NFTContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"NFTWithdrawn","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":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"TokensLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"cimoRWTokenPerBlock","type":"uint256"}],"name":"UpdateEmissionRate","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"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"Cimo","outputs":[{"internalType":"contract ICimo","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETHLeftUnclaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETHLeftUnshared","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETHPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TaxDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_allocPoint","type":"uint64"},{"internalType":"contract IERC20","name":"_lpToken","type":"address"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountTokensIn","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"addLiquidityNoFeeAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"NFTcontract","type":"address"}],"name":"addNFTContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"sender","type":"address"}],"name":"addToClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"NFTContract","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"boostWithNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockTime","type":"uint256"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEmergency","type":"bool"}],"name":"emergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUsersNFTs","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEmergency","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isNFTContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"numdays","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":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pointsPerNFT","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","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 IERC20","name":"lpToken","type":"address"},{"internalType":"uint64","name":"allocPoint","type":"uint64"},{"internalType":"uint64","name":"lastRewardBlock","type":"uint64"},{"internalType":"uint112","name":"accETHPerShare","type":"uint112"},{"internalType":"uint112","name":"weightedBalance","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"}],"name":"reinvestETHRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint64","name":"_allocPoint","type":"uint64"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_TaxDistributor","type":"address"}],"name":"setTaxDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_days","type":"uint256"}],"name":"setnumdays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"unauthorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"updateUserWeightedBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint16","name":"nftBoost","type":"uint16"},{"internalType":"uint16","name":"lockTimeBoost","type":"uint16"},{"internalType":"uint32","name":"lockedUntil","type":"uint32"},{"internalType":"uint96","name":"claimableETH","type":"uint96"},{"internalType":"uint112","name":"amount","type":"uint112"},{"internalType":"uint112","name":"weightedBalance","type":"uint112"},{"internalType":"uint256","name":"withdrawn","type":"uint256"},{"internalType":"uint112","name":"ETHrewardDebt","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_pid","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"NFTContract","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"withdrawNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]