Core Contracts

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

Missing checkpoint update in emergency withdrawal function

Summary

The emergencyWithdraw function in the veRAACToken contract is missing a critical checkpoint update that should record the user's voting power being set to zero. This oversight can lead to governance manipulation by allowing users to maintain historical voting power even after withdrawing their tokens through the emergency withdrawal mechanism.

Vulnerability Details

The vulnerability exists in the emergencyWithdraw function which fails to update the user's voting power checkpoint when tokens are withdrawn. The function is missing the crucial line:

_checkpointState.writeCheckpoint(msg.sender, 0);

This vulnerability can be exploited to manipulate governance voting in the following way:
User locks tokens and gains voting power

  • A governance proposal is created

  • User performs emergency withdrawal

  • User can still vote on the proposal using their old voting power

  • User can re-lock tokens and vote on new proposals

  • Results in one set of tokens being used to vote multiple times

Impact

This vulnerabilty allows users to maintain voting power without having tokens at risk, which could lead to governance manipulation during emergency situations when the protocol is most vulnerable

Recommendations

Add the missing checkpoint update to the emergencyWithdraw function:

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];
+ _checkpointState.writeCheckpoint(msg.sender, 0);
_burn(msg.sender, currentPower);
raacToken.safeTransfer(msg.sender, amount);
emit EmergencyWithdrawn(msg.sender, amount);
}
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.