Part 2

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

CreditDelegationBranch::settleVaultsDebt will always revert when swapping USDC causing no possible debt settleme

Summary

The calculateSwapAmount function in CreditDelegationBranch::settleVaultsDebt will return zero when tokenIn is an asset and tokenOut is USDC. This issue arises because the vault debt in USD is first converted to USDC’s decimal precision (6 decimals) and this small value then gets processed by getExpectedOutput, leading to a zero return value. This prevents swaps from executing properly, resulting in failure when settling vaults' debt.

Vulnerability Details

  • The issue occurs in the else section of settleVaultsDebt:

    ctx.usdcIn = calculateSwapAmount(
    dexSwapStrategy.dexAdapter,
    ctx.vaultAsset,
    ctx.usdc,
    usdcCollateralConfig.convertSd59x18ToTokenAmount(ctx.vaultUnsettledRealizedDebtUsdX18.abs())
    );
  • vaultUnsettledRealizedDebtUsdX18 is sent in 6 decimals by passing through usdcCollateralConfig.convertSd59x18ToTokenAmount

  • The calculateSwapAmount function calls getExpectedOutput, where the 6 decimals value is converted to 18 decimals:

    UD60x18 amountInX18 = Math.convertTokenAmountToUd60x18(swapAssetConfigData[tokenIn].decimals, amountIn);
  • But if the tokenIn is a 18 decimals token, amountInX18 will be same as amountIn, since convertTokenAmountToUd60x18 returns the same value when token decimal is same as system decimal

  • Next, expectedAmountOut is calculated from the 6 decimals amountInX18:

    expectedAmountOut = Math.convertUd60x18ToTokenAmount(
    swapAssetConfigData[tokenOut].decimals, amountInX18.mul(priceTokenInX18).div(priceTokenOutX18)
    );
  • The calculation: amountInX18.mul(priceTokenInX18).div(priceTokenOutX18) will return a 6 decimal value, but when it is passed to convertUd60x18ToTokenAmount to convert it to token decimals, it will return zero. Since tokenOut decimal is 6, the input of convertUd60x18ToTokenAmount will be divided by 1^12 and will return zero.

  • After that, this will revert due to the check in getExpectedOutput:

    if (expectedAmountOut == 0) revert Errors.ZeroExpectedSwapOutput();

This will prevent the swap from happening

Impact

  • The vault cannot settle its credit position properly, leading to failed transactions.

  • The system will not be able to back it's usd token

Tools Used

  • Manual code review

Recommendations

Convert the vaultUnsettledRealizedDebtUsdX18 to amount of asset using a price oracle before passing it to getExpectedOutput

Updates

Lead Judging Commences

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

Support

FAQs

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

Give us feedback!