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

Points are distributed even for the period of `totalStaked == 0`.

Summary

FjordPoints.distributePoints() function doesn't distribute points for the period of totalStaked == 0 but the undistributed amount of points will be distributed after totalStaked becomes larger than zero.

Vulnerability Details

The relevant code of FjordPoints.distributePoints()is following.

function distributePoints() public {
if (block.timestamp < lastDistribution + EPOCH_DURATION) {
return;
}
237 if (totalStaked == 0) {
return;
}
uint256 weeksPending = (block.timestamp - lastDistribution) / EPOCH_DURATION;
pointsPerToken =
pointsPerToken.add(weeksPending * (pointsPerEpoch.mul(PRECISION_18).div(totalStaked)));
totalPoints = totalPoints.add(pointsPerEpoch * weeksPending);
245 lastDistribution = lastDistribution + (weeksPending * 1 weeks);
emit PointsDistributed(pointsPerEpoch, pointsPerToken);
}

As shown above, the function returns in L237 when totalStaked == 0 but doesn't update lastDistribution.
Therefore, after totalStaked becomes larger than zero, the undistributed amount of points will be distributed.

Scenario 1:

  1. Assume that pointsPerEpoch = 1000.

  2. At first week, totalStaked == 0, so no points are distributed at all.

  3. At second week, totalStaked becomes 100 > 0. Then 2 * 1000 = 2000 points are distributed to the stakers at second week.

On the other hand, the above vulnerability causes newly set pointsPerEpoch is applied to the period before it set.

Scenario 2:

  1. Assume that pointsPerEpoch = 1000.

  2. At first week, totalStaked == 0, so no points are distributed at all.

  3. At first week, admin changes pointsPerEpoch to be 2000. Since totalStaked == 0, lastDistribution is not updated.

  4. At second week, totalStaked becomes 100 > 0. Then 2 * 2000 = 4000 points instead of 1000 + 2000 = 3000 points are distributed to the stakers.

Code Snippet:

Impact

Undistributed amount of points when totalStaked == 0 will be distributed after totalStaked becomes larger than zero.
Newly set pointsPerEpoch is applied to the period before it set.

Tools Used

Manual Review

Recommendations

Modify FjordPoints.distributePoints() function as follows.

function distributePoints() public {
if (block.timestamp < lastDistribution + EPOCH_DURATION) {
return;
}
if (totalStaked == 0) {
+ lastDistribution = lastDistribution + (weeksPending * 1 weeks);
return;
}
uint256 weeksPending = (block.timestamp - lastDistribution) / EPOCH_DURATION;
pointsPerToken =
pointsPerToken.add(weeksPending * (pointsPerEpoch.mul(PRECISION_18).div(totalStaked)));
totalPoints = totalPoints.add(pointsPerEpoch * weeksPending);
lastDistribution = lastDistribution + (weeksPending * 1 weeks);
emit PointsDistributed(pointsPerEpoch, pointsPerToken);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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