Core Contracts

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

Emergency Actions Can Be Executed Without Enforced Delay

Summary

The TimelockController defines an EMERGENCY_DELAY constant of 1 day but fails to enforce this delay between scheduling and executing emergency actions, allowing them to be executed immediately after scheduling.

Vulnerability Details

In the TimelockController contract, there's a mechanism for handling emergency actions through two main functions:

scheduleEmergencyAction(bytes32 id) - Marks an action as emergency by storing it in _emergencyActions mapping
executeEmergencyAction() - Executes the emergency action

The contract defines a constant:

uint256 public constant EMERGENCY_DELAY = 1 days;

However, this delay is never enforced in the code. Looking at the executeEmergencyAction function:

function executeEmergencyAction(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas,
bytes32 predecessor,
bytes32 salt
) external payable onlyRole(EMERGENCY_ROLE) nonReentrant {
bytes32 id = hashOperationBatch(targets, values, calldatas, predecessor, salt);
if (!_emergencyActions[id]) revert EmergencyActionNotScheduled(id);
delete _emergencyActions[id];
// @audit Execute calls immediately...
}

The function only checks if the action was scheduled (_emergencyActions[id]) but doesn't verify any time delay between scheduling and execution. This contradicts the purpose of having an emergency delay constant and the general timelock security pattern used in the rest of the contract.

For comparison, regular operations in the same contract enforce strict delay checks:

function executeBatch(...) {
// ...
if (block.timestamp < op.timestamp) revert OperationNotReady(id);
// ...
}

This creates an inconsistency where normal governance actions require a delay (minimum 2 days) while emergency actions can bypass all delays despite having a defined EMERGENCY_DELAY.

PoC

  1. Admin calls scheduleEmergencyAction(id)

  2. In the same block, Admin calls executeEmergencyAction() with corresponding parameters

  3. The emergency action executes successfully without waiting for the defined 1-day delay

Impact

The lack of delay enforcement on emergency actions undermines the timelock security model and could allow privileged roles to execute significant protocol changes without giving users time to react. This is especially critical since emergency actions are meant for critical situations and likely have high impact.

Tools Used

Manual code review

Recommendations

Implement the emergency delay check in executeEmergencyAction:

function executeEmergencyAction(...) {
// ...
uint256 scheduledTime = emergencyActionScheduleTimes[id];
if (block.timestamp < scheduledTime + EMERGENCY_DELAY) {
revert EmergencyActionNotReady();
}
// ...
}
Updates

Lead Judging Commences

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

TimelockController emergency actions bypass timelock by not enforcing EMERGENCY_DELAY, allowing immediate execution

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

TimelockController emergency actions bypass timelock by not enforcing EMERGENCY_DELAY, allowing immediate execution

Support

FAQs

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