编译器
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.5.0;
interface IERC20 {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
文件 3 的 5:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 4 的 5: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);
}
}
文件 5 的 5:TowerPool.sol
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./interfaces/IERC20.sol";
interface ITowerPoolFactory {
function emitDeposit(address account, uint256 amount) external;
function emitWithdraw(address account, uint256 amount) external;
}
contract TowerPool {
address public stake;
address public factory;
uint256 internal constant DURATION = 7 days;
uint256 internal constant PRECISION = 10 ** 18;
mapping(address => uint256) public pendingRewardRate;
mapping(address => bool) public isStarted;
mapping(address => uint256) public rewardRate;
mapping(address => uint256) public periodFinish;
mapping(address => uint256) public lastUpdateTime;
mapping(address => uint256) public rewardPerTokenStored;
mapping(address => mapping(address => uint256)) public storedRewardsPerUser;
mapping(address => mapping(address => uint256))
public userRewardPerTokenStored;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
address[] public rewards;
mapping(address => bool) public isReward;
uint256 internal _unlocked;
event Deposit(address indexed from, uint256 amount);
event Withdraw(address indexed from, uint256 amount);
event NotifyReward(
address indexed from,
address indexed reward,
uint256 amount
);
event ClaimRewards(
address indexed from,
address indexed reward,
uint256 amount
);
struct RewardInfo {
address towerPool;
address rewardTokenAddress;
string rewardTokenSymbol;
uint256 rewardTokenDecimals;
uint256 periodFinish;
uint256 rewardRate;
uint256 lastUpdateTime;
uint256 rewardPerTokenStored;
uint256 pendingReward;
uint256 reinvestBounty;
bool isStarted;
}
function _initialize(
address _stake,
address[] memory _allowedRewardTokens
) external {
require(factory == address(0), "TowerPool: FACTORY_ALREADY_SET");
factory = msg.sender;
stake = _stake;
for (uint256 i; i < _allowedRewardTokens.length; ++i) {
if (_allowedRewardTokens[i] != address(0)) {
rewards.push(_allowedRewardTokens[i]);
isReward[_allowedRewardTokens[i]] = true;
}
}
_unlocked = 1;
}
modifier lock() {
require(_unlocked == 1);
_unlocked = 2;
_;
_unlocked = 1;
}
function rewardsListLength() external view returns (uint256) {
return rewards.length;
}
function lastTimeRewardApplicable(
address token
) public view returns (uint256) {
return Math.min(block.timestamp, periodFinish[token]);
}
function earned(address account) external view returns (uint256[] memory earnedList) {
uint256 len = rewards.length;
earnedList = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
earnedList[i] = earned(rewards[i], account);
}
}
function earned(
address token,
address account
) public view returns (uint256) {
return
(balanceOf[account] *
(rewardPerToken(token) -
userRewardPerTokenStored[account][token])) /
PRECISION +
storedRewardsPerUser[account][token];
}
function getReward(address account, address[] memory tokens) public lock {
require(msg.sender == account || msg.sender == factory);
address[] memory _rewards = rewards;
uint256 len = _rewards.length;
for (uint256 i; i < len; ++i) {
if (isReward[_rewards[i]]) {
if (!isStarted[_rewards[i]]) {
initializeRewardsDistribution(_rewards[i]);
}
updateRewardPerToken(_rewards[i], account);
}
}
len = tokens.length;
for (uint256 i; i < len; ++i){
uint256 _reward = storedRewardsPerUser[account][tokens[i]];
if (_reward > 0) {
storedRewardsPerUser[account][tokens[i]] = 0;
_safeTransfer(tokens[i], account, _reward);
emit ClaimRewards(account, tokens[i], _reward);
}
}
}
function rewardPerToken(address token) public view returns (uint256) {
if (totalSupply == 0) {
return rewardPerTokenStored[token];
}
return
rewardPerTokenStored[token] +
(((lastTimeRewardApplicable(token) -
Math.min(lastUpdateTime[token], periodFinish[token])) *
rewardRate[token] *
PRECISION) / totalSupply);
}
function depositAll() external {
deposit(IERC20(stake).balanceOf(msg.sender));
}
function deposit(uint256 amount) public lock {
require(amount > 0);
address[] memory _rewards = rewards;
uint256 len = _rewards.length;
for (uint256 i; i < len; ++i) {
if (!isStarted[_rewards[i]]) {
initializeRewardsDistribution(_rewards[i]);
}
updateRewardPerToken(_rewards[i], msg.sender);
}
_safeTransferFrom(stake, msg.sender, address(this), amount);
totalSupply += amount;
balanceOf[msg.sender] += amount;
ITowerPoolFactory(factory).emitDeposit(msg.sender, amount);
emit Deposit(msg.sender, amount);
}
function withdrawAll() external {
withdraw(balanceOf[msg.sender]);
}
function withdraw(uint256 amount) public lock {
require(amount > 0);
address[] memory _rewards = rewards;
uint256 len = _rewards.length;
for (uint256 i; i < len; ++i) {
updateRewardPerToken(_rewards[i], msg.sender);
}
totalSupply -= amount;
balanceOf[msg.sender] -= amount;
_safeTransfer(stake, msg.sender, amount);
ITowerPoolFactory(factory).emitWithdraw(msg.sender, amount);
emit Withdraw(msg.sender, amount);
}
function left(address token) external view returns (uint256) {
if (block.timestamp >= periodFinish[token]) return 0;
uint256 _remaining = periodFinish[token] - block.timestamp;
return _remaining * rewardRate[token];
}
function notifyRewardAmount(address token, uint256 amount) external lock {
require(token != stake);
require(amount > 0);
rewardPerTokenStored[token] = rewardPerToken(token);
uint balanceBefore = IERC20(token).balanceOf(address(this));
_safeTransferFrom(token, msg.sender, address(this), amount);
uint balanceAfter = IERC20(token).balanceOf(address(this));
amount = balanceAfter - balanceBefore;
uint _rewardRate = amount / DURATION;
if (isStarted[token]) {
if (block.timestamp >= periodFinish[token]) {
rewardRate[token] = _rewardRate;
} else {
uint256 _remaining = periodFinish[token] - block.timestamp;
uint256 _left = _remaining * rewardRate[token];
require(amount > _left);
rewardRate[token] = (amount + _left) / DURATION;
}
periodFinish[token] = block.timestamp + DURATION;
lastUpdateTime[token] = block.timestamp;
} else {
if (pendingRewardRate[token] > 0) {
uint256 _left = DURATION * pendingRewardRate[token];
pendingRewardRate[token] = (amount + _left) / DURATION;
} else {
pendingRewardRate[token] = _rewardRate;
}
}
uint256 balance = IERC20(token).balanceOf(address(this));
require(
rewardRate[token] <= balance / DURATION,
"Provided reward too high"
);
if (!isStarted[token]) {
require(
pendingRewardRate[token] <= balance / DURATION,
"Provided reward too high"
);
}
emit NotifyReward(msg.sender, token, amount);
}
function initializeRewardsDistribution(address token) internal {
isStarted[token] = true;
rewardRate[token] = pendingRewardRate[token];
lastUpdateTime[token] = block.timestamp;
periodFinish[token] = block.timestamp + DURATION;
pendingRewardRate[token] = 0;
}
function whitelistNotifiedRewards(address token) external {
require(msg.sender == factory);
if (!isReward[token]) {
isReward[token] = true;
rewards.push(token);
}
if (!isStarted[token] && totalSupply > 0) {
initializeRewardsDistribution(token);
}
}
function getRewardTokenIndex(address token) public view returns (uint256) {
address[] memory _rewards = rewards;
uint256 len = _rewards.length;
for (uint256 i; i < len; ++i) {
if (_rewards[i] == token) {
return i;
}
}
return 0;
}
function removeRewardWhitelist(address token) external {
require(msg.sender == factory);
if (!isReward[token]) {
return;
}
isReward[token] = false;
uint256 idx = getRewardTokenIndex(token);
uint256 len = rewards.length;
for (uint256 i = idx; i < len - 1; ++i) {
rewards[i] = rewards[i + 1];
}
rewards.pop();
}
function poke(address account) external {
for (uint256 i; i < rewards.length; ++i) {
updateRewardPerToken(rewards[i], account);
}
}
function updateRewardPerToken(address token, address account) internal {
rewardPerTokenStored[token] = rewardPerToken(token);
lastUpdateTime[token] = lastTimeRewardApplicable(token);
storedRewardsPerUser[account][token] = earned(token, account);
userRewardPerTokenStored[account][token] = rewardPerTokenStored[token];
}
function _safeTransfer(address token, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function _safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
IERC20.transferFrom.selector,
from,
to,
value
)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function _safeApprove(
address token,
address spender,
uint256 value
) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.approve.selector, spender, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function removeExtraRewardToken(
uint256 index,
uint256 duplicateIndex
) external onlyFactoryOwner {
require(index < duplicateIndex);
require(rewards[index] == rewards[duplicateIndex]);
uint len = rewards.length;
for (uint i = duplicateIndex; i < len - 1; ++i) {
rewards[i] = rewards[i + 1];
}
rewards.pop();
}
function getRewardInfoList() external view returns (RewardInfo[] memory rewardInfoList) {
uint256 len = rewards.length;
rewardInfoList = new RewardInfo[](len);
for (uint256 i = 0; i < len; i++) {
address rewardToken = rewards[i];
RewardInfo memory rewardInfo = rewardInfoList[i];
rewardInfo.towerPool = address(this);
rewardInfo.rewardTokenAddress = rewardToken;
rewardInfo.rewardTokenSymbol = IERC20(rewardToken).symbol();
rewardInfo.rewardTokenDecimals = IERC20(rewardToken).decimals();
rewardInfo.isStarted = isStarted[rewardToken];
rewardInfo.rewardRate = rewardRate[rewardToken];
rewardInfo.lastUpdateTime = lastUpdateTime[rewardToken];
rewardInfo.periodFinish = periodFinish[rewardToken];
rewardInfo.rewardPerTokenStored = rewardPerTokenStored[rewardToken];
}
}
modifier onlyFactoryOwner() {
require(Ownable(factory).owner() == msg.sender, "NOT_AUTHORIZED");
_;
}
}
{
"compilationTarget": {
"contracts/TowerPool.sol": "TowerPool"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_stake","type":"address"},{"internalType":"address[]","name":"_allowedRewardTokens","type":"address[]"}],"name":"_initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"earnedList","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardInfoList","outputs":[{"components":[{"internalType":"address","name":"towerPool","type":"address"},{"internalType":"address","name":"rewardTokenAddress","type":"address"},{"internalType":"string","name":"rewardTokenSymbol","type":"string"},{"internalType":"uint256","name":"rewardTokenDecimals","type":"uint256"},{"internalType":"uint256","name":"periodFinish","type":"uint256"},{"internalType":"uint256","name":"rewardRate","type":"uint256"},{"internalType":"uint256","name":"lastUpdateTime","type":"uint256"},{"internalType":"uint256","name":"rewardPerTokenStored","type":"uint256"},{"internalType":"uint256","name":"pendingReward","type":"uint256"},{"internalType":"uint256","name":"reinvestBounty","type":"uint256"},{"internalType":"bool","name":"isStarted","type":"bool"}],"internalType":"struct TowerPool.RewardInfo[]","name":"rewardInfoList","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getRewardTokenIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"left","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"duplicateIndex","type":"uint256"}],"name":"removeExtraRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeRewardWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stake","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"storedRewardsPerUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"whitelistNotifiedRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]