OrderBook

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

Extreme Order Price Causes Panic(0x11) on Purchase

Author Revealed upon completion

Root + Impact

Description

  • In normal behavior, the seller creates an order with a token and price in USDC. The buyer then purchases the order by paying the exact priceInUSDC.

  • However, the contract currently allows the seller to set an extremely large priceInUSDC, and this unbounded value can cause an arithmetic overflow when computing protocol fees. This causes the buyOrder() function to revert, making it impossible for buyers to fulfill such orders, effectively locking the token in an “active but unpurchasable” state.

// Root cause in the codebase with @> marks to highlight the relevant section
// Inside buyOrder():
uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION; // @> Overflows when priceInUSDC is very large, i.e >= type(uint256).max / 3
uint256 sellerReceives = order.priceInUSDC - protocolFee; // @> This can also overflow
usdc.safeTransferFrom(msg.sender, address(this), order.priceInUSDC); // Unreachable due to revert

Risk

Likelihood:

  • Sellers can deliberately submit orders with extremely large priceInUSDC, since no cap is enforced.

  • The function will revert every time a buyer attempts to purchase such an order.

Impact:

  • Tokens in such orders gets stuck, unless the seller cancels.

  • This breaks user expectations and damages the reliability of the platform for buyers.

Proof of Concept

This test simulates a real-world scenario where a seller sets an extremely large price for their order (e.g., 1.15e77 USDC), which still passes basic validations and can be set/amended into the order. However, when a buyer attempts to fulfill this order, the buyOrder function tries to calculate the protocol fee.
Because order.priceInUSDC is so large, the multiplication results in an arithmetic overflow, even though Solidity 0.8+ reverts on overflow. This completely reverts the buy transaction, meaning:

  • The buyer cannot buy the order.

  • Their approval and intent are wasted.

  • The protocol appears broken or unresponsive.

function test_overflowOnBuyDueToLargePrice() public {
vm.startPrank(alice);
wbtc.approve(address(book), 2e8);
uint256 orderId = book.createSellOrder(address(wbtc), 2e8, 1.15e77, 2 days); // Maliciously large price
vm.stopPrank();
vm.startPrank(dan);
usdc.approve(address(book), type(uint256).max); // Even if buyer tries max
vm.expectRevert(); // Fails due to overflow in fee/transfer
book.buyOrder(orderId);
vm.stopPrank();
}

Recommended Mitigation

To prevent this, cap the priceInUSDC when creating or amending orders. This avoids ever reaching a state where overflow is possible in buyOrder. We can set the MAX_PRICE to type(uint256).max / 3 as here the protocol fees is 3% or set an amount like 1e18 i.e 1 Trillion USDC.

- remove this code
+ add this code
// --- Constants ---
uint256 public constant MAX_DEADLINE_DURATION = 3 days; // Max duration from now for a deadline
uint256 public constant FEE = 3; // 3%
uint256 public constant PRECISION = 100;
++ uint256 public constant MAX_PRICE = type(uint256).max / 3;
...
// Inside createSellOrder
-- if (_priceInUSDC == 0) revert InvalidPrice();
++ if (_priceInUSDC == 0 || _priceInUSDC >= MAX_PRICE) revert InvalidPrice();
...
// Inside amendSellOrder
-- if (_newAmountToSell == 0) revert InvalidAmount();
++ if (_newAmountToSell == 0 || _newAmountToSell >= MAX_PRICE) revert InvalidAmount();
Updates

Lead Judging Commences

yeahchibyke Lead Judge 1 day ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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