Core Contracts

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

Loss of Critical Functions Due to Premature State Deletion

Summary

The TimelockController::executeEmergencyAction function prematurely deletes the emergency action record before executing the external calls. If one of the target contracts fails to execute (e.g., an attacker contract that rejects Ether transfers), the function reverts after the state has already been modified. This leads to a loss of the emergency action, preventing it from being retried. As a result, critical governance actions may be permanently blocked, disrupting protocol operations.

Vulnerability Details

The executeEmergencyAction function is responsible for executing a batch of emergency transactions. It verifies that the action is scheduled, deletes its record from _emergencyActions, and then iterates through the list of target contracts to execute the transactions. However, the function contains a critical flaw:

  1. Premature State Deletion – The emergency action record is deleted (delete _emergencyActions[id]) before any transactions are executed. If an error occurs during execution, the function reverts after the state has already been modified.

  2. Failure in External Calls – Each target contract receives a call with the provided calldata and Ether (targets[i].call{value: values[i]}(calldatas[i])). If any of these contracts fail to execute (e.g., an attacker contract that does not accept Ether or deliberately reverts), the entire function reverts.

  3. Loss of Emergency Actions – Since the emergency action record is deleted before execution, a failure in any of the calls results in the action being lost permanently. This prevents protocol administrators from retrying the action and could block critical governance or security-related transactions.

Impact

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/governance/proposals/TimelockController.sol#L247

Loss of Critical Emergency Actions

  • The protocol loses the ability to execute a crucial emergency function.

  • If the emergency action was meant to pause withdrawals, stop a rug pull, or recover stolen funds, then the attacker successfully disables that protection.

  • Denial of Service Attack on Emergency Functions

    • Attackers could repeatedly schedule and block emergency actions, preventing admins from ever executing emergency responses.

  • Governance Takeover Exploit

    • If an emergency action was meant to stop a malicious proposal or governance attack, failing the execution leaves the attack unchecked.

    • The protocol could be drained, upgraded maliciously, or manipulated.

Tools Used

Recommendations

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);
// Execute transactions first, then delete the state
for (uint256 i = 0; i < targets.length; i++) {
(bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
if (!success) {
emit EmergencyActionFailed(id, i, targets[i], returndata); // Log failure
continue; // Skip failed transaction instead of reverting everything
}
}
// Delete state only after successful execution
+ delete _emergencyActions[id];
emit EmergencyActionExecuted(id);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!