Incorrect withdrawable check in _withdrawStrategyFunds
Description
The _withdrawStrategyFunds
function in the WithdrawalQueueHelper library contains two issues in its withdrawable amount validation:
function _withdrawStrategyFunds(
uint256 amount_,
address receiver_,
address asset_,
Strategy[] memory strategies,
IParkingLot parkingLot
) internal {
// [...]
uint256 withdrawable = strategy.strategy.previewRedeem(strategy.strategy.balanceOf(address(this)));
if (diff.mulDiv(strategy.allocation.amount, MAX_BASIS_POINTS, Math.Rounding.Floor) > withdrawable) {
revert Errors.InsufficientFunds(strategy.strategy, diff * strategy.allocation.amount, withdrawable);
}
uint256 amountToWithdraw = _calculateWithdrawalAmount(amount_, strategy);
// [...]
}
First, the code compares withdrawable
against a proportional amount calculated from diff
(which equals amount_ - float
) rather than from amount_
itself.
Second, the code uses the previewRedeem
method to determine the withdrawable amount. This method may not accurately reflect withdrawal limits. The getAvailableAssetsForWithdrawal
method provides a more accurate withdrawable amount.
Impact
Since diff
can be less than amount_
, the withdrawable check may fail to detect insufficient funds for withdrawal. In this case, the execution would fail in the actual withdrawal process and spend more gas.
Recommendations
Check the withdrawable
amount against amountToWithdraw
rather than the calculated proportional diff amount. Additionally, use the getAvailableAssetsForWithdrawal
method instead of previewRedeem
to obtain the withdrawable amount.
function _withdrawStrategyFunds(
uint256 amount_,
address receiver_,
address asset_,
Strategy[] memory strategies,
IParkingLot parkingLot
) internal {
// [...]
- uint256 withdrawable = strategy.strategy.previewRedeem(strategy.strategy.balanceOf(address(this)));
+ uint256 withdrawable = strategy.strategy.getAvailableAssetsForWithdrawal();
- if (diff.mulDiv(strategy.allocation.amount, MAX_BASIS_POINTS, Math.Rounding.Floor) > withdrawable) {
- revert Errors.InsufficientFunds(strategy.strategy, diff * strategy.allocation.amount, withdrawable);
- }
uint256 amountToWithdraw = _calculateWithdrawalAmount(amount_, strategy);
+ if (amountToWithdraw > withdrawable) revert Errors.InsufficientFunds(strategy.strategy, amountToWithdraw, withdrawable);
// [...]
}
Remediation
This issue has been acknowledged by Blueprint Finance, and fixes were implemented in the following commits: