编译器
0.8.20+commit.a1b79de6
文件 1 的 6:CasStakingPool.sol
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "./interfaces/ITreasury.sol";
contract CasStakingPool is Ownable, Pausable {
ITreasury public treasury;
mapping(address reward => bool) private _activeRewards;
mapping(address user => mapping(address token => uint256))
private _userRewards;
address[] private _rewardTokens;
error CasStakingPool_RewardNotExists(address reward);
error CasStakingPool_RewardAlreadyExists(address reward);
error CasStakingPool_InvalidArrayLength(
uint256 userLength,
uint256 rewardLength
);
event Claim(address indexed token, address indexed user, uint256 amount);
event AddReward(address indexed token);
event RemoveReward(address indexed token);
event RewardUpdate(
address indexed token,
address indexed user,
uint256 amount
);
event RewardDistribution();
modifier isActiveReward(address rewardToken) {
if (!_activeRewards[rewardToken]) {
revert CasStakingPool_RewardNotExists(rewardToken);
}
_;
}
constructor(address _owner, ITreasury _treasury) Ownable(_owner) {
treasury = _treasury;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function changeTreasury(ITreasury _treasury) external onlyOwner {
treasury = _treasury;
}
function addReward(address rewardToken) external onlyOwner {
if (_activeRewards[rewardToken]) {
revert CasStakingPool_RewardAlreadyExists(rewardToken);
}
_activeRewards[rewardToken] = true;
_rewardTokens.push(rewardToken);
emit AddReward(rewardToken);
}
function removeReward(
address rewardToken
) external onlyOwner isActiveReward(rewardToken) {
_activeRewards[rewardToken] = false;
uint256 length = _rewardTokens.length;
for (uint256 i; i < length; ) {
address reward = _rewardTokens[i];
if (reward == rewardToken) {
_rewardTokens[i] = _rewardTokens[length - 1];
_rewardTokens.pop();
break;
}
unchecked {
++i;
}
}
emit RemoveReward(rewardToken);
}
function updateUsersRewardsBatch(
address[] calldata rewardTokens,
address[] calldata users,
uint256[][] memory rewardAmounts
) external onlyOwner {
uint256 userLength = users.length;
uint256 rewardAmountsLength = rewardAmounts.length;
if (userLength != rewardAmountsLength) {
revert CasStakingPool_InvalidArrayLength(
userLength,
rewardAmountsLength
);
}
uint256 rewardsLength = rewardTokens.length;
for (uint256 i; i < userLength; ) {
uint256[] memory amounts = rewardAmounts[i];
if (rewardsLength != amounts.length) {
revert CasStakingPool_InvalidArrayLength(
rewardsLength,
amounts.length
);
}
for (uint256 j; j < rewardsLength; ) {
_updateUserReward(
users[i],
rewardTokens[j],
rewardAmounts[i][j]
);
unchecked {
++j;
}
}
unchecked {
++i;
}
}
emit RewardDistribution();
}
function updateUsersRewards(
address rewardToken,
address[] calldata users,
uint256[] calldata rewardAmounts
) external onlyOwner {
uint256 userLength = users.length;
uint256 rewardLength = rewardAmounts.length;
if (userLength != rewardLength) {
revert CasStakingPool_InvalidArrayLength(userLength, rewardLength);
}
for (uint256 i; i < userLength; ) {
_updateUserReward(users[i], rewardToken, rewardAmounts[i]);
unchecked {
++i;
}
}
emit RewardDistribution();
}
function _updateUserReward(
address user,
address rewardToken,
uint256 amount
) internal {
_userRewards[user][rewardToken] += amount;
emit RewardUpdate(rewardToken, user, amount);
}
function claimRewards() external whenNotPaused {
uint256 length = _rewardTokens.length;
for (uint256 i; i < length; ) {
address rewardToken = _rewardTokens[i];
uint256 reward = _userRewards[msg.sender][rewardToken];
_userRewards[msg.sender][rewardToken] = 0;
treasury.sendToken(rewardToken, msg.sender, reward);
emit Claim(rewardToken, msg.sender, reward);
unchecked {
++i;
}
}
}
function getRewardTokens() external view returns (address[] memory) {
return _rewardTokens;
}
function getUserRewardAmount(
address user,
address reward
) external view returns (uint256) {
return _userRewards[user][reward];
}
}
文件 2 的 6:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 3 的 6:IERC20.sol
pragma solidity ^0.8.20;
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 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 4 的 6:ITreasury.sol
pragma solidity ^0.8.20;
interface ITreasury {
function sendToken(address token, address to, uint256 amount) external;
function sendNative(uint256 amount, address to) external;
function whiteslists(address) external view returns (bool);
function withdraw(address token, uint256 amount) external;
function withdrawNative(uint256 amount) external;
receive() external payable;
fallback() external;
}
文件 5 的 6:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 6 的 6:Pausable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Pausable is Context {
bool private _paused;
event Paused(address account);
event Unpaused(address account);
error EnforcedPause();
error ExpectedPause();
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
{
"compilationTarget": {
"contracts/CasStakingPool.sol": "CasStakingPool"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract ITreasury","name":"_treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"userLength","type":"uint256"},{"internalType":"uint256","name":"rewardLength","type":"uint256"}],"name":"CasStakingPool_InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"reward","type":"address"}],"name":"CasStakingPool_RewardAlreadyExists","type":"error"},{"inputs":[{"internalType":"address","name":"reward","type":"address"}],"name":"CasStakingPool_RewardNotExists","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"AddReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","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":"token","type":"address"}],"name":"RemoveReward","type":"event"},{"anonymous":false,"inputs":[],"name":"RewardDistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"rewardToken","type":"address"}],"name":"addReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITreasury","name":"_treasury","type":"address"}],"name":"changeTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"reward","type":"address"}],"name":"getUserRewardAmount","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":"rewardToken","type":"address"}],"name":"removeReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"contract ITreasury","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"rewardAmounts","type":"uint256[]"}],"name":"updateUsersRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[][]","name":"rewardAmounts","type":"uint256[][]"}],"name":"updateUsersRewardsBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]