编译器
0.8.13+commit.abaa5c0e
文件 1 的 5: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;
}
}
文件 2 的 5:IERC20.sol
pragma solidity ^0.8.9;
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
文件 3 的 5:Ownable.sol
pragma solidity ^0.8.0;
import "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
address private _serviceAdmin;
bool private initialized;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event NewServiceAdmin(address indexed previousServiceAdmin, address indexed newServiceAdmin);
function init(address serviceAdmin_) internal {
require(!initialized, "Ownable: init done");
_setOwner(_msgSender());
_setServiceAdmin(serviceAdmin_);
initialized = true;
}
function owner() public view virtual returns (address) {
return _owner;
}
function serviceAdmin() public view virtual returns (address) {
return _serviceAdmin;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
modifier onlyServiceAdmin() {
require(serviceAdmin() == _msgSender(), "Ownable: caller is not the serviceAdmin");
_;
}
modifier anyAdmin(){
require(serviceAdmin() == _msgSender() || owner() == _msgSender(), "Ownable: Caller is not authorized");
_;
}
function renounceOwnership() external virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) external virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
function _setServiceAdmin(address newServiceAdmin) private {
address oldServiceAdmin = _serviceAdmin;
_serviceAdmin = newServiceAdmin;
emit NewServiceAdmin(oldServiceAdmin, newServiceAdmin);
}
}
文件 4 的 5:Pauseable.sol
pragma solidity ^0.8.0;
import "./Context.sol";
abstract contract Pausable is Context {
bool private pauseInit;
event Paused(address account);
event Unpaused(address account);
bool private _paused;
function _pausable_init() internal{
require(!pauseInit, "init done");
_paused = false;
pauseInit = true;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 5 的 5:StakingV1.sol
pragma solidity ^0.8.9;
import "./IERC20.sol";
import "./Ownable.sol";
import "./Pauseable.sol";
contract StakingRewards is Ownable, Pausable{
IERC20 public rewardsToken;
IERC20 public stakingToken;
uint256 public periodFinish;
uint public rewardRate ;
uint public lastUpdateTime;
uint public rewardPerTokenStored;
mapping(address => uint) public userRewardPerTokenPaid;
mapping(address => uint) public rewards;
uint private _totalSupply;
mapping(address => uint) private _balances;
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
event RewardsDurationUpdated(uint256 newDuration);
constructor(address _stakingToken, address _rewardsToken, uint256 _endTime, uint256 _rewardRate, address serviceAdmin) {
stakingToken = IERC20(_stakingToken);
rewardsToken = IERC20(_rewardsToken);
periodFinish = _endTime;
rewardRate = _rewardRate;
Ownable.init(serviceAdmin);
_pausable_init();
}
function rewardPerToken() public view returns (uint) {
if (_totalSupply == 0) {
return 0;
}
return
rewardPerTokenStored +
(((lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
}
function earned(address account) public view returns (uint) {
return
((_balances[account] *
(rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
rewards[account];
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function stake(uint _amount) external whenNotPaused updateReward(msg.sender) {
require(_amount > 0, "Cannot withdraw 0");
_totalSupply += _amount;
_balances[msg.sender] += _amount;
stakingToken.transferFrom(msg.sender, address(this), _amount);
emit Staked(msg.sender, _amount);
}
function withdraw(uint _amount) public whenNotPaused updateReward(msg.sender) {
require(_amount > 0, "Cannot withdraw 0");
require(_balances[msg.sender] >= _amount,"Can not withdraw more than the current balance");
_totalSupply -= _amount;
_balances[msg.sender] -= _amount;
stakingToken.transfer(msg.sender, _amount);
emit Withdrawn(msg.sender, _amount);
}
function getReward() public whenNotPaused updateReward(msg.sender) {
uint reward = rewards[msg.sender];
if (reward > 0){
rewards[msg.sender] = 0;
rewardsToken.transfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function exit() whenNotPaused external {
withdraw(_balances[msg.sender]);
getReward();
}
function updatePeriod(uint256 _newperiod)public anyAdmin {
require(_newperiod > periodFinish, "New time should be greater than old one");
periodFinish = _newperiod;
emit RewardsDurationUpdated(_newperiod);
}
function totalSupply() external view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) external view returns (uint256) {
return _balances[account];
}
function lastTimeRewardApplicable() public view returns (uint256) {
return block.timestamp < periodFinish ? block.timestamp : periodFinish;
}
function PauseContract()public anyAdmin{
_pause();
}
function UnPauseContract()public anyAdmin{
_unpause();
}
}
{
"compilationTarget": {
"StakingV1.sol": "StakingRewards"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"uint256","name":"_rewardRate","type":"uint256"},{"internalType":"address","name":"serviceAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousServiceAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newServiceAdmin","type":"address"}],"name":"NewServiceAdmin","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"RewardsDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"PauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"UnPauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","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":"exit","outputs":[],"stateMutability":"nonpayable","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":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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 IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"serviceAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newperiod","type":"uint256"}],"name":"updatePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]