编译器
0.8.21+commit.d9974bed
文件 1 的 23:AssetsVault.sol
pragma solidity 0.8.21;
import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
contract AssetsVault {
address public stoneVault;
address public strategyController;
modifier onlyPermit() {
require(
stoneVault == msg.sender || strategyController == msg.sender,
"not permit"
);
_;
}
constructor(address _stoneVault, address _strategyController) {
require(
_stoneVault != address(0) && _strategyController != address(0),
"ZERO ADDRESS"
);
stoneVault = _stoneVault;
strategyController = _strategyController;
}
function deposit() external payable {
require(msg.value != 0, "too small");
}
function withdraw(address _to, uint256 _amount) external onlyPermit {
TransferHelper.safeTransferETH(_to, _amount);
}
function setNewVault(address _vault) external onlyPermit {
stoneVault = _vault;
}
function getBalance() external view returns (uint256 amount) {
amount = address(this).balance;
}
receive() external payable {}
}
文件 2 的 23: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 的 23:EigenLSTRestaking.sol
pragma solidity 0.8.21;
import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {EigenStrategy} from "../EigenStrategy.sol";
import {SwappingAggregator} from "../SwappingAggregator.sol";
import {IStrategyManager} from "../../interfaces/IStrategyManager.sol";
import {IDelegationManager} from "../../interfaces/IDelegationManager.sol";
import {IEigenStrategy} from "../../interfaces/IEigenStrategy.sol";
import {ILido} from "../../interfaces/ILido.sol";
import {ILidoWithdrawalQueue} from "../../interfaces/ILidoWithdrawalQueue.sol";
contract EigenLSTRestaking is EigenStrategy {
using EnumerableSet for EnumerableSet.Bytes32Set;
address public immutable tokenAddr;
address public immutable strategyManager;
address public immutable delegationManager;
address public immutable eigenStrategy;
address public immutable LidoWithdrawalQueue;
address payable public immutable SWAPPING;
address public referral;
address public eigenOperator;
bool public buyOnDex;
bool public sellOnDex;
bytes32[] public withdrawals;
mapping(bytes32 => uint256) public withdrawingShares;
EnumerableSet.Bytes32Set private withdrawalRootsSet;
event Swap(address from, address to, uint256 sent, uint256 received);
event DepositIntoStrategy(address strategy, address token, uint256 amount);
event DelegateTo(address operator);
event WithdrawalQueued(bytes32 withdrawalRoot);
event WithdrawalCompleted(
IDelegationManager.Withdrawal withdrawal,
bytes32 root
);
event SetEigenOperator(address oldOperator, address newOperator);
event SetWithdrawQueueParams(uint256 length, uint256 amount);
event SetRouter(bool buyOnDex, bool sellOnDex);
event SetReferral(address oldAddr, address newAddr);
event Invoked(address indexed targetAddress, uint256 value, bytes data);
constructor(
address payable _controller,
address _tokenAddr,
address _lidoWithdrawalQueue,
address _strategyManager,
address _delegationManager,
address _eigenStrategy,
address payable _swap,
string memory _name
) EigenStrategy(_controller, _name) {
require(
_tokenAddr != address(0) &&
_lidoWithdrawalQueue != address(0) &&
_strategyManager != address(0) &&
_delegationManager != address(0) &&
_eigenStrategy != address(0) &&
_swap != address(0),
"ZERO ADDRESS"
);
tokenAddr = _tokenAddr;
LidoWithdrawalQueue = _lidoWithdrawalQueue;
strategyManager = _strategyManager;
delegationManager = _delegationManager;
eigenStrategy = _eigenStrategy;
SWAPPING = _swap;
}
function deposit() public payable override onlyController notAtSameBlock {
require(msg.value != 0, "zero value");
latestUpdateTime = block.timestamp;
}
function withdraw(
uint256 _amount
)
public
override
onlyController
notAtSameBlock
returns (uint256 actualAmount)
{
actualAmount = _withdraw(_amount);
}
function instantWithdraw(
uint256 _amount
) public override onlyController returns (uint256 actualAmount) {
actualAmount = _withdraw(_amount);
}
function _withdraw(
uint256 _amount
) internal returns (uint256 actualAmount) {
require(_amount != 0, "zero value");
require(_amount <= address(this).balance, "not enough");
actualAmount = _amount;
TransferHelper.safeTransferETH(controller, actualAmount);
latestUpdateTime = block.timestamp;
}
function clear() public override onlyController returns (uint256 amount) {
uint256 balance = address(this).balance;
if (balance != 0) {
TransferHelper.safeTransferETH(controller, balance);
amount = balance;
}
}
function getAllValue() public override returns (uint256 value) {
value = getInvestedValue();
}
function getInvestedValue() public override returns (uint256 value) {
uint256 etherValue = address(this).balance;
uint256 tokenValue = IERC20(tokenAddr).balanceOf(address(this));
(, uint256 claimableValue, uint256 pendingValue) = checkPendingAssets();
uint256 eigenValue = getRestakingValue();
uint256 unstakingValue = getUnstakingValue();
value =
etherValue +
tokenValue +
claimableValue +
pendingValue +
eigenValue +
unstakingValue;
}
function depositIntoStrategy(
uint256 _amount
) external onlyOwner returns (uint256 shares) {
TransferHelper.safeApprove(tokenAddr, strategyManager, _amount);
shares = IStrategyManager(strategyManager).depositIntoStrategy(
eigenStrategy,
tokenAddr,
_amount
);
emit DepositIntoStrategy(eigenStrategy, tokenAddr, _amount);
}
function delegateTo(
IDelegationManager.SignatureWithExpiry
memory _approverSignatureAndExpiry,
bytes32 _approverSalt
) external onlyOwner {
IDelegationManager(delegationManager).delegateTo(
eigenOperator,
_approverSignatureAndExpiry,
_approverSalt
);
emit DelegateTo(eigenOperator);
}
function undelegate()
external
onlyOwner
returns (bytes32[] memory withdrawalRoots)
{
require(
IEigenStrategy(eigenStrategy).shares(address(this)) == 0,
"active shares"
);
withdrawalRoots = IDelegationManager(delegationManager).undelegate(
address(this)
);
}
function queueWithdrawals(
IDelegationManager.QueuedWithdrawalParams[]
calldata _queuedWithdrawalParams
) external onlyOwner returns (bytes32[] memory withdrawalRoots) {
require(
_queuedWithdrawalParams.length == 1 &&
_queuedWithdrawalParams[0].shares.length == 1 &&
_queuedWithdrawalParams[0].strategies.length == 1,
"invalid length"
);
withdrawalRoots = IDelegationManager(delegationManager)
.queueWithdrawals(_queuedWithdrawalParams);
uint256 length = withdrawalRoots.length;
require(length == 1, "invalid root length");
bytes32 root = withdrawalRoots[0];
withdrawalRootsSet.add(root);
withdrawingShares[root] = _queuedWithdrawalParams[0].shares[0];
emit WithdrawalQueued(root);
}
function completeQueuedWithdrawal(
IDelegationManager.Withdrawal calldata _withdrawal,
IERC20[] calldata _tokens,
uint256 _middlewareTimesIndex,
bool _receiveAsTokens
) external onlyOwner {
IDelegationManager(delegationManager).completeQueuedWithdrawal(
_withdrawal,
_tokens,
_middlewareTimesIndex,
_receiveAsTokens
);
bytes32 root = calculateWithdrawalRoot(_withdrawal);
withdrawingShares[root] = 0;
withdrawalRootsSet.remove(root);
emit WithdrawalCompleted(_withdrawal, root);
}
function swapToToken(
uint256 _amount
) external onlyOwner returns (uint256 tokenAmount) {
require(_amount != 0, "zero");
require(_amount <= address(this).balance, "exceed balance");
if (!buyOnDex) {
tokenAmount = ILido(tokenAddr).submit{value: _amount}(referral);
} else {
tokenAmount = SwappingAggregator(SWAPPING).swap{value: _amount}(
tokenAddr,
_amount,
false
);
}
emit Swap(address(0), tokenAddr, _amount, tokenAmount);
}
function swapToEther(
uint256 _amount
) external onlyOwner returns (uint256 etherAmount) {
IERC20 token = IERC20(tokenAddr);
require(_amount != 0, "zero");
require(_amount <= token.balanceOf(address(this)), "exceed balance");
if (!sellOnDex) {
token.approve(LidoWithdrawalQueue, _amount);
ILidoWithdrawalQueue withdrawalQueue = ILidoWithdrawalQueue(
LidoWithdrawalQueue
);
uint256 maxAmountPerRequest = withdrawalQueue
.MAX_STETH_WITHDRAWAL_AMOUNT();
uint256 minAmountPerRequest = withdrawalQueue
.MIN_STETH_WITHDRAWAL_AMOUNT();
uint256[] memory amounts;
if (_amount <= maxAmountPerRequest) {
amounts = new uint256[](1);
amounts[0] = _amount;
} else {
uint256 length = _amount / maxAmountPerRequest + 1;
uint256 remainder = _amount % maxAmountPerRequest;
if (remainder >= minAmountPerRequest) {
amounts = new uint256[](length);
amounts[length - 1] = remainder;
} else {
amounts = new uint256[](length - 1);
}
uint256 i;
for (i; i < length - 1; i++) {
amounts[i] = maxAmountPerRequest;
}
}
uint256[] memory ids = withdrawalQueue.requestWithdrawals(
amounts,
address(this)
);
require(ids.length != 0, "Lido request withdrawal error");
etherAmount = _amount;
} else {
TransferHelper.safeApprove(tokenAddr, SWAPPING, _amount);
etherAmount = SwappingAggregator(SWAPPING).swap(
tokenAddr,
_amount,
true
);
}
emit Swap(tokenAddr, address(0), _amount, etherAmount);
}
function setRouter(bool _buyOnDex, bool _sellOnDex) external onlyOwner {
buyOnDex = _buyOnDex;
sellOnDex = _sellOnDex;
emit SetRouter(_buyOnDex, _sellOnDex);
}
function setEigenOperator(address _operator) external onlyOwner {
require(_operator != address(0), "ZERO ADDR");
require(
IDelegationManager(delegationManager).isOperator(_operator),
"not operator"
);
emit SetEigenOperator(eigenOperator, _operator);
eigenOperator = _operator;
}
function setReferral(address _referral) external onlyOwner {
require(_referral != address(0), "ZERO ADDR");
emit SetReferral(referral, _referral);
referral = _referral;
}
function claimPendingAssets(uint256[] memory _ids) external onlyOwner {
uint256 length = _ids.length;
require(length != 0, "invalid length");
for (uint256 i; i < length; i++) {
if (_ids[i] == 0) continue;
ILidoWithdrawalQueue(LidoWithdrawalQueue).claimWithdrawal(_ids[i]);
}
}
function claimAllPendingAssets() external onlyOwner {
(uint256[] memory ids, , ) = checkPendingAssets();
uint256 length = ids.length;
for (uint256 i; i < length; i++) {
if (ids[i] == 0) continue;
ILidoWithdrawalQueue(LidoWithdrawalQueue).claimWithdrawal(ids[i]);
}
}
function checkPendingAssets()
public
returns (
uint256[] memory ids,
uint256 totalClaimable,
uint256 totalPending
)
{
ILidoWithdrawalQueue queue = ILidoWithdrawalQueue(LidoWithdrawalQueue);
uint256[] memory allIds = queue.getWithdrawalRequests(address(this));
if (allIds.length == 0) {
return (new uint256[](0), 0, 0);
}
ids = new uint256[](allIds.length);
ILidoWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = queue
.getWithdrawalStatus(allIds);
uint256 j;
uint256 length = statuses.length;
for (uint256 i; i < length; i++) {
ILidoWithdrawalQueue.WithdrawalRequestStatus
memory status = statuses[i];
if (status.isClaimed) {
continue;
}
if (status.isFinalized) {
ids[j++] = allIds[i];
totalClaimable = totalClaimable + status.amountOfStETH;
} else {
totalPending = totalPending + status.amountOfStETH;
}
}
assembly {
mstore(ids, j)
}
}
function getRestakingValue() public view returns (uint256 value) {
value = IEigenStrategy(eigenStrategy).userUnderlyingView(address(this));
}
function getUnstakingValue() public view returns (uint256 value) {
uint256 length = withdrawalRootsSet.length();
uint256 i;
for (i; i < length; i++) {
value += IEigenStrategy(eigenStrategy).sharesToUnderlyingView(
withdrawingShares[withdrawalRootsSet.at(i)]
);
}
}
function getWithdrawalRoots() public view returns (bytes32[] memory roots) {
uint256 length = withdrawalRootsSet.length();
roots = new bytes32[](length);
for (uint256 i; i < length; i++) {
roots[i] = withdrawalRootsSet.at(i);
}
}
function calculateWithdrawalRoot(
IDelegationManager.Withdrawal memory withdrawal
) public pure returns (bytes32) {
return keccak256(abi.encode(withdrawal));
}
function invoke(
address target,
bytes memory data
) external onlyOwner returns (bytes memory result) {
require(target != tokenAddr, "not permit");
bool success;
(success, result) = target.call{value: 0}(data);
if (!success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
emit Invoked(target, 0, data);
}
receive() external payable {}
}
文件 4 的 23:EigenStrategy.sol
pragma solidity 0.8.21;
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {StrategyController} from "../strategies/StrategyController.sol";
abstract contract EigenStrategy is Ownable2Step {
address payable public immutable controller;
uint256 public latestUpdateTime;
uint256 public bufferTime = 12;
string public name;
modifier notAtSameBlock() {
require(
latestUpdateTime + bufferTime <= block.timestamp,
"at the same block"
);
_;
}
event TransferGovernance(address oldOwner, address newOwner);
constructor(address payable _controller, string memory _name) {
require(_controller != address(0), "ZERO ADDRESS");
controller = _controller;
name = _name;
}
modifier onlyController() {
require(controller == msg.sender, "not controller");
_;
}
function deposit() public payable virtual onlyController notAtSameBlock {}
function withdraw(
uint256 _amount
)
public
virtual
onlyController
notAtSameBlock
returns (uint256 actualAmount)
{}
function instantWithdraw(
uint256 _amount
)
public
virtual
onlyController
notAtSameBlock
returns (uint256 actualAmount)
{}
function clear() public virtual onlyController returns (uint256 amount) {}
function execPendingRequest(
uint256 _amount
) public virtual returns (uint256 amount) {}
function getAllValue() public virtual returns (uint256 value) {}
function getPendingValue() public virtual returns (uint256 value) {}
function getInvestedValue() public virtual returns (uint256 value) {}
function checkPendingStatus()
public
virtual
returns (uint256 pending, uint256 executable)
{}
function setBufferTime(uint256 _time) external onlyOwner {
bufferTime = _time;
}
}
文件 5 的 23:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[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;
}
}
文件 6 的 23:IDelegationManager.sol
pragma solidity 0.8.21;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IDelegationManager {
struct SignatureWithExpiry {
bytes signature;
uint256 expiry;
}
struct QueuedWithdrawalParams {
address[] strategies;
uint256[] shares;
address withdrawer;
}
struct Withdrawal {
address staker;
address delegatedTo;
address withdrawer;
uint256 nonce;
uint32 startBlock;
address[] strategies;
uint256[] shares;
}
event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal);
function delegateTo(
address operator,
SignatureWithExpiry memory approverSignatureAndExpiry,
bytes32 approverSalt
) external;
function undelegate(
address staker
) external returns (bytes32[] memory withdrawalRoots);
function queueWithdrawals(
QueuedWithdrawalParams[] calldata queuedWithdrawalParams
) external returns (bytes32[] memory);
function completeQueuedWithdrawal(
Withdrawal calldata withdrawal,
IERC20[] calldata tokens,
uint256 middlewareTimesIndex,
bool receiveAsTokens
) external;
function isOperator(address operator) external view returns (bool);
}
文件 7 的 23:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 8 的 23:IEigenStrategy.sol
pragma solidity 0.8.21;
interface IEigenStrategy {
function userUnderlyingView(address user) external view returns (uint256);
function shares(address user) external view returns (uint256);
function sharesToUnderlyingView(
uint256 amountShares
) external view returns (uint256);
}
文件 9 的 23:ILido.sol
pragma solidity 0.8.21;
interface ILido {
function submit(address _referral) external payable returns (uint256);
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
文件 10 的 23:ILidoWithdrawalQueue.sol
pragma solidity 0.8.21;
interface ILidoWithdrawalQueue {
struct WithdrawalRequestStatus {
uint256 amountOfStETH;
uint256 amountOfShares;
address owner;
uint256 timestamp;
bool isFinalized;
bool isClaimed;
}
function MAX_STETH_WITHDRAWAL_AMOUNT() external view returns (uint256);
function MIN_STETH_WITHDRAWAL_AMOUNT() external view returns (uint256);
function getWithdrawalRequests(
address _owner
) external view returns (uint256[] memory requestsIds);
function getWithdrawalStatus(
uint256[] calldata _requestIds
) external view returns (WithdrawalRequestStatus[] memory statuses);
function requestWithdrawals(
uint256[] calldata _amounts,
address _owner
) external returns (uint256[] memory requestIds);
function claimWithdrawals(
uint256[] calldata _requestIds,
uint256[] calldata _hints
) external;
function claimWithdrawalsTo(
uint256[] calldata _requestIds,
uint256[] calldata _hints,
address _recipient
) external;
function claimWithdrawal(uint256 _requestId) external;
}
文件 11 的 23:IQuoter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface IQuoter {
function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);
function quoteExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountOut);
function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);
function quoteExactOutputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountOut,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountIn);
}
文件 12 的 23:IStableSwap.sol
pragma solidity 0.8.21;
interface IStableSwap {
function lp_token() external view returns (address);
function coins(uint256 i) external view returns (address);
function get_dy(
int128 i,
int128 j,
uint256 dx
) external view returns (uint256);
function get_dy(
uint256 i,
uint256 j,
uint256 dx
) external view returns (uint256);
function fee() external view returns (uint256);
function admin_fee() external view returns (uint256);
function calc_withdraw_one_coin(
uint256 _token_amount,
int128 i
) external view returns (uint256);
function calc_token_amount(
uint256[2] memory,
bool
) external view returns (uint256);
function remove_liquidity_imbalance(
uint256[2] memory _amounts,
uint256 _max_burn_amount
) external returns (uint256);
function remove_liquidity_one_coin(
uint256 _token_amount,
int128 i,
uint256 _min_amount
) external returns (uint256);
function add_liquidity(
uint256[2] memory amounts,
uint256 min_mint_amount
) external payable returns (uint256);
function exchange(
int128 i,
int128 j,
uint256 dx,
uint256 min_dy
) external payable returns (uint256);
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 min_dy
) external payable returns (uint256);
}
文件 13 的 23:IStrategyManager.sol
pragma solidity 0.8.21;
interface IStrategyManager {
function depositIntoStrategy(
address strategy,
address token,
uint256 amount
) external returns (uint256 shares);
}
文件 14 的 23:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 15 的 23:IUniswapV3SwapCallback.sol
pragma solidity >=0.5.0;
interface IUniswapV3SwapCallback {
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
文件 16 的 23:IWETH9.sol
pragma solidity 0.8.21;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH9 is IERC20 {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 17 的 23:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 18 的 23:Ownable2Step.sol
pragma solidity ^0.8.0;
import "./Ownable.sol";
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
文件 19 的 23:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 20 的 23:Strategy.sol
pragma solidity 0.8.21;
import {StrategyController} from "../strategies/StrategyController.sol";
abstract contract Strategy {
address payable public immutable controller;
address public governance;
uint256 public latestUpdateTime;
uint256 public bufferTime = 12;
string public name;
modifier onlyGovernance() {
require(governance == msg.sender, "not governace");
_;
}
modifier notAtSameBlock() {
require(
latestUpdateTime + bufferTime <= block.timestamp,
"at the same block"
);
_;
}
event TransferGovernance(address oldOwner, address newOwner);
constructor(address payable _controller, string memory _name) {
require(_controller != address(0), "ZERO ADDRESS");
governance = msg.sender;
controller = _controller;
name = _name;
}
modifier onlyController() {
require(controller == msg.sender, "not controller");
_;
}
function deposit() public payable virtual onlyController notAtSameBlock {}
function withdraw(
uint256 _amount
)
public
virtual
onlyController
notAtSameBlock
returns (uint256 actualAmount)
{}
function instantWithdraw(
uint256 _amount
)
public
virtual
onlyController
notAtSameBlock
returns (uint256 actualAmount)
{}
function clear() public virtual onlyController returns (uint256 amount) {}
function execPendingRequest(
uint256 _amount
) public virtual returns (uint256 amount) {}
function getAllValue() public virtual returns (uint256 value) {}
function getPendingValue() public virtual returns (uint256 value) {}
function getInvestedValue() public virtual returns (uint256 value) {}
function checkPendingStatus()
public
virtual
returns (uint256 pending, uint256 executable)
{}
function setGovernance(address governance_) external onlyGovernance {
emit TransferGovernance(governance, governance_);
governance = governance_;
}
function setBufferTime(uint256 _time) external onlyGovernance {
bufferTime = _time;
}
}
文件 21 的 23:StrategyController.sol
pragma solidity 0.8.21;
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import {Strategy} from "./Strategy.sol";
import {AssetsVault} from "../AssetsVault.sol";
contract StrategyController {
using EnumerableSet for EnumerableSet.AddressSet;
uint256 internal constant ONE_HUNDRED_PERCENT = 1e6;
address public stoneVault;
address payable public immutable assetsVault;
EnumerableSet.AddressSet private strategies;
mapping(address => uint256) public ratios;
struct StrategyDiff {
address strategy;
bool isDeposit;
uint256 amount;
}
modifier onlyVault() {
require(stoneVault == msg.sender, "not vault");
_;
}
constructor(
address payable _assetsVault,
address[] memory _strategies,
uint256[] memory _ratios
) {
require(_assetsVault != address(0), "ZERO ADDRESS");
uint256 length = _strategies.length;
for (uint256 i; i < length; i++) {
require(_strategies[i] != address(0), "ZERO ADDRESS");
}
stoneVault = msg.sender;
assetsVault = _assetsVault;
_initStrategies(_strategies, _ratios);
}
function forceWithdraw(
uint256 _amount
) external onlyVault returns (uint256 actualAmount) {
uint256 balanceBeforeRepay = address(this).balance;
if (balanceBeforeRepay >= _amount) {
_repayToVault();
actualAmount = _amount;
} else {
actualAmount =
_forceWithdraw(_amount - balanceBeforeRepay) +
balanceBeforeRepay;
}
}
function setStrategies(
address[] memory _strategies,
uint256[] memory _ratios
) external onlyVault {
_setStrategies(_strategies, _ratios);
}
function addStrategy(address _strategy) external onlyVault {
require(!strategies.contains(_strategy), "already exist");
strategies.add(_strategy);
}
function rebaseStrategies(
uint256 _in,
uint256 _out
) external payable onlyVault {
_rebase(_in, _out);
}
function destroyStrategy(address _strategy) external onlyVault {
_destoryStrategy(_strategy);
}
function _rebase(uint256 _in, uint256 _out) internal {
require(_in == 0 || _out == 0, "only deposit or withdraw");
if (_in != 0) {
AssetsVault(assetsVault).withdraw(address(this), _in);
}
uint256 total = getAllStrategyValidValue();
if (total < _out) {
total = 0;
} else {
total = total + _in - _out;
}
uint256 length = strategies.length();
StrategyDiff[] memory diffs = new StrategyDiff[](length);
uint256 head;
uint256 tail = length - 1;
for (uint i; i < length; i++) {
address strategy = strategies.at(i);
if (ratios[strategy] == 0) {
_clearStrategy(strategy, true);
continue;
}
uint256 newPosition = (total * ratios[strategy]) /
ONE_HUNDRED_PERCENT;
uint256 position = getStrategyValidValue(strategy);
if (newPosition < position) {
diffs[head] = StrategyDiff(
strategy,
false,
position - newPosition
);
head++;
} else if (newPosition > position) {
diffs[tail] = StrategyDiff(
strategy,
true,
newPosition - position
);
if (tail != 0) {
tail--;
}
}
}
length = diffs.length;
for (uint256 i; i < length; i++) {
StrategyDiff memory diff = diffs[i];
if (diff.amount == 0) {
continue;
}
if (diff.isDeposit) {
if (address(this).balance < diff.amount) {
diff.amount = address(this).balance;
}
_depositToStrategy(diff.strategy, diff.amount);
} else {
_withdrawFromStrategy(diff.strategy, diff.amount);
}
}
_repayToVault();
}
function _repayToVault() internal {
if (address(this).balance != 0) {
TransferHelper.safeTransferETH(assetsVault, address(this).balance);
}
}
function _depositToStrategy(address _strategy, uint256 _amount) internal {
Strategy(_strategy).deposit{value: _amount}();
}
function _withdrawFromStrategy(
address _strategy,
uint256 _amount
) internal {
Strategy(_strategy).withdraw(_amount);
}
function _forceWithdraw(
uint256 _amount
) internal returns (uint256 actualAmount) {
uint256 length = strategies.length();
uint256 allRatios;
for (uint i; i < length; i++) {
address strategy = strategies.at(i);
allRatios += ratios[strategy];
}
for (uint i; i < length; i++) {
address strategy = strategies.at(i);
uint256 withAmount = (_amount * ratios[strategy]) / allRatios;
if (withAmount != 0) {
actualAmount =
Strategy(strategy).instantWithdraw(withAmount) +
actualAmount;
}
}
_repayToVault();
}
function getStrategyValue(
address _strategy
) public returns (uint256 _value) {
return Strategy(_strategy).getAllValue();
}
function getStrategyValidValue(
address _strategy
) public returns (uint256 _value) {
return Strategy(_strategy).getInvestedValue();
}
function getStrategyPendingValue(
address _strategy
) public returns (uint256 _value) {
return Strategy(_strategy).getPendingValue();
}
function getAllStrategiesValue() public returns (uint256 _value) {
uint256 length = strategies.length();
for (uint i; i < length; i++) {
_value = _value + getStrategyValue(strategies.at(i));
}
}
function getAllStrategyValidValue() public returns (uint256 _value) {
uint256 length = strategies.length();
for (uint i; i < length; i++) {
_value = _value + getStrategyValidValue(strategies.at(i));
}
}
function getAllStrategyPendingValue() public returns (uint256 _value) {
uint256 length = strategies.length();
for (uint i; i < length; i++) {
_value = _value + getStrategyPendingValue(strategies.at(i));
}
}
function getStrategies()
public
view
returns (address[] memory addrs, uint256[] memory portions)
{
uint256 length = strategies.length();
addrs = new address[](length);
portions = new uint256[](length);
for (uint256 i; i < length; i++) {
address addr = strategies.at(i);
addrs[i] = addr;
portions[i] = ratios[addr];
}
}
function _initStrategies(
address[] memory _strategies,
uint256[] memory _ratios
) internal {
require(_strategies.length == _ratios.length, "invalid length");
uint256 totalRatio;
uint256 length = _strategies.length;
for (uint i; i < length; i++) {
strategies.add(_strategies[i]);
ratios[_strategies[i]] = _ratios[i];
totalRatio = totalRatio + _ratios[i];
}
require(totalRatio <= ONE_HUNDRED_PERCENT, "exceed 100%");
}
function _setStrategies(
address[] memory _strategies,
uint256[] memory _ratios
) internal {
uint256 length = _strategies.length;
require(length == _ratios.length, "invalid length");
uint256 oldLength = strategies.length();
for (uint i; i < oldLength; i++) {
ratios[strategies.at(i)] = 0;
}
uint256 totalRatio;
for (uint i; i < length; i++) {
require(
Strategy(_strategies[i]).controller() == address(this),
"controller mismatch"
);
strategies.add(_strategies[i]);
ratios[_strategies[i]] = _ratios[i];
totalRatio = totalRatio + _ratios[i];
}
require(totalRatio <= ONE_HUNDRED_PERCENT, "exceed 100%");
}
function clearStrategy(address _strategy) public onlyVault {
_clearStrategy(_strategy, false);
}
function _clearStrategy(address _strategy, bool _isRebase) internal {
Strategy(_strategy).clear();
if (!_isRebase) {
_repayToVault();
}
}
function _destoryStrategy(address _strategy) internal {
require(_couldDestroyStrategy(_strategy), "still active");
strategies.remove(_strategy);
_repayToVault();
}
function _couldDestroyStrategy(
address _strategy
) internal returns (bool status) {
return
ratios[_strategy] == 0 && Strategy(_strategy).getAllValue() < 1e4;
}
function setNewVault(address _vault) external onlyVault {
stoneVault = _vault;
}
receive() external payable {}
}
文件 22 的 23:SwappingAggregator.sol
pragma solidity 0.8.21;
import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IQuoter} from "@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IStableSwap} from "../interfaces/IStableSwap.sol";
import {IWETH9} from "../interfaces/IWETH9.sol";
contract SwappingAggregator is ReentrancyGuard {
uint256 internal constant MULTIPLIER = 1e18;
uint256 internal constant ONE_HUNDRED_PERCENT = 1e6;
address internal immutable QUOTER =
0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;
address internal immutable ROUTER =
0xE592427A0AEce92De3Edee1F18E0157C05861564;
address internal immutable WETH9;
address internal immutable CURVE_ETH =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
mapping(address => address) public uniV3Pools;
mapping(address => address) public curvePools;
mapping(address => uint8) public curvePoolType;
mapping(address => uint256) public slippage;
mapping(address => uint24) public fees;
address public governance;
event SetSlippage(
address indexed token,
uint256 oldSlippage,
uint256 newSlippage
);
event TransferGovernance(address oldAddr, address newAddr);
modifier onlyGovernance() {
require(governance == msg.sender, "not governace");
_;
}
enum DEX_TYPE {
UNISWAPV3,
CURVE
}
constructor(
address _wETH,
address[] memory _tokens,
address[] memory _uniPools,
address[] memory _curvePools,
uint8[] memory _curvePoolTypes,
uint256[] memory _slippages,
uint24[] memory _fees
) {
uint256 length = _tokens.length;
require(
length == _uniPools.length &&
length == _curvePools.length &&
length == _curvePoolTypes.length,
"invalid length"
);
require(_wETH != address(0), "ZERO ADDRESS");
for (uint256 i; i < length; i++) {
require(
_tokens[i] != address(0) &&
_uniPools[i] != address(0) &&
_curvePools[i] != address(0),
"ZERO ADDRESS"
);
uniV3Pools[_tokens[i]] = _uniPools[i];
curvePools[_tokens[i]] = _curvePools[i];
curvePoolType[_curvePools[i]] = _curvePoolTypes[i];
slippage[_tokens[i]] = _slippages[i];
fees[_tokens[i]] = _fees[i];
}
governance = msg.sender;
WETH9 = _wETH;
}
function swap(
address _token,
uint256 _amount,
bool _isSell
) external payable returns (uint256 amount) {
if (
uniV3Pools[_token] == address(0) && curvePools[_token] == address(0)
) {
return 0;
}
(DEX_TYPE dex, uint256 expected) = getBestRouter(
_token,
_amount,
_isSell
);
if (!_isSell) {
require(_amount == msg.value, "wrong value");
}
if (expected == 0) {
return 0;
}
if (dex == DEX_TYPE.UNISWAPV3) {
amount = swapOnUniV3(_token, _amount, _isSell);
} else {
amount = swapOnCurve(_token, _amount, _isSell);
}
}
function swapOnUniV3(
address _token,
uint256 _amount,
bool _isSell
) internal nonReentrant returns (uint256 amount) {
uint256 minReceived = calMinimumReceivedAmount(
_amount,
slippage[_token]
);
address pool = uniV3Pools[_token];
if (_isSell) {
TransferHelper.safeTransferFrom(
_token,
msg.sender,
address(this),
_amount
);
TransferHelper.safeApprove(_token, ROUTER, _amount);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: _token,
tokenOut: WETH9,
fee: fees[_token],
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
amountOutMinimum: minReceived,
sqrtPriceLimitX96: 0
});
amount = ISwapRouter(ROUTER).exactInputSingle(params);
IWETH9(WETH9).withdraw(amount);
TransferHelper.safeTransferETH(msg.sender, address(this).balance);
} else {
IWETH9(WETH9).deposit{value: msg.value}();
TransferHelper.safeApprove(
WETH9,
ROUTER,
IWETH9(WETH9).balanceOf(address(this))
);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: WETH9,
tokenOut: _token,
fee: fees[_token],
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
amountOutMinimum: minReceived,
sqrtPriceLimitX96: 0
});
amount = ISwapRouter(ROUTER).exactInputSingle(params);
TransferHelper.safeTransfer(
_token,
msg.sender,
IERC20(_token).balanceOf(address(this))
);
}
}
function swapOnCurve(
address _token,
uint256 _amount,
bool _isSell
) internal nonReentrant returns (uint256 amount) {
uint256 minReceived = calMinimumReceivedAmount(
_amount,
slippage[_token]
);
address pool = curvePools[_token];
(uint256 e, uint256 t, bool wrapped) = getCurveCoinIndex(_token);
uint8 poolType = curvePoolType[pool];
if (_isSell) {
TransferHelper.safeTransferFrom(
_token,
msg.sender,
address(this),
_amount
);
TransferHelper.safeApprove(_token, pool, _amount);
if (poolType == 0) {
amount = IStableSwap(pool).exchange(
int128(int256(t)),
int128(int256(e)),
_amount,
minReceived
);
} else {
amount = IStableSwap(pool).exchange(t, e, _amount, minReceived);
}
if (wrapped) {
IWETH9 weth = IWETH9(WETH9);
weth.withdraw(weth.balanceOf(address(this)));
}
TransferHelper.safeTransferETH(msg.sender, address(this).balance);
} else {
if (poolType == 0) {
if (!wrapped) {
amount = IStableSwap(pool).exchange{value: _amount}(
int128(int256(e)),
int128(int256(t)),
_amount,
minReceived
);
} else {
IWETH9 weth = IWETH9(WETH9);
weth.deposit{value: _amount}();
weth.approve(pool, _amount);
amount = IStableSwap(pool).exchange(
int128(int256(e)),
int128(int256(t)),
_amount,
minReceived
);
}
} else {
if (!wrapped) {
amount = IStableSwap(pool).exchange{value: _amount}(
e,
t,
_amount,
minReceived
);
} else {
IWETH9 weth = IWETH9(WETH9);
weth.deposit{value: _amount}();
weth.approve(pool, _amount);
amount = IStableSwap(pool).exchange(
e,
t,
_amount,
minReceived
);
}
}
TransferHelper.safeTransfer(
_token,
msg.sender,
IERC20(_token).balanceOf(address(this))
);
}
}
function getBestRouter(
address _token,
uint256 _amount,
bool _isSell
) public returns (DEX_TYPE dex, uint256 out) {
uint256 uniV3Out = getUniV3Out(_token, _amount, _isSell);
uint256 curveOut = getCurveOut(_token, _amount, _isSell);
return
uniV3Out > curveOut
? (DEX_TYPE.UNISWAPV3, uniV3Out)
: (DEX_TYPE.CURVE, curveOut);
}
function getUniV3Out(
address _token,
uint256 _amount,
bool _isSell
) public returns (uint256 out) {
if (uniV3Pools[_token] == address(0)) {
return 0;
}
if (_isSell) {
out = IQuoter(QUOTER).quoteExactInputSingle(
_token,
WETH9,
fees[_token],
_amount,
0
);
} else {
out = IQuoter(QUOTER).quoteExactInputSingle(
WETH9,
_token,
fees[_token],
_amount,
0
);
}
}
function getCurveOut(
address _token,
uint256 _amount,
bool _isSell
) public returns (uint256 out) {
address poolAddr = curvePools[_token];
if (poolAddr == address(0)) {
return 0;
}
(uint256 e, uint256 t, ) = getCurveCoinIndex(_token);
IStableSwap pool = IStableSwap(poolAddr);
uint8 poolType = curvePoolType[poolAddr];
if (_isSell) {
if (poolType == 0) {
out = pool.get_dy(
int128(int256(t)),
int128(int256(e)),
_amount
);
} else {
out = pool.get_dy(t, e, _amount);
}
} else {
if (poolType == 0) {
out = pool.get_dy(
int128(int256(e)),
int128(int256(t)),
_amount
);
} else {
out = pool.get_dy(e, t, _amount);
}
}
}
function getCurveCoinIndex(
address _token
) public view returns (uint256 i, uint256 j, bool wrapped) {
IStableSwap pool = IStableSwap(curvePools[_token]);
if (pool.coins(0) == WETH9 || pool.coins(1) == WETH9) {
wrapped = true;
}
if (pool.coins(0) == CURVE_ETH || pool.coins(0) == WETH9) {
i = 0;
j = 1;
} else {
i = 1;
j = 0;
}
}
function calMinimumReceivedAmount(
uint256 _amount,
uint256 _slippage
) internal view returns (uint256 amount) {
amount = (_amount * _slippage) / ONE_HUNDRED_PERCENT;
}
function setSlippage(
address _token,
uint256 _slippage
) external onlyGovernance {
emit SetSlippage(_token, slippage[_token], _slippage);
slippage[_token] = _slippage;
}
function setUniRouter(
address _token,
address _uniPool,
uint256 _slippage,
uint24 _fee
) external onlyGovernance {
require(_token != address(0), "ZERO ADDRESS");
uniV3Pools[_token] = _uniPool;
slippage[_token] = _slippage;
fees[_token] = _fee;
}
function setCurveRouter(
address _token,
address _curvePool,
uint8 _curvePoolType,
uint256 _slippage
) external onlyGovernance {
require(_token != address(0), "ZERO ADDRESS");
curvePools[_token] = _curvePool;
curvePoolType[_curvePool] = _curvePoolType;
slippage[_token] = _slippage;
}
function setNewGovernance(address _governance) external onlyGovernance {
emit TransferGovernance(governance, _governance);
governance = _governance;
}
receive() external payable {}
}
文件 23 的 23:TransferHelper.sol
pragma solidity >=0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
library TransferHelper {
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}
{
"compilationTarget": {
"project:/contracts/strategies/eigen/EigenLSTRestaking.sol": "EigenLSTRestaking"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": []
}
[{"inputs":[{"internalType":"address payable","name":"_controller","type":"address"},{"internalType":"address","name":"_tokenAddr","type":"address"},{"internalType":"address","name":"_lidoWithdrawalQueue","type":"address"},{"internalType":"address","name":"_strategyManager","type":"address"},{"internalType":"address","name":"_delegationManager","type":"address"},{"internalType":"address","name":"_eigenStrategy","type":"address"},{"internalType":"address payable","name":"_swap","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"DelegateTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositIntoStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Invoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":"oldOperator","type":"address"},{"indexed":false,"internalType":"address","name":"newOperator","type":"address"}],"name":"SetEigenOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAddr","type":"address"},{"indexed":false,"internalType":"address","name":"newAddr","type":"address"}],"name":"SetReferral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"buyOnDex","type":"bool"},{"indexed":false,"internalType":"bool","name":"sellOnDex","type":"bool"}],"name":"SetRouter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"length","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetWithdrawQueueParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"sent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"received","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"TransferGovernance","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"address[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}],"indexed":false,"internalType":"struct IDelegationManager.Withdrawal","name":"withdrawal","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"WithdrawalCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalRoot","type":"bytes32"}],"name":"WithdrawalQueued","type":"event"},{"inputs":[],"name":"LidoWithdrawalQueue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWAPPING","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bufferTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyOnDex","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"address[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}],"internalType":"struct IDelegationManager.Withdrawal","name":"withdrawal","type":"tuple"}],"name":"calculateWithdrawalRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"checkPendingAssets","outputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256","name":"totalClaimable","type":"uint256"},{"internalType":"uint256","name":"totalPending","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkPendingStatus","outputs":[{"internalType":"uint256","name":"pending","type":"uint256"},{"internalType":"uint256","name":"executable","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAllPendingAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"claimPendingAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clear","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"address[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}],"internalType":"struct IDelegationManager.Withdrawal","name":"_withdrawal","type":"tuple"},{"internalType":"contract IERC20[]","name":"_tokens","type":"address[]"},{"internalType":"uint256","name":"_middlewareTimesIndex","type":"uint256"},{"internalType":"bool","name":"_receiveAsTokens","type":"bool"}],"name":"completeQueuedWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IDelegationManager.SignatureWithExpiry","name":"_approverSignatureAndExpiry","type":"tuple"},{"internalType":"bytes32","name":"_approverSalt","type":"bytes32"}],"name":"delegateTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delegationManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositIntoStrategy","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eigenOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eigenStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"execPendingRequest","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getInvestedValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPendingValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRestakingValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnstakingValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalRoots","outputs":[{"internalType":"bytes32[]","name":"roots","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"instantWithdraw","outputs":[{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"invoke","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"},{"internalType":"address","name":"withdrawer","type":"address"}],"internalType":"struct IDelegationManager.QueuedWithdrawalParams[]","name":"_queuedWithdrawalParams","type":"tuple[]"}],"name":"queueWithdrawals","outputs":[{"internalType":"bytes32[]","name":"withdrawalRoots","type":"bytes32[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellOnDex","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"setBufferTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"setEigenOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referral","type":"address"}],"name":"setReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_buyOnDex","type":"bool"},{"internalType":"bool","name":"_sellOnDex","type":"bool"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategyManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"swapToEther","outputs":[{"internalType":"uint256","name":"etherAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"swapToToken","outputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenAddr","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":"undelegate","outputs":[{"internalType":"bytes32[]","name":"withdrawalRoots","type":"bytes32[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawals","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawingShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]