Core Contracts

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

Incorrect Total Supply Check Leading to Potential Exceedance of MAX_TOTAL_SUPPLY in veRAACToken::lock function

Summary

The lock function in the veRAACToken contract checks whether totalSupply() + amount exceeds MAX_TOTAL_SUPPLY. However, the actual veRAAC tokens minted are calculated as (amount * duration) / MAX_LOCK_DURATION, which can result in a discrepancy. This allows the total veRAAC supply to exceed MAX_TOTAL_SUPPLY if many short-term locks are created, undermining the intended supply cap.

Vulnerability Details

  • The check for exceeding MAX_TOTAL_SUPPLY uses the raw amount of RAAC tokens being locked (totalSupply() + amount > MAX_TOTAL_SUPPLY) instead of the actual veRAAC tokens that will be minted.

  • The actual veRAAC tokens minted are calculated as (amount * duration) / MAX_LOCK_DURATION, which could be significantly smaller than the amount for short-term locks.

  • This discrepancy means that multiple short-term locks could collectively exceed MAX_TOTAL_SUPPLY without triggering the check

  • Supply Check: The lock function checks:

if (totalSupply() + amount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();

Here, amount is the number of RAAC tokens being locked, not the veRAAC tokens being minted.

  • Actual Minted Amount: The veRAAC minted is newPower, calculated as:

uint256 initialPower = (amount * duration) / MAX_LOCK_DURATION;
  • If duration == MAX_LOCK_DURATION (4 years), newPower = amount.

  • If duration < MAX_LOCK_DURATION, newPower < amount.

  • If duration = MIN_LOCK_DURATION (1 year), newPower = amount * 365 / 1460 = amount / 4.

  • Scenario Analysis:

    • Max Duration Lock: Lock 50M RAAC for 4 years:

      • Check: totalSupply() (0) + 50M < 100M → Passes

      • Mint: `(50M * 1460 days) / 1460 days = 50M` veRAAC

      • Total supply = 50M veRAAC (within limit)

    • Min Duration Locks: Lock 50M RAAC for 1 year, then another 50M for 1 year:

      • First lock:

        • Check: 0 + 50M < 100M → Passes

        • Mint: (50M * 365 days) / 1460 days = 12.5M veRAAC

        • Total supply = 12.5M veRAAC

      • Second lock:

        • Check: 12.5M + 50M = 62.5M < 100M → Passes

        • Mint: (50M * 365 days) / 1460 days = 12.5M veRAAC

        • Total supply = 25M veRAAC

      • Now, lock another 50M RAAC for 1 year:

        • Check: 25M + 50M = 75M < 100M → Passes

        • Mint: 12.5M veRAAC

        • Total supply = 37.5M veRAAC

      • Continue this pattern: You could lock 400M RAAC (4 * 100M) over multiple 1-year locks, minting 400M * 365 / 1460 = 100M veRAAC, hitting the cap exactly, but the check only sees totalSupply() + amount, allowing further locks.

Impact

  1. The MAX_TOTAL_SUPPLY (100M veRAAC) is intended as a cap on circulating veRAAC tokens, which represent voting power and boost capabilities. Exceeding this cap dilutes the system’s integrity, potentially inflating voting power or rewards beyond design limits.
    Example: If users lock 400M RAAC in 1-year locks (minting 100M veRAAC), then later extend locks or create new 4-year locks, the total veRAAC could grow beyond 100M, as the initial check doesn’t account for the time-weighted minting formula.

  2. Violating the total supply cap in a vote-escrow token system undermines governance and economic assumptions, potentially leading to over-allocation of voting power or rewards.

Tools Used

Manual Review

Recommendations

  • Modify the lock function to check the actual veRAAC tokens that will be minted ((amount * duration) / MAX_LOCK_DURATION) against MAX_TOTAL_SUPPLY instead of the raw amount.

Updates

Lead Judging Commences

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

Incorrect `MAX_TOTAL_SUPPLY` check in the `veRAACToken::lock/extend` function of `veRAACToken` could harm locking functionality

Support

FAQs

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