Core Contracts

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

Loss of RAAC tokens when users attempt to create subsequent locks thru `lock()`  function

Summary

Missing restriction on subsequent calls to ‘lock’ function from an user with an already existing lock
will result in loss of previously locked RAAC tokens

Vulnerability Details

Contract : veRAACToken

In vote-escrow governanace systems
some protocols prefer a single lock per user due to simplicity,

while some protocols support multiple locks per user to offer versatility of varying durations.

Even though the protocol offers increase and extend functions to modify an existing lock,
Inadvertently some users may still attempt to create subsequent locks using lock function,

An example scenario,

Step 1 : Bob creates FirstLock -- > calls lock(10000 , 400 days)

Step 2 : Bob creates SecondLock -- > calls lock(20000, 500 days)

In this scenario,
when Bob tries to withdraw FirstLock after 400 days,
not only does the system revert with a LockNotExpired()
but the system has completely lost the account of his FirstLock of 10000 RAAC.

This is because the protocol does not support multiple locks per user.
Any subsequent lock ends up overwriting the previous lock's amount and duration as seen below.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/libraries/governance/LockManager.sol#L133-L137

state.locks[user] = Lock({
amount: amount,
end: end,
exists: true
});

The issue arises from lack of restriction in the lock function
to prevent users with an existing lock from creating subsequent locks.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/tokens/veRAACToken.sol#L212-L226

function lock(uint256 amount, uint256 duration) external nonReentrant whenNotPaused {
//ISSUE ! -->> MIssing checks to restrict users with an existing lock <<-- ISSUE !
if (amount == 0) revert InvalidAmount();
if (amount > MAX_LOCK_AMOUNT) revert AmountExceedsLimit();
if (totalSupply() + amount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
......

Impact

Impact : High

Users lose thier previously locked RAAC tokens

Likelihood : Med

Recommendations

Add a condtion to restrict users with an existing lock from making subsequent calls to lock function

function lock(uint256 amount, uint256 duration) external nonReentrant whenNotPaused {
// added condition
+ if (_lockState.locks[msg.sender].exists) revert ExistingLockNotAllowed();
if (amount == 0) revert InvalidAmount();
if (amount > MAX_LOCK_AMOUNT) revert AmountExceedsLimit();
if (totalSupply() + amount > MAX_TOTAL_SUPPLY) revert TotalSupplyLimitExceeded();
Updates

Lead Judging Commences

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

veRAACToken::lock called multiple times, by the same user, leads to loss of funds

Support

FAQs

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