Assessment reports>Concrete>Informational findings>Incorrect withdrawable check in ,_withdrawStrategyFunds
Category: Coding Mistakes

Incorrect withdrawable check in _withdrawStrategyFunds

Informational Impact
Informational Severity
N/A Likelihood

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:

Zellic © 2025Back to top ↑