编译器
0.8.17+commit.8df45f5f
文件 1 的 3:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 2 的 3:IesLBR.sol
pragma solidity 0.8.17;
interface IesLBR {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function mint(address user, uint256 amount) external returns(bool);
function burn(address user, uint256 amount) external returns(bool);
}
文件 3 的 3:stakerewardV2pool.sol
pragma solidity ^0.8;
import "./IesLBR.sol";
import "./IERC20.sol";
interface IesLBRBoost {
function getUserBoost(
address user,
uint256 userUpdatedAt,
uint256 finishAt
) external view returns (uint256);
function getUnlockTime(address user)
external
view
returns (uint256 unlockTime);
}
interface IlybraFund {
function refreshReward(address user) external;
}
contract StakingRewardsV2 {
IERC20 public immutable stakingToken;
IesLBR public immutable rewardsToken;
IesLBRBoost public esLBRBoost;
IlybraFund public lybraFund;
address public owner;
uint256 public duration = 2_592_000;
uint256 public finishAt;
uint256 public updatedAt;
uint256 public rewardRate;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public userUpdatedAt;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
constructor(
address _stakingToken,
address _rewardToken,
address _boost,
address _fund
) {
owner = msg.sender;
stakingToken = IERC20(_stakingToken);
rewardsToken = IesLBR(_rewardToken);
esLBRBoost = IesLBRBoost(_boost);
lybraFund = IlybraFund(_fund);
}
modifier onlyOwner() {
require(msg.sender == owner, "not authorized");
_;
}
modifier updateReward(address _account) {
rewardPerTokenStored = rewardPerToken();
updatedAt = lastTimeRewardApplicable();
if (_account != address(0)) {
rewards[_account] = earned(_account);
userRewardPerTokenPaid[_account] = rewardPerTokenStored;
userUpdatedAt[_account] = block.timestamp;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return _min(finishAt, block.timestamp);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored +
(rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) /
totalSupply;
}
function stake(uint256 _amount) external updateReward(msg.sender) {
require(_amount > 0, "amount = 0");
stakingToken.transferFrom(msg.sender, address(this), _amount);
balanceOf[msg.sender] += _amount;
totalSupply += _amount;
}
function withdraw(uint256 _amount) external updateReward(msg.sender) {
require(_amount > 0, "amount = 0");
balanceOf[msg.sender] -= _amount;
totalSupply -= _amount;
stakingToken.transfer(msg.sender, _amount);
}
function getBoost(address _account) public view returns (uint256) {
return 100 * 1e18 + esLBRBoost.getUserBoost(
_account,
userUpdatedAt[_account],
finishAt
);
}
function earned(address _account) public view returns (uint256) {
return
((balanceOf[_account] *
getBoost(_account) *
(rewardPerToken() - userRewardPerTokenPaid[_account])) / 1e38) +
rewards[_account];
}
function getReward() external updateReward(msg.sender) {
require(
block.timestamp >= esLBRBoost.getUnlockTime(msg.sender),
"Your lock-in period has not ended. You can't claim your esLBR now."
);
uint256 reward = rewards[msg.sender];
if (reward > 0) {
rewards[msg.sender] = 0;
lybraFund.refreshReward(msg.sender);
rewardsToken.mint(msg.sender, reward);
}
}
function setRewardsDuration(uint256 _duration) external onlyOwner {
require(finishAt < block.timestamp, "reward duration not finished");
duration = _duration;
}
function setBoost(address _boost) external onlyOwner {
esLBRBoost = IesLBRBoost(_boost);
}
function notifyRewardAmount(uint256 _amount)
external
onlyOwner
updateReward(address(0))
{
if (block.timestamp >= finishAt) {
rewardRate = _amount / duration;
} else {
uint256 remainingRewards = (finishAt - block.timestamp) *
rewardRate;
rewardRate = (_amount + remainingRewards) / duration;
}
require(rewardRate > 0, "reward rate = 0");
finishAt = block.timestamp + duration;
updatedAt = block.timestamp;
}
function _min(uint256 x, uint256 y) private pure returns (uint256) {
return x <= y ? x : y;
}
}
{
"compilationTarget": {
"contracts/stakerewardV2pool.sol": "StakingRewardsV2"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_boost","type":"address"},{"internalType":"address","name":"_fund","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"esLBRBoost","outputs":[{"internalType":"contract IesLBRBoost","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lybraFund","outputs":[{"internalType":"contract IlybraFund","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IesLBR","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_boost","type":"address"}],"name":"setBoost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userUpdatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]