Core Contracts

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

Inadequate distribution period management in FeeCollector Contract

Summary

The FeeCollector contract initializes a distribution period in the constructor but lacks mechanisms to handle period transitions, leading to reward distribution issues.

Vulnerability Details

// Lines 152-153
distributionPeriod.startTime = block.timestamp;
distributionPeriod.endTime = block.timestamp + 7 days;

The contract initializes a single distribution period but does not implement mechanisms to:

  1. Create new periods after the initial period expires

  2. Handle transitions between periods

  3. Track or validate period states during distributions

This is further complicated by the distribution logic in _processDistributions() (Lines 401-424), which creates new periods without proper period management:

TimeWeightedAverage.createPeriod(
distributionPeriod,
block.timestamp + 1,
7 days,
shares[0],
totalVeRAACSupply
);

Impact

  1. Reward Distribution Errors
    Rewards will continue to be distributed using the same period parameters even after the initial period expires
    No validation of period status during distributions
    Potential for rewards to be distributed in expired periods

  2. Financial Impact
    Incorrect reward calculations for veRAAC holders
    Unfair distribution of protocol fees
    Accumulated rewards may be calculated incorrectly

  3. System State
    No proper tracking of distribution periods
    No historical record of distributions
    Inability to audit or verify distribution correctness

Tools Used

Manual code review

Recommendations

  1. Implement proper period management:

struct DistributionPeriod {
uint256 startTime;
uint256 endTime;
uint256 totalRewards;
bool isActive;
}
function _createNewPeriod() internal {
require(block.timestamp >= distributionPeriod.endTime, "Current period not ended");
distributionPeriod = DistributionPeriod({
startTime: block.timestamp,
endTime: block.timestamp + 7 days,
totalRewards: 0,
isActive: true
});
emit NewPeriodCreated(distributionPeriod.startTime, distributionPeriod.endTime);
}
function distributeCollectedFees() external override nonReentrant whenNotPaused {
if (!hasRole(DISTRIBUTOR_ROLE, msg.sender)) revert UnauthorizedCaller();
if (block.timestamp >= distributionPeriod.endTime) {
_createNewPeriod();
}
require(distributionPeriod.isActive, "Period not active");
// ... rest of the distribution logic
}
  1. Add period validation:

modifier onlyActivePeriod() {
require(
block.timestamp >= distributionPeriod.startTime &&
block.timestamp < distributionPeriod.endTime &&
distributionPeriod.isActive,
"Invalid period"
);
_;
}
  1. Implement period tracking:

mapping(uint256 => DistributionPeriod) public distributionPeriods;
uint256 public currentPeriodId;
function _createNewPeriod() internal {
currentPeriodId++;
distributionPeriods[currentPeriodId] = DistributionPeriod({
startTime: block.timestamp,
endTime: block.timestamp + 7 days,
totalRewards: 0,
isActive: true
});
}
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!