DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: low
Invalid

Loss of Precision in Financial Calculations Due to Integer Division and Rounding

Summary

In the LibFertilizer.sol function remainingRecapitalization, there could potentially be a loss of precision when calculating the totalDollars value. The calculation involves multiplication, division, and then further manipulation. Loss of precision can occur due to rounding errors inherent in integer arithmetic in Solidity.

Vulnerability Details

This function calculates the remaining recapitalization amount. Let's dissect it:

  1. Calculating totalDollars:

dollarPerUnripeLP() returns the dollar value per unripe LP token.

unripeLP().totalSupply() gives the total number of unripe LP tokens.

DECIMALS is a constant defining the number of decimal places (e.g., 1e18 for 18 decimals).

• The multiplication and division result in the total dollar value represented by all unripe LP tokens.

  1. Rounding Down to Nearest USDC:

• The value of totalDollars is then rounded down to the nearest USDC (assuming USDC has 6 decimal places).

• This is done by dividing by 1e6 to remove the fractional part and then multiplying by 1e6 to retain the integer part.

Now, let's consider potential precision issues:

  • Integer Division Rounding
    Suppose:

dollarPerUnripeLP() returns 1e12

unripeLP().totalSupply() returns 1884592

DECIMALS is 1e18

The calculation of totalDollars would be:

totalDollars = 1e12 * 1884592 / 1e18 = 0.1884592 (truncated to 0 due to integer division)

Here, due to integer division, the fractional part 0.1884592 is truncated, leading to a loss of precision.

  • Rounding Down
    Suppose after the calculation, totalDollars is 1234567.

• After dividing by 1e6, totalDollars becomes 1.234567.

• Multiplying by 1e6 rounds it down to 1234566, which is the nearest lower integer.

Impact

The impact of potential precision issues in the remainingRecapitalization() function, as used in the functions (addUnderlying(), addFertilizer(), and mintFertilizer()), could manifest in several ways:

  1. Incorrect Calculation of Token Amounts: If there's a loss of precision in calculating the totalDollars value within remainingRecapitalization(), it could result in incorrect token amounts being added as underlying assets (usdAmount) in the addUnderlying() and addFertilizer() functions. This could lead to inaccuracies in the liquidity provision process and potentially affect the functioning of the system.

  2. Inaccurate Determination of Recapitalization Limit: In the mintFertilizer() function, the calculation of remaining relies on the remainingRecapitalization() function. If there's a loss of precision in this calculation, it could lead to inaccurate determination of the remaining recapitalization amount. This might result in users being able to mint more fertilizer tokens than what's actually available for recapitalization, leading to potential imbalances in the system.

  3. Validation Failures: In the mintFertilizer() function, the require statement checks if fertilizerAmountOut is less than or equal to the remaining recapitalization amount. If there's a loss of precision in this calculation, it could result in false positives or false negatives in the validation checks, leading to incorrect behavior and potential vulnerabilities.

Tools Used

Manual Review

Recommendations

• Use Fixed-Point Arithmetic: Represent values with fixed decimal places to maintain precision.

// Define a constant for the number of decimal places
uint256 constant DECIMALS = 1e18;
// Use fixed-point arithmetic for all calculations
function remainingRecapitalization() internal view returns (uint256 remaining) {
AppStorage storage s = LibAppStorage.diamondStorage();
// Convert all values to fixed-point
uint256 totalDollars =
- C.dollarPerUnripeLP().mul(C.unripeLP().totalSupply()).div(DECIMALS);
+ C.dollarPerUnripeLP().mul(C.unripeLP().totalSupply()).mul(DECIMALS).div(DECIMALS);
// Handle rounding down to nearest USDC
totalDollars = totalDollars / 1e6 * 1e6; // round down to nearest USDC
if (s.recapitalized >= totalDollars) return 0;
return totalDollars.sub(s.recapitalized);
}

• Carefully Choose Data Types: Use data types that support sufficient precision for your calculations.

• Avoid Rounding Manipulations: Minimize unnecessary rounding manipulations to reduce precision loss.

Updates

Lead Judging Commences

giovannidisiena Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Precision loss

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.