Core Contracts

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

There is no way to stop veRAAC token emergency withdrawals.

Summary

In the veRAACToken contract to verify that emergency withdrawals are enabled the emergencyWithdrawDelay variable is checked:

if (emergencyWithdrawDelay == 0 || block.timestamp < emergencyWithdrawDelay)
revert EmergencyWithdrawNotEnabled();

The problem is that there is no way to reset this variable back to 0, meaning that emergency withdrawals will be enabled indefinitely or the delay would have to be constantly extended by scheduling and enabling withdrawals again and again.

Vulnerability Details

This PoC can be added to veRAACToken.test.js. Users can withdraw at any time after emergency withdraw is enabled:

it("should allow users to withdraw a year later", async () => {
const amount = ethers.parseEther("1000");
const duration = 365 * 24 * 3600;
await raacToken.mint(users[0].address, amount);
await raacToken.connect(users[0]).approve(await veRAACToken.getAddress(), amount);
await veRAACToken.connect(users[0]).lock(amount, duration);
// Schedule emergency withdraw action
const EMERGENCY_WITHDRAW_ACTION = ethers.keccak256(
ethers.toUtf8Bytes("enableEmergencyWithdraw")
);
await veRAACToken.connect(owner).scheduleEmergencyAction(EMERGENCY_WITHDRAW_ACTION);
// Wait for emergency delay
await time.increase(EMERGENCY_DELAY);
// Enable emergency withdraw
await veRAACToken.connect(owner).enableEmergencyWithdraw();
// Wait a year
await time.increase(365 * 24 * 3600);
// Get initial balances
const initialBalance = await raacToken.balanceOf(users[0].address);
// Perform emergency withdrawal
await expect(veRAACToken.connect(users[0]).emergencyWithdraw())
.to.emit(veRAACToken, "EmergencyWithdrawn")
.withArgs(users[0].address, amount);
// Verify balance changes
const finalBalance = await raacToken.balanceOf(users[0].address);
expect(finalBalance - initialBalance).to.equal(amount);
});

After this there is no way to return to a state where veRAACToken emergency withdrawals are completetly disabled.

Impact

After an emergency withdrawal veRAACToken contract might be unusable or difficult to mantain.

Tools Used

Manual review + hardhat tests

Recommendations

Add an onlyOwner function to set emergencyWithdrawDelay = 0

Updates

Lead Judging Commences

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

veRAACToken::emergencyWithdraw permanently enables lock-bypassing after activation with no way to disable it, permanently breaking token time-locking functionality

Support

FAQs

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

Give us feedback!