Core Contracts

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

veRAAC Token Max Total Supply Check can be Bypassed

Summary

The lock function in the veRAACToken contract contains a flawed check to prevent exceeding the max total supply of veRAACToken. The function checks whether totalSupply() + amount exceeds MAX_TOTAL_SUPPLY, but the amount of veRAACTokens minted depends on both the lock amount and the lock duration, meaning the actual minted amount can be higher than the deposit amount. This can result in exceeding the max total supply limit.


Vulnerability Details

The incorrect total supply check assumes that the veRAACTokens minted are equal to the lock amount:

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

However, the minted amount is actually calculated based on the lock amount and lock duration, which can be greater than amount. Because of this, the check is ineffective, and the total supply of veRAACToken can exceed MAX_TOTAL_SUPPLY, violating supply constraints.

Code Reference:

function lock(uint256 amount, uint256 duration) external nonReentrant whenNotPaused {
if (amount == 0) revert InvalidAmount();
if (amount > MAX_LOCK_AMOUNT) revert AmountExceedsLimit();
if (totalSupply() + amount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
if (duration < MIN_LOCK_DURATION || duration > MAX_LOCK_DURATION)
revert InvalidLockDuration();
// Transfer tokens first
raacToken.safeTransferFrom(msg.sender, address(this), amount);
// Calculate unlock time
uint256 unlockTime = block.timestamp + duration;
// Create lock position
_lockState.createLock(msg.sender, amount, duration);
_updateBoostState(msg.sender, amount);
// Calculate voting power (minted veRAAC amount depends on lock duration too)
(int128 bias, int128 slope) = _votingState.calculateAndUpdatePower(
msg.sender,
amount,
unlockTime
);
// Update checkpoints
uint256 newPower = uint256(uint128(bias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
// **Incorrect max supply check: minted amount is not equal to locked amount**
_mint(msg.sender, newPower);
emit LockCreated(msg.sender, amount, unlockTime);
}

Exploitation Scenario:

  1. A user locks 100 tokens for 4 years, receiving 400 veRAACTokens due to the extended duration multiplier.

  2. The contract checks whether totalSupply() + 100 exceeds MAX_TOTAL_SUPPLY, which it does not.

  3. However, the actual minted veRAACTokens are 400, which are then added to the total supply.

  4. the total supply can exceed the MAX_TOTAL_SUPPLY limit, breaking the protocol constraints.

Impact

  • Total Supply Exceeds Defined Limits: The protocol's intended supply cap for veRAACToken is bypassed.


Suggested Fixes

  1. Check Minted veRAACToken Amount Instead of Lock Amount

    • Modify the check to use the actual minted amount (newPower) instead of the raw amount.

    • Example Fix:

    uint256 newPower = uint256(uint128(bias));
    if (totalSupply() + newPower > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
  2. Precompute Minted Amount Before Checking Total Supply

    • Instead of checking totalSupply() + amount, first compute the actual veRAACTokens to be minted and use that for validation.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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.