OrderBook

First Flight #43
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

Order Price Manipulation After Buyer Decision

Order Price Manipulation in OrderBook.sol::amendSellOrder

Description

  • Normal Behavior: A seller can update their order's price at any time using amendSellOrder(). This is intended to let them adjust prices based on market conditions.

  • Issue: A seller can change the price after a buyer has seen the order and decided to purchase, but before the buyer actually calls buyOrder(). This creates a front-running window, where the seller can raise the price at the last second, causing buyers to pay more than they expected. This is especially problematic in off-chain UIs where buyers may not see real-time price updates.

// Seller can arbitrarily modify price at any time
@> order.priceInUSDC = _newPriceInUSDC;

Risk

Likelihood:

  • This occurs whenever buyers rely on off-chain UIs to view order prices before calling buyOrder()

  • Attackers can use bots or scripts to detect pending buyer intent (e.g., mempool monitoring) and raise prices accordingly

Impact:

  • Buyers may unintentionally purchase at an inflated price, leading to loss of funds or poor user trust

  • Makes the protocol vulnerable to "seller griefing" or malicious UX behavior

Proof of Concept

No on-chain exploit is necessary, this is an economic attack based on timing.

  1. Buyer views an order listed at 1000 USDC.

  2. Buyer prepares to call buyOrder(orderId) based on that price.

  3. Before the transaction is mined, the seller uses amendSellOrder() to change the price to 5000 USDC.

  4. Buyer's transaction succeeds, but they now pay 5000 USDC instead of 1000 USDC.

This leads to an unfair outcome despite correct contract execution.

Recommended Mitigation

- order.priceInUSDC = _newPriceInUSDC;
+ // Option 1: Prevent price changes if buyer has signaled interest (off-chain intent or on-chain "lock")
+ require(!order.lockedForBuyer, "Buyer already interested");
+ // Option 2: Track price history for buyer-side validation
+ order.priceHistory.push(_newPriceInUSDC);
+ // Option 3: Rate-limit price amendments to reduce manipulation
+ require(block.timestamp > order.lastAmendTime + 5 minutes, "Too frequent");
+ order.lastAmendTime = block.timestamp;
Updates

Lead Judging Commences

yeahchibyke Lead Judge
about 1 month ago
yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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