Core Contracts

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

Unused `distributionCap` Fails to Enforce Any Reward Limit

BaseGauge.sol

Overview

The code snippet shows:

uint256 public distributionCap;
function setDistributionCap(uint256 newCap) external {
if (!hasRole(FEE_ADMIN, msg.sender)) revert UnauthorizedCaller();
distributionCap = newCap;
emit DistributionCapUpdated(newCap);
}

But in the actual reward distribution flow:

  • notifyRewardAmount(uint256 amount) calls:

    if (amount > periodState.emission) revert RewardCapExceeded();
    ...
    rewardRate = notifyReward(periodState, amount, periodState.emission, getPeriodDuration());

    to set rewardRate based on the period’s emission.

  • No check references distributionCap or compares amount against distributionCap.

Hence, a user or admin can pass an amount to notifyRewardAmount(...) that exceeds distributionCap, and the contract never reverts. The only check is if (amount > periodState.emission) revert RewardCapExceeded();.

Impact

  1. Misleading Admin Setting
    The distributionCap variable is presumably intended to impose a final limit on how many reward tokens can be distributed from this gauge. But because the code never references it, an admin who sets distributionCap is not truly limiting anything.

  2. Incomplete or Contradictory Behavior
    If the protocol’s design calls for a maximum distribution cap across an entire gauge’s lifetime, ignoring it in notifyRewardAmount or _updateReward means the gauge can exceed that cap with no revert.

  3. Potential Overdistribution
    The contract checks only periodState.emission, but if distributionCap is supposed to be an additional or global distribution limit beyond the per-period emission, it’s never enforced.

Proof / PoC Example

A minimal test:

function testDistributionCapIgnored() public {
// 1) Admin sets distributionCap = 500k tokens
baseGauge.setDistributionCap(500_000e18);
// 2) Another admin calls notifyRewardAmount with 1 million tokens
// There's no revert referencing distributionCap.
// The contract only checks periodState.emission, not distributionCap.
baseGauge.notifyRewardAmount(1_000_000e18);
// => Succeeds if periodState.emission >= 1_000_000e18, ignoring distributionCap entirely
}

If distributionCap was intended as a global or per-call limit, the call should revert but does not.

Recommendation

  1. Enforce distributionCap
    In notifyRewardAmount(...), add:

    if (distributionCap > 0 && amount > distributionCap) {
    revert("Amount exceeds distributionCap");
    }

    or a similar check ensuring the newly requested distribution does not surpass distributionCap. Possibly also track total distributed to ensure cumulative distributions cannot exceed the cap.

  2. Remove distributionCap
    If the protocol logic only uses periodState.emission to limit distributions, remove distributionCap altogether to reduce confusion.

  3. Document Distinct Purposes
    If the contract intends to have both a “per‐period limit” (via periodState.emission) and an overall distribution limit (distributionCap), each must be clearly checked, documented, and enforced. Right now, only periodState.emission is used.

Updates

Lead Judging Commences

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

BaseGauge lacks enforcement of both distributionCap and MAX_REWARD_RATE limits

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

BaseGauge lacks enforcement of both distributionCap and MAX_REWARD_RATE limits

Support

FAQs

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

Give us feedback!