DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: low
Invalid

Incorrect Calculation of `pointsPerToken` Due to Division Before Multiplication

Summary

In the distributePoints function, pointsPerToken is calculated incorrectly. The code performs division before multiplication, which can cause rounding errors and result in different values instead of the correct value.

Vulnerability Details

The distributePoints function in the Solidity contract is designed to check whether an epoch has completed and then update the pointsPerToken state variable based on the number of epochs that have passed (weeksPending), the pointsPerEpoch value, and the total number of tokens staked (totalStaked).

pointsPerToken = pointsPerToken.add(
weeksPending * (pointsPerEpoch.mul(PRECISION_18).div(totalStaked))
);

In this calculation, the multiplication by weeksPending is performed after the division of pointsPerEpoch by totalStaked. This sequence can lead to significant precision loss, which can negatively impact the accuracy of the pointsPerToken calculation.

Assume the following values:

  • pointsPerEpoch = 100 * 10^18

  • PRECISION_18 = 10^18

  • totalStaked = (100 * 10^18) * 10^18 + 1 FjordTokens

  • weeksPending = 2

Given the current implementation, the calculation proceeds as follows:

  1. Division First:

    Result = (pointsPerEpoch.mul(PRECISION_18).div(totalStaked))

    Which results in:

    Result = (100 * 10^18 * 10^18) / ((100 * 10^18) * 10^18 + 1) ≈ 0

    Since Solidity rounds down the result in integer division, this calculation results in 0.

  2. Multiplication by weeksPending:

    pointsPerToken = 2 * 0 = 0

The final result is 0, which is clearly incorrect in this context.

To avoid this issue, the multiplication by weeksPending should occur before the division:

  1. Multiplication First:

    Result = weeksPending * pointsPerEpoch

    Which results in:

    Result = 2 * (100 * 10^18) = 200 * 10^18
  2. Division After:

    pointsPerToken = (200 * 10^18 * 10^18) / ((100 * 10^18) * 10^18 + 1)

    Which results in:

    pointsPerToken = 2 * 10^38 / (10^38 + 1) ≈ 1 (due to rounding behavior)

Impact

The impact is directly proportional to the weeksPending value. Due to this rounding issue, the pointsPerToken calculation results in an incorrect value.

Tools Used

Manual Review

Recommendations

add the following code

pointsPerToken = pointsPerToken.add(weeksPending.mul(pointsPerEpoch.mul(PRECISION_18)).div(totalStaked));
Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Division before multiplication

Support

FAQs

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