Core Contracts

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

Failure to Enforce `maxTotalLocked` Allows System-Wide Locking Limit to be Bypassed and Affects Governance Calculations

Summary

The LockManager.sol contract defines a system-wide maximum locked token limit (maxTotalLocked), but this limit is never enforced in either createLock() or increaseLock().

While per-user limits are correctly enforced (MAX_LOCK_AMOUNT for lock() and maxLockAmount for increaseLock()), the absence of a global total cap check allows multiple users to collectively exceed the intended total locked supply, leading to potential governance and economic distortions.

Vulnerability Details

First off, _lockState.totalLocked isn't capped at MAX_TOTAL_LOCKED_AMOUNT in both veRAACToken.lock() and veRAACToken.increase(). Such check is implemented in LockManager.increaseLock() but the associated code lines have been commented out.

LockManager.sol#L163-L164

// Maximum total locked amount
// if (state.totalLocked + additionalAmount > state.maxTotalLocked) revert AmountExceedsLimit();

As an example, multiple users can lock tokens up to their individual limit, leading to a higher total than maxTotalLocked allows, breaking tokenomics and will specifically dilute the boost multiplier for a user's rewards long term due to totalVeSupply, the denominator that continues to grow larger (because of unbounded _lockState.totalLocked) returning a smaller than intended votingPowerRatio in BoostCalculatorcalculateBoost():

BoostCalculator.sol#L86-L90

// Calculate voting power ratio with higher precision
uint256 votingPowerRatio = (veBalance * 1e18) / totalVeSupply;
// Calculate boost within min-max range
uint256 boostRange = params.maxBoost - params.minBoost;
uint256 boost = params.minBoost + ((votingPowerRatio * boostRange) / 1e18);

Note: The above issue will surface should MAX_TOTAL_SUPPLY is being reached proportionately slower than MAX_TOTAL_LOCKED_AMOUNT.

Regardless, users can always sneak through increase() that's devoid of MAX_TOTAL_SUPPLY check and indefinitely make _lockState.totalLocked and totalVeSupply separately grow unbounded.

Impact

The unexpected behavior in tokenomics and governance, e.g. boost, calculations could lead to disproportionate voting power, i.e. users using multiple accounts could extend/consolidate their voting power unbounded whereas normal users are getting dwarfed correspondingly with their voting ability. In extreme cases, precision issue could surface on voters with very small voting power (i.e., veBalance or point.bias) and assigned params.minBoost only.

Tools Used

Manual

Recommendations

Uncomment such crucial check in LockManager.increaseLock(), and implement the same check in LockManager.createLock().

Updates

Lead Judging Commences

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

`veRAACToken::lock` function doesn't check MAX_TOTAL_LOCKED_AMOUNT

Support

FAQs

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

Give us feedback!