Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: low
Invalid

Missing zero-output check during swap fulfillment defeats protocol's intended objective

Summary

The fulfillSwap() function in the StabilityBranch contract lacks a critical check to ensure that the output amount of tokens (ctx.amountOut) is not zero after a swap is executed. While the protocol is designed to protect users from receiving less than their specified minimum amount, the absence of a zero-output check undermines this intention, potentially allowing users to receive no tokens at all.

Vulnerability Details

When users initiate a swap, the contract verifies that the expected amount of assets to be received (expectedAssetOut) is not zero and that it meets or exceeds the minimum amount specified by the user (minAmountsOut).

ctx.expectedAssetOut =
getAmountOfAssetOut(vaultIds[i], ud60x18(amountsIn[i]), ctx.collateralPriceX18).intoUint256();
// revert if the slippage wouldn't pass or the expected output was 0
>> if (ctx.expectedAssetOut == 0) revert Errors.ZeroOutputTokens();
if (ctx.expectedAssetOut < minAmountsOut[i]) {
revert Errors.SlippageCheckFailed(minAmountsOut[i], ctx.expectedAssetOut);
}

However, during the execution of the swap in the fulfillSwap() function, the contract only checks that ctx.amountOut is greater than or equal to minAmountOut.

ctx.amountOut =
collateral.convertUd60x18ToTokenAmount(ctx.amountOutBeforeFeesX18.sub(ctx.baseFeeX18.add(ctx.swapFeeX18)));
// slippage check
ctx.minAmountOut = request.minAmountOut;
>> // @audit-info Missing 0-output check
if (ctx.amountOut < ctx.minAmountOut) {
revert Errors.SlippageCheckFailed(ctx.minAmountOut, ctx.amountOut);
}
---SNIP---
// @audit-info Users may receive 0 assets
>> IERC20(ctx.asset).safeTransfer(user, ctx.amountOut);

There is no validation to ensure that ctx.amountOut is not zero. This oversight means that if the calculated amount after fees results in zero, users could receive no tokens, if they set their minimum amount out to zero.

Impact

Much as the protocol aims to protect users from this scenario, the lack of a zero output check poses a risk to users, as it could lead to scenarios where they receive no tokens despite having initiated a valid swap.

Tools Used

Manual Review

Recommendations

To align the protocol's functionality with its intended goals, implement an additional check in the fulfillSwap() function. This check should ensure that ctx.amountOut is not zero before proceeding with the swap.

ctx.amountOut =
collateral.convertUd60x18ToTokenAmount(ctx.amountOutBeforeFeesX18.sub(ctx.baseFeeX18.add(ctx.swapFeeX18)));
// slippage check
ctx.minAmountOut = request.minAmountOut;
// @audit-info Add 0-output check
+ if (ctx.amountOut == 0) {
+ revert Errors.ZeroOutputTokens();
+ }
if (ctx.amountOut < ctx.minAmountOut) {
revert Errors.SlippageCheckFailed(ctx.minAmountOut, ctx.amountOut);
}
---SNIP---
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.