Core Contracts

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

: Incorrect Period Finish Calculation in `_updateReward`

Summary

In the BaseGauge contract, the _updateReward function updates the lastUpdateTime using the lastTimeRewardApplicable function. However, due to an incorrect implementation of the periodFinish function, the reward period never properly ends. As a result, rewards continue to accrue indefinitely, allowing users to earn rewards beyond the intended period.

Vulnerability Details

  • What Went Wrong:
    The lastTimeRewardApplicable function is defined as:

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

and the periodFinish function is implemented as:

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

Here, getPeriodDuration() returns a fixed duration (e.g., 7 days for RAAC or 30 days for RWA). However, since lastUpdateTime is updated in the _updateReward function:

lastUpdateTime = lastTimeRewardApplicable();

each interaction updates lastUpdateTime to the current block.timestamp. This means that periodFinish() becomes block.timestamp + getPeriodDuration() on every call, and the condition in lastTimeRewardApplicable almost always returns block.timestamp.
Consequently, the reward calculation never recognizes that the reward period has ended, and users continue to accumulate rewards even after the intended period expiration.
Why It Matters:
The intended design is that once the reward period expires, no additional rewards should accrue. However, due to the shifting lastUpdateTime, the system incorrectly treats every call as if it were still within an active reward period. This leads to an unintended and continuous accumulation of rewards.

Impact

Infinite Reward Accrual:
Users can earn rewards indefinitely because the reward period never properly closes.
Economic Imbalance:
This bug undermines the reward distribution mechanism, potentially leading to excessive token minting and diluting the value of rewards.
Exploitation Risk:
Malicious users could take advantage of the perpetual reward accrual to manipulate the system's economics, affecting both current and future stakeholders.

Tools Used

Manual Code Review: We analyzed the implementation of _updateReward, lastTimeRewardApplicable, and periodFinish functions, and identified that updating lastUpdateTime on every call prevents the reward period from ever ending.

Recommendations

Separate Reward Period Tracking:
Redesign the reward period logic so that periodFinish is calculated based on a fixed start time for the reward period rather than on the mutable lastUpdateTime. For example:

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

This change ensures that the reward period is fixed and does not shift with each user interaction.
Adjust Update Mechanism:
Modify _updateReward to update lastUpdateTime appropriately without affecting the fixed reward period. Ensure that new stakes or withdrawals do not inadvertently extend the reward period.

Updates

Lead Judging Commences

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

BaseGauge period end time miscalculation creates circular dependency between periodFinish() and lastUpdateTime, preventing periods from naturally ending and disrupting reward distribution

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

BaseGauge period end time miscalculation creates circular dependency between periodFinish() and lastUpdateTime, preventing periods from naturally ending and disrupting reward distribution

Support

FAQs

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