Margin values are determined by markPrice
which is easily influenced by skew impact. An attacker can create a large position to push skew in one direction and force other traders to be liquidated. As each trader is liquidated, it further worsens the skew and causes cascading liquidations.
The function getAccountMarginRequirementUsdAndUnrealizedPnlUsd
is used to calculate Initial Margin (IM), Maintenance Margin (MM) and unrealized PnL. These variables are used during liquidateAccounts
to check if an account has sufficient margin.
The issue lies with using markPrice
to compute these variables, which is easily influenced by skew. 1) A well-capitalized attacker could create a position to greatly imbalance skew, 2) When obtaining markPrice
for the to-be-liquidated account, a sell simulation is performed which further worsens skew, returning a more undesirable price:
The higher the markPrice
, the higher notionalValueX18
is and therefore a higher IM/MM is required to avoid liquidation.
Consider this scenario:
Bob has a -100 short entered at $5
Alice the whale creates a +1000 long and pushes price to $6
Price impact is calculated as if Bob closed his entire position. I.e. if Bob were to go +100 long, in an already long-skewed market which pushes price even higher to $6.1
Bob's notionalValueX18
is calculated as 100 * 6.1 = $610
Bob's IM and MM requirements are raised putting him at liquidation risk
Bob's also experiences a PnL loss of (6.1) * 100 = -$110
See coded POC here: https://gist.github.com/giraffe0x/d4efa0dd15eabc86153bc5a716d2c77e
This could also happen to longs but the risk is greater for shorts, as increasing markPrice
not only increases IM/MM but also means lower PnL.
High. A whale attacker can easily influence markPrice and liquidate other users unfairly, short traders are most at risk.
This also results in cascading liquidations as each liquidated position pushes price further in the undesired direction (e.g. in a long-skewed market, a short position is liquidated, long-skew increases, markPrice increases, more short positions are liquidated).
https://github.com/Cyfrin/2024-07-zaros/blob/main/src/perpetuals/leaves/TradingAccount.sol#L232
Manual Review
Consider using an oracle price instead of markPrice to calculate margin values. The purpose of using mark/fill price in Perps is to provide an auto-correct mechanism for price to converge with oracle price. It should not be used to determine liquidations which then further aggravates the gap between mark and oracle price.
Consider a rate-limited liquidation mechanism to prevent cascading liquidations. For example. within a 5-minute window, only $X amount of liquidations allowed. This would give time for the market to absorb any liquidations and avoid cascading sharp drawdowns.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.