Conflicting strategy can lead to reverting the whole completeQueuedWithdrawal()
and temporary freeze user assets from other strategies
#218
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
duplicate-132
satisfactory
satisfies C4 submission criteria; eligible for awards
Lines of code
https://github.com/code-423n4/2023-04-eigenlayer/blob/main/src/contracts/core/StrategyManager.sol#L787-L789
Vulnerability details
A user might want to withdraw funds from multiple strategies at the same time via
queueWithdrawal()
.If any of those strategies revert when trying to complete the withdrawal via
completeQueuedWithdrawal()
, the whole transaction will fail, and no funds from any of the other strategies would be able to be withdrawn.An strategy may fail because of it being malicious (as described on the doc header of
slashQueuedWithdrawal()
), or because it may contain a bug in thewithdraw()
function to prevent this user or any other user from calling it.Impact
Users won't be able to withdraw any of their queued funds from any strategy supposed to be withdrawable after the withdraw period via
completeQueuedWithdrawal()
.Users will be forced to re-stake the asset shares with
receiveAsTokens = false
, create a new queue withdrawal without the conflicting strategy, and wait again for the withdrawal period.This can be considered a temporary freeze of funds, as the users won't be able to dispose of their assets as they should.
A conflicting strategy should not affect the ability of a user to withdraw assets from any other strategy in the platform.
Proof of Concept
StrategyManager::_completeQueuedWithdrawal()
will fail when one of the strategies fail to withdraw the tokens.The conflicting line that can revert is:
queuedWithdrawal.strategies[i].withdraw()
This will prevent tokens from other strategies to be withdrawn.
Link to code
Coded POC
This tests how only one conflicting strategy can revert the whole
completeQueuedWithdrawal()
operation, affecting the withdrawal of the assets from the other strategies.Create a file
src/test/mocks/ReverterWithdraw.sol
like the following to simulate a conflicting strategy:Add this test to
src/test/StrategyManagerUnit.t.sol
and runforge test -m "testCompleteQueuedWithdrawal_FailsWithConflictingStrategy"
.Include
import "../mocks/ReverterWithdraw.sol";
at the start of the file.Tools Used
Manual Review
Recommended Mitigation Steps
Add an
uint256[] indicesToSkip
parameter to_completeQueuedWithdrawal()
to skip conflicting strategies (just like it is already done inslashQueuedWithdrawal()
).Skipped strategies can be re-staked to be retried again later, but the rest of the strategies will be withdrawable immediately.
Assessed type
Token-Transfer
The text was updated successfully, but these errors were encountered: