Skip to content

Latest commit

 

History

History
56 lines (33 loc) · 2.3 KB

066.md

File metadata and controls

56 lines (33 loc) · 2.3 KB

Muscular Ceramic Dragonfly

Medium

Inadequate Rounding in checkMinOrderSize Allows Processing of Invalid Orders

Summary

The lack of proper handling for rounding errors in the checkMinOrderSize function will cause financial risks for the platform and users as an attacker will exploit rounding discrepancies to process orders below the minimum size requirement.

Root Cause

In checkMinOrderSize(IERC20 tokenIn, uint256 amountIn) there is insufficient rounding control when calculating the USD equivalent of an order.

https://github.com/sherlock-audit/2024-11-oku/blob/main/oku-custom-order-types/contracts/automatedTrigger/AutomationMaster.sol#L144-L150

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

A user attempts to place an order for 10 TokenA. In the checkMinOrderSize function, the following calculations are performed:

  1. amountIn = 10 (number of tokens)

  2. tokenPriceUSD = 0.001 (current price of the token in USD)

  3. orderValueUSD = (10 * 0.001 * 10^18) / (10^18), resulting in orderValueUSD = 10 USD (initial value)

  4. However, due to potential rounding errors, if tokenPriceUSD is rounded down to a smaller value (for example, $0.000999999999999999), the calculated orderValueUSD could be: orderValueUSD = (10 * 0.000999999999999999 * 10^18) / (10^18), resulting in orderValueUSD = 9.999999999999999 USD.

As a result, the checkMinOrderSize function incorrectly determines that the order for 10 TokenA meets the minimum size requirement since 9.999999999999999 < 10, and the order will be processed when it should have been rejected.

Impact

The platform suffers an approximate loss of funds due to the acceptance of invalid orders. The attacker gains the ability to exploit the rounding error for profit, while users face unexpected financial losses from processed trades.

PoC

No response

Mitigation

function checkMinOrderSize(IERC20 tokenIn, uint256 amountIn) external view returns (bool) {  
    uint256 tokenPriceUSD = getTokenPriceInUSD(tokenIn); // Assume this function gets the current price  
    uint256 orderValueUSD = (amountIn * tokenPriceUSD + (1 ether - 1)) / (10 ** tokenIn.decimals()); // Adjusted rounding  
  
    // Check if the order value meets the minimum size  
    return orderValueUSD >= minOrderSizeUSD;   
}