Core Contracts

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

Emergency Actions Can Be Executed Immediately, Bypassing Documented 1-Day Delay Period

Link to Affected Code:

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/proposals/TimelockController.sol#L237-L263

// Constant defined but never used
uint256 public constant EMERGENCY_DELAY = 1 days;
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];
// No delay check before execution
// ...execute calls immediately
}

Description:
The TimelockController defines EMERGENCY_DELAY = 1 days and documents emergency actions having a 1-day delay, but the executeEmergencyAction function allows immediate execution after scheduling. The function lacks any validation against the EMERGENCY_DELAY period between scheduling and execution. Emergency actions have 1-day delay

Impact:
The vulnerability allows:

  1. Immediate execution of emergency actions

  2. Bypass of intended safety delay

  3. Breaks core safety mechanism of protocol governance

Proof of Concept:

// 1. Schedule emergency action
uint256 scheduledTime = block.timestamp;
controller.scheduleEmergencyAction(id);
// 2. Can execute immediately
controller.executeEmergencyAction(
targets,
values,
calldatas,
predecessor,
salt
);
// Succeeds without waiting EMERGENCY_DELAY (1 day)

Recommended Mitigation:
Add delay enforcement to emergency actions:

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);
// Get scheduling timestamp
uint256 scheduledAt = emergencyActionSchedules[id];
if (block.timestamp < scheduledAt + EMERGENCY_DELAY)
revert EmergencyDelayNotElapsed();
delete _emergencyActions[id];
// Rest of execution logic...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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 3 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.