编译器
0.8.25+commit.b61c2a91
文件 1 的 15:Address.sol
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
library Address {
error AddressEmptyCode(address target);
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}
文件 2 的 15: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 的 15:EnumerableSet.sol
pragma solidity ^0.8.20;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 value => uint256) _positions;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 position = set._positions[value];
if (position != 0) {
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[valueIndex] = lastValue;
set._positions[lastValue] = position;
}
set._values.pop();
delete set._positions[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 4 的 15:Errors.sol
pragma solidity ^0.8.20;
library Errors {
error InsufficientBalance(uint256 balance, uint256 needed);
error FailedCall();
error FailedDeployment();
}
文件 5 的 15:IERC1155.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155 is IERC165 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}
文件 6 的 15:IERC1155Receiver.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 7 的 15:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 8 的 15: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);
}
文件 9 的 15:ILockNFT.sol
pragma solidity >=0.8.0 <0.9.0;
interface ILockNFT {
function lockBatchNFTInAnyPeriod(uint256[] calldata _tokenIds) external;
function lockSingleNFTInAnyPeriod(uint256 _tokenId) external;
event NFTLocked(
address staker,
uint256 nftIndex,
uint256 amountUSA,
uint256 activerPeriodIndex
);
event BatchNftLocked(
address stakerAddress,
uint256[] tokenIds,
uint256 totalUSAStaked,
uint256 activePeriodIndex
);
event SetUsaLockAmount(uint256 _amount);
event BatchOfNftsUnstaked(uint256[] _tokenIds);
event NftUnstaked(uint256 tokenId);
}
文件 10 的 15:ILockPeriodContract.sol
pragma solidity >=0.8.0 <0.9.0;
interface ILockPeriodContract {
struct PeriodInfo {
uint8 isFinalized;
uint88 totalLockedInPeriod;
uint88 totalRewardedInPeriod_USA_1;
uint32 timestampPeriodStart;
uint88 totalRewardedInPeriod_WETH_2;
uint88 totalRewardedInPeriod_Stable_3;
uint32 timestampPeriodEnd;
}
struct StakeInfo {
uint8 lastUpdatePeriodIndex;
uint88 amountStaked;
uint88 rewardDebt_USA_1;
uint88 rewardPaid_USA_1;
uint88 rewardDebt_WETH_2;
uint88 rewardPaid_WETH_2;
uint88 rewardDebt_Stable_3;
uint88 rewardPaid_Stable_3;
}
enum ContractState {
NONE,
ACTIVE_LOCKED,
UNLOCKED_REDEEMABLE,
FRESH_PERIOD,
CONTRACT_UNLOCKED_INACTIVE
}
function returnPeriodIndexCounter() external view returns (uint256);
function isActivePeriodFinalized() external view returns (bool);
function isPreviousPeriodFinalized() external view returns (bool);
function returnContractStateInContract()
external
view
returns (ContractState);
function returnActivePeriodInContract() external view returns (uint256);
function returnLockPeriod() external view returns (uint256);
function returnStandardWindowDuration() external view returns (uint256);
function returnNextPeriod() external view returns (uint256);
function returnPeriodRewardPerStakedToken(
uint256 _periodIndex
) external view returns (uint256, uint256, uint256);
function totalTokensLocked() external view returns (uint256);
function returnTotalRewardsDistributed()
external
view
returns (
uint256 totalRewardsDistributed_USA_1,
uint256 totalRewardsDistributed_WETH_2,
uint256 totalRewardsDistributed_Stable_3
);
function rewardPerToken_USA_1(
uint256 _periodIndex
) external view returns (uint256);
function rewardPerToken_WETH_2(
uint256 _periodIndex
) external view returns (uint256);
function rewardPerToken_Stable_3(
uint256 _periodIndex
) external view returns (uint256);
function returnUserStakeInfo(
address _user
)
external
view
returns (
uint8 lastUpdatePeriodIndex,
uint88 amountStaked,
uint88 rewardDebt_USA_1,
uint88 rewardPaid_USA_1,
uint88 rewardDebt_WETH_2,
uint88 rewardPaid_WETH_2,
uint88 rewardDebt_Stable_3,
uint88 rewardPaid_Stable_3
);
function returnRewardClaimableUser(
address _user
) external view returns (uint256, uint256, uint256);
function returnPeriodInfo(
uint256 _periodIndex
)
external
view
returns (
uint8 isFinalized,
uint88 totalLockedInPeriod,
uint88 totalRewardedInPeriod_USA_1,
uint32 timestampPeriodStart,
uint88 totalRewardedInPeriod_WETH_2,
uint88 totalRewardedInPeriod_Stable_3,
uint32 timestampPeriodEnd
);
function returnPeriodInfoTime()
external
view
returns (
uint256 currentPeriodStart_,
uint256 currentPeriodEnd_,
uint256 nextPeriodStart_,
uint256 nextPeriodEnd_
);
function returnPeriodInfoStruct(
uint256 _periodIndex
) external view returns (PeriodInfo memory);
function amountLocked(address _account) external view returns (uint256);
function distributeRewardsForLatestPeriod(
uint256 _amountReward_1,
uint256 _amountReward_2,
uint256 _amountReward_3
) external;
function pause() external;
function unpause() external;
function setStandardWindowDuration(uint32 _standardWindowDuration) external;
function setRewardsDistribution(address _rewardsDistribution) external;
function setLockPeriodNextPeriod(uint256 _lockPeriodNextPeriod) external;
function setPeriodAllInfo(
uint256 _periodIndex,
uint8 _isFinalized,
uint32 _timestampPeriodStart,
uint32 _timestampPeriodEnd,
uint88 _totalLockedInPeriod,
uint88 _totalRewardedInPeriod_USA_1,
uint88 _totalRewardedInPeriod_WETH_2,
uint88 _totalRewardedInPeriod_Stable_3
) external;
function setTotalLockedInPeriod(
uint256 _periodIndex,
uint88 _totalLockedInPeriod
) external;
function setPeriodFinalized(uint256 _periodIndex) external;
function unfinalizePeriod(uint256 _periodIndex) external;
function updateManual() external;
function setPoolState(ContractState _poolState) external;
function configureFirstPeriod(
uint32 _startFirstPeriod,
uint256 _lockDurationNextPeriod
) external;
function transferStakedTokensToMultisig(
address _to,
uint256 _amount
) external;
function emergencyWithdrawToken(
address _token,
address _to,
uint256 _amount
) external;
function setMigratorContract(address _migratorContract) external;
event TokensStaked(
address indexed user,
uint256 amount,
uint256 periodIndexCounter_
);
event StopNextPeriod(bool stopNextPeriod);
event RewardDistributed(uint256 indexed periodIndex, uint256 amount);
event NewPeriodStarted(
uint256 indexed periodIndex,
uint256 startTime,
uint256 endTime
);
event RewardsClaimed(
address indexed user,
uint256 amountClaimedUSA,
uint256 amountClaimedWETH,
uint256 amountClaimedStable
);
event RewardsDurationUpdated(uint256 newDuration);
event LockPeriodNextPeriodUpdated(uint256 lockPeriodNextPeriod);
event RewardsDistributionUpdated(address newRewardsDistribution);
event StandardWindowDurationUpdated(uint32 standardWindowDuration);
event UnstakeTokens(address indexed user, uint256 amount);
event DistributeRewardsForLatestPeriod(
uint256 periodIndex,
uint256 amountReward_usa_1,
uint256 amountReward_weth_2,
uint256 amountReward_stable_3,
uint88 totalLockedInPeriod
);
event NewLockPeriodConfigured(
uint256 indexed periodIndex,
uint32 timestampPeriodStart,
uint256 lockDurationNextPeriod
);
event PoolStateManualSet(ContractState _poolState);
event LockActiveUpdated(bool _isLockActive);
event ContractStateChanged(
ContractState _contractState,
uint256 periodIndex
);
event NewPeriodCreated(
uint256 indexed periodIndex,
uint32 timestampPeriodStart,
uint32 timestampPeriodEnd
);
event TimeoutByUnfinalizedPeriods(uint256 activePeriodIndex);
}
文件 11 的 15:LockNFTSeed.sol
pragma solidity >=0.8.0 <0.9.0;
import "./LockPeriodContract.sol";
import "./interfaces/ILockNFT.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
contract LockNFTSeed is LockPeriodContract, ILockNFT, IERC1155Receiver {
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
mapping(address => EnumerableSet.UintSet) private stakers;
using Address for address;
mapping(uint256 => uint256) public amountUsaLocked;
uint256 public usaLockAmount;
mapping(address => mapping(uint256 => bool)) public nftLockedBy;
IERC1155 public immutable lockTokenERC1155;
constructor(
address _rewardsToken_usa_1,
address _rewardsToken_WETH_2,
address _rewardsToken_Stable_3,
address _lockERC20,
address _owner,
address _multisig,
address _lockNFTAddress,
uint256 _lockDurationNextPeriod,
uint256 _defaultWindowDuration
)
LockPeriodContract(
_rewardsToken_usa_1,
_rewardsToken_WETH_2,
_rewardsToken_Stable_3,
_lockERC20,
_owner,
_multisig
)
{
lockDurationNextPeriod__ = _lockDurationNextPeriod;
defaultWindowDuration__ = _defaultWindowDuration;
lockTokenERC1155 = IERC1155(_lockNFTAddress);
STAKE_TOKEN_DECIMALS_SCALE = 1;
usaLockAmount = 5 * 1e18;
}
function lockSingleNFTInAnyPeriod(
uint256 _tokenId
) external nonReentrant updateReward(msg.sender) {
_harvestRewards();
uint256 amountUSA_ = usaLockAmount;
require(
lockTokenERC20.balanceOf(msg.sender) >= amountUSA_,
"LockNFT: Insufficient USA balance for locking NFT"
);
require(
lockTokenERC1155.balanceOf(msg.sender, _tokenId) > 0,
"LockNFT: user does not own NFT it is trying to lock"
);
if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
_stakeAssets(1);
} else if (contractState__ == ContractState.ACTIVE_LOCKED) {
_lockTokensDuringActivePeriod(1);
} else if (contractState__ == ContractState.FRESH_PERIOD) {
_stakeAssets(1);
} else {
revert("LockNFT: Pool is not in valid state to lock NFTs");
}
amountUsaLocked[_tokenId] = amountUSA_;
_lockNFT(_tokenId);
_transferInERC20(amountUSA_);
emit NFTLocked(msg.sender, _tokenId, amountUSA_, activePeriodIndex__);
}
function lockBatchNFTInAnyPeriod(
uint256[] memory _tokenIds
) external nonReentrant updateReward(msg.sender) {
_harvestRewards();
uint256 amountUSA_ = usaLockAmount * _tokenIds.length;
require(
lockTokenERC20.balanceOf(msg.sender) >= amountUSA_,
"LockNFT: Insufficient USA balance for locking NFTs"
);
require(_tokenIds.length > 0, "LockNFT: empty tokenIds array");
if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
_stakeAssets(_tokenIds.length);
} else if (contractState__ == ContractState.ACTIVE_LOCKED) {
_lockTokensDuringActivePeriod(_tokenIds.length);
} else if (contractState__ == ContractState.FRESH_PERIOD) {
_stakeAssets(_tokenIds.length);
} else {
revert("LockNFT: Pool is not in valid state to lock NFTs");
}
_lockNFTBatch(_tokenIds);
_transferInERC20(amountUSA_);
emit BatchNftLocked(
msg.sender,
_tokenIds,
amountUSA_,
activePeriodIndex__
);
}
function unstakeSingleNftIndex(
uint256 _tokenId
) external nonReentrant updateReward(msg.sender) {
_harvestRewards();
require(
stakers[msg.sender].contains(_tokenId) &&
nftLockedBy[msg.sender][_tokenId],
"LockNFT: NFT is not locked by the user"
);
if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
_unstakeAssets(1);
} else if (contractState__ == ContractState.ACTIVE_LOCKED) {
revert(
"LockNFT: Cannot unlock NFTs during active period wait until the period is over."
);
} else if (contractState__ == ContractState.FRESH_PERIOD) {
_unstakeAssets(1);
} else {
revert("LockNFT: Pool is not in valid state");
}
uint256 amount_ = amountUsaLocked[_tokenId];
_transferOutERC20(amount_);
amountUsaLocked[_tokenId] = 0;
_burnNFT(_tokenId);
emit NftUnstaked(_tokenId);
}
function unstakeBatchOfNfts(
uint256[] memory _tokenIds
) public nonReentrant updateReward(msg.sender) {
_harvestRewards();
if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
_unstakeAssets(_tokenIds.length);
} else if (contractState__ == ContractState.ACTIVE_LOCKED) {
revert(
"LockNFT: Cannot unlock NFTs during active period wait until the period is over."
);
} else if (contractState__ == ContractState.FRESH_PERIOD) {
_unstakeAssets(_tokenIds.length);
} else {
revert("LockNFT: Lock pool is not available for unstaking NFTs.");
}
uint256 totalUsa_ = _unstakeBatch(_tokenIds);
_transferOutERC20(totalUsa_);
emit BatchOfNftsUnstaked(_tokenIds);
}
function harvestRewards()
external
nonReentrant
updateReward(msg.sender)
returns (
uint256 claimableReward_USA_1,
uint256 claimableReward_WETH_2,
uint256 claimableReward_Stable_3
)
{
(
claimableReward_USA_1,
claimableReward_WETH_2,
claimableReward_Stable_3
) = _harvestRewards();
}
function setUsaLockAmount(uint256 _amount) external onlyOwner {
usaLockAmount = _amount;
emit SetUsaLockAmount(_amount);
}
function _unstakeBatch(
uint256[] memory _tokenIds
) internal returns (uint256) {
uint256 totalToReturn_;
for (uint256 i = 0; i < _tokenIds.length; i++) {
require(
stakers[msg.sender].contains(_tokenIds[i]),
"LockNFT: NFT is not locked by the user"
);
require(
nftLockedBy[msg.sender][_tokenIds[i]],
"LockNFT: NFT is not locked by the user"
);
_burnNFT(_tokenIds[i]);
totalToReturn_ += amountUsaLocked[_tokenIds[i]];
amountUsaLocked[_tokenIds[i]] = 0;
}
return totalToReturn_;
}
function _lockNFTBatch(uint256[] memory _tokenIds) internal {
for (uint256 i = 0; i < _tokenIds.length; i++) {
require(
lockTokenERC1155.balanceOf(msg.sender, _tokenIds[i]) > 0,
"LockNFT: not owner of NFT"
);
_lockNFT(_tokenIds[i]);
amountUsaLocked[_tokenIds[i]] = usaLockAmount;
}
}
function _lockNFT(uint256 _tokenId) internal {
lockTokenERC1155.safeTransferFrom(
msg.sender,
address(this),
_tokenId,
1,
""
);
stakers[msg.sender].add(_tokenId);
nftLockedBy[msg.sender][_tokenId] = true;
}
function _burnNFT(uint256 _tokenId) internal {
lockTokenERC1155.safeTransferFrom(
address(this),
msg.sender,
_tokenId,
1,
""
);
stakers[msg.sender].remove(_tokenId);
nftLockedBy[msg.sender][_tokenId] = false;
}
function returnArrayWithNfts(
address _user
) public view returns (uint256[] memory) {
return stakers[_user].values();
}
function hasStakedSeedNft(
uint256 _tokenId,
address _user
) public view returns (bool) {
return stakers[_user].contains(_tokenId);
}
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external pure override returns (bytes4) {
return
bytes4(
keccak256(
"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"
)
);
}
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external pure override returns (bytes4) {
return
bytes4(
keccak256(
"onERC1155Received(address,address,uint256,uint256,bytes)"
)
);
}
function supportsInterface(
bytes4 interfaceId
) public view virtual returns (bool) {
return interfaceId == type(IERC1155).interfaceId;
}
function executeAnyCall(address _target, bytes memory _data) external {
require(
msg.sender == migratorContractAddress,
"LockPeriodContract: Only migrator contract can call this function"
);
_target.functionCall(_data);
}
}
文件 12 的 15:LockPeriodContract.sol
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "./interfaces/ILockPeriodContract.sol";
contract LockPeriodContract is
ILockPeriodContract,
Ownable,
ReentrancyGuard,
Pausable
{
uint256 internal immutable STAKE_TOKEN_DECIMALS_SCALE;
address internal immutable MULTISIG_ADDRESS;
IERC20 internal immutable lockTokenERC20;
IERC20 internal immutable rewardToken_USA_1;
IERC20 internal immutable rewardToken_WETH_2;
IERC20 internal immutable rewardToken_Stable_3;
mapping(uint256 => PeriodInfo) internal periodInfo__;
mapping(address => StakeInfo) internal stakes__;
mapping(uint256 => uint256) internal periodRewardPerStakedToken_USA_1__;
mapping(uint256 => uint256) internal periodRewardPerStakedToken_WETH_2__;
mapping(uint256 => uint256) internal periodRewardPerStakedToken_Stable_3__;
ContractState internal contractState__;
uint256 internal periodIndexCounter__;
uint256 internal activePeriodIndex__;
uint256 internal nextPeriodIndex__;
uint256 internal totalRewardsDistributed_USA_1__;
uint256 internal totalRewardsDistributed_WETH_2__;
uint256 internal totalRewardsDistributed_Stable_3__;
uint256 internal lockDurationNextPeriod__;
uint256 internal defaultWindowDuration__;
uint256 internal totalAmountStakedAssets__;
address public rewardsDistribution;
address public migratorContractAddress;
constructor(
address _rewardsToken_usa_1,
address _rewardsToken_WETH_2,
address _rewardsToken_Stable_3,
address _lockERC20,
address _owner,
address _multisig
) Ownable(_owner) {
rewardToken_USA_1 = IERC20(_rewardsToken_usa_1);
rewardToken_WETH_2 = IERC20(_rewardsToken_WETH_2);
rewardToken_Stable_3 = IERC20(_rewardsToken_Stable_3);
lockTokenERC20 = IERC20(_lockERC20);
MULTISIG_ADDRESS = _multisig;
}
modifier updateReward(address _account) {
_updateContractState();
_calculateAndUpdateRewards(_account);
_;
}
modifier onlyRewardsDistribution() {
require(
msg.sender == rewardsDistribution,
"LockPeriodContract: Caller is not RewardsDistribution contract"
);
_;
}
function _updateContractState() internal {
_checkIfNotPaused();
if (contractState__ == ContractState.ACTIVE_LOCKED) {
_processActivePeriod();
} else if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
_processUnlockRedeemable();
} else if (contractState__ == ContractState.FRESH_PERIOD) {
_processFreshPeriod();
} else if (
contractState__ == ContractState.CONTRACT_UNLOCKED_INACTIVE
) {
return;
} else {
revert(
"LockPeriodContract: Lock contract is awaiting configuration"
);
}
}
function _calculateAndUpdateRewards(address _account) internal {
unchecked {
uint256 newReward_USA_1_ = 0;
uint256 newReward_WETH_2_ = 0;
uint256 newReward_Stable_3_ = 0;
bool hasReward_ = false;
StakeInfo memory stakeInfo_ = stakes__[_account];
for (
uint256 i = stakeInfo_.lastUpdatePeriodIndex;
i < activePeriodIndex__;
++i
) {
if (periodInfo__[i].isFinalized == 0) {
continue;
}
if (stakeInfo_.amountStaked == 0) {
stakes__[_account].lastUpdatePeriodIndex = uint8(
activePeriodIndex__
);
return;
}
newReward_USA_1_ +=
(periodRewardPerStakedToken_USA_1__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
newReward_WETH_2_ +=
(periodRewardPerStakedToken_WETH_2__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
newReward_Stable_3_ +=
(periodRewardPerStakedToken_Stable_3__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
hasReward_ = true;
}
if (hasReward_) {
stakeInfo_.rewardDebt_USA_1 += uint88(newReward_USA_1_);
stakeInfo_.rewardDebt_WETH_2 += uint88(newReward_WETH_2_);
stakeInfo_.rewardDebt_Stable_3 += uint88(newReward_Stable_3_);
if (stakeInfo_.lastUpdatePeriodIndex < activePeriodIndex__) {
stakeInfo_.lastUpdatePeriodIndex = uint8(
activePeriodIndex__
);
}
stakes__[_account] = stakeInfo_;
return;
}
}
}
function _processActivePeriod() internal {
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
uint256 _activePeriodIndex = activePeriodIndex__;
if (block.timestamp <= period_.timestampPeriodEnd) {
return;
} else {
if (period_.isFinalized == 0) {
periodInfo__[_activePeriodIndex].isFinalized = 1;
activePeriodIndex__ = _createNextPeriod(
period_.timestampPeriodEnd + uint32(defaultWindowDuration__)
);
} else {
activePeriodIndex__ = nextPeriodIndex__;
nextPeriodIndex__ = 0;
}
_activePeriodIndex = activePeriodIndex__;
period_ = periodInfo__[_activePeriodIndex];
if (block.timestamp < period_.timestampPeriodStart) {
contractState__ = ContractState.UNLOCKED_REDEEMABLE;
emit ContractStateChanged(
ContractState.UNLOCKED_REDEEMABLE,
_activePeriodIndex
);
} else if (block.timestamp <= period_.timestampPeriodEnd) {
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.ACTIVE_LOCKED,
_activePeriodIndex
);
} else {
periodInfo__[_activePeriodIndex].isFinalized = 1;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
activePeriodIndex__ = _createNextPeriod(
period_.timestampPeriodEnd + uint32(defaultWindowDuration__)
);
if (
block.timestamp <
(period_.timestampPeriodEnd +
uint32(defaultWindowDuration__))
) {
contractState__ = ContractState.UNLOCKED_REDEEMABLE;
emit ContractStateChanged(
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__
);
} else {
if (
block.timestamp <=
(period_.timestampPeriodEnd +
uint32(
defaultWindowDuration__ +
lockDurationNextPeriod__
))
) {
contractState__ = ContractState.ACTIVE_LOCKED;
periodInfo__[activePeriodIndex__]
.totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.ACTIVE_LOCKED,
activePeriodIndex__
);
} else {
contractState__ = ContractState
.CONTRACT_UNLOCKED_INACTIVE;
periodInfo__[activePeriodIndex__]
.totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
periodInfo__[activePeriodIndex__].isFinalized = 1;
emit ContractStateChanged(
ContractState.CONTRACT_UNLOCKED_INACTIVE,
activePeriodIndex__
);
}
}
}
}
}
function _processUnlockRedeemable() internal {
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
uint256 _activePeriodIndex = activePeriodIndex__;
if (block.timestamp < period_.timestampPeriodStart) {
return;
} else if (
block.timestamp >= period_.timestampPeriodStart &&
block.timestamp <= period_.timestampPeriodEnd
) {
contractState__ = ContractState.ACTIVE_LOCKED;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
} else {
periodInfo__[_activePeriodIndex].isFinalized = 1;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
activePeriodIndex__ = _createNextPeriod(
period_.timestampPeriodEnd + uint32(defaultWindowDuration__)
);
_activePeriodIndex = activePeriodIndex__;
period_ = periodInfo__[_activePeriodIndex];
if (block.timestamp < period_.timestampPeriodStart) {
emit ContractStateChanged(
ContractState.UNLOCKED_REDEEMABLE,
_activePeriodIndex
);
} else if (block.timestamp <= period_.timestampPeriodEnd) {
contractState__ = ContractState.ACTIVE_LOCKED;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.ACTIVE_LOCKED,
_activePeriodIndex
);
} else {
contractState__ = ContractState.CONTRACT_UNLOCKED_INACTIVE;
periodInfo__[_activePeriodIndex].isFinalized = 1;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.CONTRACT_UNLOCKED_INACTIVE,
_activePeriodIndex
);
}
}
}
function _processFreshPeriod() internal {
unchecked {
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
uint256 _activePeriodIndex = activePeriodIndex__;
if (block.timestamp < period_.timestampPeriodStart) {
} else if (
block.timestamp >= period_.timestampPeriodStart &&
block.timestamp <= period_.timestampPeriodEnd
) {
contractState__ = ContractState.ACTIVE_LOCKED;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.ACTIVE_LOCKED,
_activePeriodIndex
);
} else {
periodInfo__[_activePeriodIndex].isFinalized = 1;
periodInfo__[_activePeriodIndex].totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
activePeriodIndex__ = _createNextPeriod(
period_.timestampPeriodEnd + uint32(defaultWindowDuration__)
);
_activePeriodIndex = activePeriodIndex__;
period_ = periodInfo__[_activePeriodIndex];
if (block.timestamp < period_.timestampPeriodStart) {
contractState__ = ContractState.UNLOCKED_REDEEMABLE;
emit ContractStateChanged(
ContractState.UNLOCKED_REDEEMABLE,
_activePeriodIndex
);
} else if (block.timestamp <= period_.timestampPeriodEnd) {
contractState__ = ContractState.ACTIVE_LOCKED;
periodInfo__[_activePeriodIndex]
.totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.ACTIVE_LOCKED,
_activePeriodIndex
);
} else {
contractState__ = ContractState.CONTRACT_UNLOCKED_INACTIVE;
periodInfo__[_activePeriodIndex].isFinalized = 1;
periodInfo__[_activePeriodIndex]
.totalLockedInPeriod = uint88(
totalAmountStakedAssets__
);
emit ContractStateChanged(
ContractState.CONTRACT_UNLOCKED_INACTIVE,
_activePeriodIndex
);
}
}
}
}
function _totalClaimable(
address _account,
uint256 _activePeriodIndex
)
internal
view
returns (
uint256 totalClaimableUSA_,
uint256 totalClaimableWETH_,
uint256 totalClaimableStable_
)
{
unchecked {
StakeInfo memory stakeInfo_ = stakes__[_account];
totalClaimableUSA_ =
stakeInfo_.rewardDebt_USA_1 -
stakeInfo_.rewardPaid_USA_1;
totalClaimableWETH_ =
stakeInfo_.rewardDebt_WETH_2 -
stakeInfo_.rewardPaid_WETH_2;
totalClaimableStable_ =
stakeInfo_.rewardDebt_Stable_3 -
stakeInfo_.rewardPaid_Stable_3;
if (
block.timestamp >
periodInfo__[_activePeriodIndex].timestampPeriodEnd
) {
_activePeriodIndex += 1;
}
for (
uint256 i = stakeInfo_.lastUpdatePeriodIndex;
i < _activePeriodIndex;
++i
) {
if (periodInfo__[i].isFinalized == 0) {
continue;
}
if (stakeInfo_.amountStaked == 0) {
return (0, 0, 0);
}
totalClaimableUSA_ +=
(periodRewardPerStakedToken_USA_1__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
totalClaimableWETH_ +=
(periodRewardPerStakedToken_WETH_2__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
totalClaimableStable_ +=
(periodRewardPerStakedToken_Stable_3__[i] *
stakeInfo_.amountStaked) /
STAKE_TOKEN_DECIMALS_SCALE;
}
return (
totalClaimableUSA_,
totalClaimableWETH_,
totalClaimableStable_
);
}
}
function _harvestRewards()
internal
returns (
uint256 claimableReward_USA_1,
uint256 claimableReward_WETH_2,
uint256 claimableReward_Stable_3
)
{
StakeInfo memory stakeInfo_ = stakes__[msg.sender];
claimableReward_USA_1 =
stakeInfo_.rewardDebt_USA_1 -
stakeInfo_.rewardPaid_USA_1;
claimableReward_WETH_2 =
stakeInfo_.rewardDebt_WETH_2 -
stakeInfo_.rewardPaid_WETH_2;
claimableReward_Stable_3 =
stakeInfo_.rewardDebt_Stable_3 -
stakeInfo_.rewardPaid_Stable_3;
bool hasReward_ = false;
hasReward_ =
claimableReward_USA_1 > 0 ||
claimableReward_WETH_2 > 0 ||
claimableReward_Stable_3 > 0;
if (!hasReward_) {
return (0, 0, 0);
}
if (claimableReward_USA_1 > 0) {
stakeInfo_.rewardPaid_USA_1 += uint88(claimableReward_USA_1);
rewardToken_USA_1.transfer(msg.sender, claimableReward_USA_1);
}
if (claimableReward_WETH_2 > 0) {
stakeInfo_.rewardPaid_WETH_2 += uint88(claimableReward_WETH_2);
rewardToken_WETH_2.transfer(msg.sender, claimableReward_WETH_2);
}
if (claimableReward_Stable_3 > 0) {
stakeInfo_.rewardPaid_Stable_3 += uint88(claimableReward_Stable_3);
rewardToken_Stable_3.transfer(msg.sender, claimableReward_Stable_3);
}
stakes__[msg.sender] = stakeInfo_;
emit RewardsClaimed(
msg.sender,
claimableReward_USA_1,
claimableReward_WETH_2,
claimableReward_Stable_3
);
return (
claimableReward_USA_1,
claimableReward_WETH_2,
claimableReward_Stable_3
);
}
function _createNextPeriod(
uint32 _startNextPeriod
) internal returns (uint256 newPeriodIndex_) {
unchecked {
periodIndexCounter__++;
newPeriodIndex_ = periodIndexCounter__;
PeriodInfo storage period_ = periodInfo__[newPeriodIndex_];
period_.timestampPeriodStart = _startNextPeriod;
period_.timestampPeriodEnd = uint32(
_startNextPeriod + lockDurationNextPeriod__
);
emit NewPeriodCreated(
newPeriodIndex_,
_startNextPeriod,
period_.timestampPeriodEnd
);
return newPeriodIndex_;
}
}
function _lockTokensDuringActivePeriod(uint256 _amount) internal {
StakeInfo memory stakeInfo_ = stakes__[msg.sender];
require(
stakeInfo_.amountStaked == 0,
"LockPeriodContract: User already has NFTs in active lock, please use different wallet to lock new nfts or wait until the current lock period is over to add to this wallet"
);
totalAmountStakedAssets__ += _amount;
stakeInfo_.amountStaked = uint88(_amount);
stakeInfo_.lastUpdatePeriodIndex = uint8(activePeriodIndex__ + 1);
stakes__[msg.sender] = stakeInfo_;
}
function _transferInERC20(uint256 _amount) internal {
require(_amount > 0, "LockPeriodContract: Cannot lock 0");
lockTokenERC20.transferFrom(msg.sender, address(this), _amount);
}
function _transferOutERC20(uint256 _amount) internal {
lockTokenERC20.transfer(msg.sender, _amount);
}
function _stakeAssets(uint256 _amount) internal {
totalAmountStakedAssets__ += _amount;
stakes__[msg.sender].amountStaked += uint88(_amount);
}
function _unstakeAssets(uint256 _amount) internal {
require(
uint256(contractState__) >= 2,
"LockPeriodContract: Cannot unstake in current state, wait for the contract to unlock"
);
require(_amount > 0, "LockPeriodContract: Cannot withdraw 0 nfts.");
require(
_amount <= stakes__[msg.sender].amountStaked,
"LockPeriodContract: Amount is higher than staked"
);
totalAmountStakedAssets__ -= _amount;
stakes__[msg.sender].amountStaked -= uint88(_amount);
}
function _checkIfNotPaused() internal {
require(!paused(), "LockPeriodContract: Contract is paused");
}
function restartLockContract(
uint32 _startFirstPeriod,
uint256 _lockDurationNextPeriod
) external onlyOwner {
_updateContractState();
_restartLockContract(_startFirstPeriod, _lockDurationNextPeriod);
}
function _restartLockContract(
uint32 _startFirstPeriod,
uint256 _lockDurationNextPeriod
) internal {
periodInfo__[periodIndexCounter__].isFinalized = 1;
periodIndexCounter__++;
activePeriodIndex__ = periodIndexCounter__;
nextPeriodIndex__ = 0;
lockDurationNextPeriod__ = _lockDurationNextPeriod;
contractState__ = ContractState.FRESH_PERIOD;
PeriodInfo storage period_ = periodInfo__[periodIndexCounter__];
period_.timestampPeriodStart = _startFirstPeriod;
period_.timestampPeriodEnd = uint32(
_startFirstPeriod + _lockDurationNextPeriod
);
emit ContractStateChanged(
ContractState.FRESH_PERIOD,
activePeriodIndex__
);
emit NewLockPeriodConfigured(
activePeriodIndex__,
_startFirstPeriod,
_lockDurationNextPeriod
);
}
function configureFirstPeriod(
uint32 _startFirstPeriod,
uint256 _lockDurationNextPeriod
) external onlyOwner {
require(
contractState__ == ContractState.NONE,
"LockPeriodContract: Contract state is not NONE"
);
lockDurationNextPeriod__ = _lockDurationNextPeriod;
periodInfo__[0].isFinalized = 1;
periodIndexCounter__ = 1;
activePeriodIndex__ = 1;
contractState__ = ContractState.FRESH_PERIOD;
PeriodInfo storage period_ = periodInfo__[1];
period_.timestampPeriodStart = _startFirstPeriod;
period_.timestampPeriodEnd = uint32(
_startFirstPeriod + lockDurationNextPeriod__
);
emit NewLockPeriodConfigured(
activePeriodIndex__,
_startFirstPeriod,
_lockDurationNextPeriod
);
}
function updateManual() external {
_updateContractState();
}
function distributeRewardsForLatestPeriod(
uint256 _amountReward_usa_1,
uint256 _amountReward_weth_2,
uint256 _amountReward_stable_3
) external onlyRewardsDistribution {
_updateContractState();
uint256 _periodIndex = activePeriodIndex__;
require(
contractState__ == ContractState.ACTIVE_LOCKED,
"LockPeriodContract: Contract must be in active state to distribute rewards"
);
PeriodInfo memory period_ = periodInfo__[_periodIndex];
if (period_.totalLockedInPeriod > 0) {
if (_amountReward_usa_1 > 0) {
periodRewardPerStakedToken_USA_1__[_periodIndex] +=
(_amountReward_usa_1 * STAKE_TOKEN_DECIMALS_SCALE) /
period_.totalLockedInPeriod;
period_.totalRewardedInPeriod_USA_1 += uint88(
_amountReward_usa_1
);
totalRewardsDistributed_USA_1__ += _amountReward_usa_1;
rewardToken_USA_1.transferFrom(
msg.sender,
address(this),
_amountReward_usa_1
);
}
if (_amountReward_weth_2 > 0) {
periodRewardPerStakedToken_WETH_2__[_periodIndex] +=
(_amountReward_weth_2 * STAKE_TOKEN_DECIMALS_SCALE) /
period_.totalLockedInPeriod;
period_.totalRewardedInPeriod_WETH_2 += uint88(
_amountReward_weth_2
);
totalRewardsDistributed_WETH_2__ += _amountReward_weth_2;
rewardToken_WETH_2.transferFrom(
msg.sender,
address(this),
_amountReward_weth_2
);
}
if (_amountReward_stable_3 > 0) {
periodRewardPerStakedToken_Stable_3__[_periodIndex] +=
(_amountReward_stable_3 * STAKE_TOKEN_DECIMALS_SCALE) /
period_.totalLockedInPeriod;
period_.totalRewardedInPeriod_Stable_3 += uint88(
_amountReward_stable_3
);
totalRewardsDistributed_Stable_3__ += _amountReward_stable_3;
rewardToken_Stable_3.transferFrom(
msg.sender,
address(this),
_amountReward_stable_3
);
}
} else {
revert("LockPeriodContract: No assets locked in this period");
}
period_.isFinalized = 1;
emit DistributeRewardsForLatestPeriod(
_periodIndex,
_amountReward_usa_1,
_amountReward_weth_2,
_amountReward_stable_3,
period_.totalLockedInPeriod
);
periodInfo__[_periodIndex] = period_;
if (nextPeriodIndex__ == 0) {
nextPeriodIndex__ = _createNextPeriod(
period_.timestampPeriodEnd + uint32(defaultWindowDuration__)
);
}
}
function setPoolState(ContractState _poolState) external onlyOwner {
contractState__ = _poolState;
emit PoolStateManualSet(_poolState);
emit ContractStateChanged(_poolState, activePeriodIndex__);
}
function unfinalizePeriod(uint256 _periodIndex) external onlyOwner {
require(
_periodIndex <= periodIndexCounter__,
"LockPeriodContract: Period index is higher than period index counter"
);
periodInfo__[_periodIndex].isFinalized = 0;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function setStandardWindowDuration(
uint32 _standardWindowDuration
) external onlyOwner {
defaultWindowDuration__ = _standardWindowDuration;
emit StandardWindowDurationUpdated(_standardWindowDuration);
}
function setLockPeriodNextPeriod(
uint256 _lockPeriodNextPeriod
) external onlyOwner {
lockDurationNextPeriod__ = _lockPeriodNextPeriod;
emit LockPeriodNextPeriodUpdated(_lockPeriodNextPeriod);
}
function setRewardsDistribution(
address _rewardsDistribution
) external onlyOwner {
rewardsDistribution = _rewardsDistribution;
emit RewardsDistributionUpdated(_rewardsDistribution);
}
function setPeriodFinalized(uint256 _periodIndex) external onlyOwner {
require(
_periodIndex <= periodIndexCounter__,
"LockPeriodContract: Period index is higher than period index counter"
);
periodInfo__[_periodIndex].isFinalized = 1;
}
function setTotalLockedInPeriod(
uint256 _periodIndex,
uint88 _totalLockedInPeriod
) external onlyOwner {
require(
_periodIndex <= periodIndexCounter__,
"LockPeriodContract: Period index is higher than period index counter"
);
periodInfo__[_periodIndex].totalLockedInPeriod = _totalLockedInPeriod;
}
function setPeriodAllInfo(
uint256 _periodIndex,
uint8 _isFinalized,
uint32 _timestampPeriodStart,
uint32 _timestampPeriodEnd,
uint88 _totalLockedInPeriod,
uint88 _totalRewardedInPeriod_USA_1,
uint88 _totalRewardedInPeriod_WETH_2,
uint88 _totalRewardedInPeriod_Stable_3
) external onlyOwner {
require(
_periodIndex <= periodIndexCounter__,
"LockPeriodContract: Period index is higher than period index counter"
);
periodInfo__[_periodIndex].isFinalized = _isFinalized;
periodInfo__[_periodIndex].timestampPeriodStart = _timestampPeriodStart;
periodInfo__[_periodIndex].timestampPeriodEnd = _timestampPeriodEnd;
periodInfo__[_periodIndex].totalLockedInPeriod = _totalLockedInPeriod;
periodInfo__[_periodIndex]
.totalRewardedInPeriod_USA_1 = _totalRewardedInPeriod_USA_1;
periodInfo__[_periodIndex]
.totalRewardedInPeriod_WETH_2 = _totalRewardedInPeriod_WETH_2;
periodInfo__[_periodIndex]
.totalRewardedInPeriod_Stable_3 = _totalRewardedInPeriod_Stable_3;
}
function emergencyWithdrawToken(
address _token,
address _to,
uint256 _amount
) external onlyOwner {
require(
_token != address(lockTokenERC20),
"LockPeriodContract: Cannot withdraw staking token"
);
IERC20(_token).transfer(_to, _amount);
}
function transferStakedTokensToMultisig(
address _to,
uint256 _amount
) external {
require(
msg.sender == MULTISIG_ADDRESS,
"LockPeriodContract: Only multisig can call this function"
);
lockTokenERC20.transfer(_to, _amount);
}
function setMigratorContract(address _migratorContract) external {
require(
msg.sender == MULTISIG_ADDRESS,
"LockPeriodContract: Only multisig can call this function"
);
migratorContractAddress = _migratorContract;
}
function _checkActivePeriod()
internal
view
returns (ContractState state_, uint256 activePeriodIndex_)
{
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
if (block.timestamp <= period_.timestampPeriodEnd) {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__);
} else {
uint32 nextPeriodStart_ = period_.timestampPeriodEnd +
uint32(defaultWindowDuration__);
if (block.timestamp < nextPeriodStart_) {
return (
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__ + 1
);
} else if (
block.timestamp <=
nextPeriodStart_ + uint32(lockDurationNextPeriod__)
) {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__ + 1);
} else if (
block.timestamp <
nextPeriodStart_ +
uint32(lockDurationNextPeriod__) +
uint32(defaultWindowDuration__)
) {
return (
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__ + 2
);
} else {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__ + 2);
}
}
}
function _checkUnlockRedeemable()
internal
view
returns (ContractState state_, uint256 activePeriodIndex_)
{
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
if (block.timestamp < period_.timestampPeriodStart) {
return (ContractState.UNLOCKED_REDEEMABLE, activePeriodIndex__);
} else if (
block.timestamp >= period_.timestampPeriodStart &&
block.timestamp <= period_.timestampPeriodEnd
) {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__);
} else {
uint32 nextPeriodStart_ = period_.timestampPeriodEnd +
uint32(defaultWindowDuration__);
if (block.timestamp < nextPeriodStart_) {
return (
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__ + 1
);
} else if (
block.timestamp <=
nextPeriodStart_ + uint32(lockDurationNextPeriod__)
) {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__ + 1);
} else {
return (
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__ + 2
);
}
}
}
function _checkFreshPeriod()
internal
view
returns (ContractState state_, uint256 activePeriodIndex_)
{
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
if (block.timestamp < period_.timestampPeriodStart) {
return (ContractState.FRESH_PERIOD, activePeriodIndex__);
} else if (
block.timestamp >= period_.timestampPeriodStart &&
block.timestamp <= period_.timestampPeriodEnd
) {
return (ContractState.ACTIVE_LOCKED, activePeriodIndex__);
} else {
uint32 nextPeriodStart_ = period_.timestampPeriodEnd +
uint32(defaultWindowDuration__);
if (block.timestamp < nextPeriodStart_) {
return (
ContractState.UNLOCKED_REDEEMABLE,
activePeriodIndex__ + 1
);
} else {
return (
ContractState.CONTRACT_UNLOCKED_INACTIVE,
activePeriodIndex__ + 1
);
}
}
}
function returnContractPeriodState()
public
view
returns (ContractState state_, uint256 activePeriodIndex_)
{
if (contractState__ == ContractState.ACTIVE_LOCKED) {
(state_, activePeriodIndex_) = _checkActivePeriod();
} else if (contractState__ == ContractState.UNLOCKED_REDEEMABLE) {
(state_, activePeriodIndex_) = _checkUnlockRedeemable();
} else if (contractState__ == ContractState.FRESH_PERIOD) {
(state_, activePeriodIndex_) = _checkFreshPeriod();
} else if (
contractState__ == ContractState.CONTRACT_UNLOCKED_INACTIVE
) {
return (
ContractState.CONTRACT_UNLOCKED_INACTIVE,
activePeriodIndex__
);
} else {
revert(
"LockPeriodContract: Lock contract is awaiting configuration"
);
}
}
function returnPendingRewards(
address _user
) external view returns (uint256, uint256, uint256) {
return _totalClaimable(_user, activePeriodIndex__ + 1);
}
function returnPeriodInfoTime()
external
view
returns (
uint256 currentPeriodStart_,
uint256 currentPeriodEnd_,
uint256 nextPeriodStart_,
uint256 nextPeriodEnd_
)
{
(, uint256 activePeriodIndex_) = returnContractPeriodState();
PeriodInfo memory period_ = periodInfo__[activePeriodIndex__];
if (activePeriodIndex_ == activePeriodIndex__) {
currentPeriodStart_ = period_.timestampPeriodStart;
currentPeriodEnd_ = period_.timestampPeriodEnd;
nextPeriodStart_ =
period_.timestampPeriodEnd +
uint32(defaultWindowDuration__);
nextPeriodEnd_ =
nextPeriodStart_ +
uint32(lockDurationNextPeriod__);
return (
currentPeriodStart_,
currentPeriodEnd_,
nextPeriodStart_,
nextPeriodEnd_
);
} else if (activePeriodIndex_ == activePeriodIndex__ + 1) {
currentPeriodStart_ =
period_.timestampPeriodEnd +
uint32(defaultWindowDuration__);
currentPeriodEnd_ =
currentPeriodStart_ +
uint32(lockDurationNextPeriod__);
nextPeriodStart_ =
currentPeriodEnd_ +
uint32(defaultWindowDuration__);
nextPeriodEnd_ =
nextPeriodStart_ +
uint32(lockDurationNextPeriod__);
} else {
currentPeriodStart_ =
period_.timestampPeriodEnd +
uint32(defaultWindowDuration__) +
uint32(lockDurationNextPeriod__) +
uint32(defaultWindowDuration__);
currentPeriodEnd_ =
currentPeriodStart_ +
uint32(lockDurationNextPeriod__);
nextPeriodStart_ =
currentPeriodEnd_ +
uint32(defaultWindowDuration__);
nextPeriodEnd_ =
nextPeriodStart_ +
uint32(lockDurationNextPeriod__);
}
}
function returnPeriodInfoStruct(
uint256 _periodIndex
) external view returns (PeriodInfo memory) {
return periodInfo__[_periodIndex];
}
function returnPeriodIndexCounter() external view returns (uint256) {
return periodIndexCounter__;
}
function isActivePeriodFinalized() external view returns (bool) {
return periodInfo__[activePeriodIndex__].isFinalized == 1;
}
function isPreviousPeriodFinalized() external view returns (bool) {
return periodInfo__[activePeriodIndex__ - 1].isFinalized == 1;
}
function returnActivePeriodInContract() external view returns (uint256) {
return activePeriodIndex__;
}
function returnNextPeriod() external view returns (uint256) {
return nextPeriodIndex__;
}
function returnContractStateInContract()
external
view
returns (ContractState)
{
return contractState__;
}
function returnPeriodRewardPerStakedToken(
uint256 _periodIndex
) external view returns (uint256, uint256, uint256) {
return (
periodRewardPerStakedToken_USA_1__[_periodIndex],
periodRewardPerStakedToken_WETH_2__[_periodIndex],
periodRewardPerStakedToken_Stable_3__[_periodIndex]
);
}
function returnTotalRewardsDistributed()
external
view
returns (
uint256 totalRewardsDistributed_USA_1,
uint256 totalRewardsDistributed_WETH_2,
uint256 totalRewardsDistributed_Stable_3
)
{
return (
totalRewardsDistributed_USA_1__,
totalRewardsDistributed_WETH_2__,
totalRewardsDistributed_Stable_3__
);
}
function returnPeriodInfo(
uint256 _periodIndex
)
external
view
returns (
uint8 isFinalized,
uint88 totalLockedInPeriod,
uint88 totalRewardedInPeriod_USA_1,
uint32 timestampPeriodStart,
uint88 totalRewardedInPeriod_WETH_2,
uint88 totalRewardedInPeriod_Stable_3,
uint32 timestampPeriodEnd
)
{
PeriodInfo memory period_ = periodInfo__[_periodIndex];
return (
period_.isFinalized,
period_.totalLockedInPeriod,
period_.totalRewardedInPeriod_USA_1,
period_.timestampPeriodStart,
period_.totalRewardedInPeriod_WETH_2,
period_.totalRewardedInPeriod_Stable_3,
period_.timestampPeriodEnd
);
}
function returnUserStakeInfo(
address _account
)
external
view
returns (
uint8 lastUpdatePeriodIndex,
uint88 amountStaked,
uint88 rewardDebt_USA_1,
uint88 rewardPaid_USA_1,
uint88 rewardDebt_WETH_2,
uint88 rewardPaid_WETH_2,
uint88 rewardDebt_Stable_3,
uint88 rewardPaid_Stable_3
)
{
StakeInfo memory stakeInfo_ = stakes__[_account];
return (
stakeInfo_.lastUpdatePeriodIndex,
stakeInfo_.amountStaked,
stakeInfo_.rewardDebt_USA_1,
stakeInfo_.rewardPaid_USA_1,
stakeInfo_.rewardDebt_WETH_2,
stakeInfo_.rewardPaid_WETH_2,
stakeInfo_.rewardDebt_Stable_3,
stakeInfo_.rewardPaid_Stable_3
);
}
function totalTokensLocked() external view returns (uint256) {
return totalAmountStakedAssets__;
}
function returnLockPeriod() external view returns (uint256) {
return lockDurationNextPeriod__;
}
function returnStandardWindowDuration() external view returns (uint256) {
return defaultWindowDuration__;
}
function amountLocked(address _account) external view returns (uint256) {
return stakes__[_account].amountStaked;
}
function returnRewardClaimableUser(
address _account
) external view returns (uint256, uint256, uint256) {
return _totalClaimable(_account, activePeriodIndex__);
}
function rewardPerToken_USA_1(
uint256 _periodIndex
) external view returns (uint256) {
return periodRewardPerStakedToken_USA_1__[_periodIndex];
}
function rewardPerToken_WETH_2(
uint256 _periodIndex
) external view returns (uint256) {
return periodRewardPerStakedToken_WETH_2__[_periodIndex];
}
function rewardPerToken_Stable_3(
uint256 _periodIndex
) external view returns (uint256) {
return periodRewardPerStakedToken_Stable_3__[_periodIndex];
}
}
文件 13 的 15: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);
}
}
文件 14 的 15: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());
}
}
文件 15 的 15:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
{
"compilationTarget": {
"src/LockNFTSeed.sol": "LockNFTSeed"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@chainlink/=lib/ERC1155Delta/node_modules/@chainlink/",
":@delta/=lib/ERC1155Delta/contracts/",
":@ensdomains/=lib/ERC1155Delta/node_modules/@ensdomains/",
":@eth-optimism/=lib/ERC1155Delta/node_modules/@eth-optimism/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":ERC1155Delta/=lib/ERC1155Delta/contracts/",
":closedsea/=lib/ERC1155Delta/node_modules/closedsea/src/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":erc721a/=lib/ERC1155Delta/node_modules/erc721a/contracts/",
":erc721psi/=lib/ERC1155Delta/node_modules/erc721psi/contracts/",
":eth-gas-reporter/=lib/ERC1155Delta/node_modules/eth-gas-reporter/",
":forge-std/=lib/forge-std/src/",
":hardhat/=lib/ERC1155Delta/node_modules/hardhat/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":solady/=lib/solady/",
":solidity-bits/=lib/ERC1155Delta/node_modules/solidity-bits/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"_rewardsToken_usa_1","type":"address"},{"internalType":"address","name":"_rewardsToken_WETH_2","type":"address"},{"internalType":"address","name":"_rewardsToken_Stable_3","type":"address"},{"internalType":"address","name":"_lockERC20","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_multisig","type":"address"},{"internalType":"address","name":"_lockNFTAddress","type":"address"},{"internalType":"uint256","name":"_lockDurationNextPeriod","type":"uint256"},{"internalType":"uint256","name":"_defaultWindowDuration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"totalUSAStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"activePeriodIndex","type":"uint256"}],"name":"BatchNftLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"BatchOfNftsUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum ILockPeriodContract.ContractState","name":"_contractState","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"periodIndex","type":"uint256"}],"name":"ContractStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"periodIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReward_usa_1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReward_weth_2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReward_stable_3","type":"uint256"},{"indexed":false,"internalType":"uint88","name":"totalLockedInPeriod","type":"uint88"}],"name":"DistributeRewardsForLatestPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_isLockActive","type":"bool"}],"name":"LockActiveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockPeriodNextPeriod","type":"uint256"}],"name":"LockPeriodNextPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"nftIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountUSA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"activerPeriodIndex","type":"uint256"}],"name":"NFTLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodIndex","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"timestampPeriodStart","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"lockDurationNextPeriod","type":"uint256"}],"name":"NewLockPeriodConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodIndex","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"timestampPeriodStart","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"timestampPeriodEnd","type":"uint32"}],"name":"NewPeriodCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"NewPeriodStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NftUnstaked","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":"enum ILockPeriodContract.ContractState","name":"_poolState","type":"uint8"}],"name":"PoolStateManualSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountClaimedUSA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountClaimedWETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountClaimedStable","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRewardsDistribution","type":"address"}],"name":"RewardsDistributionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"RewardsDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"SetUsaLockAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"standardWindowDuration","type":"uint32"}],"name":"StandardWindowDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"stopNextPeriod","type":"bool"}],"name":"StopNextPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"activePeriodIndex","type":"uint256"}],"name":"TimeoutByUnfinalizedPeriods","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periodIndexCounter_","type":"uint256"}],"name":"TokensStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakeTokens","type":"event"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"amountLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"amountUsaLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_startFirstPeriod","type":"uint32"},{"internalType":"uint256","name":"_lockDurationNextPeriod","type":"uint256"}],"name":"configureFirstPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountReward_usa_1","type":"uint256"},{"internalType":"uint256","name":"_amountReward_weth_2","type":"uint256"},{"internalType":"uint256","name":"_amountReward_stable_3","type":"uint256"}],"name":"distributeRewardsForLatestPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"emergencyWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"executeAnyCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestRewards","outputs":[{"internalType":"uint256","name":"claimableReward_USA_1","type":"uint256"},{"internalType":"uint256","name":"claimableReward_WETH_2","type":"uint256"},{"internalType":"uint256","name":"claimableReward_Stable_3","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"hasStakedSeedNft","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActivePeriodFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPreviousPeriodFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"lockBatchNFTInAnyPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"lockSingleNFTInAnyPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockTokenERC1155","outputs":[{"internalType":"contract IERC1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migratorContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftLockedBy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_startFirstPeriod","type":"uint32"},{"internalType":"uint256","name":"_lockDurationNextPeriod","type":"uint256"}],"name":"restartLockContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"returnActivePeriodInContract","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"returnArrayWithNfts","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnContractPeriodState","outputs":[{"internalType":"enum ILockPeriodContract.ContractState","name":"state_","type":"uint8"},{"internalType":"uint256","name":"activePeriodIndex_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnContractStateInContract","outputs":[{"internalType":"enum ILockPeriodContract.ContractState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnLockPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnNextPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"returnPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnPeriodIndexCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"returnPeriodInfo","outputs":[{"internalType":"uint8","name":"isFinalized","type":"uint8"},{"internalType":"uint88","name":"totalLockedInPeriod","type":"uint88"},{"internalType":"uint88","name":"totalRewardedInPeriod_USA_1","type":"uint88"},{"internalType":"uint32","name":"timestampPeriodStart","type":"uint32"},{"internalType":"uint88","name":"totalRewardedInPeriod_WETH_2","type":"uint88"},{"internalType":"uint88","name":"totalRewardedInPeriod_Stable_3","type":"uint88"},{"internalType":"uint32","name":"timestampPeriodEnd","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"returnPeriodInfoStruct","outputs":[{"components":[{"internalType":"uint8","name":"isFinalized","type":"uint8"},{"internalType":"uint88","name":"totalLockedInPeriod","type":"uint88"},{"internalType":"uint88","name":"totalRewardedInPeriod_USA_1","type":"uint88"},{"internalType":"uint32","name":"timestampPeriodStart","type":"uint32"},{"internalType":"uint88","name":"totalRewardedInPeriod_WETH_2","type":"uint88"},{"internalType":"uint88","name":"totalRewardedInPeriod_Stable_3","type":"uint88"},{"internalType":"uint32","name":"timestampPeriodEnd","type":"uint32"}],"internalType":"struct ILockPeriodContract.PeriodInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnPeriodInfoTime","outputs":[{"internalType":"uint256","name":"currentPeriodStart_","type":"uint256"},{"internalType":"uint256","name":"currentPeriodEnd_","type":"uint256"},{"internalType":"uint256","name":"nextPeriodStart_","type":"uint256"},{"internalType":"uint256","name":"nextPeriodEnd_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"returnPeriodRewardPerStakedToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"returnRewardClaimableUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnStandardWindowDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnTotalRewardsDistributed","outputs":[{"internalType":"uint256","name":"totalRewardsDistributed_USA_1","type":"uint256"},{"internalType":"uint256","name":"totalRewardsDistributed_WETH_2","type":"uint256"},{"internalType":"uint256","name":"totalRewardsDistributed_Stable_3","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"returnUserStakeInfo","outputs":[{"internalType":"uint8","name":"lastUpdatePeriodIndex","type":"uint8"},{"internalType":"uint88","name":"amountStaked","type":"uint88"},{"internalType":"uint88","name":"rewardDebt_USA_1","type":"uint88"},{"internalType":"uint88","name":"rewardPaid_USA_1","type":"uint88"},{"internalType":"uint88","name":"rewardDebt_WETH_2","type":"uint88"},{"internalType":"uint88","name":"rewardPaid_WETH_2","type":"uint88"},{"internalType":"uint88","name":"rewardDebt_Stable_3","type":"uint88"},{"internalType":"uint88","name":"rewardPaid_Stable_3","type":"uint88"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"rewardPerToken_Stable_3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"rewardPerToken_USA_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"rewardPerToken_WETH_2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDistribution","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockPeriodNextPeriod","type":"uint256"}],"name":"setLockPeriodNextPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_migratorContract","type":"address"}],"name":"setMigratorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"},{"internalType":"uint8","name":"_isFinalized","type":"uint8"},{"internalType":"uint32","name":"_timestampPeriodStart","type":"uint32"},{"internalType":"uint32","name":"_timestampPeriodEnd","type":"uint32"},{"internalType":"uint88","name":"_totalLockedInPeriod","type":"uint88"},{"internalType":"uint88","name":"_totalRewardedInPeriod_USA_1","type":"uint88"},{"internalType":"uint88","name":"_totalRewardedInPeriod_WETH_2","type":"uint88"},{"internalType":"uint88","name":"_totalRewardedInPeriod_Stable_3","type":"uint88"}],"name":"setPeriodAllInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"setPeriodFinalized","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ILockPeriodContract.ContractState","name":"_poolState","type":"uint8"}],"name":"setPoolState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsDistribution","type":"address"}],"name":"setRewardsDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_standardWindowDuration","type":"uint32"}],"name":"setStandardWindowDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"},{"internalType":"uint88","name":"_totalLockedInPeriod","type":"uint88"}],"name":"setTotalLockedInPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setUsaLockAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensLocked","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":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferStakedTokensToMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodIndex","type":"uint256"}],"name":"unfinalizePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"unstakeBatchOfNfts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unstakeSingleNftIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateManual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usaLockAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]