TempleGold

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

Lack of Function Modifier Checking `rewardDistributionCoolDown`

Summary

In the distributeRewards() function, there is a check for rewardDistributionCoolDown, but the check is not correctly implemented to enforce the cooldown period before distributing rewards again. This can potentially lead to incorrect or premature reward distributions, violating the intended logic of the contract.

Vulnerability Details

function distributeRewards() updateReward(address(0), 0) external {
if (distributionStarter != address(0) && msg.sender != distributionStarter) {
revert CommonEventsAndErrors.InvalidAccess();
}
if (totalSupply == 0) {
revert NoStaker();
}
// Mint and distribute TGLD if no cooldown set
if (lastRewardNotificationTimestamp + rewardDistributionCoolDown > block.timestamp) {
revert CannotDistribute();
}
_distributeGold();
uint256 rewardAmount = nextRewardAmount;
// revert if next reward is 0 or less than reward duration (final dust amounts)
if (rewardAmount < rewardDuration) {
revert CommonEventsAndErrors.ExpectedNonZero();
}
nextRewardAmount = 0;
_notifyReward(rewardAmount);
lastRewardNotificationTimestamp = uint32(block.timestamp);
}

https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/TempleGoldStaking.sol#L180C1-L195C1

Problem: The check if (lastRewardNotificationTimestamp + rewardDistributionCoolDown > block.timestamp) is intended to enforce a cooldown period between reward distributions. However, the comparison logic here might not achieve the intended cooldown effect due to potential overflow issues with uint160 type for rewardDistributionCoolDown.

  • Risk: This oversight can allow rewards to be distributed more frequently than intended, possibly leading to incorrect reward allocation or exploitation of the reward distribution mechanism.

  • Type Mismatch: Depending on how rewardDistributionCoolDown is defined and its type (it appears as uint160), there could be unintended behavior due to type mismatches or arithmetic overflow.


    Let's break down the check with an example:

  • Suppose lastRewardNotificationTimestamp is 100 and rewardDistributionCoolDown is 200.

  • If block.timestamp is 300, the check 100 + 200 > 300 would evaluate to false, which correctly allows distribution.

  • However, if block.timestamp is 150, then 100 + 200 > 150 would evaluate to true, incorrectly preventing distribution because 100 + 200 overflows and wraps around due to being more than block.timestamp.

Impact

Without proper cooldown management, rewards could be distributed prematurely, potentially leading to unintended incentives or economic imbalances within the staking ecosystem.

Tools Used

Recommendations

This revised logic ensures that rewards are distributed only if enough time (rewardDistributionCoolDown seconds) has passed since the last distribution, using safe arithmetic operations to prevent unexpected behaviors.

if (rewardDistributionCoolDown > 0 && lastRewardNotificationTimestamp + uint256(rewardDistributionCoolDown) > block.timestamp) {
revert CannotDistribute();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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