编译器
0.8.18+commit.87f61d96
文件 1 的 17:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 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;
}
}
文件 3 的 17:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 4 的 17:IAccessControlHolder.sol
pragma solidity 0.8.18;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
interface IAccessControlHolder {
function acl() external view returns (IAccessControl);
}
文件 5 的 17:IContractsRepostiory.sol
pragma solidity 0.8.18;
interface IContractsRepostiory {
error ContractDoesNotExist();
error OnlyRepositoryOnwer();
function getContract(bytes32 contractId) external view returns (address);
function tryGetContract(bytes32 contractId) external view returns (address);
function setContract(bytes32 contractId, address contractAddress) external;
}
文件 6 的 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);
}
文件 7 的 17:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 8 的 17:ISpartaStaking.sol
pragma solidity 0.8.18;
interface ISpartaStaking {
error RewardBalanceTooSmall();
error BeforeStakingStart();
error AfterStakingFinish();
error TokensAlreadyClaimed();
error RoundDoesNotExist();
error BeforeReleaseTime();
error NotValidUnlockTimestamp();
error ToEarlyToWithdrawReward();
error StartNotValid();
error MinimalUnstakingPeriod();
error CannotUnstake();
error CurrentImplementation();
struct TokensToClaim {
bool taken;
uint256 release;
uint256 value;
}
event Staked(address indexed wallet, uint256 value);
event Unstaked(
address indexed wallet,
uint256 tokensAmount,
uint256 tokensToClaim,
uint256 duration
);
event TokensClaimed(
address indexed wallet,
uint256 indexed roundId,
uint256 tokensToClaimid
);
event RewardTaken(address indexed wallet, uint256 amount);
event Initialized(
uint256 start,
uint256 duration,
uint256 reward,
uint256 unlockTokensTimestamp
);
event MovedToNextImplementation(
address indexed by,
uint256 balance,
uint256 reward
);
function finishAt() external view returns (uint256);
function stake(uint256 amount) external;
function stakeAs(address wallet, uint256 amount) external;
function unlockTokens(address to, uint256 amount) external;
function unlockTokensTimestamp() external view returns (uint256);
}
文件 9 的 17:IStakedSparta.sol
pragma solidity 0.8.18;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IStakedSparta is IERC20 {
function mintTo(address to, uint256 amount) external;
function burnFrom(address wallet, uint256 amount) external;
}
文件 10 的 17:IWithFees.sol
pragma solidity 0.8.18;
interface IWithFees {
error OnlyFeesManagerAccess();
error OnlyWithFees();
error ETHTransferFailed();
function treasury() external view returns (address);
function fees() external view returns (uint256);
function transfer() external;
}
文件 11 的 17: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);
}
}
文件 12 的 17:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 13 的 17:SpartaStaking.sol
pragma solidity 0.8.18;
import {IStakedSparta} from "../tokens/interfaces/IStakedSparta.sol";
import {ISpartaStaking} from "./interfaces/ISpartaStaking.sol";
import {ToInitialize} from "../ToInitialize.sol";
import {WithFees} from "../WithFees.sol";
import {ZeroAddressGuard} from "../ZeroAddressGuard.sol";
import {ZeroAmountGuard} from "../ZeroAmountGuard.sol";
import {IAccessControl, IAccessControlHolder} from "../IAccessControlHolder.sol";
import {IContractsRepostiory} from "../IContractsRepostiory.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract SpartaStaking is
ISpartaStaking,
ToInitialize,
Ownable,
WithFees,
ZeroAddressGuard,
ZeroAmountGuard
{
using SafeERC20 for IERC20;
uint256 constant UNLOCK_TIMESTAMP_MINIMUM_DIFF = 30 days;
uint256 constant MINIML_UNSTAKING_PERIOD = 10 days;
bytes32 constant SPARTA_STAKING_CONTRACT_ID = keccak256("SPARTA_STAKING");
IERC20 public immutable sparta;
IStakedSparta public immutable stakedSparta;
IContractsRepostiory public immutable contractsRepository;
uint256 public totalSupply;
uint256 public rewardPerTokenStored;
uint256 public rewardRate;
uint256 public start;
uint256 public updatedAt;
uint256 public duration;
uint256 public override unlockTokensTimestamp;
mapping(address => uint256) public balanceOf;
mapping(address => uint256) public rewards;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public userTokensToClaimCounter;
mapping(address => mapping(uint256 => TokensToClaim))
public userTokensToClaim;
modifier isOngoing() {
if (block.timestamp < start) {
revert BeforeStakingStart();
}
if (finishAt() < block.timestamp) {
revert AfterStakingFinish();
}
_;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
updatedAt = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
modifier canUstake(uint256 amount, uint256 duration_) {
if (amount == 0) {
revert ZeroAmount();
}
if (amount > balanceOf[msg.sender]) {
revert CannotUnstake();
}
if (duration_ < MINIML_UNSTAKING_PERIOD) {
revert MinimalUnstakingPeriod();
}
_;
}
constructor(
IERC20 sparta_,
IStakedSparta stakedSparta_,
IAccessControl acl_,
IContractsRepostiory contractRepository_,
address treasury_,
uint256 fees_
) Ownable() WithFees(acl_, treasury_, fees_) {
sparta = sparta_;
stakedSparta = stakedSparta_;
contractsRepository = contractRepository_;
}
function stake(uint256 _amount) external {
stakeAs(msg.sender, _amount);
}
function initialize(
uint256 amount_,
uint256 start_,
uint256 duration_,
uint256 unlockTokensTimestamp_
)
external
notInitialized
onlyOwner
notZeroAmount(amount_)
notZeroAmount(duration_)
{
if (sparta.balanceOf(address(this)) < amount_) {
revert RewardBalanceTooSmall();
}
if (block.timestamp > start_) {
revert StartNotValid();
}
if (
start_ + duration_ + UNLOCK_TIMESTAMP_MINIMUM_DIFF >
unlockTokensTimestamp_
) {
revert NotValidUnlockTimestamp();
}
duration = duration_;
start = start_;
rewardRate = amount_ / duration_;
updatedAt = block.timestamp;
unlockTokensTimestamp = unlockTokensTimestamp_;
initialized = true;
emit Initialized(start_, duration_, amount_, unlockTokensTimestamp_);
}
function withdrawTokensToClaimFromRounds(
uint256[] calldata rounds
) external {
uint256 roundsLength = rounds.length;
for (uint roundIndex = 0; roundIndex < roundsLength; ) {
withdrawTokensToClaim(rounds[roundIndex]);
unchecked {
++roundIndex;
}
}
}
function unlockTokens(
address to,
uint256 amount
)
external
isInitialized
notZeroAddress(to)
notZeroAmount(amount)
onlyOwner
{
if (block.timestamp < unlockTokensTimestamp) {
revert ToEarlyToWithdrawReward();
}
sparta.safeTransfer(to, amount);
}
function moveToNextSpartaStaking()
external
updateReward(msg.sender)
isInitialized
{
ISpartaStaking current = currentImplementation();
uint256 balance = balanceOf[msg.sender];
if (balance == 0) {
revert ZeroAmount();
}
balanceOf[msg.sender] = 0;
stakedSparta.burnFrom(msg.sender, balance);
totalSupply -= balance;
sparta.forceApprove(address(current), balance);
current.stakeAs(msg.sender, balance);
emit MovedToNextImplementation(msg.sender, balance, 0);
}
function moveToNextSpartaStakingWithReward()
external
isInitialized
updateReward(msg.sender)
{
ISpartaStaking current = currentImplementation();
uint256 balance = balanceOf[msg.sender];
uint256 reward = rewards[msg.sender];
uint256 total = balance + reward;
stakedSparta.burnFrom(msg.sender, balance);
if (total == 0) {
revert ZeroAmount();
}
balanceOf[msg.sender] = 0;
rewards[msg.sender] = 0;
totalSupply -= balance;
sparta.forceApprove(address(current), total);
current.stakeAs(msg.sender, total);
emit MovedToNextImplementation(msg.sender, balance, reward);
}
function toEnd() external view returns (uint256) {
return block.timestamp >= finishAt() ? 0 : finishAt() - block.timestamp;
}
function totalLocked(address wallet) external view returns (uint256) {
return totalPendingToClaim(wallet) + earned(wallet) + balanceOf[wallet];
}
function getUserAllocations(
address _wallet
) external view returns (TokensToClaim[] memory) {
uint256 counter = userTokensToClaimCounter[_wallet];
TokensToClaim[] memory toClaims = new TokensToClaim[](counter);
for (uint256 i = 0; i < counter; ) {
toClaims[i] = userTokensToClaim[_wallet][i];
unchecked {
++i;
}
}
return toClaims;
}
function unstake(
uint256 amount,
uint256 after_
)
public
payable
onlyWithFees
isInitialized
canUstake(amount, after_)
updateReward(msg.sender)
{
uint256 round = userTokensToClaimCounter[msg.sender];
uint256 tokensToWidthdraw = calculateWithFee(amount, after_);
uint256 releaseTime = after_ + block.timestamp;
uint256 spartaFees = amount - tokensToWidthdraw;
userTokensToClaim[msg.sender][round] = TokensToClaim(
false,
releaseTime,
tokensToWidthdraw
);
++userTokensToClaimCounter[msg.sender];
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
if (spartaFees > 0) {
sparta.transfer(treasury, spartaFees);
}
stakedSparta.burnFrom(msg.sender, amount);
emit Unstaked(msg.sender, amount, tokensToWidthdraw, releaseTime);
}
function stakeAs(
address wallet,
uint256 amount
)
public
isInitialized
isOngoing
notZeroAddress(wallet)
updateReward(wallet)
{
sparta.safeTransferFrom(msg.sender, address(this), amount);
balanceOf[wallet] += amount;
totalSupply += amount;
stakedSparta.mintTo(wallet, amount);
emit Staked(wallet, amount);
}
function getReward()
public
payable
isInitialized
onlyWithFees
updateReward(msg.sender)
{
uint256 reward = rewards[msg.sender];
if (reward == 0) {
revert ZeroAmount();
}
sparta.safeTransfer(msg.sender, reward);
rewards[msg.sender] = 0;
emit RewardTaken(msg.sender, reward);
}
function withdrawTokensToClaim(uint256 round) public payable onlyWithFees {
TokensToClaim storage tokensToClaim = userTokensToClaim[msg.sender][
round
];
if (tokensToClaim.release == 0) {
revert RoundDoesNotExist();
}
if (block.timestamp < tokensToClaim.release) {
revert BeforeReleaseTime();
}
if (tokensToClaim.taken) {
revert TokensAlreadyClaimed();
}
sparta.safeTransfer(msg.sender, tokensToClaim.value);
tokensToClaim.taken = true;
emit TokensClaimed(msg.sender, tokensToClaim.value, round);
}
function finishAt() public view override returns (uint256) {
return start + duration;
}
function rewardPerToken() public view returns (uint) {
if (totalSupply == 0 || block.timestamp < start) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored +
(rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) /
totalSupply;
}
function lastTimeRewardApplicable() public view returns (uint) {
return _min(finishAt(), block.timestamp);
}
function earned(address _account) public view returns (uint256) {
return
((balanceOf[_account] *
(rewardPerToken() - userRewardPerTokenPaid[_account])) / 1e18) +
rewards[_account];
}
function totalPendingToClaim(address wallet) public view returns (uint256) {
uint256 toClaim = 0;
uint256 rounds = userTokensToClaimCounter[wallet];
for (uint256 roundIndex = 0; roundIndex < rounds; ) {
TokensToClaim memory tokensToClaim = userTokensToClaim[wallet][
roundIndex
];
if (!tokensToClaim.taken) {
toClaim += tokensToClaim.value;
}
unchecked {
++roundIndex;
}
}
return toClaim;
}
function currentImplementation() public view returns (ISpartaStaking) {
address spartaStakingAddress = contractsRepository.getContract(
SPARTA_STAKING_CONTRACT_ID
);
if (spartaStakingAddress == address(this)) {
revert CurrentImplementation();
}
return SpartaStaking(spartaStakingAddress);
}
function calculateWithFee(
uint256 input,
uint256 _duration
) public pure returns (uint256) {
uint256 saturatedDuration = _duration > 110 days ? 110 days : _duration;
uint256 feesNominator = ((110 days - saturatedDuration) * 500) / 1 days;
uint256 feesOnAmount = (input * feesNominator) / 100000;
return input - feesOnAmount;
}
function _min(uint x, uint y) private pure returns (uint) {
return x <= y ? x : y;
}
}
文件 14 的 17:ToInitialize.sol
pragma solidity 0.8.18;
contract ToInitialize {
error AlreadyInitialized();
error NotInitialized();
bool internal initialized;
modifier isInitialized() {
_isInitialized();
_;
}
function _isInitialized() internal view {
if (!initialized) {
revert NotInitialized();
}
}
modifier notInitialized() {
if (initialized) {
revert AlreadyInitialized();
}
_;
}
}
文件 15 的 17:WithFees.sol
pragma solidity 0.8.18;
import {IAccessControlHolder, IAccessControl} from "./IAccessControlHolder.sol";
import {IWithFees} from "./IWithFees.sol";
contract WithFees is IAccessControlHolder, IWithFees {
address public immutable override treasury;
uint256 public immutable override fees;
IAccessControl public immutable override acl;
bytes32 public constant FEES_MANAGER = keccak256("FEES_MANAGER");
modifier onlyWithFees() {
if (fees != msg.value) {
revert OnlyWithFees();
}
_;
}
modifier onlyFeesManagerAccess() {
if (!acl.hasRole(FEES_MANAGER, msg.sender)) {
revert OnlyFeesManagerAccess();
}
_;
}
constructor(IAccessControl acl_, address treasury_, uint256 value_) {
acl = acl_;
treasury = treasury_;
fees = value_;
}
function transfer() external onlyFeesManagerAccess {
(bool sent, ) = treasury.call{value: address(this).balance}("");
if (!sent) {
revert ETHTransferFailed();
}
}
}
文件 16 的 17:ZeroAddressGuard.sol
pragma solidity 0.8.18;
contract ZeroAddressGuard {
error ZeroAddress();
modifier notZeroAddress(address _addr) {
_ensureIsNotZeroAddress(_addr);
_;
}
function _ensureIsNotZeroAddress(address _addr) internal pure {
if (_addr == address(0)) {
revert ZeroAddress();
}
}
}
文件 17 的 17:ZeroAmountGuard.sol
pragma solidity 0.8.18;
contract ZeroAmountGuard {
error ZeroAmount();
modifier notZeroAmount(uint256 _amount) {
_ensureIsNotZero(_amount);
_;
}
function _ensureIsNotZero(uint256 _amount) internal pure {
if (_amount == 0) {
revert ZeroAmount();
}
}
}
{
"compilationTarget": {
"contracts/staking/SpartaStaking.sol": "SpartaStaking"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"sparta_","type":"address"},{"internalType":"contract IStakedSparta","name":"stakedSparta_","type":"address"},{"internalType":"contract IAccessControl","name":"acl_","type":"address"},{"internalType":"contract IContractsRepostiory","name":"contractRepository_","type":"address"},{"internalType":"address","name":"treasury_","type":"address"},{"internalType":"uint256","name":"fees_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AfterStakingFinish","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BeforeReleaseTime","type":"error"},{"inputs":[],"name":"BeforeStakingStart","type":"error"},{"inputs":[],"name":"CannotUnstake","type":"error"},{"inputs":[],"name":"CurrentImplementation","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"MinimalUnstakingPeriod","type":"error"},{"inputs":[],"name":"NotInitialized","type":"error"},{"inputs":[],"name":"NotValidUnlockTimestamp","type":"error"},{"inputs":[],"name":"OnlyFeesManagerAccess","type":"error"},{"inputs":[],"name":"OnlyWithFees","type":"error"},{"inputs":[],"name":"RewardBalanceTooSmall","type":"error"},{"inputs":[],"name":"RoundDoesNotExist","type":"error"},{"inputs":[],"name":"StartNotValid","type":"error"},{"inputs":[],"name":"ToEarlyToWithdrawReward","type":"error"},{"inputs":[],"name":"TokensAlreadyClaimed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTokensTimestamp","type":"uint256"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"MovedToNextImplementation","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":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensToClaimid","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensToClaim","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"FEES_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acl","outputs":[{"internalType":"contract IAccessControl","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"calculateWithFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractsRepository","outputs":[{"internalType":"contract IContractsRepostiory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentImplementation","outputs":[{"internalType":"contract ISpartaStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","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":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"getUserAllocations","outputs":[{"components":[{"internalType":"bool","name":"taken","type":"bool"},{"internalType":"uint256","name":"release","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct ISpartaStaking.TokensToClaim[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"},{"internalType":"uint256","name":"unlockTokensTimestamp_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"moveToNextSpartaStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"moveToNextSpartaStakingWithReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"sparta","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stakeAs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedSparta","outputs":[{"internalType":"contract IStakedSparta","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"start","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"totalLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"totalPendingToClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unlockTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockTokensTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"after_","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"updatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userTokensToClaim","outputs":[{"internalType":"bool","name":"taken","type":"bool"},{"internalType":"uint256","name":"release","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userTokensToClaimCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"}],"name":"withdrawTokensToClaim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"rounds","type":"uint256[]"}],"name":"withdrawTokensToClaimFromRounds","outputs":[],"stateMutability":"nonpayable","type":"function"}]