TempleGold

TempleDAO
Foundry
25,000 USDC
View results
Submission Details
Severity: high
Invalid

TempleGoldStaking.sol#_rewardPerToken() - reward per token does not get reset each auction and bricks the rewards

Summary

The reward per token variable is the heart of the staking mechanism, calculating how much rewards people are eligible for, calculated based on the current supply and time passed. During regular auctions, it's value always starts from 0 and keeps an accurate representation of rewards earned. However the TempleGoldStaking runs all of the auctions inside itself, without resetting the reward per token from previous auctions, leading to overinflation of the earned rewards for further auctions, which would unintetionally brick the rewards for stakers.

Vulnerability Details

The easiest way to showcase this is with an example scenario:

  1. User A stakes for the first time. We do the staking first since the contract MUST have staked tokens before beginning the first auction. The user stakes 1000 tokens, so the totalSupply and his balance are 1000, rewardPerToken and claimable are 0. The lastUpdateTime will be 0 for simplicity

  2. We begin an auction with 10000 TGLD and 10000 duration, so the rewardRate = 1. The lastUpdate = 1000 for the example

  3. Nobody else stakes for the entire 10000 duration. User A can either claim or hold for new auctions. This is intended and he should be able to claim all of his rewards at all times.

  4. A new auction begins with the same parameters: 10000 TGLD and 10000 duration, so the rewardRate = 1, lastUpdate = 10000. This time the rewardPerToken will get updated via it's formula (10000 - 1000) / 1000 * 1e18 = 9e18 . This value holds the rewards User A can claim from the first auction.

  5. User B stakes into the second auction. The user stakes 1000 tokens, so the totalSupply is 2000, his balance is 1000, lastUpdate = 11000, which leads to rewardPerToken getting updated to 10e18(due to 1000 seconds passing)

  6. The second auction finishes as well. User A has had stakes for both auctions and wishes to claim. He initiates a claim at the finish timestamp 20000. This means his rewardPerToken is calculated as (20000 - 11000)e18 / 2000 + 10e18 = 14.5e18. Now he should receive his claimable tokens based on this value, which are calculated as 1000(his stake) * 14.5(rewardPerToken) - claimable(0 until now) = 14500 TGLD. For User A this seems fair, since he is eligible for all rewards from auction 1 and a part of auction 2 rewards. However rewardPerToken for User B has the same value of 14.5e18, leading to the same calculation as above.

  7. User B is eligible for the same amount of rewards as User A even though he had been staking for only 1 auction instead of 2. This, and also considering the fact that the total TGLD of both auctions is 20000 but the earned for the users is 29000, leads to users being unable to claim their rewards after the first claimer.

Impact

User are unable to fully claim their funds after the first claimer. This happens for every auction after the first one, since the rewardPerToken does not get reset to 0 for the new stakers.

Tools Used

Manual Review

Recommendations

The rewardPerToken should get reset every new auction. It's value should only be perceived for users who are keeping their stake between auctions, to allow them to claim past AND current rewards.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

ptsanev Submitter
11 months ago
ptsanev Submitter
11 months ago
inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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