Core Contracts

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

Bypass of minimum lock duration in veRAACToken

Summary

The increase function in veRAACToken.sol allows users to bypass the minimum lock duration requirement by adding tokens to an existing lock after some time has passed, enabling shorter-than-intended lock periods and potential governance and boost manipulation.

Vulnerability Details

When users lock tokens via the function lock in veRAAC token, there are proper checks in place to see to that the MIN_LOCK_DURATION is not breached:

function lock(
uint256 amount,
uint256 duration
) external nonReentrant whenNotPaused {
//...
if (duration < MIN_LOCK_DURATION || duration > MAX_LOCK_DURATION)
revert InvalidLockDuration(); //condition to check the MIN_LOCK_DURATION
//rest of the code...
}

But, the veRAACToken::function increase updates the lock amount without recalculating or validating the remaining lock duration:

function increase(uint256 amount) external nonReentrant whenNotPaused {
//@audit - we can bypass the MIN lock duration by calling this function after the lock is created and some time has passed.
// Increase lock using LockManager
_lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
// Update voting power
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState
.calculateAndUpdatePower(
msg.sender,
userLock.amount + amount,
userLock.end
);
// Update checkpoints
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
// Transfer additional tokens and mint veTokens
raacToken.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}

A user could use the following attack path to exploit the vulnerability to manipulate governance and boost they might receive:

Attack path

1. User creates lock with 100 RAAC for 365 days (meets minimum)
2. Waits 300 days
3. Calls increase(900 RAAC) - total locked = 1000 RAAC
4. Lock now expires in 65 days
5. Effective lock duration for new tokens: 65 days << 365 minimum

Due to this vulnerabillity, the malicious user gains voting power and boosts their rewards for 1000 RAAC with only 65-day commitment.

Impact

This loophole undermines the protocol's governance integrity by allowing users to gain disproportionate voting power with minimal commitment. It creates an unfair advantage for sophisticated users who can exploit this mechanism, potentially leading to skewed governance outcomes.

Tools Used

Manual review

Recommendations

Can add checks in the increase function to solve this issue:

uint256 remaining = lock.end - block.timestamp;
require(remaining >= MIN_LOCK_DURATION, "Can't add to expiring lock");
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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