Part 2

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

settleVaultDebts will increase vaults' debt/credit instead of settling it

Summary

Comparator mistake in CreditDelegationBranch.settleVaultDebts will break the functionality and make it does the opposite of its intention.

Vulnerability Details

An overview of CreditDelegationBranch.settleVaultDebts is like the following:

  1. For given vaultId, get unsettledRealizedDebtUsd

  2. If unsettledRealizedDebtUsd < 0, convert vault's collateral asset to usdc

    1. usdcOutis roughly abs(unsettledRealizedDebtUsd)

    2. vault.marketUnrealizedDebtUsd -= usdcOut

  3. Otherwise, convert market's usdc to vault's collateral asset

    1. usdcIn is roughly unsettledRealizedDebtUsd

    2. vault.depositedUsdc -= usdcIn

Here, vault.unsettledRealizedDebtUsd = vault.marketUnrealizedDebtUsd - vault.depositedUsdc

Let's check what happens for unsettledRealizedDebtUsd < 0

If unsettledRealizedDebtUsd < 0it means marketUnrealizedDebtUsd < depositedUsdc, i.e. deposited USDC is greater than vault's debt.

According to the above flow (No. 2), the protocol swaps vault's collateral asset to usdc. So usdc balance will be increased further. What's more, by 2.ii.,unsettledRealizedDebtUsdAfter = unsettledRealizedDebtUsdBefore - usdcOuti.e. the credit has been increased, instead of being settled.

Similar thing happens for the case when unsettledRealizedDebtUsd > 0. i.e. usdc being swapped to collateral asset in spite of usdc shortage. And vault debt being increased by unsettledRealizedDebtUsdby 3.ii.

So the current functionality is broken, it worsens the situation instead of settling it.

Impact

  • Impossible to settle vaults debts

  • Incorrect accounting of USD token backing

Tools Used

Manual Review

Recommendations

Vault is in credit when unsettledRealizedDebtUsd < 0, in debt when unsettledRealizedDebtUsd > 0.

Current code should be fixed like the following:

diff --git a/src/market-making/branches/CreditDelegationBranch.sol b/src/market-making/branches/CreditDelegationBranch.sol
index d091d5c..ea4fdef 100644
--- a/src/market-making/branches/CreditDelegationBranch.sol
+++ b/src/market-making/branches/CreditDelegationBranch.sol
@@ -433,7 +433,7 @@ contract CreditDelegationBranch is EngineAccessControl {
DexSwapStrategy.loadExisting(vault.swapStrategy.assetDexSwapStrategyId);
// if the vault is in debt, swap its assets to USDC
- if (ctx.vaultUnsettledRealizedDebtUsdX18.lt(SD59x18_ZERO)) {
+ if (ctx.vaultUnsettledRealizedDebtUsdX18.gt(SD59x18_ZERO)) {
// get swap amount; both input and output in native precision
ctx.swapAmount = calculateSwapAmount(
dexSwapStrategy.dexAdapter,
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

settleVaultDebt functions in opposite direction because of `ctx.vaultUnsettledRealizedDebtUsdX18.lt(SD59x18_ZERO)` having an inversed comparator (should have been gt)

Support

FAQs

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