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
5 months ago
yeahchibyke Lead Judge 5 months 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.

Give us feedback!