Part 2

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

Incorrect Realized Debt Calculation in Market::getRealizedDebtUsd

Summary

There is a miscalculation in Market::getRealizedDebtUsd. The creditDeposits are collateral deposited by perps engine by calling CreditDelegationBranch::depositCreditForMarket. This credit deposit is later converted to USDC to back usd token of engine. So this credit deposit is not debt rather credit. The getRealizedDebtUsd function adds both netUsdTokenIssuance and usd value of all credit deposits and return the value. This is not correct as credit deposit is used to cover debt.


Vulnerability Details

getRealizedDebtUsd incorrectly adds getCreditDepositsValueUsd(self) instead of subtracting it. convertMarketsCreditDepositsToUsdc converts credit deposits to USDC, adding them to usdcCreditPerVaultShare. This means credit deposits are not actual debt but rather equivalent to deposited USDC, so they must be subtracted. netUsdTokenIssuance is the debt and credit deposit is the value that is used to back the usd token issued.


Impact

  • Overstates the market's realized debt, leading to miscalculated vault unsettled debt.

  • This overestimation will cause users to receive less tokens in StabilityBranch's swap

  • CreditDelegationBranch::settleVaultsDebt will not work correctly, as vault.getUnsettledRealizedDebt will not return correct value


Recommendation

Modify getRealizedDebtUsd to subtract the credit deposits instead of adding them:

function getRealizedDebtUsd(Data storage self) internal view returns (SD59x18 realizedDebtUsdX18) {
// prepare the credit deposits usd value variable;
UD60x18 creditDepositsValueUsdX18;
// if the credit deposits usd value cache is up to date, return the stored value
if (block.timestamp <= self.lastCreditDepositsValueRehydration) {
creditDepositsValueUsdX18 = ud60x18(self.creditDepositsValueCacheUsd);
} else {
// otherwise, we'll need to loop over credit deposits to calculate it
creditDepositsValueUsdX18 = getCreditDepositsValueUsd(self);
}
// finally after determining the market's latest credit deposits usd value, sum it with the stored net usd
// token issuance to return the net realized debt usd value
- realizedDebtUsdX18 = creditDepositsValueUsdX18.intoSD59x18().add(sd59x18(self.netUsdTokenIssuance));
+ realizedDebtUsdX18 = sd59x18(self.netUsdTokenIssuance).sub(creditDepositsValueUsdX18.intoSD59x18());
}
Updates

Lead Judging Commences

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

Market::getRealizedDebtUsd incorrectly adds creditDeposits to netUsdTokenIssuance when calculating debt, causing accounting errors because credit deposits should reduce debt

Support

FAQs

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

Give us feedback!