code-423n4 / 2024-07-basin-validation

0 stars 0 forks source link

Division by Zero Error in updateReserve Function #123

Closed c4-bot-1 closed 3 months ago

c4-bot-1 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-07-basin/blob/7d5aacbb144d0ba0bc358dfde6e0cc913d25310e/src/functions/Stable2.sol#L387

Vulnerability details

Vulnerability Details

The updateReserve function is responsible for calculating the step size to update the reserve value based on the target price and the current price. It uses the difference between the pd.lutData.highPrice and pd.lutData.lowPrice to determine the step size.

If the pd.lutData.highPrice and pd.lutData.lowPrice are equal, this means the target price is exactly between the high and low prices in the lookup table. In this case, the expression (pd.lutData.highPrice - pd.lutData.lowPrice) will be zero, which will lead to a division by zero error when calculating the step size.

Code

function updateReserve(PriceData memory pd, uint256 reserve) internal pure returns (uint256) {
        if (pd.targetPrice > pd.currentPrice) {
            // if the targetPrice is greater than the currentPrice,
            // the reserve needs to be decremented to increase currentPrice.
            return reserve
                - pd.maxStepSize * (pd.targetPrice - pd.currentPrice) / (pd.lutData.highPrice - pd.lutData.lowPrice);
        } else {
            // if the targetPrice is less than the currentPrice,
            // the reserve needs to be incremented to decrease currentPrice.
            return reserve
                + pd.maxStepSize * (pd.currentPrice - pd.targetPrice) / (pd.lutData.highPrice - pd.lutData.lowPrice);
        }
    }

Impact

If the updateReserve function encounters a division by zero error, it will revert the entire transaction, preventing the function from successfully executing. This can have significant consequences, as the calcReserveAtRatioSwap and calcReserveAtRatioLiquidity functions rely on the updateReserve function to converge on the correct reserve value.

If the updateReserve function fails, the calling functions will not be able to properly calculate the reserve values, which could lead to incorrect pricing, swaps, or liquidity calculations.

This issue could potentially affect the overall functionality and reliability of the Stable2 contract, especially in cases where the target price is close to the midpoint between the high and low prices in the lookup table.

Poc

function testUpdateReserveWithHighAndLowPriceEqual() public {
    Stable2.PriceData memory pd;
    pd.lutData.highPrice = 1_000_000;
    pd.lutData.lowPrice = 1_000_000;
    pd.targetPrice = 1_000_000;
    pd.currentPrice = 999_999;
    pd.maxStepSize = 1_000;

    uint256 updatedReserve = stable2.updateReserve(pd, 10_000);
    assertEq(updatedReserve, 9_000, "Reserve should be decremented by the full step size");

    pd.targetPrice = 1_000_001;
    pd.currentPrice = 1_000_000;
    updatedReserve = stable2.updateReserve(pd, 10_000);
    assertEq(updatedReserve, 11_000, "Reserve should be incremented by the full step size");
}

Mitigation

Add a check to handle the case where the high and low prices are equal.

Assessed type

Math

nevillehuang commented 3 months ago

Likely Invalid, known issue [L-4]