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:
-
Contracts to disconnect:
- Dual Governance - 0xcdF49b058D606AD34c5789FD8c3BF8B3E54bA2db
- Veto Signaling Escrow - 0xA8F14D033f377779274Ae016584a05bF14Dccaf8 (proxy)
- Escrow - 0xb84317C0E142D8911A0d69Dc32c48d87753B8d1C (impl)
- Tiebreaker Core Committee - 0x175742c3DDD88B0192df3EcF98f180A79cb259D0
- Tiebreaker Sub Committees:
- Builders Sub Committee - 0x74836470337Ba5d2a92fe16E44AD862E28fcf9B3
- Node Operators Sub Committee - 0xb9d82E1A49f6a66E8a07260BA05Cf9Ac8a938B1C
- Ethereum Ecosystem Sub Committee - 0x7dAdae4e1a0DB43F6bcfA75295666fc044605679
-
Newly deployed contracts:
- Dual Governance - 0xC1db28B3301331277e307FDCfF8DE28242A4486E
- Veto Signaling Escrow - 0x165813A31446a98c84E20Dda8C101BB3C8228e1c (proxy)
- Escrow - 0xd6A67636c05BeB5B4a5c90D408b03A63c4e39426 (impl)
- Tiebreaker Core Committee - 0xf65614d73952Be91ce0aE7Dd9cFf25Ba15bEE2f5
- Tiebreaker Sub Committees:
- Builders Sub Committee - 0x3D3ba54D54bbFF40F2Dfa2A8e27bD4dE3dab2951
- Node Operators Sub Committee - 0xDBfa0B8A15a503f25224fcA5F84a3853230A715C
- Ethereum Ecosystem Sub Committee - 0xBF048f2111497B6Df5E062811f5fC422804D4baE
- Dual Governance Config Provider for disconnected DualGovernance contract - 0xc934E90E76449F09f2369BB85DCEa056567A327a
During the upgrade the following tooling contracts will be used:
DGUpgradeOmnibusMainnet0x67988077f29FbA661911d9567E05cc52C51ca1B0 - contains the list of the vote items required to apply the Dual Governance fix.DGUpgradeStateVerifierMainnet0x487b764a2085ffd595D9141BAec0A766B7904786 - called as the final step of the vote to confirm that the contracts have been configured correctly.
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:
- Finalize the configuration of the new
DualGovernanceinstance — which can only be performed by the AdminExecutor— 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
WithdrawalQueueandValidatorExitBusOracleas sealable withdrawal blockers. - Register Aragon
Votingas Proposer, assigning it to the current AdminExecutor. - Set Aragon
Votingas Proposals Canceller. - Set the Reseal Committee address to
0xFFe21561251c49AdccFad065C94Fb4931dF49081(Reseal Committee, used in the current setup).
- Set the
Governanceaddress in theEmergencyProtectedTimelockto the newly deployedDualGovernanceinstance. - Replace the config provider in the old
DualGovernancewith the newImmutableDualGovernanceConfigProvider, effectively “bricking” the old instance and ensuring it cannot enter a vulnerable state, even unintentionally. - Verify the resulting state of the new
DualGovernanceonchain using theDGUpgradeStateVerifierMainnetcontract 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
DualGovernanceto 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
Escrowinstance.
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
