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.
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:
However, this delay is never enforced in the code. Looking at the executeEmergencyAction function:
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:
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.
Admin calls scheduleEmergencyAction(id)
In the same block, Admin calls executeEmergencyAction() with corresponding parameters
The emergency action executes successfully without waiting for the defined 1-day delay
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.
Manual code review
Implement the emergency delay check in executeEmergencyAction:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.