TempleGold

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

Zero total supply before a user stakes in `TempleGoldStaking` within the reward distribution leads to locked funds for that frame.

Summary

The scenario where the reward distribution starting before anyone staking leading to stuck funds is fixed by checking for total supply before starting distribution, but a similar scenario exist during the reward distribution period where there are no stakes (zero total supply of staking token) when a user stakes at any point during a staking period as funds were withdrawn at a earlier point during that distribution period

This results in locked funds which were not allocated in `rewardPerTokenStored` for that particular time frame within the reward distribution period when there was zero total supply.

Vulnerability Details

  • The vulnerability arises during the distribution period when before a user stakes there is zero total supply as stakes were withdrawn during that distribution period, which results in locked TGLD reward token for the frame when there was no total supply until a user stakes.

  • The `rewardPerTokenStored` will not account anything for that particular frame as the total supply was 0 for that frame, and the token that was supposed to be allocated in that frame will remain locked in the contract as it is not assigned.

  • Before the user deposits are updated, updateReward is called and in there the rewardPerTokenStored will not be updated as there was no total supply for the scenario this finding discusses on, thus those particular reward for that time frame will never be allocated.

Impact

Locked reward TGLD token in `TempleGoldStaking` contract as there was no supply before (all supply was withdrawn) a user has staked within a distribution period.

PoC

  1. Alice stakes some tokens, and then starts the reward distribution period.

  2. After x days within the distribution period performs a withdrawal of all the assets, now the total supply will be 0.

  3. Now after y time has passed from the Alice withdrawal, the total supply will be 0 as there are no stakes, and at this particular point suppose Bob performs stake operation and updateReward is called before Bob's updation are performed and as total supply is still 0, the rewardPerTokenStored will remain as it is as expected but the reward that was supposed to be distributed for that time frame when total supply was 0 will be stuck forever.

  4. Because the next rewardPerTokenStored will now be calculated from the timestamp when that user staked, therefore the token allocation for the period when total supply was 0 will be neglected.

Tools Used

Manual Review

Recommendations

In the updateReward modifier, whenever total supply is detected as 0, then for this discussed scenario where from the last updation time stamp to current, there were reward tokens (which were expected to be allocated in rewardPerToken but can't be done due to total supply being 0), then allocate those tokens for nextRewardAmount.

modifier updateReward(address _account, uint256 _index) {
{
+ if (totalSupply == 0) {
+ uint256 tokensForCurrentTimeFrame = (_lastTimeRewardApplicable(rewardData.periodFinish) - rewardData.lastUpdateTime) * rewardData.rewardRate;
+ nextRewardAmount += tokensForCurrentTimeFrame;
+ }
// stack too deep
rewardData.rewardPerTokenStored = uint216(_rewardPerToken());
rewardData.lastUpdateTime = uint40(_lastTimeRewardApplicable(rewardData.periodFinish));
if (_account != address(0)) {
StakeInfo memory _stakeInfo = _stakeInfos[_account][_index];
uint256 vestingRate = _getVestingRate(_stakeInfo);
claimableRewards[_account][_index] = _earned(_stakeInfo, _account, _index);
userRewardPerTokenPaid[_account][_index] = vestingRate * uint256(rewardData.rewardPerTokenStored) / 1e18;
}
}
_;
}
Updates

Lead Judging Commences

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

At the first time a account is called in that index, `userRewardPerTokenPaid[_account][_index]`will equal to 0

Support

FAQs

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