Dual Governance Security Upgrade Plan: RageQuit ETH Withdrawal Delay Fix

TL;DR

This post outlines the deployment plan for a fix addressing the Dual Governance weakness reported through Immunefi. The fix involves redeploying certain Dual Governance contracts, configuring them, and linking the existing EmergencyProtectedTimelock and Admin Executor contracts to a newly deployed DualGovernance instance.

The fix was audited by Certora and is currently being reviewed by Statemind, which will also verify the deployment and review the tooling contracts used during the voting phase. A special Immunefi contest was conducted on the fixed version of the contracts, with no vulnerabilities identified during the process.

Upgrade Components

Due to the immutable structure of the Dual Governance contracts, the fix requires disconnecting the EmergencyProtectedTimelock from the current DualGovernance instance and connecting it to a newly deployed version with the fix applied.

The TiebreakerCoreCommittee, along with its subcommittees, will also be updated, as it includes immutable reference to the DualGovernance contract. The composition of the committee and its subcommittees will remain unchanged, as stated in the original post.

The old DualGovernance instance will be reconfigured with a new ImmutableDualGovernanceConfigProvider to prevent entry into a vulnerable state and allow users to freely withdraw funds from the old Escrow.

After the upgrade, the final Dual Governance setup will look as shown below:

The full list of upgraded contracts is:

During the upgrade the following tooling contracts will be used:

The full list of contracts is also available in the documentation.

Vote Structure

To apply the fix, the DGUpgradeOmnibusMainnet contract contains a single Aragon vote item that submits a Dual Governance proposal with the following actions:

  1. Finalize the configuration of the new DualGovernance instance — which can only be performed by the Admin Executor — to match the current mainnet setup:
    • Set the tiebreaker activation timeout to 31536000 seconds (1 year).
    • Set the tiebreaker committee address to the newly deployed Tiebreaker Core Committee.
    • Add WithdrawalQueue and ValidatorExitBusOracle as sealable withdrawal blockers.
    • Register Aragon Voting as Proposer, assigning it to the current Admin Executor.
    • Set Aragon Voting as Proposals Canceller.
    • Set the Reseal Committee address to 0xFFe21561251c49AdccFad065C94Fb4931dF49081 (Reseal Committee, used in the current setup).
  2. Set the Governance address in the EmergencyProtectedTimelock to the newly deployed DualGovernance instance.
  3. Replace the config provider in the old DualGovernance with the new ImmutableDualGovernanceConfigProvider, effectively “bricking” the old instance and ensuring it cannot enter a vulnerable state, even unintentionally.
  4. Verify the resulting state of the new DualGovernance onchain using the DGUpgradeStateVerifierMainnet contract to ensure all steps were executed correctly.

Notes

The current DualGovernance and Escrow contract instances will be detached from the EmergencyProtectedTimelock, making user interaction with them highly unlikely, though not entirely impossible. To ensure the old Escrow cannot enter a vulnerable state, the outdated DualGovernance instance will be updated to use a new configuration provider contract. This configuration sets:

  • RageQuit support thresholds to their maximum values - 100% for the second seal and 99.(9)₁₆% for the first seal - making it virtually impossible for the old DualGovernance to enter the RageQuit state.
  • All other parameters are set to minimal values, allowing users to unlock their funds without a timelock if they were mistakenly locked in the old Escrow instance.

Verification

The contract fix has been audited by Certora and is currently under review by Statemind. Statemind will also perform deployment verification and review the vote-related DGUpgradeOmnibusMainnet and DGUpgradeStateVerifierMainnet contracts.

All reports will be published before the vote goes onchain.

The upgrade was successfully completed and tested on the Hoodi testnet, with contract bytecode identical to that deployed on mainnet.

Thanks

Lido Contributors are thankful to the whitehat reporter and security partners — Immunefi, Certora, and Statemind.

Note to tokenholders: please stay tuned for the upgrade vote in the upcoming voting slot.

Context links

Security disclosure post
New contract addresses
Certora Audit report

12 Likes

I’m glad that the bug was found quickly before anything terrible happened.

4 Likes

The above issue has been reviewed by the OpenZeppelin security services team and below is a summary of our analysis.

Issue Summary
Previously, the rageQuitExtensionPeriodStartedAt timestamp could be repeatedly overwritten, allowing the Rage Quit extension period to be indefinitely extended. This could prevent withdrawals from being processed as intended, creating a denial-of-service condition for users attempting to exit.

Root Cause

  • The startRageQuitExtensionPeriod function sets the rageQuitExtensionPeriodStartedAt timestamp to now + delay.

  • This timestamp is used in checkEthWithdrawalsDelayPassed to determine if withdrawals can proceed.

  • If startRageQuitExtensionPeriod could be called repeatedly, the timestamp could be pushed further into the future each time, blocking withdrawals indefinitely.

Impact

  • Malicious or repeated calls to startRageQuitExtensionPeriod could continuously delay withdrawals for affected users.

  • This effectively locks funds until the extension period passes without further calls to the function.

Fix Implemented

  • Added a guard to startRageQuitExtensionPeriod to revert if rageQuitExtensionPeriodStartedAt is already set (non-zero).

  • This ensures the timestamp can only be set once, preventing any overwriting or extension abuse.

Security Considerations

  • The fix prevents timestamp manipulation after the initial setting, eliminating the possibility of indefinite extension.

  • Withdrawal logic remains intact, and users can exit as expected once the legitimate delay passes.

Status
The fix has been reviewed and confirmed to address the identified vulnerability. No further action is required from Lido at this time regarding the identified vulnerability.

8 Likes

The Statemind team has successfully completed the audit and deployment verification of the Escrow fix, including the review of the DGUpgradeOmnibusMainnet and DGUpgradeStateVerifierMainnet contracts.

The final report is available here: Statemind Dual Governance Escrow Fix Review Report (Aug 2025).

The Aragon vote to apply the upgrade is scheduled for September 3, 2025.

4 Likes

The Voting Has Started

The Vote #191, which fixes the Dual Governance RageQuit mechanism, has just begun and will be open for your “For” or “Against” input until the end of the main phase: Sep 6, 14:01 UTC.

For instructions on how to verify the vote items, please follow this guide.

3 Likes

Vote #191 was successfully passed and enacted!

Voting statistics:

  • “No” — 2 (0.01%)
  • “Yes” — 51,379,450 (5.13%)

The voting items are now submitted to the Dual Governance with proposal #4 (expected to be executed on Sep 12).

3 Likes

Dual Governance Proposal #4 has been successfully executed - the RageQuit mechanism fix is now fully enabled and in effect!

3 Likes