编译器
0.8.20+commit.a1b79de6
文件 1 的 17:AnimaStaker.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../Manager/ManagerModifier.sol";
import "./IAnimaStaker.sol";
import "./IAnimaChamberData.sol";
import "./IAnimaChamber.sol";
import "./IAnimaStakingRewards.sol";
import "../Anima/IAnima.sol";
import "./IAnimaStakerStorage.sol";
import "../Utils/ArrayUtils.sol";
error NotOwner(address _owner, address _sender, uint256 _tokenId);
contract AnimaStaker is
ManagerModifier,
IAnimaStaker,
Pausable,
ReentrancyGuard
{
IAnima public ANIMA;
IAnimaChamber public ANIMA_CHAMBER;
IAnimaChamberData public ANIMA_CHAMBER_DATA;
IAnimaStakerStorage public ANIMA_STAKER_STORAGE;
IAnimaStakingRewards public ANIMA_STAKING_REWARDS;
constructor(
address _manager,
address _anima,
address _animaChamber,
address _animaChamberData,
address _animaStakerStorage,
address _animaStakingRewards
) ManagerModifier(_manager) {
ANIMA = IAnima(_anima);
ANIMA_CHAMBER = IAnimaChamber(_animaChamber);
ANIMA_CHAMBER_DATA = IAnimaChamberData(_animaChamberData);
ANIMA_STAKING_REWARDS = IAnimaStakingRewards(_animaStakingRewards);
ANIMA_STAKER_STORAGE = IAnimaStakerStorage(_animaStakerStorage);
}
function stake(uint256 _amount) external whenNotPaused nonReentrant {
_stake(_amount);
}
function expand(
uint256 _amount,
uint _chamberId
) external whenNotPaused nonReentrant {
_add(_amount, _chamberId);
}
function expandBatch(
uint256[] calldata _amounts,
uint256[] calldata _chamberIds
) external whenNotPaused nonReentrant {
ArrayUtils.ensureSameLength(_amounts.length, _chamberIds.length);
ArrayUtils.checkForDuplicates(_chamberIds);
for (uint256 i = 0; i < _amounts.length; i++) {
_add(_amounts[i], _chamberIds[i]);
}
}
function stakeBatch(
uint256[] calldata _amounts
) external whenNotPaused nonReentrant {
for (uint256 i = 0; i < _amounts.length; i++) {
_stake(_amounts[i]);
}
}
function unstake(uint256 _tokenId) external whenNotPaused nonReentrant {
_unstake(_tokenId);
}
function unstakeBatch(
uint256[] calldata _tokenId
) external whenNotPaused nonReentrant {
for (uint256 i = 0; i < _tokenId.length; i++) {
_unstake(_tokenId[i]);
}
}
function _stake(uint256 _amount) internal {
ANIMA.transferFrom(msg.sender, address(ANIMA_STAKER_STORAGE), _amount);
uint256 chamberId = ANIMA_CHAMBER.mintFor(msg.sender);
ANIMA_CHAMBER_DATA.setStakedAnima(chamberId, _amount);
ANIMA_STAKER_STORAGE.changeDelta(int(_amount));
}
function _add(uint256 _amount, uint256 _chamberId) internal {
address animaChamberOwner = ANIMA_CHAMBER.ownerOf(_chamberId);
if (animaChamberOwner != msg.sender) {
revert NotOwner(animaChamberOwner, msg.sender, _chamberId);
}
ANIMA.transferFrom(msg.sender, address(ANIMA_STAKER_STORAGE), _amount);
(bool isStaked, uint realmId) = ANIMA_STAKING_REWARDS
.unregisterChamberStaked(_chamberId);
uint256 current = ANIMA_CHAMBER_DATA.getAndResetStakedAnima(_chamberId);
ANIMA_CHAMBER_DATA.setStakedAnima(_chamberId, current + _amount);
if (isStaked) {
ANIMA_STAKING_REWARDS.registerChamberStaked(_chamberId, realmId);
}
ANIMA_STAKER_STORAGE.changeDelta(int(_amount));
}
function _unstake(uint256 _chamberId) internal {
address animaChamberOwner = ANIMA_CHAMBER.ownerOf(_chamberId);
if (animaChamberOwner != msg.sender) {
revert NotOwner(animaChamberOwner, msg.sender, _chamberId);
}
ANIMA_STAKING_REWARDS.collectManager(_chamberId, true, true);
ANIMA_CHAMBER.burn(_chamberId);
uint amountStaked = ANIMA_CHAMBER_DATA.getAndResetStakedAnima(_chamberId);
ANIMA_STAKER_STORAGE.unstakeAndChangeDelta(animaChamberOwner, amountStaked);
}
function updateRewards(address _rewards) external onlyAdmin {
ANIMA_STAKING_REWARDS = IAnimaStakingRewards(_rewards);
}
function pause() external onlyAdmin {
_pause();
}
function unpause() external onlyAdmin {
_unpause();
}
}
文件 2 的 17:ArrayUtils.sol
pragma solidity ^0.8.17;
library ArrayUtils {
error ArrayLengthMismatch(uint _length1, uint _length2);
error InvalidArrayOrder(uint index);
function ensureSameLength(uint _l1, uint _l2) internal pure {
if (_l1 != _l2) {
revert ArrayLengthMismatch(_l1, _l2);
}
}
function ensureSameLength(uint _l1, uint _l2, uint _l3) internal pure {
ensureSameLength(_l1, _l2);
ensureSameLength(_l1, _l3);
}
function ensureSameLength(
uint _l1,
uint _l2,
uint _l3,
uint _l4
) internal pure {
ensureSameLength(_l1, _l2);
ensureSameLength(_l1, _l3);
ensureSameLength(_l1, _l4);
}
function ensureSameLength(
uint _l1,
uint _l2,
uint _l3,
uint _l4,
uint _l5
) internal pure {
ensureSameLength(_l1, _l2);
ensureSameLength(_l1, _l3);
ensureSameLength(_l1, _l4);
ensureSameLength(_l1, _l5);
}
function checkForDuplicates(uint[] memory _ids) internal pure {
int lastId = -1;
for (uint i = 0; i < _ids.length; i++) {
if (int(_ids[i]) <= lastId) {
revert InvalidArrayOrder(i);
}
lastId = int(_ids[i]);
}
}
function checkForDuplicates(
address[] memory _tokenAddrs,
uint[] memory _tokenIds
) internal pure {
address lastAddress;
int256 lastTokenId = -1;
for (uint i = 0; i < _tokenAddrs.length; i++) {
if (_tokenAddrs[i] > lastAddress) {
lastTokenId = -1;
}
if (_tokenAddrs[i] < lastAddress || int(_tokenIds[i]) <= lastTokenId) {
revert InvalidArrayOrder(i);
}
lastAddress = _tokenAddrs[i];
lastTokenId = int(_tokenIds[i]);
}
}
function toSingleValueDoubleArray(
uint[] memory _vals
) internal pure returns (uint[][] memory result) {
result = new uint[][](_vals.length);
for (uint i = 0; i < _vals.length; i++) {
result[i] = ArrayUtils.toMemoryArray(_vals[i], 1);
}
}
function toMemoryArray(
uint _value,
uint _length
) internal pure returns (uint[] memory result) {
result = new uint[](_length);
for (uint i = 0; i < _length; i++) {
result[i] = _value;
}
}
function toMemoryArray(
uint[] calldata _value
) internal pure returns (uint[] memory result) {
result = new uint[](_value.length);
for (uint i = 0; i < _value.length; i++) {
result[i] = _value[i];
}
}
function toMemoryArray(
address _address,
uint _length
) internal pure returns (address[] memory result) {
result = new address[](_length);
for (uint i = 0; i < _length; i++) {
result[i] = _address;
}
}
function toMemoryArray(
address[] calldata _addresses
) internal pure returns (address[] memory result) {
result = new address[](_addresses.length);
for (uint i = 0; i < _addresses.length; i++) {
result[i] = _addresses[i];
}
}
}
文件 3 的 17: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;
}
}
文件 4 的 17:IAnima.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IAnima is IERC20, IERC20Metadata {
function CAP() external view returns (uint256);
function mintFor(address _for, uint256 _amount) external;
function burnFrom(address account, uint256 amount) external;
}
文件 5 的 17:IAnimaChamber.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IAnimaChamber is IERC721 {
function burn(uint256 _tokenId) external;
function mintFor(address _for) external returns (uint256);
function tokensOfOwner(
address _owner
) external view returns (uint256[] memory);
}
文件 6 的 17:IAnimaChamberData.sol
pragma solidity ^0.8.17;
interface IAnimaChamberData {
function stakedAnima(uint256 _tokenId) external view returns (uint256);
function mintedAt(uint256 _tokenId) external view returns (uint256);
function stakedAnimaBatch(
uint256[] calldata _tokenId
) external view returns (uint256[] memory result);
function setStakedAnima(uint256 _tokenId, uint256 _amount) external;
function getAndResetStakedAnima(
uint _tokenId
) external returns (uint256 result);
}
文件 7 的 17:IAnimaStaker.sol
pragma solidity ^0.8.17;
interface IAnimaStaker {
function stake(uint256 _amount) external;
function stakeBatch(uint256[] calldata _amounts) external;
function unstake(uint256 _tokenId) external;
function unstakeBatch(uint256[] calldata _tokenId) external;
}
文件 8 的 17:IAnimaStakerStorage.sol
pragma solidity ^0.8.17;
interface IAnimaStakerStorage {
function unstakeAndChangeDelta(address _for, uint256 _amount) external;
function getTotal() external view returns (uint);
function getEpochChanges(uint _epoch) external view returns (int);
function getEpochChangesBatch(
uint startEpoch,
uint endEpoch
) external view returns (int[] memory result);
function changeDelta(int _delta) external;
}
文件 9 的 17:IAnimaStakingRewards.sol
pragma solidity ^0.8.17;
interface IAnimaStakingRewards {
function stakerCollect(
uint256 _tokenId,
bool _compound,
uint[] calldata _params
) external;
function stakerCollectBatch(
uint256[] calldata _tokenId,
bool[] calldata _compound,
uint[][] calldata _params
) external;
function realmerCollect(uint256 _realmId) external;
function realmerCollectBatch(uint256[] calldata _realmIds) external;
function collectManager(
uint256 _tokenId,
bool _forStaker,
bool _forRealmer
) external;
function registerChamberStaked(uint256 _chamberId, uint256 _realmId) external;
function unregisterChamberStaked(
uint256 _chamberId
) external returns (bool wasStaked, uint realmId);
function unregisterChamberStaked(
uint256 _chamberId,
uint256 _realmId
) external returns (bool success);
}
文件 10 的 17:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 11 的 17: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);
}
文件 12 的 17:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 13 的 17:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 14 的 17:IManager.sol
pragma solidity ^0.8.4;
interface IManager {
function isAdmin(address _addr) external view returns (bool);
function isManager(address _addr, uint256 _type) external view returns (bool);
function addManager(address _addr, uint256 _type) external;
function removeManager(address _addr, uint256 _type) external;
function addAdmin(address _addr) external;
function removeAdmin(address _addr) external;
}
文件 15 的 17:ManagerModifier.sol
pragma solidity ^0.8.4;
import "../Manager/IManager.sol";
abstract contract ManagerModifier {
IManager public immutable MANAGER;
constructor(address _manager) {
MANAGER = IManager(_manager);
}
modifier onlyAdmin() {
require(MANAGER.isAdmin(msg.sender), "Manager: Not an Admin");
_;
}
modifier onlyManager() {
require(MANAGER.isManager(msg.sender, 0), "Manager: Not manager");
_;
}
modifier onlyMinter() {
require(MANAGER.isManager(msg.sender, 1), "Manager: Not minter");
_;
}
modifier onlyTokenMinter() {
require(MANAGER.isManager(msg.sender, 2), "Manager: Not token minter");
_;
}
modifier onlyBinder() {
require(MANAGER.isManager(msg.sender, 3), "Manager: Not binder");
_;
}
modifier onlyConfigManager() {
require(MANAGER.isManager(msg.sender, 4), "Manager: Not config manager");
_;
}
modifier onlyTokenSpender() {
require(MANAGER.isManager(msg.sender, 5), "Manager: Not token spender");
_;
}
modifier onlyTokenEmitter() {
require(MANAGER.isManager(msg.sender, 6), "Manager: Not token emitter");
_;
}
modifier onlyPauser() {
require(
MANAGER.isAdmin(msg.sender) || MANAGER.isManager(msg.sender, 6),
"Manager: Not pauser"
);
_;
}
}
文件 16 的 17: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());
}
}
文件 17 的 17: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;
}
}
{
"compilationTarget": {
"contracts/AnimaStaking/AnimaStaker.sol": "AnimaStaker"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_anima","type":"address"},{"internalType":"address","name":"_animaChamber","type":"address"},{"internalType":"address","name":"_animaChamberData","type":"address"},{"internalType":"address","name":"_animaStakerStorage","type":"address"},{"internalType":"address","name":"_animaStakingRewards","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_length1","type":"uint256"},{"internalType":"uint256","name":"_length2","type":"uint256"}],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidArrayOrder","type":"error"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"NotOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ANIMA","outputs":[{"internalType":"contract IAnima","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANIMA_CHAMBER","outputs":[{"internalType":"contract IAnimaChamber","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANIMA_CHAMBER_DATA","outputs":[{"internalType":"contract IAnimaChamberData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANIMA_STAKER_STORAGE","outputs":[{"internalType":"contract IAnimaStakerStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANIMA_STAKING_REWARDS","outputs":[{"internalType":"contract IAnimaStakingRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER","outputs":[{"internalType":"contract IManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_chamberId","type":"uint256"}],"name":"expand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_chamberIds","type":"uint256[]"}],"name":"expandBatch","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenId","type":"uint256[]"}],"name":"unstakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"updateRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]