Part 2

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

Incorrect calculation of realized debt in `getRealizedDebtUsd()`

Summary

The getRealizedDebtUsd() function incorrectly adds credit deposits to net USD token issuance instead of subtracting them, causing accounting issues throughout the market-making engine.

Vulnerability Details

When traders close profitable positions, the trading engine calls withdrawUsdTokenFromMarket() which mints USD tokens and increases the market's netUsdTokenIssuance:

File: CreditDelegationBranch.sol
283: // now we realize the added usd debt of the market
284: // note: USD Token is assumed to be 1:1 with the system's usd accounting
285: if (market.isAutoDeleverageTriggered(delegatedCreditUsdX18, marketTotalDebtUsdX18)) {
286: // if the market is in the ADL state, it reduces the requested USD
287: // Token amount by multiplying it by the ADL factor, which must be < 1
288: UD60x18 adjustedUsdTokenToMintX18 =
289: market.getAutoDeleverageFactor(delegatedCreditUsdX18, marketTotalDebtUsdX18).mul(amountX18);
290:
291: amountToMint = adjustedUsdTokenToMintX18.intoUint256();
292: market.updateNetUsdTokenIssuance(adjustedUsdTokenToMintX18.intoSD59x18());
293: } else {
294: // if the market is not in the ADL state, it realizes the full requested USD Token amount
295: market.updateNetUsdTokenIssuance(amountX18.intoSD59x18());
296: }

However, when traders are liquidated or settle negative PnL positions, collateral is transferred via depositCreditForMarket which adds to creditDeposits:

File: CreditDelegationBranch.sol
212: // note: storage updates must occur using zaros internal precision
213: if (collateralAddr == usdToken) {
214: // if the deposited collateral is USD Token, it reduces the market's realized debt
215: market.updateNetUsdTokenIssuance(unary(amountX18.intoSD59x18()));
216: } else {
217: if (collateralAddr == usdc) {
218: market.settleCreditDeposit(address(0), amountX18);
219: } else {
220: // deposits the received collateral to the market to be distributed to vaults
221: // to be settled in the future
222: market.depositCredit(collateralAddr, amountX18);
223: }
224: }

And depositCredit() increases the creditDeposits mapping.

File: Market.sol
396: function depositCredit(Data storage self, address asset, UD60x18 amountX18) internal {
397: AssetToAmountMap.update(self.creditDeposits, asset, amountX18, true);
398: }

The key issue is that getRealizedDebtUsd() adds these credit deposits to netUsdTokenIssuance when calculating realized debt, instead of subtracting them to offset the debt.

File: Market.sol
234: function getRealizedDebtUsd(Data storage self) internal view returns (SD59x18 realizedDebtUsdX18) {
235: // prepare the credit deposits usd value variable;
236: UD60x18 creditDepositsValueUsdX18;
237:
238: // if the credit deposits usd value cache is up to date, return the stored value
239: if (block.timestamp <= self.lastCreditDepositsValueRehydration) {
240: creditDepositsValueUsdX18 = ud60x18(self.creditDepositsValueCacheUsd);
241: } else {
242: // otherwise, we'll need to loop over credit deposits to calculate it
243: creditDepositsValueUsdX18 = getCreditDepositsValueUsd(self);
244: }
245:
246: // finally after determining the market's latest credit deposits usd value, sum it with the stored net usd
247: // token issuance to return the net realized debt usd value
248: realizedDebtUsdX18 = creditDepositsValueUsdX18.intoSD59x18().add(sd59x18(self.netUsdTokenIssuance));
249: }

Impact

The incorrect calculation of realized debt breaks core accounting functionality across the market-making engine since the value is used extensively for credit capacity and debt calculations.

Recommendations

Modify getRealizedDebtUsd() to subtract credit deposits from net USD token issuance instead of adding them when calculating the realized debt.

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 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.