Skip to content

Latest commit

 

History

History
117 lines (77 loc) · 4.23 KB

015.md

File metadata and controls

117 lines (77 loc) · 4.23 KB

Flaky Merlot Parrot

Medium

Imprecise Exchange Rate Calculations Will Cause Order Failures for Traders as Rounding Errors Prevent Expected Execution

Summary

The imprecise exchange rate calculation in AutomationMaster.sol will cause order failures for traders as rounding errors prevent expected execution during the checkUpkeep() and performUpkeep() processes in Brackets.sol.

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

Root Cause

In AutomationMaster.sol: _getExchangeRate(), the following line:

//AutomationMaster.sol: _getExchangeRate()
return (priceIn * 1e8) / priceOut;

introduces rounding errors due to integer division. When this function is called by getExchangeRate() in AutomationMaster.sol, which is further invoked by checkInRange() in Brackets.sol, it leads to imprecise exchange rates being used for critical comparisons.

Internal pre-conditions

  1. AutomationMaster.getExchangeRate() must be called by Brackets.sol during checkUpkeep() or performUpkeep().
  2. The priceIn and priceOut values for a token pair must result in a fractional exchange rate when multiplied and divided by 1e8.

External pre-conditions

  1. The external oracles providing priceIn and priceOut values must return rates that result in fine-grained differences not representable by the current precision.
  2. Traders must place orders with tight limits (e.g., stopLimitPrice) sensitive to small variations.

Attack Path

  1. A trader places a bracket order via Brackets.sol with strict conditions (e.g., stopLimitPrice of 1.23456789).
  2. The system processes the order and calls checkUpkeep(), which invokes checkInRange() in Brackets.sol.
  3. checkInRange() calls AutomationMaster.getExchangeRate() to retrieve the current exchange rate.
  4. AutomationMaster.getExchangeRate() uses _getExchangeRate() to compute the rate:
 //AutomationMaster.getExchangeRate()
return (priceIn * 1e8) / priceOut;

The calculation suffers a rounding error (e.g., 1.23456789 becomes 1.234567).

  1. The rounded exchange rate fails to satisfy the checkInRange() condition, causing the order to fail.

Impact

1- Missed Trade Opportunities: Orders fail to trigger during favorable market conditions due to slight inaccuracies, causing potential financial losses for traders.

2- User Trust Erosion: Repeated failures from imperceptible rate differences undermine user confidence in the platform.

3- Automation Disruption: Automated strategies depending on precise rate calculations become unreliable, affecting advanced users and bots.

PoC

Proof-of-Concept Contract: The contract below isolates the rounding error issue and demonstrates how fractional values are truncated due to integer division:

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

contract TestRoundingError {
    function _getExchangeRate(uint256 priceIn, uint256 priceOut) public pure returns (uint256 exchangeRate) {
        // Vulnerable code demonstrating rounding errors
        return (priceIn * 1e8) / priceOut;
    }
}
  1. Deploy the above contract.

  2. Call calculateExchangeRate(123456789, 98765432):

priceIn = 123456789;  // Mock oracle value for tokenIn
priceOut = 98765432;  // Mock oracle value for tokenOut

Expected result: 1.24999999 Actual result: 1 (due to rounding).

  1. Compare this to strict order conditions, which fail due to the discrepancy.

Mitigation

  1. Increase Precision:

Use a higher scaling factor to reduce the impact of rounding errors:

uint256 exchangeRate = (priceIn * 1e18) / priceOut;
This minimizes precision loss while remaining computationally efficient.
  1. Incorporate Error Margins:

Allow comparisons with a tolerance range to handle minor inaccuracies:

uint256 acceptableErrorMargin = exchangeRate / 10000; // 0.01% margin
if (actualExchangeRate >= expectedExchangeRate - acceptableErrorMargin &&
    actualExchangeRate <= expectedExchangeRate + acceptableErrorMargin) {
    // Proceed with execution
}

3.Adopt Fixed-Point Arithmetic:

Consider libraries like ABDKMathQuad for higher precision if ultra-accurate computations are required.