YieldEthStakingLido lacks a limit on the max stake amount, which may result in the unstake exceeding MAX_STETH_WITHDRAWAL_AMOUNT, resulting in the token not being retrieved.
mediumLines of code
Vulnerability details
Vulnerability details
in YieldEthStakingLido
The main processes are as follows:
- stake() -> stEth balnace increase
- unstake () -> unstETH.requestWithdrawals(allShares)
- repay() -> unstETH.claimWithdrawal()
The issue is the second step, unstETH is with a maximum withdrawal limit: MAX_STETH_WITHDRAWAL_AMOUNT
soliditycontract YieldEthStakingLido is YieldStakingBase { ... function protocolRequestWithdrawal(YieldStakeData storage sd) internal virtual override { IYieldAccount yieldAccount = IYieldAccount(yieldAccounts[msg.sender]); uint256[] memory requestAmounts = new uint256[](1); requestAmounts[0] = sd.withdrawAmount; bytes memory result = yieldAccount.execute( address(unstETH), @> abi.encodeWithSelector(IUnstETH.requestWithdrawals.selector, requestAmounts, address(yieldAccount)) ); uint256[] memory withdrawReqIds = abi.decode(result, (uint256[])); require(withdrawReqIds.length > 0 && withdrawReqIds[0] > 0, Errors.YIELD_ETH_WITHDRAW_FAILED); sd.withdrawReqId = withdrawReqIds[0]; }
https://docs.lido.fi/contracts/withdrawal-queue-erc721/#requestwithdrawals
each amount in _amounts must be greater than or equal to MIN_STETH_WITHDRAWAL_AMOUNT and lower than or equal to MAX_STETH_WITHDRAWAL_AMOUNT
current configuration: https://github.com/lidofinance/lido-dao/blob/master/contracts/0.8.9/WithdrawalQueue.sol#L57
solidity/// @notice maximum amount of stETH that is possible to withdraw by a single request /// Prevents accumulating too much funds per single request fulfillment in the future. /// @dev To withdraw larger amounts, it's recommended to split it to several requests uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1000 * 1e18;
lido suggests that if it exceeds this value, it needs to be taken in batches, but YieldEthStakingLido.sol can only be taken at once!
So if the stake amount exceeds this value, it will not be possible to unstake() and the token will be locked in the contract
Assumption.
leverageFactor = 50000 , eth price = $2500.
Then as long as the value of the nft is greater than: 1000 * $2500 / 5 = $500,000 it will be possible to stake() more than MAX_STETH_WITHDRAWAL_AMOUNT.
After that, when the user performs an unstake() it will fail, causing the token to be locked.
Impact
Excessive amount of stake will result in failure to unstake().
Recommended Mitigation
YieldStakingBase add method checkStakeAmount
Each sub contract override implements its own maximum amount limit, YieldEthStakingLido suggests a maximum of MAX_STETH_WITHDRAWAL_AMOUNT / 2.
Assessed type
Context
