DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: high
Valid

LiquidateAccounts fails to properly modify the Skew and newOpenInterest of a market following liquidation of a user.

Summary

The LiquidationBranch::liquidateAccounts function fails to properly update the ctx.newSkew after liquidation of a user alongside ctx.newOpenInterestX18.

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/branches/LiquidationBranch.sol#L105-L210

Vulnerability Details

Early within liquidateAccounts execution flow, we initialize the LiquidationContext memory ctx. At initialization, ctx.newSkew18 and ctx.newOpenInterestX18 will be initialized to zero. ThroughoutliquidateAccounts various context variables will be assigned values through external calls to other branches and leaves in the protocol, however there is no implemented logic that edits the value ctx.newSkewX18 and there is no logic that edits the value of ctx.newOpenInterestX18. Therefore, we are always simply calling perpMarket.updateOpenInterest(0, 0)

function liquidateAccounts(uint128[] calldata accountsIds) external {
...
LiquidationContext memory ctx;
...
// update perp market's open interest and skew; we don't enforce ipen
// interest and skew caps during liquidations as:
// 1) open interest and skew are both decreased by liquidations
// 2) we don't want liquidation to be DoS'd in case somehow those cap
// checks would fail
perpMarket.updateOpenInterest(ctx.newOpenInterestX18, ctx.newSkewX18);
}

Within PerpMarket.sol:

function updateOpenInterest(Data storage self, UD60x18 newOpenInterest, SD59x18 newSkew) internal {
self.skew = newSkew.intoInt256().toInt128();
self.openInterest = newOpenInterest.intoUint128();
}

Clearly, after any user is liquidated, the market's total skew and openInterest are both reset to 0.

Impact

Since any and all liquidations will completely reset any market's skew and openInterest, the market will behave entirely unpredictably following the liquidation of any user. self.skew is a kew component to many methods within PerpMarket.sol such as getCurrentFundingVelocity, getOrderFeeUSD, and more. Even non-maliciously this could cascade to brick outlying functionality of the protocol. Furthermore, malicious traders now have an avanue through which they can reset the skew of any market they participate in simply by opening a burner account and holding liquidatable positions with small monetary amounts in said market.

Tools Used

Manual Review

Recommendations

Implement logic that calculates how the liquidation of a user affects a market's skew and newOpenInterest and implement it within liquidateAccounts

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

`liquidateAccounts` calls `updateOpenInterest` with uninitialized OI and skew)

Support

FAQs

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