Core Contracts

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

Potential Division by Zero in `_applyBoost(...)` When `totalVeSupply` == 0

BaseGauge.sol

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/gauges/BaseGauge.sol#L229

The _applyBoost(...) function in BaseGauge calls BoostCalculator.calculateBoost(...) using totalVeSupply as a denominator, but never checks for totalVeSupply == 0. On a brand-new system or an extreme scenario, this can cause a division-by-zero revert or an undefined ratio. Properly handling zero supply—either by revert, default ratio, or documented fallback—will prevent unexpected reverts or nonsensical boosts.

Overview

The _applyBoost function uses:

function _applyBoost(address account, uint256 baseWeight) internal view virtual returns (uint256) {
if (baseWeight == 0) return 0;
IERC20 veToken = IERC20(IGaugeController(controller).veRAACToken());
uint256 veBalance = veToken.balanceOf(account);
uint256 totalVeSupply = veToken.totalSupply();
BoostCalculator.BoostParameters memory params = ...
uint256 boost = BoostCalculator.calculateBoost(
veBalance,
totalVeSupply,
params
);
return (baseWeight * boost) / 1e18;
}

If no one has minted veRAAC yet (e.g., at system launch or if a meltdown event caused all veRAAC to be burned), totalVeSupply may be zero. In many typical ratio or fraction calculations, dividing by zero triggers a revert or yields an undefined result. The snippet shows no check for totalVeSupply == 0 before calling BoostCalculator.calculateBoost, and no fallback path if totalVeSupply is zero.

Depending on the internal logic of BoostCalculator.calculateBoost, this may lead to:

  • Division by Zero revert,

  • An unintended “infinite” ratio or big number, or

  • A silent zero result—collapsing a user’s intended boost to zero even if they actually hold the entire supply (which just so happens to be the only supply).

Attack/PoC Example

  1. Freshly Deployed System
    A new gauge is deployed. No user has locked tokens in veRAAC, so veToken.totalSupply() == 0.

  2. First Staker
    A user attempts to stake in the gauge or calls a function that triggers _applyBoost(...).

  3. Division by Zero

    • If BoostCalculator tries to compute veBalance / totalVeSupply, it reverts or produces a nonsensical ratio.

    • The gauge might revert or silently produce a meaningless value for boost.

Impact

  • System Disruption
    If _applyBoost reverts, new stakers cannot proceed until at least one user obtains nonzero veRAAC supply. This is a poor user experience and might hamper initial gauge usage.

  • Incorrect Boost
    In a scenario where the “only” user has 100% of veRAAC (but totalVeSupply is still zero from a function’s perspective), the function might produce zero or an extremely large ratio—either incorrectly awarding no boost or an infinite one.

  • Confusion
    If the function gracefully returns zero or reverts, it breaks the intuitive notion that early adopters with the entire supply should get maximum boost. Instead, the system reverts or yields zero.

Recommendation

  1. Check totalVeSupply == 0
    In _applyBoost(...), do something like:

    if (totalVeSupply == 0) {
    // Either revert or treat the user as if they have 100% of supply => max boost
    return baseWeight; // or (baseWeight * params.maxBoost) / 1e18
    }

    That way, a brand-new system gracefully handles the first user or scenario with zero supply.

  2. Document Behavior
    If the design wants a revert when totalVeSupply == 0, explicitly state that no gauge boost is possible until veRAAC is minted. Alternatively, auto-assign a default ratio for the user. The key is clarity.

  3. Verify BoostCalculator
    Ensure the library’s calculateBoost(...) properly checks for a zero denominator, either returning zero or some default ratio. This ensures no revert or nonsense data.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!