OrderBook

First Flight #43
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

Protocol fee rounding loss

Root + Impact

Description

  • Normally buyOrder takes a cut of the sale price as protocol fee then sends the rest to the seller.

  • The code uses integer division, dropping any remainder dust

// @> integer division throws away dust up to PRECISION−1 units
uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION;

Risk

Likelihood:

  • Sellers can pick any USDC price

  • Rounding loss happens on each fill.

Impact:

  • Protocol revenue shrinks by the sum of discarded dust across trades


Proof of Concept

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OrderBook.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @notice Simple USDC mock for testing
contract USDCMock is ERC20 {
constructor() ERC20("USDC", "USDC") {
_mint(msg.sender, 1_000_000e6);
}
}
/// @notice Test token
contract TestToken is ERC20 {
constructor() ERC20("TEST", "TST") {
_mint(msg.sender, 10e18);
}
}
/// @notice Demonstrates dust loss
contract RoundingExploit {
OrderBook ob;
USDCMock usdc;
TestToken token;
constructor() {
usdc = new USDCMock();
token = new TestToken();
ob = new OrderBook(address(token), address(token), address(token), address(usdc), msg.sender);
token.approve(address(ob), type(uint256).max);
usdc.approve(address(ob), type(uint256).max);
}
function run() external {
// Seller lists 1 TEST for 33 USDC → expected fee = 0.99 → rounds down to 0
ob.createSellOrder(address(token), 1e18, 33e6, 1 days);
ob.buyOrder(1);
// totalFees == 0, seller got full 33 USDC
}
}

Recommended Mitigation

- uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION;
+ // Round up to capture all dust
+ uint256 protocolFee = (order.priceInUSDC * FEE + PRECISION - 1) / PRECISION;
uint256 sellerReceives = order.priceInUSDC - protocolFee;
Updates

Lead Judging Commences

yeahchibyke Lead Judge
about 1 month ago
yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Fee can be bypassed

Protocol Suffers Potential Revenue Leakage due to Precision Loss in Fee Calculation

Support

FAQs

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