Core Contracts

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

Non-Consecutive Reward Periods

Summary

The updatePeriod() function incorrectly calculates the start time of the next reward period, skipping a period when called at the exact end of the current period. This creates gaps between periods, violating the invariant that reward periods must be consecutive.

Vulnerability Details

function updatePeriod() external override onlyController {
uint256 currentTime = block.timestamp;
uint256 periodEnd = periodState.periodStartTime + getPeriodDuration();
if (currentTime < periodEnd) {
revert PeriodNotElapsed();
}
uint256 periodDuration = getPeriodDuration();
// Calculate average weight for the ending period
uint256 avgWeight = periodState.votingPeriod.calculateAverage(periodEnd);
// Calculate the start of the next period (ensure it's in the future)
uint256 nextPeriodStart = ((currentTime / periodDuration) + 2) * periodDuration;
// Reset period state
periodState.distributed = 0;
periodState.periodStartTime = nextPeriodStart;
// Create new voting period
TimeWeightedAverage.createPeriod(
periodState.votingPeriod,
nextPeriodStart,
periodDuration,
avgWeight,
WEIGHT_PRECISION
);
}

In updatePeriod(), the next period's start time is calculated as

uint256 nextPeriodStart = ((currentTime / periodDuration) + 2) * periodDuration;

For example:

If periodDuration = 7 days and currentTime = 1,209,600 (end of week 2):

  • currentTime / periodDuration = 2 (since 1,209,600 / 604,800 = 2)

  • nextPeriodStart = (2 + 2) * 604,800 = 2,419,200 (start of week 4)

  • Week 3 (1,814,400) is skipped entirely.

Impact

No rewards are distributed during the skipped period. Functions like getTimeWeightedWeight() return incorrect values during the gap.

Tools Used

Foundry

Recommendations

Calculate nextPeriodStart to start immediately after the current period ends

// Corrected calculation (no +2 offset)
uint256 nextPeriodStart = periodState.periodStartTime + periodDuration;
Updates

Lead Judging Commences

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

BaseGauge::updatePeriod uses ((currentTime / periodDuration) + 2) calculation causing entire reward periods to be skipped, resulting in permanent loss of user rewards

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

BaseGauge::updatePeriod uses ((currentTime / periodDuration) + 2) calculation causing entire reward periods to be skipped, resulting in permanent loss of user rewards

Support

FAQs

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

Give us feedback!