Core Contracts

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

PowerCheckpoint State is not updated during an emergency withdraw.

Summary

PowerCheckpoint State is not updated during an emergency withdraw.

Vulnerability Details

When Users Try to Lock their RAAC Token for veRAACToken for governance Voting SLOC#212, increase amount SLOC#251, extends period SLOC#280 and release token SLOC#311 at that time Powercheckpoint update state which is used for users pre-checking history on the which block.number and voting power held by the user. but when user try to withdraw on emergency at that time PowerCheckpoint is not updated SLOC#367-384.

// File: contracts/core/tokens/veRAACToken.sol
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]; // deleting lockstate
delete _votingState.points[msg.sender]; // deleting votingstate
// <@ root cause, not deleting powerCheckpoint for msg.sender
_burn(msg.sender, currentPower);
raacToken.safeTransfer(msg.sender, amount);
emit EmergencyWithdrawn(msg.sender, amount);
}

Impact

When users withdraw in emergency without updating the PowerCheckpoint, their voting power at the time of the withdrawal may not be updated in contract. This could lead to inaccurate or stale voting power data for future interactions, as the system relies on PowerCheckpoints to track changesPer-User Voting power history. As a result, it might cause inconsistencies when users attempt to vote or interact with the protocol after emergency withdrawals.

Tools Used

  • Manual Review

  • Foundry

Recommended Mitigation

  • Update Powercheckpoint storage state in Contract for current caller to 0.

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 7 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.

Give us feedback!