Core Contracts

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

In `veRAACToken` the `emergencyWithdraw` function does not write the checkpoint which results in incorrect voting power calculation

The emergencyWithdraw function does not write the checkpoint when the user's lock is removed. This causes incorrect voting power calculation.

Vulnerability Details

emergencyWithdraw doesn't call _checkpointState.writeCheckpoint(msg.sender, 0); when the voting power is removed. It is an important step when user's power changes so that votes calculations are performed with reals votes owned by user.

function emergencyWithdraw() external nonReentrant {
if (
emergencyWithdrawDelay == 0 ||
block.timestamp < emergencyWithdrawDelay
) revert EmergencyWithdrawNotEnabled();
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
if (userLock.amount == 0) revert NoTokensLocked();
uint256 amount = userLock.amount;
uint256 currentPower = balanceOf(msg.sender);
delete _lockState.locks[msg.sender];
delete _votingState.points[msg.sender];
_burn(msg.sender, currentPower);
raacToken.safeTransfer(msg.sender, amount);
emit EmergencyWithdrawn(msg.sender, amount);
}

We can see that withdraw function writes the checkpoint when the user removes the lock.

function withdraw() external nonReentrant {
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
if (userLock.amount == 0) revert LockNotFound();
if (block.timestamp < userLock.end) revert LockNotExpired();
uint256 amount = userLock.amount;
uint256 currentPower = balanceOf(msg.sender);
// Clear lock data
delete _lockState.locks[msg.sender];
delete _votingState.points[msg.sender];
// Update checkpoints
_checkpointState.writeCheckpoint(msg.sender, 0);
// Burn veTokens and transfer RAAC
_burn(msg.sender, currentPower);
raacToken.safeTransfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}

Impact

User votes are going to be incorrectly calcualted leading to inflated votes. User can use inflated votes to vote for proposals even when he shouldn't be able to do that.

Tools Used

Manual Review, Hardhat

Recommendations

Add _checkpointState.writeCheckpoint(msg.sender, 0); to emergencyWithdraw function.

Updates

Lead Judging Commences

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

veRAACToken::emergencyWithdraw doesn't update checkpoint - innacurate historical voting power, inconsistent state

Support

FAQs

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