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.
The boostDecimals and usdDecimals are set such that usdDecimals > PRICE_DECIMALS.
The getAmountOut function returns a value that, when divided by 10 (usdDecimals - PRICE_DECIMALS)**, results in truncation of decimal places.
External pre-conditions
The pool contract's getAmountOut function behaves correctly and returns accurate amounts.
The usdDecimals and PRICE_DECIMALS are set consistently across the protocol to prevent mismatches.
Attack Path
An attacker or protocol operator ensures that usdDecimals is significantly higher than PRICE_DECIMALS.
The boostPrice function is called, and the calculation amountOut / 10 (usdDecimals - PRICE_DECIMALS)** truncates the decimal precision.
The inaccurate price value leads to incorrect liquidity management decisions, such as adding or removing liquidity based on flawed price data.
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
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;
}
Align Decimal Places:
Ensure that usdDecimals and PRICE_DECIMALS are aligned or standardized across the protocol to prevent mismatches that lead to precision loss.
Implement Precision Checks:
Add require statements to verify that usdDecimals is not excessively larger than PRICE_DECIMALS, preventing unexpected precision truncation.
Develop unit tests that simulate various usdDecimals and PRICE_DECIMALS configurations to ensure accurate price calculations across different scenarios.
Documentation:
Clearly document the decimal handling logic within the contract to guide future developers and auditors in understanding and maintaining the code.
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:
Internal pre-conditions
The boostDecimals and usdDecimals are set such that usdDecimals > PRICE_DECIMALS.
The getAmountOut function returns a value that, when divided by 10 (usdDecimals - PRICE_DECIMALS)**, results in truncation of decimal places.
External pre-conditions
The pool contract's getAmountOut function behaves correctly and returns accurate amounts.
The usdDecimals and PRICE_DECIMALS are set consistently across the protocol to prevent mismatches.
Attack Path
An attacker or protocol operator ensures that usdDecimals is significantly higher than PRICE_DECIMALS.
The boostPrice function is called, and the calculation amountOut / 10 (usdDecimals - PRICE_DECIMALS)** truncates the decimal precision.
The inaccurate price value leads to incorrect liquidity management decisions, such as adding or removing liquidity based on flawed price data.
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
Mitigation
Implement fixed-point arithmetic by scaling the numerator before division to retain decimal precision.
Ensure that usdDecimals and PRICE_DECIMALS are aligned or standardized across the protocol to prevent mismatches that lead to precision loss.
Add require statements to verify that usdDecimals is not excessively larger than PRICE_DECIMALS, preventing unexpected precision truncation.
Develop unit tests that simulate various usdDecimals and PRICE_DECIMALS configurations to ensure accurate price calculations across different scenarios.
Clearly document the decimal handling logic within the contract to guide future developers and auditors in understanding and maintaining the code.