OrderBook

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

L - TestOrderBook.t.sol - Invalid decimal assumption for tokens

Root + Impact

Description

The OrderBook contract should work with real-world token decimals to ensure accurate price calculations and user expectations. Mock tokens in tests should mirror the decimal precision to catch potential integration issues.

The test suite incorrectly assumes WBTC has 8 decimals and WSOL has 18 decimals, when both actually use 9 decimals in production. This mismatch could lead to frontend integration errors where users think they're trading different amounts than actually executed.

function setUp() public {
usdc = new MockUSDC(6);
@> wbtc = new MockWBTC(8); // Incorrect: Real WBTC uses 9 decimals
weth = new MockWETH(18);
@> wsol = new MockWSOL(18); // Incorrect: Real WSOL uses 9 decimals
}

Risk

Likelihood:

  • Frontend developers will use test results to implement decimal handling logic

  • Integration testing with incorrect decimals won't catch real-world decimal mismatches

Impact:

  • Users may create orders with 10x price discrepancy (0.1 WBTC sold at 1 WBTC price)

  • Frontend confusion where displayed amounts don't match on-chain amounts

  • Potential arbitrage opportunities for users who understand the decimal mismatch

  • Loss of user trust due to unexpected order execution amounts

Proof of Concept

This test demonstrates how the incorrect decimal assumption creates a 10x discrepancy between expected and actual amounts. When a user intends to sell 1 WBTC, they actually end up selling only 0.1 WBTC due to the decimal mismatch, creating an overpriced order that benefits buyers.

function test_Invalid_decimal_assumption() public {
// Test decimals vs real decimals
uint256 wbtcDecimals = wbtc.decimals(); // 8 decimals (test)
uint256 REAL_WBTC_DECIMALS = 9; // 9 decimals (mainnet)
uint256 numberOfUnits = 1;
// Alice thinks she's selling 1 WBTC for $100k
vm.startPrank(alice);
wbtc.mint(alice, 2);
wbtc.approve(address(book), numberOfUnits * 10 ** wbtcDecimals);
uint256 orderId = book.createSellOrder(
address(wbtc),
numberOfUnits * 10 ** wbtcDecimals, // 1e8 (0.1 real WBTC)
100_000e6, // $100k
2 days
);
(,,,uint256 amountToSell,,,) = book.orders(orderId);
vm.stopPrank();
console2.log("Amount to sell:", amountToSell); // 100000000 (0.1 WBTC)
uint256 expectedRealAmount = numberOfUnits * 10 ** REAL_WBTC_DECIMALS;
console2.log("Expected real WBTC:", expectedRealAmount); // 1000000000 (1 WBTC)
// Order contains 10x less WBTC than expected
assert(amountToSell != expectedRealAmount);
}

Recommended Mitigation

Update the test setup to use correct decimal values that match mainnet token implementations. This ensures that integration testing accurately reflects real world behavior and prevents frontend teams from implementing incorrect decimal handling logic.

function setUp() public {
usdc = new MockUSDC(6);
- wbtc = new MockWBTC(8);
+ wbtc = new MockWBTC(9); // Match real WBTC decimals
weth = new MockWETH(18);
- wsol = new MockWSOL(18);
+ wsol = new MockWSOL(9); // Match real WSOL decimals
}

This simple change aligns the test environment with production token standards.

Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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