Summary
The increase and extend functions in the veRAACToken contract do not check the upper limits for lockTime and totalLockedAmount. This can lead to exceeding the maximum allowed lock duration and total locked amount, potentially causing issues within the protocol.
Vulnerability Details
The current increase function in the veRAACToken contract is:
function increase(uint256 amount) external nonReentrant whenNotPaused {LockManager
_lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount + amount,
userLock.end
);
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
raacToken.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}
The function does not check if the total locked amount exceeds the maximum allowed limit.
Similarly, the extend function in the veRAACToken contract is:
function extend(uint256 newDuration) external nonReentrant whenNotPaused {
uint256 newUnlockTime = _lockState.extendLock(msg.sender, newDuration);
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount,
newUnlockTime
);
uint256 oldPower = balanceOf(msg.sender);
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
if (newPower > oldPower) {
_mint(msg.sender, newPower - oldPower);
} else if (newPower < oldPower) {
_burn(msg.sender, oldPower - newPower);
}
emit LockExtended(msg.sender, newUnlockTime);
}
The function does not check if the new lock duration exceeds the maximum allowed duration.
Links:
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L282
https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/veRAACToken.sol#L253
Impact
This issue can lead to exceeding the maximum allowed lock duration and total locked amount, potentially causing issues with token accounting and user balances within the protocol.
Tools Used
Manual code review.
Recommendations
Update the increase and extend functions to include checks for the upper limits of lockTime and totalLockedAmount. Additionally, update the LockManager contract to include these checks.
Corrected increase Function in veRAACToken
function increase(uint256 amount) external nonReentrant whenNotPaused {
if (_lockState.totalLocked + amount > MAX_TOTAL_LOCKED_AMOUNT) revert TotalLockedAmountExceeded();
_lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
...
emit LockIncreased(msg.sender, amount);
}
Corrected extend Function in veRAACToken
function extend(uint256 newDuration) external nonReentrant whenNotPaused {
uint256 newUnlockTime = _lockState.extendLock(msg.sender, newDuration);
if (newUnlockTime > block.timestamp + MAX_LOCK_DURATION) revert InvalidLockDuration();
...
emit LockExtended(msg.sender, newUnlockTime);
}
This ensures that the upper limits for lockTime and totalLockedAmount are correctly enforced, leading to accurate token accounting and user balances.