Insufficient token withdrawal handling in _withdrawTokens
function that can lead to blocked withdrawals and DOS
The issue is that _withdrawTokens
function does not properly handle cases where the total amount of tokens withdrawn from the specified deposits is less than the requested maxTokens
amount. This can potentially lead to unexpected reverts and prevent legitimate token withdrawals.
The issue lies in the _withdrawTokens
function,
https://github.com/Cyfrin/2024-05-Beanstalk-3/blob/662d26f12ee219ee92dc485c06e01a4cb5ee8dfb/protocol/contracts/beanstalk/silo/ConvertFacet.sol#L125-L213
specifically in this part:
https://github.com/Cyfrin/2024-05-Beanstalk-3/blob/662d26f12ee219ee92dc485c06e01a4cb5ee8dfb/protocol/contracts/beanstalk/silo/ConvertFacet.sol#L201-L203
This require
statement checks if the total amount of tokens withdrawn i.e (a.active.tokens
) is exactly equal to the requested maxTokens
amount.
Albeit, it's possible that there can be scenarios where the specified deposits do not have enough non-germinating tokens to reach the maxTokens
amount. In such cases, the function will revert with the error message "Convert: Not enough tokens removed", even though it has legitimately withdrawn all available tokens from the given deposits.
The issue is valid because there's no consideration of the possibility of having insufficient tokens in the deposits to fulfill the exact maxTokens
amount. It assumes that the specified deposits will always have enough tokens to meet the requested withdrawal amount which may not always be so.
As a result of this,
Legitimate token withdrawals may be blocked if the specified deposits do not have enough non-germinating tokens to reach the maxTokens
amount, even though all available tokens have been withdrawn and users will be unable to convert their deposits if the _withdrawTokens
function reverts due to insufficient tokens, even when they have provided all available deposits.
Additionally, in can possibly disallow users from executing the convert
function in certain scenarios.
Modify the require
statement in the _withdrawTokens
function to handle cases where less than maxTokens
can be legitimately withdrawn due to deposit constraints.
We tried to come up with modification that will work and we think this will do:
https://github.com/your-repo/ConvertFacet.sol#L201-L204
This modification introduces an additional condition to the require
statement:
If a.active.tokens
equals maxTokens
, it means the exact requested amount has been withdrawn, and the function can proceed.
If i
has reached stems.length
(all deposits have been processed) and a.active.tokens
is still less than maxTokens
, it means there are not enough non-germinating deposits to fulfill the requested amount. In this case, the function should also proceed since it has withdrawn all available tokens.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.