sherlock-audit / 2024-10-axion

2 stars 3 forks source link

Potential Integer Division Precision Loss in boostPrice Function Leads to Inaccurate Price Calculations #6

Open CipherHawk0 opened 1 month ago

CipherHawk0 commented 1 month ago

Summary

The use of integer division in the boostPrice function will cause a medium impact on the protocol's price calculations as the function may truncate decimal precision, leading to inaccurate BOOST price representations and flawed liquidity management decisions.

Root Cause

In SolidlyV2AMO.sol, the boostPrice function calculates the price of the BOOST token by dividing amountOut by a scaling factor derived from usdDecimals and PRICE_DECIMALS. This operation uses integer division, which can lead to precision loss if not properly handled.

Relevant Code Snippet:

function boostPrice() public view override returns (uint256 price) {
    uint256 amountOut = IPair(pool).getAmountOut(10 ** boostDecimals, boost);
    price = amountOut / 10 ** (usdDecimals - PRICE_DECIMALS);
}

Internal pre-conditions

  1. The boostDecimals and usdDecimals are set such that usdDecimals > PRICE_DECIMALS.

  2. The getAmountOut function returns a value that, when divided by 10 (usdDecimals - PRICE_DECIMALS)**, results in truncation of decimal places.

External pre-conditions

  1. The pool contract's getAmountOut function behaves correctly and returns accurate amounts.

  2. The usdDecimals and PRICE_DECIMALS are set consistently across the protocol to prevent mismatches.

Attack Path

  1. An attacker or protocol operator ensures that usdDecimals is significantly higher than PRICE_DECIMALS.

  2. The boostPrice function is called, and the calculation amountOut / 10 (usdDecimals - PRICE_DECIMALS)** truncates the decimal precision.

  3. The inaccurate price value leads to incorrect liquidity management decisions, such as adding or removing liquidity based on flawed price data.

  4. The protocol may misallocate funds, causing imbalances in the BOOST-USD pool and destabilizing the BOOST peg.

Impact

The protocol experiences a medium risk of inaccurate BOOST price calculations, leading to flawed liquidity management and potential destabilization of the BOOST peg, which can result in financial inefficiencies and loss of user trust.

PoC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./SolidlyV2AMO.sol";

contract PrecisionLossAttack {
    SolidlyV2AMO amo;

    constructor(address amoAddress) {
        amo = SolidlyV2AMO(amoAddress);
    }

    function exploit() public view returns (uint256 inaccuratePrice) {
        // Mock the pool's getAmountOut to return a value that causes precision loss
        // Assume getAmountOut returns 123456789 (BOOST amount to USD)
        // With usdDecimals = 6 and PRICE_DECIMALS = 2
        // price = 123456789 / 10^(6 - 2) = 123456789 / 10,000 = 12,345 (truncated from 12,345.6789)
        inaccuratePrice = amo.boostPrice();
    }
}

Mitigation

  1. Use Fixed-Point Arithmetic:

Implement fixed-point arithmetic by scaling the numerator before division to retain decimal precision.

function boostPrice() public view override returns (uint256 price) {
    uint256 amountOut = IPair(pool).getAmountOut(10 ** boostDecimals, boost);
    // Multiply by a scaling factor before division to preserve decimal places
    price = (amountOut * 10 ** PRICE_DECIMALS) / 10 ** usdDecimals;
}
  1. Align Decimal Places:

Ensure that usdDecimals and PRICE_DECIMALS are aligned or standardized across the protocol to prevent mismatches that lead to precision loss.

  1. Implement Precision Checks:

Add require statements to verify that usdDecimals is not excessively larger than PRICE_DECIMALS, preventing unexpected precision truncation.

function boostPrice() public view override returns (uint256 price) {
    require(usdDecimals >= PRICE_DECIMALS, "Invalid decimal configuration");
    uint256 amountOut = IPair(pool).getAmountOut(10 ** boostDecimals, boost);
    price = (amountOut * 10 ** PRICE_DECIMALS) / 10 ** usdDecimals;
}
  1. Comprehensive Testing:

Develop unit tests that simulate various usdDecimals and PRICE_DECIMALS configurations to ensure accurate price calculations across different scenarios.

  1. Documentation:

Clearly document the decimal handling logic within the contract to guide future developers and auditors in understanding and maintaining the code.

mz8t commented 1 month ago

price decimals is 6, that us acceptable precision