TempleGold

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

`TempleGoldStaking::distributeRewards()` doesn't emit an event despite changing state

Summary

TempleGoldStaking::distributeReward() function is used to distribute TGLD emission rewards minted to the TempleGoldStaking contract to stakers. It starts another epoch of rewards distribution and calculates new rewardRate from any left over rewards up until now. Despite performing major state changes, it doesn't emit a corresponding event.

Vulnerability Details

It is an unskippable best practice to emit an event whenever a state change happens to a contract. TempleGoldStaking::distributeRewards() calls TempleGoldStaking::_notifyReward() function which in turn perform operations and update the nextRewardAmount and rewardData state variables. Despite making crucial state changes, the function doesn't emit an event.

Impact

As events are used by off-chain services to track contract activities, incorrect event emission may cause unforseen discrepancies. Despite perhaps not seeing the need to emit events in some cases at the moment, it is always better to do so since contracts are immutable but the need to index such events may come up at any time in the future.

Recommendations

Update TempleGoldStaking::distributeRewards() to emit a suitable event and append it to the events list in ITempleGoldStaking.

interface ITempleGoldStaking {
event GoldDistributionNotified(uint256 amount, uint256 timestamp);
event Staked(address indexed staker, uint256 amount);
event MigratorSet(address migrator);
event Withdrawn(address indexed staker, address to, uint256 stakeIndex, uint256 amount);
event RewardDistributionCoolDownSet(uint160 cooldown);
event DistributionStarterSet(address indexed starter);
event VestingPeriodSet(uint32 _period);
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
event RewardPaid(address indexed staker, address toAddress, uint256 index, uint256 reward);
event RewardDurationSet(uint256 duration);
+ event RewardsDistributed(uint256 rewardAmount);
}
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);
+ emit RewardsDistributed(rewardAmount);
}

Tools Used

Manual Review.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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