编译器
0.8.11+commit.d7f03943
文件 1 的 9:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 9: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 的 9:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 9:Interfaces.sol
pragma solidity 0.8.11;
import "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";
interface IWomDepositor {
function deposit(uint256 _amount, address _stakeAddress) external returns (bool);
}
interface IWETH {
function deposit() external payable;
function withdraw(uint wad) external;
}
interface IAsset is IERC20 {
function underlyingToken() external view returns (address);
function pool() external view returns (address);
function cash() external view returns (uint120);
function liability() external view returns (uint120);
function decimals() external view returns (uint8);
function underlyingTokenDecimals() external view returns (uint8);
function setPool(address pool_) external;
function underlyingTokenBalance() external view returns (uint256);
function transferUnderlyingToken(address to, uint256 amount) external;
function mint(address to, uint256 amount) external;
function burn(address to, uint256 amount) external;
function addCash(uint256 amount) external;
function removeCash(uint256 amount) external;
function addLiability(uint256 amount) external;
function removeLiability(uint256 amount) external;
}
interface IWmxLocker {
struct EarnedData {
address token;
uint256 amount;
}
struct LockedBalance {
uint112 amount;
uint32 unlockTime;
}
function lock(address _account, uint256 _amount) external;
function checkpointEpoch() external;
function epochCount() external view returns (uint256);
function balanceAtEpochOf(uint256 _epoch, address _user) external view returns (uint256 amount);
function totalSupplyAtEpoch(uint256 _epoch) external view returns (uint256 supply);
function queueNewRewards(address _rewardsToken, uint256 reward) external;
function getReward(address _account, bool _stake) external;
function getReward(address _account) external;
function balanceOf(address _account) external view returns (uint256 amount);
function balances(address _account) external view returns (uint112 locked, uint32 nextUnlockIndex);
function claimableRewards(address _account) external view returns (EarnedData[] memory userRewards);
function getVotes(address account) external view returns (uint256);
function getPastVotes(address account, uint256 timestamp) external view returns (uint256 votes);
function lockedBalances(address _user) external view returns (
uint256 total,
uint256 unlockable,
uint256 locked,
LockedBalance[] memory lockData
);
}
interface IBribeVoter {
function vote(IERC20[] calldata _lpVote, int256[] calldata _deltas) external returns (uint256[][] memory bribeRewards);
function votes(address _user, address _lpToken) external view returns (uint256);
function infos(address _lpToken) external view returns (uint104 supplyBaseIndex, uint104 supplyVoteIndex, uint40 nextEpochStartTime, uint128 claimable, bool whitelist, address gaugeManager, address bribe);
}
interface IMasterWombatRewarder {
function rewardTokens() external view returns (address[] memory tokens);
}
interface IExtraRewardsDistributor {
function addReward(address _token, uint256 _amount) external;
}
interface IWomDepositorWrapper {
function getMinOut(uint256, uint256) external view returns (uint256);
function deposit(
uint256,
uint256,
bool,
address _stakeAddress
) external;
}
interface ITokenFactory{
function CreateDepositToken(address) external returns(address);
function CreateBribesVotingToken() external returns(address);
}
interface IBribesRewardFactory {
function CreateBribesRewards(address _stakingToken, address _lptoken, bool _callOperatorOnGetReward) external returns (address);
}
interface IRewards{
function asset() external returns(address);
function stake(address, uint256) external;
function stakeFor(address, uint256) external;
function withdraw(address, uint256) external;
function withdraw(uint256 assets, address receiver, address owner) external;
function exit(address) external;
function getReward(address) external;
function queueNewRewards(address, uint256) external;
function notifyRewardAmount(uint256) external;
function addExtraReward(address) external;
function extraRewardsLength() external view returns (uint256);
function stakingToken() external view returns (address);
function rewardToken() external view returns(address);
function earned(address _token, address _account) external view returns (uint256);
function updateOperatorData(address operator_, uint256 pid_) external;
function setRewardTokenPaused(address token_, bool paused_) external;
function balanceOf(address _account) external view returns (uint256 amount);
function rewardTokensList() external view returns (address[] memory);
function tokenRewards(address _token) external view returns (address token, uint256 periodFinish, uint256 rewardRate, uint256 lastUpdateTime, uint256 rewardPerTokenStored, uint256 queuedRewards, uint256 currentRewards, uint256 historicalRewards, bool paused);
}
interface IGauge {
function notifyRewardAmount(IERC20 token, uint256 amount) external;
}
interface IBribe {
function onVote(
address user,
uint256 newVote,
uint256 originalTotalVotes
) external returns (uint256[] memory rewards);
function pendingTokens(address _user) external view returns (uint256[] memory rewards);
function rewardTokens() external view returns (IERC20[] memory tokens);
function rewardLength() external view returns (uint256);
}
interface IVe {
function vote(address user, int256 voteDelta) external;
}
interface INftLocker {
function voteBoost(address _account) external view returns (uint256);
}
interface IBribeRewardsPool is IRewards {
function withdrawAndUnwrapFrom(address _from, uint256 _amount, address _claimRecipient) external returns(bool);
function updateBribesConfig(bool _callOperatorOnGetReward) external;
function updateRatioConfig(uint256 _duration, uint256 _maxRewardRatio) external;
}
interface ITokenMinter is IERC20 {
function mint(address,uint256) external;
function burn(address,uint256) external;
function setOperator(address) external;
function updateOperator(address) external;
function getFactAmounMint(uint256 _amount) external view returns(uint256 amount);
}
interface IStaker{
function deposit(address, address) external returns (bool);
function withdraw(address) external returns (uint256);
function withdrawLp(address, address, uint256) external returns (bool);
function withdrawAllLp(address, address) external returns (bool);
function lock(uint256 _lockDays) external;
function releaseLock(uint256 _slot) external returns(uint256);
function getGaugeRewardTokens(address _lptoken, address _gauge) external returns (address[] memory tokens);
function claimCrv(address, uint256) external returns (address[] memory tokens, uint256[] memory balances);
function balanceOfPool(address, address) external view returns (uint256);
function operator() external view returns (address);
function depositor() external view returns (address);
function veWom() external view returns (address);
function execute(address _to, uint256 _value, bytes calldata _data) external returns (bool, bytes memory);
function setVote(bytes32 hash, bool valid) external;
function setDepositor(address _depositor) external;
function setOwner(address _owner) external;
}
interface IPool {
function deposit(
address token,
uint256 amount,
uint256 minimumLiquidity,
address to,
uint256 deadline,
bool shouldStake
) external returns (uint256);
function withdraw(
address token,
uint256 liquidity,
uint256 minimumAmount,
address to,
uint256 deadline
) external returns (uint256 amount);
function quotePotentialSwap(
address fromToken,
address toToken,
int256 fromAmount
) external view returns (uint256 potentialOutcome, uint256 haircut);
function quotePotentialDeposit(
address token,
uint256 amount
) external view returns (uint256 liquidity, uint256 reward);
function quotePotentialWithdraw(
address token,
uint256 liquidity
) external view returns (uint256 amount, uint256 fee);
function withdrawFromOtherAsset(
address fromToken,
address toToken,
uint256 liquidity,
uint256 minimumAmount,
address to,
uint256 deadline
) external returns (uint256 amount);
function swap(
address fromToken,
address toToken,
uint256 fromAmount,
uint256 minimumToAmount,
address to,
uint256 deadline
) external returns (uint256 actualToAmount, uint256 haircut);
function quoteAmountIn(
address fromToken,
address toToken,
int256 toAmount
) external view returns (uint256 amountIn, uint256 haircut);
function addressOfAsset(address token) external view returns (address);
}
interface IWombatRouter {
function getAmountOut(
address[] calldata tokenPath,
address[] calldata poolPath,
int256 amountIn
) external view returns (uint256 amountOut, uint256[] memory haircuts);
function getAmountIn(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 amountOut
) external view returns (uint256 amountIn, uint256[] memory haircuts);
function swapExactTokensForTokens(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 fromAmount,
uint256 minimumToAmount,
address to,
uint256 deadline
) external returns (uint256 amountOut);
function swapExactNativeForTokens(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 minimumamountOut,
address to,
uint256 deadline
) external payable returns (uint256 amountOut);
function swapExactTokensForNative(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 amountIn,
uint256 minimumamountOut,
address to,
uint256 deadline
) external returns (uint256 amountOut);
function addLiquidityNative(
IPool pool,
uint256 minimumLiquidity,
address to,
uint256 deadline,
bool shouldStake
) external payable returns (uint256 liquidity);
function removeLiquidityNative(
IPool pool,
uint256 liquidity,
uint256 minimumAmount,
address to,
uint256 deadline
) external returns (uint256 amount);
function removeLiquidityFromOtherAssetAsNative(
IPool pool,
address fromToken,
uint256 liquidity,
uint256 minimumAmount,
address to,
uint256 deadline
) external returns (uint256 amount);
}
interface IBooster {
struct PoolInfo {
address lptoken;
address token;
address gauge;
address crvRewards;
bool shutdown;
}
function crv() external view returns (address);
function owner() external view returns (address);
function voterProxy() external view returns (address);
function poolLength() external view returns (uint256);
function poolInfo(uint256 _pid) external view returns (PoolInfo memory);
function depositFor(uint256 _pid, uint256 _amount, bool _stake, address _receiver) external returns (bool);
function setOwner(address _owner) external;
function setPoolManager(address _poolManager) external;
function voterProxyClaimRewards(uint256 _pid, address[] memory pendingTokens) external returns (uint256[] memory pendingRewards);
function addPool(address _lptoken, address _gauge) external returns (uint256);
function addCreatedPool(address _lptoken, address _gauge, address _token, address _crvRewards) external returns (uint256);
function approveDistribution(address _distro, address[] memory _distributionTokens, uint256 _amount) external;
function approvePoolsCrvRewardsDistribution(address _token) external;
function distributeRewards(uint256 _pid, address _lpToken, address _rewardToken, address[] memory _transferTo, uint256[] memory _transferAmount, bool[] memory _callQueue) external;
function lpPendingRewards(address _lptoken, address _token) external returns (uint256);
function earmarkRewards(uint256 _pid) external;
function shutdownPool(uint256 _pid) external returns (bool);
function forceShutdownPool(uint256 _pid) external returns (bool);
function gaugeMigrate(address _newGauge, uint256[] memory migratePids) external;
function voteExecute(address _voting, uint256 _value, bytes calldata _data) external returns (bytes memory);
function mintRatio() external view returns (uint256);
function customMintRatio(uint256 _pid) external view returns (uint256);
function crvLockRewards() external view returns (address);
function cvxLocker() external view returns (address);
}
interface IBoosterEarmark {
function earmarkIncentive() external view returns (uint256);
function distributionByTokenLength(address _token) external view returns (uint256);
function distributionByTokens(address, uint256) external view returns (address, uint256, bool);
function distributionTokenList() external view returns (address[] memory);
function addPool(address _lptoken, address _gauge) external returns (uint256);
function addCreatedPool(address _lptoken, address _gauge, address _token, address _crvRewards) external returns (uint256);
}
interface ISwapRouter {
function swapExactTokensForTokens(
address[] calldata tokenPath,
address[] calldata poolPath,
uint256 amountIn,
uint256 minimumamountOut,
address to,
uint256 deadline
) external returns (uint256 amountOut);
function getAmountOut(
address[] calldata tokenPath,
address[] calldata poolPath,
int256 amountIn
) external view returns (uint256 amountOut, uint256[] memory haircuts);
}
interface IWomSwapDepositor {
function pool() external view returns (address);
function deposit(uint256 _amount, address _stakeAddress, uint256 _minAmountOut, uint256 _deadline) external returns (bool);
}
interface IMasterWombatV2 {
function getAssetPid(address asset) external view returns (uint256 pid);
function poolLength() external view returns (uint256);
function pendingTokens(uint256 _pid, address _user)
external
view
returns (
uint256 pendingRewards,
IERC20[] memory bonusTokenAddresses,
string[] memory bonusTokenSymbols,
uint256[] memory pendingBonusRewards
);
function rewarderBonusTokenInfo(uint256 _pid)
external
view
returns (IERC20[] memory bonusTokenAddresses, string[] memory bonusTokenSymbols);
function massUpdatePools() external;
function updatePool(uint256 _pid) external;
function deposit(uint256 _pid, uint256 _amount) external returns (uint256, uint256[] memory);
function multiClaim(uint256[] memory _pids)
external
returns (
uint256 transfered,
uint256[] memory rewards,
uint256[][] memory additionalRewards
);
function withdraw(uint256 _pid, uint256 _amount) external returns (uint256, uint256[] memory);
function emergencyWithdraw(uint256 _pid) external;
function migrate(uint256[] calldata _pids) external;
function depositFor(
uint256 _pid,
uint256 _amount,
address _user
) external;
function updateFactor(address _user, uint256 _newVeWomBalance) external;
}
文件 5 的 9: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());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
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);
}
}
文件 6 的 9:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.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 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
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");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 7 的 9:WomDepositor.sol
pragma solidity 0.8.11;
import "./Interfaces.sol";
import "@openzeppelin/contracts-0.8/access/Ownable.sol";
import "@openzeppelin/contracts-0.8/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-0.8/utils/Address.sol";
import { SafeERC20 } from "@openzeppelin/contracts-0.8/token/ERC20/utils/SafeERC20.sol";
contract WomDepositor is Ownable {
using SafeERC20 for IERC20;
using Address for address;
address public wom;
address public staker;
address public minter;
address public booster;
uint256 public earmarkPid;
uint256 public lockDays;
uint256 public smartLockPeriod;
uint256 public checkOldSlot;
uint256 public currentSlot;
uint256 public lastLockAt;
bool public executing;
mapping(uint256 => uint256) public slotEnds;
mapping(address => uint256) public customLockDays;
mapping(address => uint256) public customLockMinAmount;
mapping(uint256 => bool) public lockedCustomSlots;
mapping(uint256 => bool) public releasedCustomSlots;
address[] public customLockAccounts;
struct SlotInfo {
uint256 number;
uint256 amount;
}
mapping(address => SlotInfo[]) public customLockSlots;
event UpdateOperator(address operator);
event SetLockConfig(uint256 lockDays, uint256 smartLockPeriod);
event SetBooster(address booster, uint256 pid);
event SetCustomLockDays(address indexed account, uint256 lockDays, uint256 minAmount);
event Deposit(address indexed account, address stakeAddress, uint256 amount);
event SmartLockReleased(address indexed sender, uint256 indexed slot);
event SmartLockCheck(address indexed sender, uint256 indexed checkOldSlot, bool isLockedCustomSlot);
event SmartLock(address indexed sender, bool indexed customLockDays, uint256 indexed slot, uint256 amountToLock, uint256 senderLockDays, uint256 currentSlot, uint256 checkOldSlot);
event ReleaseCustomLock(address indexed sender, uint256 index, uint256 indexed slot, uint256 amount);
constructor(
address _wom,
address _staker,
address _minter,
address _booster
) public {
wom = _wom;
staker = _staker;
minter = _minter;
booster = _booster;
}
function setLockConfig(uint256 _lockDays, uint256 _smartLockPeriod) external onlyOwner {
require(_smartLockPeriod <= 7 days, "MAX_SMART_LOCK_PERIOD");
lockDays = _lockDays;
smartLockPeriod = _smartLockPeriod;
emit SetLockConfig(_lockDays, _smartLockPeriod);
}
function setBooster(address _booster, uint256 _earmarkPid) external onlyOwner {
booster = _booster;
earmarkPid = _earmarkPid;
emit SetBooster(_booster, _earmarkPid);
}
function updateMinterOperator() external onlyOwner {
address depositor = IStaker(staker).depositor();
ITokenMinter(minter).setOperator(depositor);
emit UpdateOperator(depositor);
}
function setCustomLock(address _account, uint256 _lockDays, uint256 _minAmount) external onlyOwner {
_setCustomLock(_account, _lockDays, _minAmount);
}
function _setCustomLock(address _account, uint256 _lockDays, uint256 _minAmount) internal {
if (customLockMinAmount[_account] == 0) {
customLockAccounts.push(_account);
}
customLockDays[_account] = _lockDays;
customLockMinAmount[_account] = _minAmount;
emit SetCustomLockDays(_account, _lockDays, _minAmount);
}
function deposit(
uint256 _amount,
uint256,
bool,
address _stakeAddress
) external {
deposit(_amount, _stakeAddress);
}
function deposit(
uint256 _amount,
bool,
address _stakeAddress
) external {
deposit(_amount, _stakeAddress);
}
function deposit(uint256 _amount, address _stakeAddress) public returns (bool) {
require(customLockDays[msg.sender] == 0, "custom");
_smartLock(_amount);
bool depositOnly = _stakeAddress == address(0);
if(depositOnly){
ITokenMinter(minter).mint(msg.sender, _amount);
}else{
ITokenMinter(minter).mint(address(this), _amount);
IERC20(minter).safeApprove(_stakeAddress, 0);
IERC20(minter).safeApprove(_stakeAddress, _amount);
IRewards(_stakeAddress).stakeFor(msg.sender, _amount);
}
emit Deposit(msg.sender, _stakeAddress, _amount);
return true;
}
function _smartLock(uint256 _amount) internal virtual {
IERC20(wom).transferFrom(msg.sender, address(this), _amount);
if (currentSlot > 1 && checkOldSlot >= currentSlot - 1) {
checkOldSlot = 0;
}
if (slotEnds[checkOldSlot] != 0 && slotEnds[checkOldSlot] < block.timestamp) {
if (!lockedCustomSlots[checkOldSlot]) {
IStaker(staker).releaseLock(checkOldSlot);
slotEnds[checkOldSlot] = slotEnds[currentSlot - 1];
currentSlot = currentSlot - 1;
emit SmartLockReleased(msg.sender, checkOldSlot);
}
checkOldSlot = checkOldSlot + 1;
emit SmartLockCheck(msg.sender, checkOldSlot, lockedCustomSlots[checkOldSlot]);
}
if (executing || (lastLockAt + smartLockPeriod > block.timestamp && customLockDays[msg.sender] == 0)) {
return;
}
executing = true;
uint256 slot = currentSlot;
currentSlot = currentSlot + 1;
uint256 senderLockDays = lockDays;
uint256 amountToLock = _amount;
if (customLockDays[msg.sender] > 0) {
senderLockDays = customLockDays[msg.sender];
customLockSlots[msg.sender].push(SlotInfo(slot, _amount));
lockedCustomSlots[slot] = true;
} else {
amountToLock = IERC20(wom).balanceOf(address(this));
}
if (IERC20(wom).balanceOf(staker) > 0) {
IBooster(booster).earmarkRewards(earmarkPid);
}
IERC20(wom).safeTransfer(staker, amountToLock);
IStaker(staker).lock(senderLockDays);
slotEnds[slot] = block.timestamp + senderLockDays * 86400;
lastLockAt = block.timestamp;
executing = false;
emit SmartLock(msg.sender, customLockDays[msg.sender] > 0, slot, amountToLock, senderLockDays, currentSlot, checkOldSlot);
}
function depositCustomLock(uint256 _amount) public {
require(customLockDays[msg.sender] > 0, "!custom");
require(_amount >= customLockMinAmount[msg.sender], "<customLockMinAmount");
_smartLock(_amount);
}
function releaseCustomLock(uint256 _index) public {
SlotInfo memory slot = customLockSlots[msg.sender][_index];
require(slotEnds[slot.number] < block.timestamp, "!ends");
IStaker(staker).releaseLock(slot.number);
IERC20(wom).safeTransfer(msg.sender, slot.amount);
lockedCustomSlots[slot.number] = false;
slotEnds[slot.number] = slotEnds[currentSlot - 1];
checkOldSlot = slot.number + 1;
uint256 len = customLockSlots[msg.sender].length;
if (_index != len - 1) {
customLockSlots[msg.sender][_index] = customLockSlots[msg.sender][len - 1];
}
customLockSlots[msg.sender].pop();
currentSlot = currentSlot - 1;
emit ReleaseCustomLock(msg.sender, _index, slot.number, slot.amount);
}
function getCustomLockAccounts() public view returns (address[] memory) {
return customLockAccounts;
}
function getCustomLockSlotsLength(address _account) public view returns (uint256) {
return customLockSlots[_account].length;
}
function rescueTokens(address[] memory _tokens, address _recipient) public onlyOwner {
for (uint256 i; i < _tokens.length; i++) {
require(_tokens[i] != wom, "!wom");
IERC20(_tokens[i]).safeTransfer(_recipient, IERC20(_tokens[i]).balanceOf(address(this)));
}
}
}
文件 8 的 9:WomDepositorV2.sol
pragma solidity 0.8.11;
import "./WomDepositor.sol";
contract WomDepositorV2 is WomDepositor {
event Migrated(uint256 currentSlot, uint256 checkOldSlot, uint256 customLockAccountsLen, uint256 lockDays, uint256 smartLockPeriod, uint256 lastLockAt);
WomDepositor public oldDepositor;
bool public migrated;
constructor(
address _wom,
address _staker,
address _minter,
address _booster,
address _oldDepositor
) public WomDepositor(_wom, _staker, _minter, _booster) {
if (_oldDepositor == address(0)) {
migrated = true;
} else {
oldDepositor = WomDepositor(_oldDepositor);
}
}
function _smartLock(uint256 _amount) internal override {
require(migrated, "!migrated");
super._smartLock(_amount);
}
function migrate(address[] memory _oldCustomLockAccounts, uint256[] memory _oldCustomLockSlotLengths) public onlyOwner {
require(!migrated, "migrated");
require(_oldCustomLockAccounts.length == _oldCustomLockSlotLengths.length, "length_mismatch");
uint256 oldCurrentSlot = oldDepositor.currentSlot();
for (uint256 i = currentSlot; i < oldCurrentSlot; i++) {
slotEnds[i] = oldDepositor.slotEnds(i);
currentSlot++;
}
require(oldCurrentSlot == currentSlot, "!current_slot");
for (uint256 i = 0; i < _oldCustomLockAccounts.length; i++) {
address account = _oldCustomLockAccounts[i];
_setCustomLock(account, oldDepositor.customLockDays(account), oldDepositor.customLockMinAmount(account));
uint256 length = _oldCustomLockSlotLengths[i];
for (uint256 j = 0; j < length; j++) {
(uint256 number, uint256 amount) = oldDepositor.customLockSlots(account, j);
customLockSlots[account].push(SlotInfo(number, amount));
lockedCustomSlots[number] = oldDepositor.lockedCustomSlots(number);
releasedCustomSlots[number] = oldDepositor.releasedCustomSlots(number);
}
}
lockDays = oldDepositor.lockDays();
smartLockPeriod = oldDepositor.smartLockPeriod();
checkOldSlot = oldDepositor.checkOldSlot();
lastLockAt = oldDepositor.lastLockAt();
migrated = true;
emit Migrated(currentSlot, checkOldSlot, customLockAccounts.length, lockDays, smartLockPeriod, lastLockAt);
}
}
文件 9 的 9:WomDepositorV3.sol
pragma solidity 0.8.11;
import "./WomDepositorV2.sol";
contract WomDepositorV3 is WomDepositorV2 {
mapping(address => bool) public mintManagers;
event SetMintManager(address minter, bool active);
event Mint(address indexed to, uint256 amount, address indexed minter);
constructor(
address _wom,
address _staker,
address _minter,
address _booster,
address _oldDepositor
) public WomDepositorV2(_wom, _staker, _minter, _booster, _oldDepositor) {
}
function setMintManager(address _mintManager, bool _active) external onlyOwner {
mintManagers[_mintManager] = _active;
emit SetMintManager(_mintManager, _active);
}
function mint(address _to, uint256 _amount) external {
require(mintManagers[msg.sender], "!mintManager");
ITokenMinter(minter).mint(_to, _amount);
emit Mint(_to, _amount, msg.sender);
}
}
{
"compilationTarget": {
"contracts/WomDepositorV3.sol": "WomDepositorV3"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 800
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_wom","type":"address"},{"internalType":"address","name":"_staker","type":"address"},{"internalType":"address","name":"_minter","type":"address"},{"internalType":"address","name":"_booster","type":"address"},{"internalType":"address","name":"_oldDepositor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"stakeAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"checkOldSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"customLockAccountsLen","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"smartLockPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastLockAt","type":"uint256"}],"name":"Migrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"Mint","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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"slot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReleaseCustomLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"booster","type":"address"},{"indexed":false,"internalType":"uint256","name":"pid","type":"uint256"}],"name":"SetBooster","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"lockDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"SetCustomLockDays","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"smartLockPeriod","type":"uint256"}],"name":"SetLockConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"SetMintManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"bool","name":"customLockDays","type":"bool"},{"indexed":true,"internalType":"uint256","name":"slot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountToLock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"senderLockDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"checkOldSlot","type":"uint256"}],"name":"SmartLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"checkOldSlot","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isLockedCustomSlot","type":"bool"}],"name":"SmartLockCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"slot","type":"uint256"}],"name":"SmartLockReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"UpdateOperator","type":"event"},{"inputs":[],"name":"booster","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkOldSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"customLockAccounts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"customLockDays","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"customLockMinAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"customLockSlots","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"_stakeAddress","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_stakeAddress","type":"address"}],"name":"deposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"_stakeAddress","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositCustomLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"earmarkPid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCustomLockAccounts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getCustomLockSlotsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastLockAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDays","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedCustomSlots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_oldCustomLockAccounts","type":"address[]"},{"internalType":"uint256[]","name":"_oldCustomLockSlotLengths","type":"uint256[]"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oldDepositor","outputs":[{"internalType":"contract WomDepositor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"releaseCustomLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"releasedCustomSlots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_booster","type":"address"},{"internalType":"uint256","name":"_earmarkPid","type":"uint256"}],"name":"setBooster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_lockDays","type":"uint256"},{"internalType":"uint256","name":"_minAmount","type":"uint256"}],"name":"setCustomLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockDays","type":"uint256"},{"internalType":"uint256","name":"_smartLockPeriod","type":"uint256"}],"name":"setLockConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mintManager","type":"address"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setMintManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slotEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"smartLockPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"staker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateMinterOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wom","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]