The maxWithdrawal() function of V3Vault calculates the maximum amount of underlying tokens an account can withdraw based on the shares it owns.
The initial problem with maxWithdrawal() and V3Vault overall was that they were not implemented according to the specs of ERC-4626 standard as outlined in the original issue. In the case of maxWithdrawal() it did not consider the following part of the spec:
MUST factor in both global and user-specific limits, like if withdrawals are entirely disabled (even temporarily) it MUST return 0.
In order to remediate the issue and make the V3Vault ERC-4626 compliant, protocol devs prepared the following PR, where maxWithdrawal() was refactored so that it includes the actual daily limit that is applied when withdrawing assets:
This means that maxWithdraw() improperly converts balance a second time and will overinflate the result, especially when debtExchangeRateX96 is high.
Impact
V3Vault::maxWithdraw() inflates the actual amount that can be withdrawn, which can impact badly protocols and contracts integrating with the vault. The possibility is quite real considering that maxWithdraw() is part of the official ERC-4626 which is very widely adopted.
Recommended mitigation steps
Refactor V3Vault::maxWithdraw() so that it does not convert balance to assets a second time:
Lines of code
https://github.com/revert-finance/lend/blob/audit/src/V3Vault.sol#L345
Vulnerability details
Vulnerability details
The
maxWithdrawal()
function ofV3Vault
calculates the maximum amount of underlying tokens an account can withdraw based on the shares it owns.The initial problem with
maxWithdrawal()
andV3Vault
overall was that they were not implemented according to the specs of ERC-4626 standard as outlined in the original issue. In the case ofmaxWithdrawal()
it did not consider the following part of the spec:In order to remediate the issue and make the
V3Vault
ERC-4626 compliant, protocol devs prepared the following PR, wheremaxWithdrawal()
was refactored so that it includes the actual daily limit that is applied when withdrawing assets:https://github.com/revert-finance/lend/blob/audit/src/V3Vault.sol#L335-L347
The problem with the new code is this part:
If we take a look at
_getBalanceAndReserves()
we can see that the returnedbalance
is already converted toassets
:https://github.com/revert-finance/lend/blob/audit/src/V3Vault.sol#L1107-L1116
This means that
maxWithdraw()
improperly convertsbalance
a second time and will overinflate the result, especially whendebtExchangeRateX96
is high.Impact
V3Vault::maxWithdraw()
inflates the actual amount that can be withdrawn, which can impact badly protocols and contracts integrating with the vault. The possibility is quite real considering thatmaxWithdraw()
is part of the official ERC-4626 which is very widely adopted.Recommended mitigation steps
Refactor
V3Vault::maxWithdraw()
so that it does not convertbalance
to assets a second time:Assessed type
Math