编译器
0.8.17+commit.8df45f5f
文件 1 的 10:BaseAdminOperation.sol
pragma solidity ^0.8.4;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {TransferHelper} from "./util/TransferHelper.sol";
abstract contract BaseAdminOperation is Pausable, Ownable {
event AdminUpdated(address indexed addr, bool flag);
mapping(address => bool) public isAdmin;
modifier onlyAdmin() {
require(_msgSender() == owner() || isAdmin[_msgSender()], "BaseAdminOperation: !admin");
_;
}
function pause() public onlyAdmin {
_pause();
}
function unpause() public onlyAdmin {
_unpause();
}
function setAdmin(address addr, bool flag) public onlyAdmin {
isAdmin[addr] = flag;
emit AdminUpdated(addr, flag);
}
function inCaseTokenGotStuck(address stuckToken) external virtual onlyOwner {
if (stuckToken == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
TransferHelper.safeTransferETH(_msgSender(), address(this).balance);
} else {
uint256 amount = IERC20(stuckToken).balanceOf(address(this));
TransferHelper.safeTransfer(stuckToken, _msgSender(), amount);
}
}
}
文件 2 的 10:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 10: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);
}
文件 4 的 10:IRewarder.sol
pragma solidity ^0.8.0;
import "./IWooStakingManager.sol";
interface IRewarder {
event ClaimOnRewarder(address indexed from, address indexed to, uint256 amount);
event SetStakingManagerOnRewarder(address indexed manager);
function rewardToken() external view returns (address);
function stakingManager() external view returns (IWooStakingManager);
function pendingReward(address _user) external view returns (uint256 rewardAmount);
function claim(address _user) external returns (uint256 rewardAmount);
function claim(address _user, address _to) external returns (uint256 rewardAmount);
function setStakingManager(address _manager) external;
function updateReward() external;
function updateRewardForUser(address _user) external;
function clearRewardToDebt(address _user) external;
}
文件 5 的 10:IWooStakingManager.sol
pragma solidity 0.8.17;
interface IWooStakingManager {
event StakeWooOnStakingManager(address indexed user, uint256 amount);
event UnstakeWooOnStakingManager(address indexed user, uint256 amount);
event AddMPOnStakingManager(address indexed user, uint256 amount);
event CompoundMPOnStakingManager(address indexed user);
event CompoundRewardsOnStakingManager(address indexed user, uint256 wooAmount);
event CompoundAllOnStakingManager(address indexed user);
event CompoundAllForUsersOnStakingManager(address[] users, uint256[] wooRewards);
event SetAutoCompoundOnStakingManager(address indexed user, bool flag);
event SetMPRewarderOnStakingManager(address indexed rewarder);
event SetWooPPOnStakingManager(address indexed wooPP);
event SetStakingLocalOnStakingManager(address indexed stakingProxy);
event SetCompounderOnStakingManager(address indexed compounder);
event AddRewarderOnStakingManager(address indexed rewarder);
event RemoveRewarderOnStakingManager(address indexed rewarder);
event ClaimRewardsOnStakingManager(address indexed user);
function stakeWoo(address _user, uint256 _amount) external;
function unstakeWoo(address _user, uint256 _amount) external;
function mpBalance(address _user) external view returns (uint256);
function wooBalance(address _user) external view returns (uint256);
function wooTotalBalance() external view returns (uint256);
function totalBalance(address _user) external view returns (uint256);
function totalBalance() external view returns (uint256);
function compoundMP(address _user) external;
function addMP(address _user, uint256 _amount) external;
function compoundRewards(address _user) external;
function compoundAll(address _user) external;
function compoundAllForUsers(address[] memory _users) external;
function setAutoCompound(address _user, bool _flag) external;
function pendingRewards(
address _user
) external view returns (uint256 mpRewardAmount, address[] memory rewardTokens, uint256[] memory amounts);
}
文件 6 的 10:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 7 的 10:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
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());
}
}
文件 8 的 10: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() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
}
文件 9 的 10:SimpleRewarder.sol
pragma solidity ^0.8.4;
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IRewarder} from "../interfaces/IRewarder.sol";
import {IWooStakingManager} from "../interfaces/IWooStakingManager.sol";
import {BaseAdminOperation} from "../BaseAdminOperation.sol";
import {TransferHelper} from "../util/TransferHelper.sol";
contract SimpleRewarder is IRewarder, BaseAdminOperation, ReentrancyGuard {
event SetRewardPerBlockOnRewarder(uint256 rewardPerBlock);
address public immutable rewardToken;
uint256 public accTokenPerShare;
uint256 public immutable tokenPerShareDecimal;
uint256 public rewardPerBlock;
uint256 public lastRewardBlock;
uint256 totalRewardClaimable = 0;
IWooStakingManager public stakingManager;
mapping(address => uint256) public rewardDebt;
mapping(address => uint256) public rewardClaimable;
constructor(address _rewardToken, address _stakingManager) {
tokenPerShareDecimal = 1e30;
rewardToken = _rewardToken;
stakingManager = IWooStakingManager(_stakingManager);
lastRewardBlock = block.number;
setAdmin(_stakingManager, true);
}
modifier onlyStakingManager() {
require(_msgSender() == address(stakingManager), "BaseRewarder: !stakingManager");
_;
}
function pendingReward(address _user) external view returns (uint256 rewardAmount) {
uint256 _totalWeight = totalWeight();
uint256 _userWeight = weight(_user);
uint256 _userReward = (accTokenPerShare * _userWeight) / tokenPerShareDecimal;
if (_totalWeight != 0) {
uint256 rewards = (block.number - lastRewardBlock) * rewardPerBlock;
_userReward += (rewards * _userWeight) / _totalWeight;
}
uint256 newUserReward = _userReward - rewardDebt[_user];
return rewardClaimable[_user] + newUserReward;
}
function allPendingReward() external view returns (uint256 rewardAmount) {
return (block.number - lastRewardBlock) * rewardPerBlock;
}
function claim(address _user) external onlyAdmin returns (uint256 rewardAmount) {
rewardAmount = _claim(_user, _user);
}
function claim(address _user, address _to) external onlyStakingManager returns (uint256 rewardAmount) {
rewardAmount = _claim(_user, _to);
}
function _claim(address _user, address _to) internal returns (uint256 rewardAmount) {
updateRewardForUser(_user);
rewardAmount = rewardClaimable[_user];
rewardClaimable[_user] = 0;
totalRewardClaimable -= rewardAmount;
TransferHelper.safeTransfer(rewardToken, _to, rewardAmount);
emit ClaimOnRewarder(_user, _to, rewardAmount);
}
function updateReward() public nonReentrant {
uint256 _totalWeight = totalWeight();
if (_totalWeight == 0) {
lastRewardBlock = block.number;
return;
}
uint256 rewards = (block.number - lastRewardBlock) * rewardPerBlock;
accTokenPerShare += (rewards * tokenPerShareDecimal) / _totalWeight;
lastRewardBlock = block.number;
}
function updateRewardForUser(address _user) public nonReentrant {
uint256 _totalWeight = totalWeight();
if (_totalWeight == 0) {
lastRewardBlock = block.number;
return;
}
uint256 rewards = (block.number - lastRewardBlock) * rewardPerBlock;
accTokenPerShare += (rewards * tokenPerShareDecimal) / _totalWeight;
lastRewardBlock = block.number;
uint256 accUserReward = (weight(_user) * accTokenPerShare) / tokenPerShareDecimal;
uint256 newUserReward = accUserReward - rewardDebt[_user];
rewardClaimable[_user] += newUserReward;
totalRewardClaimable += newUserReward;
rewardDebt[_user] = accUserReward;
}
function clearRewardToDebt(address _user) public onlyStakingManager {
rewardDebt[_user] = (weight(_user) * accTokenPerShare) / tokenPerShareDecimal;
}
function totalWeight() public view returns (uint256) {
return stakingManager.totalBalance();
}
function weight(address _user) public view returns (uint256) {
return stakingManager.totalBalance(_user);
}
function setStakingManager(address _manager) external onlyAdmin {
if (address(stakingManager) != address(0)) {
setAdmin(address(stakingManager), false);
}
stakingManager = IWooStakingManager(_manager);
setAdmin(_manager, true);
emit SetStakingManagerOnRewarder(_manager);
}
function setRewardPerBlock(uint256 _rewardPerBlock) external onlyAdmin {
updateReward();
rewardPerBlock = _rewardPerBlock;
emit SetRewardPerBlockOnRewarder(_rewardPerBlock);
}
}
文件 10 的 10:TransferHelper.sol
pragma solidity ^0.8.0;
library TransferHelper {
function safeApprove(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::safeApprove: approve failed"
);
}
function safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::safeTransfer: transfer failed"
);
}
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper::transferFrom: transferFrom failed"
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
}
}
{
"compilationTarget": {
"contracts/rewarders/SimpleRewarder.sol": "SimpleRewarder"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_stakingManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"flag","type":"bool"}],"name":"AdminUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimOnRewarder","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":false,"internalType":"uint256","name":"rewardPerBlock","type":"uint256"}],"name":"SetRewardPerBlockOnRewarder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"SetStakingManagerOnRewarder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"accTokenPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPendingReward","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"clearRewardToDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stuckToken","type":"address"}],"name":"inCaseTokenGotStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardBlock","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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardPerBlock","type":"uint256"}],"name":"setRewardPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setStakingManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingManager","outputs":[{"internalType":"contract IWooStakingManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPerShareDecimal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeight","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"updateRewardForUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"weight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]