TempleGold

TempleDAO
Foundry
25,000 USDC
View results
Submission Details
Severity: medium
Valid

Incorrect `vestingRate` Calculation Due to Updated `vestingPeriod`

Summary

Stakers from previous epochs receive incorrect rewards due to the new vestingPeriod being used in the calculation.

Vulnerability Details

In the TempleGoldStaking contract, the vestingPeriod is a global state variable used to set the unlock time for stakes (StakeInfo.fullyVestedAt) (_applyStake()#498).

The vestingPeriod can be updated after reward epoch ends (rewardData.periodFinish < block.timestamp).

The flow:

Given above contexts, if the vestingPeriod is updated in a new epoch, the issue arise when calculating the vestingRate for a staking of previous epoch, it will be calculated based on the new vestingPeriod incorrectly:

File: contracts\templegold\TempleGoldStaking.sol
484: function _getVestingRate(StakeInfo memory _stakeInfo) internal view returns (uint256 vestingRate) {
...
491: vestingRate = (block.timestamp - _stakeInfo.stakeTime) * 1e18 / vestingPeriod;
492: }

For example:

  1. The vestingPeriod is set to 20 days for a reward epoch.

  2. Alice stakes tokens on 07-06-2024, setting her StakeInfo.fullyVestedAt to 07-26-2024.

  3. The reward epoch ends on 07-16-2024.

  4. The vestingPeriod is updated to 12 days.

  5. The distributeRewards() is called to start a new reward epoch, the rewardData.periodFinish is updated to 07-28-2024.

  6. When Alice claims rewards on 07-25-2024: When updateReward(), the vestingRate is calculated using the new vestingPeriod: 19 days * 1e18 / 10 days, resulting in a much higher than intended rate. The correct rate should be calculated by on previous vestingRate: 19 days * 1e18 / 20 days.

Impact

When calculating the vestingRate for a staking info from a previous epoch, the new vestingPeriod is used, leading to incorrect reward calculations.

Tools Used

vscode

Recommendations

Save the vestingPeriod for each reward epoch within the rewardData. This way, the vestingPeriod used for calculating the vestingRate will correspond to the period during which the stake was made.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Changes to vesting period is not handled inside `_getVestingRate`

Support

FAQs

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