Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

Race Condition in Price Impact Calculation Allows Trade Execution at Stale Prices Leading to Market Manipulation

Summary

A critical vulnerability has been identified in the _fillOrder function within the SettlementBranch contract, specifically in the interaction between price impact calculation and trade execution timing. The core issue resides in the price calculation mechanics of the SettlementBranch.sol contract, particularly in how it interfaces with PerpMarket.sol for order execution.

The vulnerability manifests in the temporal disconnect between price calculation and state updates. The system calculates fill prices using perpMarket.getMarkPrice() based on the current market skew, but this price becomes stale by the time the trade executes because the market state (specifically the skew) changes during execution. This creates a fundamental inconsistency in the price impact model.

The issue emerges from the following execution flow in the contract system:

// Initial price calculation in fillMarketOrder/fillOffchainOrders
ctx.fillPriceX18 = perpMarket.getMarkPrice(sd59x18(ctx.offchainOrder.sizeDelta), ctx.indexPriceX18);
// Subsequent state changes in _fillOrder
(ctx.newOpenInterestX18, ctx.newSkewX18) = perpMarket.checkOpenInterestLimits(
sizeDeltaX18,
ctx.oldPositionSizeX18,
ctx.newPositionSizeX18,
true
);
perpMarket.updateOpenInterest(ctx.newOpenInterestX18, ctx.newSkewX18);

This sequence creates a race condition between price calculation and state updates. The mark price calculation incorporates the market impact based on the current skew, but the actual execution occurs in a different market state with an updated skew. This divergence becomes particularly problematic in high-volatility scenarios or with large order sizes that significantly impact the market skew.

Exploitation Vectors

The vulnerability becomes exploitable through market manipulation strategies. An attacker can observe pending transactions and execute front-running attacks that manipulate the skew between price calculation and execution. The impact is amplified in markets with steep price impact curves or during periods of low liquidity.

The following market conditions exacerbate the vulnerability:

  • Large order sizes that materially affect market skew

  • Markets with high price impact sensitivity

  • Periods of volatility where price impact calculations are more significant

  • Concentrated trading activity that rapidly changes market skew

Impact

The price discrepancy manifests in two primary ways within the system:

First, at the transaction level, where the executed price fails to reflect the true market impact of the trade. The price impact calculation uses getMarkPrice() with the initial skew, while the actual market impact should reflect the final skew state after execution.

Second, at the system level, where this discrepancy can be systematically exploited through strategic order placement and timing. Market makers and liquidity providers may face unexpected losses due to trades executing at prices that don't properly reflect their market impact.

Mitigation

The recommended solution involves restructuring the price calculation and execution flow to ensure atomicity. This can be achieved through two potential approaches:

First approach - Post-update price calculation:

function _fillOrder(...) {
MarketState memory initialState = perpMarket.getCurrentState();
MarketState memory finalState = perpMarket.calculateFinalState(initialState, orderParams);
perpMarket.updateState(finalState);
uint256 fillPrice = perpMarket.calculateFinalPrice(finalState, orderParams);
executeTradeAtPrice(fillPrice);
}

Second approach - Atomic execution with pre-calculation:

function _fillOrder(...) {
(MarketState memory newState, uint256 fillPrice) = perpMarket.calculateStateAndPrice(orderParams);
require(validatePriceImpact(newState, fillPrice), "Invalid price impact");
perpMarket.atomicStateUpdate(newState);
executeTradeAtPrice(fillPrice);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
4 months ago
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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