Core Contracts

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

Unlimited Gauge Emissions Due to Fixed Rate Implementation

Summary

The GaugeController implements a fixed emission rate system where each gauge type (RWA and RAAC) has predetermined token emission rates. While individual gauges have proper caps, the protocol lacks a global emission control mechanism, allowing unlimited total emissions when multiple gauges are active.

Vulnerability Details

The root cause of the vulnerability lies in the GaugeController's emission calculation and distribution logic:\

// GaugeController.sol
function _calculateRWAEmission() internal view returns (uint256) {
// Monthly RWA emission calculation
return 1000000 * 10**18; // Fixed 1,000,000 tokens monthly
}
function _calculateRAACEmission() internal view returns (uint256) {
// Weekly RAAC emission calculation
return 250000 * 10**18; // Fixed 250,000 tokens weekly
}

Reward Distribution Logic:

// GaugeController.sol
function _calculateReward(address gauge) internal view returns (uint256) {
Gauge storage g = gauges[gauge];
uint256 totalWeight = getTotalWeight();
if (totalWeight == 0) return 0;
uint256 gaugeShare = (g.weight * WEIGHT_PRECISION) / totalWeight;
uint256 typeShare = (typeWeights[g.gaugeType] * WEIGHT_PRECISION) / MAX_TYPE_WEIGHT;
// @audit-issue each gauge gets its full type emission multiplied by its share
uint256 periodEmission = g.gaugeType == GaugeType.RWA ?
_calculateRWAEmission() : // 1M monthly
_calculateRAACEmission(); // 250K weekly
return (periodEmission * gaugeShare * typeShare) / (WEIGHT_PRECISION * WEIGHT_PRECISION);
}

Notice anyone can call distributeRewardsto assign rewards to any active gauge.

function distributeRewards(
address gauge
) external override nonReentrant whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
if (!gauges[gauge].isActive) revert GaugeNotActive();
uint256 reward = _calculateReward(gauge);
if (reward == 0) return;
// @audit-issue anyone can distribute the full amont of rewards to all active gauges.
IGauge(gauge).notifyRewardAmount(reward);
emit RewardDistributed(gauge, msg.sender, reward);
}

The vulnerability exists because:

  • Each gauge type has a fixed emission rate that doesn't scale with the number of active gauges.

  • Every active gauge can receive rewards up to their individual cap in each period.

  • The emission rates are hardcoded and cannot be adjusted based on market conditions or protocol state.

Impact

  • Anyone can call distributeRewards and distribute the hardcoded amount of rewards for all active gauges until the emission for that period is reached.

  • With N active gauges, the protocol could emit up to N * (fixed_rate) tokens per period

  • Fixed rates ignore market conditions and total token supply, potentially leading to severe inflation

  • Each new gauge can claim the full emission rate

Tools Used

Manual Review

Recommendations

  1. Implement protocol-wide emission caps for each period

  2. Replace fixed emission rates with governance-controlled parameters

  3. Scale emission rates based on the number of active gauges

Updates

Lead Judging Commences

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

GaugeController's distributeRewards lacks time-tracking, allowing attackers to repeatedly distribute full period rewards until hitting emission caps

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

GaugeController's distributeRewards lacks time-tracking, allowing attackers to repeatedly distribute full period rewards until hitting emission caps

Support

FAQs

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

Give us feedback!