code-423n4 / 2024-01-salty-findings

7 stars 4 forks source link

Inflexible Precision in Arbitrage Calculation #673

Closed c4-bot-6 closed 5 months ago

c4-bot-6 commented 6 months ago

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/arbitrage/ArbitrageSearch.sol#L63

Vulnerability details

Inflexible Precision in Arbitrage Calculation

LoC

https://github.com/code-423n4/2024-01-salty/blob/main/src/arbitrage/ArbitrageSearch.sol#L63

Summary

The MIDPOINT_PRECISION variable in ArbitrageSearch contract is set to a fixed value of 0.001 ETH which introduces a specific vulnerability related to the precision of arbitrage calculations in varying market conditions.

Vulnerability Details

The value of MIDPOINT_PRECISION is used to determine a small increment just right of the midpoint in the _rightMoreProfitable function. This increment is crucial in determining the direction in which the potential profit of an arbitrage opportunity is higher.

The chosen precision level may not be suitable under all conditions. In highly volatile markets or when dealing with tokens whose values significantly differ from ETH, this fixed precision could lead to suboptimal arbitrage decisions.

Code Snippet

// Used to estimate the point just to the right of the midpoint
uint256 constant public MIDPOINT_PRECISION = 0.001e18; // .001 ETH precision for arb search
function _rightMoreProfitable( uint256 midpoint, uint256 reservesA0, uint256 reservesA1, uint256 reservesB0, uint256 reservesB1, uint256 reservesC0, uint256 reservesC1 ) internal pure returns (bool rightMoreProfitable) {
        unchecked
            {
            // Calculate the AMM output of the midpoint
            uint256 amountOut = (reservesA1 * midpoint) / (reservesA0 + midpoint);
            amountOut = (reservesB1 * amountOut) / (reservesB0 + amountOut);
            amountOut = (reservesC1 * amountOut) / (reservesC0 + amountOut);

            int256 profitMidpoint = int256(amountOut) - int256(midpoint);

            // If the midpoint isn't profitable then we can remove the right half the range as nothing there will be profitable there either.
            if ( profitMidpoint < int256(PoolUtils.DUST) )
                return false;

            // Calculate the AMM output of a point just to the right of the midpoint
            midpoint += MIDPOINT_PRECISION;

            amountOut = (reservesA1 * midpoint) / (reservesA0 + midpoint);
            amountOut = (reservesB1 * amountOut) / (reservesB0 + amountOut);
            amountOut = (reservesC1 * amountOut) / (reservesC0 + amountOut);

            int256 profitRightOfMidpoint = int256(amountOut) - int256(midpoint);

            return profitRightOfMidpoint > profitMidpoint;
            }
        }

Impact

In certain market conditions, especially during high volatility, the fixed precision might not capture the most profitable arbitrage opportunity. This can lead to either missed profits or even potential losses if the arbitrage trade turns out to be less profitable than calculated.

The fixed precision might cause the algorithm to overlook better arbitrage opportunities that lie outside the set precision range. This inaccuracy can affect the overall efficiency of the arbitrage strategy.

Example Scenario

In a situation where ETH experiences a sudden price spike or drop, the fixed precision level might not be adequate to capture profitable arbitrage opportunities accurately. The algorithm could either overestimate or underestimate the profitability of a trade, leading to less than optimal decisions.

Recommendations

  1. Allow MIDPOINT_PRECISION to be dynamically adjusted, possibly in response to market conditions or through governance decisions. This adjustment should be secured to prevent unauthorized manipulation.

  2. Implement a mechanism to monitor market conditions in real-time, possibly using oracles, and adjust the precision accordingly to optimize for current market volatility and token value disparities.

Assessed type

Math

c4-judge commented 5 months ago

Picodes marked the issue as unsatisfactory: Insufficient proof