Part 2

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

Double deleveraging in `_fillOrder()`

Summary

The auto deleveraging mechanism is incorrectly applied twice when processing positive PnL in the _fillOrder() function.

Vulnerability Details

In _fillOrder(), when processing positive PnL, the code first applies auto-deleveraging through getAdjustedProfitForMarketId() and then passes this already deleveraged amount to withdrawUsdTokenFromMarket() which applies deleveraging again:

File: SettlementBranch.sol
494: // if trader's old position had positive pnl then credit that to the trader
495: if (ctx.pnlUsdX18.gt(SD59x18_ZERO)) {
496: IMarketMakingEngine marketMakingEngine = IMarketMakingEngine(perpsEngineConfiguration.marketMakingEngine);
497:
498: ctx.marginToAddX18 = //@audit first deleveraging
499: marketMakingEngine.getAdjustedProfitForMarketId(marketId, ctx.pnlUsdX18.intoUD60x18().intoUint256());
500:
501: tradingAccount.deposit(perpsEngineConfiguration.usdToken, ctx.marginToAddX18);
502:
503: // mint settlement tokens credited to trader; tokens are minted to
504: // address(this) since they have been credited to the trader's margin
505: marketMakingEngine.withdrawUsdTokenFromMarket(marketId, ctx.marginToAddX18.intoUint256()); //@audit second deleveraging
506: }
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: }

Impact

The protocol becomes insolvent as positions record single deleveraged amounts while minted tokens reflect double deleveraged amounts.

Recommendations

Pass the original pnlUsdX18 amount to withdrawUsdTokenFromMarket() instead of the already deleveraged marginToAddX18.

Updates

Lead Judging Commences

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

`SettlementBranch._fillOrder` profit adjustment is applied to positive PnL twice.

Support

FAQs

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