Core Contracts

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

Unhandled Distribution Period Overwrite Leading to Incorrect Reward Calculations**

Summary

The FeeCollector contract contains a critical flaw in its reward distribution mechanism where the TimeWeightedAverage.createPeriod function overwrites the active distributionPeriod without accounting for ongoing distributions. This oversight disrupts time-weighted reward calculations, potentially causing incorrect payouts to veRAAC token holders and undermining the protocol’s reward distribution integrity.

Vulnerability Details

FeeCollector Contract_processDistributions Function:

if (shares[0] > 0) {
uint256 totalVeRAACSupply = veRAACToken.getTotalVotingPower();
if (totalVeRAACSupply > 0) {
TimeWeightedAverage.createPeriod( // ❌ Overwrites existing period
distributionPeriod,
block.timestamp + 1,
7 days,
shares[0],
totalVeRAACSupply
);
totalDistributed += shares[0];
} else {
shares[3] += shares[0];
}
}

Root Cause

  • Overwriting Active Periods: The createPeriod function resets the distributionPeriod state without checking if an active period is already ongoing. Subsequent distributions will overwrite the existing period’s startTime and endTime, disrupting the time-weighted reward calculations.

  • Lack of State Continuity: The contract fails to track historical periods or prorate rewards across overlapping time windows, leading to data loss for unclaimed rewards from previous periods.

  1. Initialization: The distributionPeriod is initialized in the constructor with a fixed 7-day duration.

  2. First Distribution: When distributeCollectedFees is called, createPeriod sets:

    • startTime = block.timestamp + 1

    • endTime = startTime + 7 days

  3. Second Distribution: If distributeCollectedFees is called again before the current endTime, the existing distributionPeriod is overwritten with a new period starting at the new block.timestamp + 1, discarding the remaining time from the previous period.

Impact

Users claiming rewards during overlapping periods will receive incorrect amounts, as calculations rely on the most recent (and potentially truncated) distributionPeriod.

Tools Used

Manual Review

Recommendations

** Implement Period Queueing**

Track historical periods to preserve time-weighted data:

// Add array to track all periods
TimeWeightedAverage.Period[] public distributionPeriods;
// Modify _processDistributions
if (shares[0] > 0) {
uint256 totalVeRAACSupply = veRAACToken.getTotalVotingPower();
if (totalVeRAACSupply > 0) {
// Create new period without overwriting
TimeWeightedAverage.Period memory newPeriod;
TimeWeightedAverage.createPeriod(
newPeriod,
block.timestamp,
block.timestamp + 7 days,
shares[0],
totalVeRAACSupply
);
distributionPeriods.push(newPeriod);
totalDistributed += shares[0];
} else {
shares[3] += shares[0];
}
}
Updates

Lead Judging Commences

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

Time-Weighted Average Logic is Not Applied to Reward Distribution in `FeeCollector`

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

Time-Weighted Average Logic is Not Applied to Reward Distribution in `FeeCollector`

Support

FAQs

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