Part 2

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

ncorrect Debt Distribution in `distributeDebtToVaults()` Can Cause Vaults to Receive Excess or Insufficient Debt

Bug Description:

The distributeDebtToVaults() function is responsible for distributing realized and unrealized debt to vaults based on their share of total delegated credit. However, the function incorrectly assumes that dividing newRealizedDebtUsdX18 and newUnrealizedDebtUsdX18 by totalVaultSharesX18 will always produce valid and accurate results:

self.realizedDebtUsdPerVaultShare = newRealizedDebtUsdX18.div(totalVaultSharesX18).intoInt256().toInt128();
self.unrealizedDebtUsdPerVaultShare = newUnrealizedDebtUsdX18.div(totalVaultSharesX18).intoInt256().toInt128();

The critical issue is that totalVaultSharesX18 (i.e., totalDelegatedCreditUsd converted to SD59x18) can be extremely small or even zero.

  • If totalVaultSharesX18 == 0, this results in a division by zero, causing a revert and halting all market operations.

  • If totalVaultSharesX18 is a very small number, but newRealizedDebtUsdX18 or newUnrealizedDebtUsdX18 is large, the division can create an extremely large debt-per-share value, leading to overflow when converting to int128.

  • In scenarios where vault credit fluctuates rapidly, a single vault with minimal credit can receive an excessive amount of debt, potentially forcing liquidation when it shouldn't be necessary.

Impact:

If totalVaultSharesX18 == 0, debt distribution completely fails, preventing the market from functioning and halting all transactions. If totalVaultSharesX18 is too small, vaults may be incorrectly overburdened with debt, leading to wrongful liquidations and financial loss.

Mitigation:

Before dividing, ensure totalVaultSharesX18 is greater than a safe minimum threshold and revert gracefully if it's zero:

if (totalVaultSharesX18.isZero()) {
revert Errors.NoDelegatedCredit(self.id);
}
SD59x18 debtPerVaultShare = newRealizedDebtUsdX18.div(totalVaultSharesX18);
require(debtPerVaultShare.abs() < SD59x18.wrap(type(int128).max), "Debt per share overflow");
Updates

Lead Judging Commences

inallhonesty Lead Judge
6 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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