Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

re-updating `lastUpdateTime` in `BaseGauge.sol::notifyRewardAmount()` could be problamatic.

Summary

notifyRewardAmount is as follow -

function notifyRewardAmount(uint256 amount) external override onlyController updateReward(address(0)) {
if (amount > periodState.emission) revert RewardCapExceeded();
rewardRate = notifyReward(periodState, amount, periodState.emission, getPeriodDuration());
periodState.distributed += amount;
// $mynotes - balance of specific guage contract.
uint256 balance = rewardToken.balanceOf(address(this));
if (rewardRate * getPeriodDuration() > balance) {
revert InsufficientRewardBalance();
}
@ -1 > lastUpdateTime = block.timestamp;
emit RewardNotified(amount);
}

firstly it will call modifier updateReward() ->

modifier updateReward(address account) {
_updateReward(account);
_;
}
function _updateReward(address account) internal {
rewardPerTokenStored = getRewardPerToken();
@ -> lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
UserState storage state = userStates[account];
state.rewards = earned(account);
state.rewardPerTokenPaid = rewardPerTokenStored;
state.lastUpdateTime = block.timestamp;
emit RewardUpdated(account, state.rewards);
}
}

lastTimeRewardApplicable() ->

function lastTimeRewardApplicable() public view returns (uint256) {
return block.timestamp < periodFinish() ? block.timestamp : periodFinish();
}

periodFinish() ->

function periodFinish() public view returns (uint256) {
return lastUpdateTime + getPeriodDuration();
}

getPeriodDuration() ->

function getPeriodDuration() public view virtual returns (uint256) {
return 7 days; // Default period duration, can be overridden by child contracts
}
  1. So, if block.timestamp is greater than periodFinish(), then lastUpdateTime = periodFinish().

  2. But code line marked as @ -1 > is reupdating lastUpdateTime to block.timestamp.

lastUpdateTime = block.timestamp;
  1. Which is incorrect, it should only be value that's being updated in modifier.

Vulnerability Details

Same as above.

Impact

lastUpdateTime is associated with reward claim on gauge contracts, it's incorrect value could either lead to delay of reward or early reward claim, not good for user and protcol repectively.

Tools Used

Manual

Recommendations

remove lastUpdateTime = block.timestamp; from notifyRewardAmount() functions.

Updates

Lead Judging Commences

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

BaseGauge sets user's lastUpdateTime to uncapped block.timestamp while global lastUpdateTime uses capped lastTimeRewardApplicable(), generating reward calc inconsistencies after period ends

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

BaseGauge sets user's lastUpdateTime to uncapped block.timestamp while global lastUpdateTime uses capped lastTimeRewardApplicable(), generating reward calc inconsistencies after period ends

Support

FAQs

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