Core Contracts

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

Incorrect Supply Cap Check in veRAACToken Prevents Valid Locks (Wrong Token Comparison)

Link to Affected Code:

LOCK_Function

Description:

The lock function performs an incorrect supply cap check by comparing RAAC tokens against veRAAC supply limit. This logic is only correct if both tokens maintain a 1:1 ratio. But according to this callculation, its only a 1:1 ratio if a user is locking their RAAC tokens for 4 years. Look at here:

function calculateVeAmount(uint256 amount, uint256 lockDuration) external pure returns (uint256) {
if (amount == 0 || lockDuration == 0) return 0;
if (lockDuration > MAX_LOCK_DURATION) lockDuration = MAX_LOCK_DURATION;
// Calculate voting power as a linear function of lock duration
return (amount * lockDuration) / MAX_LOCK_DURATION;
}

So the cap check can revert with TotalSupplyLimitExceeded for valid locks up because of this comparism:

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

This check is fundamentally wrong because:

  1. totalSupply() returns veRAAC tokens

  2. amount is in RAAC tokens

  3. The actual veRAAC minted is (amount * duration) / MAX_LOCK_DURATION

  4. Comparing different token units leads to incorrect restrictions

Impact:

  • Prevents valid lock operations that would mint less veRAAC than MAX_TOTAL_SUPPLY

  • Creates unnecessary DoS for users trying to lock RAAC tokens

Proof of Concept:

Let's look a this scenerio where totalSupply is a 91m and a user wants to lock 10m RAAC tokens for a year.

The calculation in the current code is
// totalSupply() + amount > MAX_TOTAL_SUPPLY
// 91m veRaac + 10m RAAC > 100m veRaac
// Reverts because of the storage cap
This is totally wrong because of the wrong comparism.
Here is the actual way its suppose to be
This is totally wrong because the `calculateVeAmount` formula returns the actual veRaac we are to get :
// (10m * 1 year)/4 = 2,500,000 veRacc which is a valid lockup
// 91m + 2,5m < 100m so it passes

Recommended Mitigation:


- Calculate actual veRAAC amount before supply cap check:

function lock(uint256 amount, uint256 duration) external nonReentrant whenNotPaused {
if (amount == 0) revert InvalidAmount();
if (amount > MAX_LOCK_AMOUNT) revert AmountExceedsLimit();
// Calculate actual veRAAC to be minted
uint256 veAmount = (amount * duration) / MAX_LOCK_DURATION;
if (totalSupply() + veAmount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
// Rest of function...
}
Updates

Lead Judging Commences

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