Core Contracts

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

Funds Misallocation Due to Single Period Tracking in FeeCollector contract

Summary

The FeeCollector contract fails to maintain a history of distribution periods by overwriting a single distributionPeriod variable with each new distribution, leading to inaccurate reward calculations. This prevents the contract from properly implementing a time-weighted reward distribution, causing users to lose rewards from earlier periods if their voting power changes.

Vulnerability Details

The root cause of this vulnerability lies in the contract’s use of a single distributionPeriod variable of type TimeWeightedAverage.Period, which is updated in the _processDistributions function each time a new fee distribution occurs.
_processDistributions overwrites the existing distributionPeriod with data for the new 7-day period, discarding all information about previous periods.

if (shares[0] > 0) {
uint256 totalVeRAACSupply = veRAACToken.getTotalVotingPower();
if (totalVeRAACSupply > 0) {
TimeWeightedAverage.createPeriod(
distributionPeriod,
block.timestamp + 1,
7 days,
shares[0],
totalVeRAACSupply
);
totalDistributed += shares[0];
} else {
shares[3] += shares[0]; // Add to treasury if no veRAAC holders
}
}

In the _processDistributions function, when fees are distributed, shares[0] (the portion for veRAAC holders) is assigned to a new period, and totalDistributed is incremented to reflect the cumulative rewards. However, the reward calculation in _calculatePendingRewards, using the formula (totalDistributed * userVotingPower) / totalVotingPower relies solely on the user’s current voting power at the time of claiming, ignoring their historical voting power across past periods. Because distributionPeriod only stores the latest period’s data (e.g., startTime, endTime, value, and weight), the contract cannot reference earlier periods’ details, such as the total voting power or reward amounts specific to those times. This means the TimeWeightedAverage library, despite its capability to track time-weighted values via fields like weightedSum, is underutilized, its data is overwritten and never used for reward computation.

This design conflicts with the intended time-weighted distribution mechanism described in the protocol documentation, which states that it accounts for total voting power changes. A true time-weighted system requires tracking a history of all distribution periods to calculate rewards based on a user’s voting power over time, not just the most recent period.

Impact

  1. Users who participated in earlier distribution periods with high voting power but later reduced or withdrew their stakes receive fewer rewards or none at all, if their current voting power is low when they claim. This not only undermines fairness but also discourages long-term participation, as historical contributions are effectively erased.

  2. Users could exploit this by increasing their voting power just before claiming, gaining disproportionate rewards for past periods they didn’t fully participate in.

Tools Used

Manual Review

Recommendations

To address this issue, modify the contract to maintain a history of distribution periods rather than relying on a single distributionPeriod variable. Replace distributionPeriod with a mapping or array (e.g., mapping(uint256 => Period) public distributionPeriods with an incrementing periodId) to store each period’s data persistently. Update _processDistributions to create and store a new period entry without overwriting previous ones, and adjust _calculatePendingRewards to iterate over all past periods, calculating rewards based on the user’s voting power during each period using the TimeWeightedAverage library’s time-weighted features (e.g., leveraging weightedSum).

Updates

Lead Judging Commences

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

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

inallhonesty Lead Judge 7 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.

Give us feedback!