From 629bc07e661ab6d91a3b2d41ec70d50d299bbded Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 12 Sep 2024 13:39:35 +0400 Subject: [PATCH 1/4] DualGovernanceConfigProvider.sol -> ImmutableDualGovernanceConfigProvider.sol --- ...rovider.sol => ImmutableDualGovernanceConfigProvider.sol} | 0 test/unit/DualGovernance.t.sol | 2 +- test/unit/libraries/DualGovernanceStateMachine.t.sol | 5 ++++- test/utils/SetupDeployment.sol | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) rename contracts/{DualGovernanceConfigProvider.sol => ImmutableDualGovernanceConfigProvider.sol} (100%) diff --git a/contracts/DualGovernanceConfigProvider.sol b/contracts/ImmutableDualGovernanceConfigProvider.sol similarity index 100% rename from contracts/DualGovernanceConfigProvider.sol rename to contracts/ImmutableDualGovernanceConfigProvider.sol diff --git a/test/unit/DualGovernance.t.sol b/test/unit/DualGovernance.t.sol index bf3bf14d..1b5c9075 100644 --- a/test/unit/DualGovernance.t.sol +++ b/test/unit/DualGovernance.t.sol @@ -18,7 +18,7 @@ import { DualGovernanceConfig, IDualGovernanceConfigProvider, ImmutableDualGovernanceConfigProvider -} from "contracts/DualGovernanceConfigProvider.sol"; +} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; import {IDualGovernance} from "contracts/interfaces/IDualGovernance.sol"; import {IWstETH} from "contracts/interfaces/IWstETH.sol"; diff --git a/test/unit/libraries/DualGovernanceStateMachine.t.sol b/test/unit/libraries/DualGovernanceStateMachine.t.sol index be1bbeef..7e447cae 100644 --- a/test/unit/libraries/DualGovernanceStateMachine.t.sol +++ b/test/unit/libraries/DualGovernanceStateMachine.t.sol @@ -7,7 +7,10 @@ import {Durations} from "contracts/types/Duration.sol"; import {PercentsD16} from "contracts/types/PercentD16.sol"; import {DualGovernanceStateMachine, State} from "contracts/libraries/DualGovernanceStateMachine.sol"; -import {DualGovernanceConfig, ImmutableDualGovernanceConfigProvider} from "contracts/DualGovernanceConfigProvider.sol"; +import { + DualGovernanceConfig, + ImmutableDualGovernanceConfigProvider +} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; import {UnitTest} from "test/utils/unit-test.sol"; import {EscrowMock} from "test/mocks/EscrowMock.sol"; diff --git a/test/utils/SetupDeployment.sol b/test/utils/SetupDeployment.sol index c181fcd1..e5a1eda3 100644 --- a/test/utils/SetupDeployment.sol +++ b/test/utils/SetupDeployment.sol @@ -39,7 +39,7 @@ import { DualGovernanceConfig, IDualGovernanceConfigProvider, ImmutableDualGovernanceConfigProvider -} from "contracts/DualGovernanceConfigProvider.sol"; +} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; import {ResealCommittee} from "contracts/committees/ResealCommittee.sol"; import {TiebreakerCore} from "contracts/committees/TiebreakerCore.sol"; From 49fa62a2a5268858fe6ce8bec6bf7c4b88f970e9 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 12 Sep 2024 13:42:04 +0400 Subject: [PATCH 2/4] AssetsAccounting.accountClaimedStETH() -> AssetssAccounting.accountClaimedETH() --- contracts/Escrow.sol | 2 +- contracts/libraries/AssetsAccounting.sol | 2 +- test/unit/libraries/AssetsAccounting.t.sol | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/Escrow.sol b/contracts/Escrow.sol index adec929b..673eae62 100644 --- a/contracts/Escrow.sol +++ b/contracts/Escrow.sol @@ -480,7 +480,7 @@ contract Escrow is IEscrow { WITHDRAWAL_QUEUE.claimWithdrawals(unstETHIds, hints); ETHValue ethBalanceAfter = ETHValues.fromAddressBalance(address(this)); - _accounting.accountClaimedStETH(ethBalanceAfter - ethBalanceBefore); + _accounting.accountClaimedETH(ethBalanceAfter - ethBalanceBefore); } function _checkCallerIsDualGovernance() internal view { diff --git a/contracts/libraries/AssetsAccounting.sol b/contracts/libraries/AssetsAccounting.sol index 32872bd7..c47af26c 100644 --- a/contracts/libraries/AssetsAccounting.sol +++ b/contracts/libraries/AssetsAccounting.sol @@ -173,7 +173,7 @@ library AssetsAccounting { emit ETHWithdrawn(holder, stETHSharesToWithdraw, ethWithdrawn); } - function accountClaimedStETH(Context storage self, ETHValue amount) internal { + function accountClaimedETH(Context storage self, ETHValue amount) internal { self.stETHTotals.claimedETH = self.stETHTotals.claimedETH + amount; emit ETHClaimed(amount); } diff --git a/test/unit/libraries/AssetsAccounting.t.sol b/test/unit/libraries/AssetsAccounting.t.sol index b624ed33..27c3642d 100644 --- a/test/unit/libraries/AssetsAccounting.t.sol +++ b/test/unit/libraries/AssetsAccounting.t.sol @@ -306,10 +306,10 @@ contract AssetsAccountingUnitTests is UnitTest { } // --- - // accountClaimedStETH + // accountClaimedETH // --- - function testFuzz_accountClaimedStETH_happyPath(ETHValue amount, ETHValue totalClaimedETH) external { + function testFuzz_accountClaimedETH_happyPath(ETHValue amount, ETHValue totalClaimedETH) external { vm.assume(amount.toUint256() < type(uint128).max / 2); vm.assume(totalClaimedETH.toUint256() < type(uint128).max / 2); @@ -318,7 +318,7 @@ contract AssetsAccountingUnitTests is UnitTest { vm.expectEmit(); emit AssetsAccounting.ETHClaimed(amount); - AssetsAccounting.accountClaimedStETH(_accountingContext, amount); + AssetsAccounting.accountClaimedETH(_accountingContext, amount); checkAccountingContextTotalCounters( SharesValues.ZERO, totalClaimedETH + amount, SharesValues.ZERO, ETHValues.ZERO From 92039e1611d591b2fbf3a8c4dfa68b644486eb73 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 12 Sep 2024 13:52:42 +0400 Subject: [PATCH 3/4] TiebreakerCore -> TiebreakerCoreCommittee --- ...erCore.sol => TiebreakerCoreCommittee.sol} | 6 ++-- .../committees/TiebreakerSubCommittee.sol | 18 +++++----- ...rCore.sol => ITiebreakerCoreCommittee.sol} | 2 +- docs/specification.md | 36 +++++++++---------- test/unit/committees/TiebreakerCore.t.sol | 18 ++++++---- .../committees/TiebreakerSubCommittee.t.sol | 25 +++++++------ test/utils/SetupDeployment.sol | 12 +++---- 7 files changed, 64 insertions(+), 53 deletions(-) rename contracts/committees/{TiebreakerCore.sol => TiebreakerCoreCommittee.sol} (96%) rename contracts/interfaces/{ITiebreakerCore.sol => ITiebreakerCoreCommittee.sol} (90%) diff --git a/contracts/committees/TiebreakerCore.sol b/contracts/committees/TiebreakerCoreCommittee.sol similarity index 96% rename from contracts/committees/TiebreakerCore.sol rename to contracts/committees/TiebreakerCoreCommittee.sol index ac0cce57..11a97009 100644 --- a/contracts/committees/TiebreakerCore.sol +++ b/contracts/committees/TiebreakerCoreCommittee.sol @@ -8,8 +8,8 @@ import {Timestamp} from "../types/Timestamp.sol"; import {ITimelock} from "../interfaces/ITimelock.sol"; import {ITiebreaker} from "../interfaces/ITiebreaker.sol"; -import {ITiebreakerCore} from "../interfaces/ITiebreakerCore.sol"; import {IDualGovernance} from "../interfaces/IDualGovernance.sol"; +import {ITiebreakerCoreCommittee} from "../interfaces/ITiebreakerCoreCommittee.sol"; import {HashConsensus} from "./HashConsensus.sol"; import {ProposalsList} from "./ProposalsList.sol"; @@ -19,10 +19,10 @@ enum ProposalType { ResumeSealable } -/// @title Tiebreaker Core Contract +/// @title Tiebreaker Core Committee Contract /// @notice This contract allows a committee to vote on and execute proposals for scheduling and resuming sealable addresses /// @dev Inherits from HashConsensus for voting mechanisms and ProposalsList for proposal management -contract TiebreakerCore is ITiebreakerCore, HashConsensus, ProposalsList { +contract TiebreakerCoreCommittee is ITiebreakerCoreCommittee, HashConsensus, ProposalsList { error ResumeSealableNonceMismatch(); error ProposalDoesNotExist(uint256 proposalId); diff --git a/contracts/committees/TiebreakerSubCommittee.sol b/contracts/committees/TiebreakerSubCommittee.sol index 01dabf8f..4e6e0dc6 100644 --- a/contracts/committees/TiebreakerSubCommittee.sol +++ b/contracts/committees/TiebreakerSubCommittee.sol @@ -6,7 +6,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {Durations} from "../types/Duration.sol"; import {Timestamp} from "../types/Timestamp.sol"; -import {ITiebreakerCore} from "../interfaces/ITiebreakerCore.sol"; +import {ITiebreakerCoreCommittee} from "../interfaces/ITiebreakerCoreCommittee.sol"; import {HashConsensus} from "./HashConsensus.sol"; import {ProposalsList} from "./ProposalsList.sol"; @@ -20,15 +20,15 @@ enum ProposalType { /// @notice This contract allows a subcommittee to vote on and execute proposals for scheduling and resuming sealable addresses /// @dev Inherits from HashConsensus for voting mechanisms and ProposalsList for proposal management contract TiebreakerSubCommittee is HashConsensus, ProposalsList { - address immutable TIEBREAKER_CORE; + address public immutable TIEBREAKER_CORE_COMMITTEE; constructor( address owner, address[] memory committeeMembers, uint256 executionQuorum, - address tiebreakerCore + address tiebreakerCoreCommittee ) HashConsensus(owner, Durations.from(0)) { - TIEBREAKER_CORE = tiebreakerCore; + TIEBREAKER_CORE_COMMITTEE = tiebreakerCoreCommittee; _addMembers(committeeMembers, executionQuorum); } @@ -42,7 +42,7 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { /// @param proposalId The ID of the proposal to schedule function scheduleProposal(uint256 proposalId) public { _checkCallerIsMember(); - ITiebreakerCore(TIEBREAKER_CORE).checkProposalExists(proposalId); + ITiebreakerCoreCommittee(TIEBREAKER_CORE_COMMITTEE).checkProposalExists(proposalId); (bytes memory proposalData, bytes32 key) = _encodeApproveProposal(proposalId); _vote(key, true); _pushProposal(key, uint256(ProposalType.ScheduleProposal), proposalData); @@ -71,7 +71,8 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { (, bytes32 key) = _encodeApproveProposal(proposalId); _markUsed(key); Address.functionCall( - TIEBREAKER_CORE, abi.encodeWithSelector(ITiebreakerCore.scheduleProposal.selector, proposalId) + TIEBREAKER_CORE_COMMITTEE, + abi.encodeWithSelector(ITiebreakerCoreCommittee.scheduleProposal.selector, proposalId) ); } @@ -122,7 +123,8 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { (, bytes32 key, uint256 nonce) = _encodeSealableResume(sealable); _markUsed(key); Address.functionCall( - TIEBREAKER_CORE, abi.encodeWithSelector(ITiebreakerCore.sealableResume.selector, sealable, nonce) + TIEBREAKER_CORE_COMMITTEE, + abi.encodeWithSelector(ITiebreakerCoreCommittee.sealableResume.selector, sealable, nonce) ); } @@ -137,7 +139,7 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { view returns (bytes memory data, bytes32 key, uint256 nonce) { - nonce = ITiebreakerCore(TIEBREAKER_CORE).getSealableResumeNonce(sealable); + nonce = ITiebreakerCoreCommittee(TIEBREAKER_CORE_COMMITTEE).getSealableResumeNonce(sealable); data = abi.encode(sealable, nonce); key = keccak256(data); } diff --git a/contracts/interfaces/ITiebreakerCore.sol b/contracts/interfaces/ITiebreakerCoreCommittee.sol similarity index 90% rename from contracts/interfaces/ITiebreakerCore.sol rename to contracts/interfaces/ITiebreakerCoreCommittee.sol index 44af6301..9bfb2a09 100644 --- a/contracts/interfaces/ITiebreakerCore.sol +++ b/contracts/interfaces/ITiebreakerCoreCommittee.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -interface ITiebreakerCore { +interface ITiebreakerCoreCommittee { function getSealableResumeNonce(address sealable) external view returns (uint256 nonce); function scheduleProposal(uint256 _proposalId) external; function sealableResume(address sealable, uint256 nonce) external; diff --git a/docs/specification.md b/docs/specification.md index 3549cd5c..53628a42 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -35,7 +35,7 @@ This document provides the system description on the code architecture level. A * [Contract: ProposalsList.sol](#contract-proposalslistsol) * [Contract: HashConsensus.sol](#contract-hashconsensussol) * [Contract: ResealCommittee.sol](#contract-resealcommitteesol) - * [Contract: TiebreakerCore.sol](#contract-tiebreakercoresol) + * [Contract: TiebreakerCoreCommittee.sol](#contract-tiebreakercorecommitteesol) * [Contract: TiebreakerSubCommittee.sol](#contract-tiebreakersubcommitteesol) * [Contract: EmergencyActivationCommittee.sol](#contract-emergencyactivationcommitteesol) * [Contract: EmergencyExecutionCommittee.sol](#contract-emergencyexecutioncommitteesol) @@ -56,12 +56,12 @@ The system is composed of the following main contracts: * [`ImmutableDualGovernanceConfigProvider.sol`](#contract-immutabledualgovernanceconfigprovidersol) is a singleton contract that stores the configurable parameters of the DualGovernance system in an immutable manner. * [`ResealManager.sol`](#contract-resealmanagersol) is a singleton contract responsible for extending or resuming sealable contracts paused by the [GateSeal emergency protection mechanism](https://github.com/lidofinance/gate-seals). This contract is essential due to the dynamic timelock of Dual Governance, which may prevent the DAO from extending the pause in time. It holds the authority to manage the pausing and resuming of specific protocol components protected by GateSeal. -Additionally, the system uses several committee contracts that allow members to execute, acquiring quorum, a narrow set of actions while protecting management of the committees by the Dual Governance mechanism: - +Additionally, the system uses several committee contracts that allow members to execute, acquiring quorum, a narrow set of actions while protecting management of the committees by the Dual Governance mechanism: + * [`ResealCommittee.sol`](#contract-resealcommitteesol) is a committee contract that allows members to obtain a quorum and reseal contracts temporarily paused by the [GateSeal emergency protection mechanism](https://github.com/lidofinance/gate-seals). -* [`TiebreakerCore.sol`](#contract-tiebreakercoresol) is a committee contract designed to approve proposals for execution in extreme situations where the Dual Governance system is deadlocked. This includes scenarios such as the inability to finalize user withdrawal requests during ongoing `RageQuit` or when the system is held in a locked state for an extended period. The `TiebreakerCore` consists of multiple `TiebreakerSubCommittee` contracts appointed by the DAO. -* [`TiebreakerSubCommittee.sol`](#contract-tiebreakersubcommitteesol) is a committee contracts that provides ability to participate in `TiebreakerCore` for external actors. -* [`EmergencyActivationCommittee`](#contract-emergencyactivationcommitteesol) is a committee contract responsible for activating Emergency Mode by acquiring quorum. Only the EmergencyExecutionCommittee can execute proposals. This committee is expected to be active for a limited period following the initial deployment or update of the DualGovernance system. +* [`TiebreakerCoreCommittee.sol`](#contract-tiebreakercorecommitteesol) is a committee contract designed to approve proposals for execution in extreme situations where the Dual Governance system is deadlocked. This includes scenarios such as the inability to finalize user withdrawal requests during ongoing `RageQuit` or when the system is held in a locked state for an extended period. The `TiebreakerCoreCommittee` consists of multiple `TiebreakerSubCommittee` contracts appointed by the DAO. +* [`TiebreakerSubCommittee.sol`](#contract-tiebreakersubcommitteesol) is a committee contracts that provides ability to participate in `TiebreakerCoreCommittee` for external actors. +* [`EmergencyActivationCommittee`](#contract-emergencyactivationcommitteesol) is a committee contract responsible for activating Emergency Mode by acquiring quorum. Only the EmergencyExecutionCommittee can execute proposals. This committee is expected to be active for a limited period following the initial deployment or update of the DualGovernance system. * [`EmergencyExecutionCommittee`](#contract-emergencyexecutioncommitteesol) is a committee contract that enables quorum-based execution of proposals during Emergency Mode or disabling the DualGovernance mechanism by assigning the EmergencyProtectedTimelock to Aragon Voting. Like the EmergencyActivationCommittee, this committee is also intended for short-term use after the system’s deployment or update. @@ -1167,11 +1167,11 @@ Executes a reseal of the sealable contract by calling the `resealSealable` metho * Proposal MUST be scheduled for execution and passed the timelock duration. -## Contract: TiebreakerCore.sol +## Contract: TiebreakerCoreCommittee.sol -`TiebreakerCore` is a smart contract that extends the `HashConsensus` and `ProposalsList` contracts to manage the scheduling of proposals and the resuming of sealable contracts through a consensus-based mechanism. It interacts with a DualGovernance contract to execute decisions once consensus is reached. +`TiebreakerCoreCommittee` is a smart contract that extends the `HashConsensus` and `ProposalsList` contracts to manage the scheduling of proposals and the resuming of sealable contracts through a consensus-based mechanism. It interacts with a DualGovernance contract to execute decisions once consensus is reached. -### Function: TiebreakerCore.scheduleProposal +### Function: TiebreakerCoreCommittee.scheduleProposal ```solidity function scheduleProposal(uint256 proposalId) @@ -1184,7 +1184,7 @@ Schedules a proposal for execution by voting on it and adding it to the proposal * MUST be called by a member. * Proposal with the given id MUST be submitted into `EmergencyProtectedTimelock` -### Function: TiebreakerCore.getScheduleProposalState +### Function: TiebreakerCoreCommittee.getScheduleProposalState ```solidity function getScheduleProposalState(uint256 proposalId) @@ -1194,7 +1194,7 @@ function getScheduleProposalState(uint256 proposalId) Returns the state of a scheduled proposal including support count, quorum, and execution status. -### Function: TiebreakerCore.executeScheduleProposal +### Function: TiebreakerCoreCommittee.executeScheduleProposal ```solidity function executeScheduleProposal(uint256 proposalId) @@ -1206,7 +1206,7 @@ Executes a scheduled proposal by calling the `tiebreakerScheduleProposal` functi * Proposal MUST be scheduled for execution and passed the timelock duration. -### Function: TiebreakerCore.getSealableResumeNonce +### Function: TiebreakerCoreCommittee.getSealableResumeNonce ```solidity function getSealableResumeNonce(address sealable) view returns (uint256) @@ -1214,7 +1214,7 @@ function getSealableResumeNonce(address sealable) view returns (uint256) Returns the current nonce for resuming operations of a sealable contract. -### Function: TiebreakerCore.sealableResume +### Function: TiebreakerCoreCommittee.sealableResume ```solidity function sealableResume(address sealable, uint256 nonce) @@ -1227,7 +1227,7 @@ Submits a request to resume operations of a sealable contract by voting on it an * MUST be called by a member. * The provided nonce MUST match the current nonce of the sealable contract. -### Function: TiebreakerCore.getSealableResumeState +### Function: TiebreakerCoreCommittee.getSealableResumeState ```solidity function getSealableResumeState(address sealable, uint256 nonce) @@ -1237,7 +1237,7 @@ function getSealableResumeState(address sealable, uint256 nonce) Returns the state of a sealable resume request including support count, quorum, and execution status. -### Function: TiebreakerCore.executeSealableResume +### Function: TiebreakerCoreCommittee.executeSealableResume ```solidity function executeSealableResume(address sealable) @@ -1251,7 +1251,7 @@ Executes a sealable resume request by calling the `tiebreakerResumeSealable` fun ## Contract: TiebreakerSubCommittee.sol -`TiebreakerSubCommittee` is a smart contract that extends the functionalities of `HashConsensus` and `ProposalsList` to manage the scheduling of proposals and the resumption of sealable contracts through a consensus mechanism. It interacts with the `TiebreakerCore` contract to execute decisions once consensus is reached. +`TiebreakerSubCommittee` is a smart contract that extends the functionalities of `HashConsensus` and `ProposalsList` to manage the scheduling of proposals and the resumption of sealable contracts through a consensus mechanism. It interacts with the `TiebreakerCoreCommittee` contract to execute decisions once consensus is reached. ### Function: TiebreakerSubCommittee.scheduleProposal @@ -1282,7 +1282,7 @@ Returns the state of a scheduled proposal including support count, quorum, and e function executeScheduleProposal(uint256 proposalId) ``` -Executes a scheduled proposal by calling the scheduleProposal function on the TiebreakerCore contract. +Executes a scheduled proposal by calling the scheduleProposal function on the `TiebreakerCoreCommittee` contract. #### Preconditions @@ -1314,7 +1314,7 @@ Returns the state of a sealable resume request including support count, quorum, function executeSealableResume(address sealable) public ``` -Executes a sealable resume request by calling the sealableResume function on the TiebreakerCore contract and increments the nonce. +Executes a sealable resume request by calling the sealableResume function on the `TiebreakerCoreCommittee` contract and increments the nonce. #### Preconditions diff --git a/test/unit/committees/TiebreakerCore.t.sol b/test/unit/committees/TiebreakerCore.t.sol index d950b835..e956957c 100644 --- a/test/unit/committees/TiebreakerCore.t.sol +++ b/test/unit/committees/TiebreakerCore.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import {TiebreakerCore} from "contracts/committees/TiebreakerCore.sol"; +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; import {HashConsensus} from "contracts/committees/HashConsensus.sol"; import {Durations, Duration} from "contracts/types/Duration.sol"; import {Timestamp} from "contracts/types/Timestamp.sol"; @@ -33,7 +33,7 @@ contract EmergencyProtectedTimelockMock is TargetMock { } contract TiebreakerCoreUnitTest is UnitTest { - TiebreakerCore internal tiebreakerCore; + TiebreakerCoreCommittee internal tiebreakerCore; uint256 internal quorum = 2; address internal owner = makeAddr("owner"); address[] internal committeeMembers = [address(0x1), address(0x2), address(0x3)]; @@ -47,7 +47,7 @@ contract TiebreakerCoreUnitTest is UnitTest { emergencyProtectedTimelock = address(new EmergencyProtectedTimelockMock()); EmergencyProtectedTimelockMock(payable(emergencyProtectedTimelock)).setProposalsCount(1); dualGovernance = address(new DualGovernanceMock(emergencyProtectedTimelock)); - tiebreakerCore = new TiebreakerCore(owner, dualGovernance, timelock); + tiebreakerCore = new TiebreakerCoreCommittee(owner, dualGovernance, timelock); vm.prank(owner); tiebreakerCore.addMembers(committeeMembers, quorum); @@ -55,7 +55,7 @@ contract TiebreakerCoreUnitTest is UnitTest { function testFuzz_constructor_HappyPath(address _owner, address _dualGovernance, Duration _timelock) external { vm.assume(_owner != address(0)); - new TiebreakerCore(_owner, _dualGovernance, _timelock); + new TiebreakerCoreCommittee(_owner, _dualGovernance, _timelock); } function test_scheduleProposal_HappyPath() external { @@ -87,7 +87,9 @@ contract TiebreakerCoreUnitTest is UnitTest { function test_scheduleProposal_RevertOn_ProposalDoesNotExist() external { uint256 nonExistentProposalId = proposalId + 1; - vm.expectRevert(abi.encodeWithSelector(TiebreakerCore.ProposalDoesNotExist.selector, nonExistentProposalId)); + vm.expectRevert( + abi.encodeWithSelector(TiebreakerCoreCommittee.ProposalDoesNotExist.selector, nonExistentProposalId) + ); vm.prank(committeeMembers[0]); tiebreakerCore.scheduleProposal(nonExistentProposalId); } @@ -95,7 +97,9 @@ contract TiebreakerCoreUnitTest is UnitTest { function test_scheduleProposal_RevertOn_ProposalIdIsZero() external { uint256 nonExistentProposalId = 0; - vm.expectRevert(abi.encodeWithSelector(TiebreakerCore.ProposalDoesNotExist.selector, nonExistentProposalId)); + vm.expectRevert( + abi.encodeWithSelector(TiebreakerCoreCommittee.ProposalDoesNotExist.selector, nonExistentProposalId) + ); vm.prank(committeeMembers[0]); tiebreakerCore.scheduleProposal(nonExistentProposalId); } @@ -142,7 +146,7 @@ contract TiebreakerCoreUnitTest is UnitTest { uint256 wrongNonce = 999; vm.prank(committeeMembers[0]); - vm.expectRevert(abi.encodeWithSelector(TiebreakerCore.ResumeSealableNonceMismatch.selector)); + vm.expectRevert(abi.encodeWithSelector(TiebreakerCoreCommittee.ResumeSealableNonceMismatch.selector)); tiebreakerCore.sealableResume(sealable, wrongNonce); } diff --git a/test/unit/committees/TiebreakerSubCommittee.t.sol b/test/unit/committees/TiebreakerSubCommittee.t.sol index 81c3d871..774ae27c 100644 --- a/test/unit/committees/TiebreakerSubCommittee.t.sol +++ b/test/unit/committees/TiebreakerSubCommittee.t.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import {ITiebreakerCore} from "contracts/interfaces/ITiebreakerCore.sol"; +import {ITiebreakerCoreCommittee} from "contracts/interfaces/ITiebreakerCoreCommittee.sol"; -import {TiebreakerCore} from "contracts/committees/TiebreakerCore.sol"; +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; import {TiebreakerSubCommittee, ProposalType} from "contracts/committees/TiebreakerSubCommittee.sol"; import {HashConsensus} from "contracts/committees/HashConsensus.sol"; import {Timestamp} from "contracts/types/Timestamp.sol"; import {UnitTest} from "test/utils/unit-test.sol"; -import {ITiebreakerCore} from "contracts/interfaces/ITiebreakerCore.sol"; import {TargetMock} from "test/utils/target-mock.sol"; @@ -81,7 +80,9 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { tiebreakerSubCommittee.scheduleProposal(proposalId); vm.prank(committeeMembers[2]); - vm.expectCall(tiebreakerCore, abi.encodeWithSelector(ITiebreakerCore.scheduleProposal.selector, proposalId)); + vm.expectCall( + tiebreakerCore, abi.encodeWithSelector(ITiebreakerCoreCommittee.scheduleProposal.selector, proposalId) + ); tiebreakerSubCommittee.executeScheduleProposal(proposalId); (,,, bool isExecuted) = tiebreakerSubCommittee.getScheduleProposalState(proposalId); @@ -105,7 +106,9 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { function test_scheduleProposal_RevertOn_ProposalDoesNotExist() external { uint256 nonExistentProposalId = proposalId + 1; - vm.expectRevert(abi.encodeWithSelector(TiebreakerCore.ProposalDoesNotExist.selector, nonExistentProposalId)); + vm.expectRevert( + abi.encodeWithSelector(TiebreakerCoreCommittee.ProposalDoesNotExist.selector, nonExistentProposalId) + ); vm.prank(committeeMembers[0]); tiebreakerSubCommittee.scheduleProposal(nonExistentProposalId); } @@ -113,7 +116,7 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { function test_sealableResume_HappyPath() external { vm.mockCall( tiebreakerCore, - abi.encodeWithSelector(ITiebreakerCore.getSealableResumeNonce.selector, sealable), + abi.encodeWithSelector(ITiebreakerCoreCommittee.getSealableResumeNonce.selector, sealable), abi.encode(0) ); @@ -145,7 +148,7 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { function test_executeSealableResume_HappyPath() external { vm.mockCall( tiebreakerCore, - abi.encodeWithSelector(ITiebreakerCore.getSealableResumeNonce.selector, sealable), + abi.encodeWithSelector(ITiebreakerCoreCommittee.getSealableResumeNonce.selector, sealable), abi.encode(0) ); @@ -155,7 +158,9 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { tiebreakerSubCommittee.sealableResume(sealable); vm.prank(committeeMembers[2]); - vm.expectCall(tiebreakerCore, abi.encodeWithSelector(ITiebreakerCore.sealableResume.selector, sealable, 0)); + vm.expectCall( + tiebreakerCore, abi.encodeWithSelector(ITiebreakerCoreCommittee.sealableResume.selector, sealable, 0) + ); tiebreakerSubCommittee.executeSealableResume(sealable); (,,, bool isExecuted) = tiebreakerSubCommittee.getSealableResumeState(sealable); @@ -165,7 +170,7 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { function test_executeSealableResume_RevertOn_QuorumNotReached() external { vm.mockCall( tiebreakerCore, - abi.encodeWithSelector(ITiebreakerCore.getSealableResumeNonce.selector, sealable), + abi.encodeWithSelector(ITiebreakerCoreCommittee.getSealableResumeNonce.selector, sealable), abi.encode(0) ); @@ -220,7 +225,7 @@ contract TiebreakerSubCommitteeUnitTest is UnitTest { function test_getSealableResumeState_HappyPath() external { vm.mockCall( tiebreakerCore, - abi.encodeWithSelector(ITiebreakerCore.getSealableResumeNonce.selector, sealable), + abi.encodeWithSelector(ITiebreakerCoreCommittee.getSealableResumeNonce.selector, sealable), abi.encode(0) ); diff --git a/test/utils/SetupDeployment.sol b/test/utils/SetupDeployment.sol index e5a1eda3..28e39256 100644 --- a/test/utils/SetupDeployment.sol +++ b/test/utils/SetupDeployment.sol @@ -42,7 +42,7 @@ import { } from "contracts/ImmutableDualGovernanceConfigProvider.sol"; import {ResealCommittee} from "contracts/committees/ResealCommittee.sol"; -import {TiebreakerCore} from "contracts/committees/TiebreakerCore.sol"; +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; // --- // Util Libraries @@ -120,7 +120,7 @@ abstract contract SetupDeployment is Test { ImmutableDualGovernanceConfigProvider internal _dualGovernanceConfigProvider; ResealCommittee internal _resealCommittee; - TiebreakerCore internal _tiebreakerCoreCommittee; + TiebreakerCoreCommittee internal _tiebreakerCoreCommittee; TiebreakerSubCommittee[] internal _tiebreakerSubCommittees; // --- @@ -406,21 +406,21 @@ abstract contract SetupDeployment is Test { address owner, IDualGovernance dualGovernance, Duration timelock - ) internal returns (TiebreakerCore) { - return new TiebreakerCore({owner: owner, dualGovernance: address(dualGovernance), timelock: timelock}); + ) internal returns (TiebreakerCoreCommittee) { + return new TiebreakerCoreCommittee({owner: owner, dualGovernance: address(dualGovernance), timelock: timelock}); } function _deployTiebreakerSubCommittee( address owner, uint256 quorum, address[] memory members, - TiebreakerCore tiebreakerCore + TiebreakerCoreCommittee tiebreakerCore ) internal returns (TiebreakerSubCommittee) { return new TiebreakerSubCommittee({ owner: owner, executionQuorum: quorum, committeeMembers: members, - tiebreakerCore: address(tiebreakerCore) + tiebreakerCoreCommittee: address(tiebreakerCore) }); } From 31102bcff79583eebbc69800b901cb76cd67c908 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 12 Sep 2024 13:55:07 +0400 Subject: [PATCH 4/4] Use Durations.ZERO constant inside committees inside Durations.from(0) --- contracts/committees/EmergencyActivationCommittee.sol | 2 +- contracts/committees/EmergencyExecutionCommittee.sol | 2 +- contracts/committees/TiebreakerSubCommittee.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/committees/EmergencyActivationCommittee.sol b/contracts/committees/EmergencyActivationCommittee.sol index 34d10e98..dce5ba81 100644 --- a/contracts/committees/EmergencyActivationCommittee.sol +++ b/contracts/committees/EmergencyActivationCommittee.sol @@ -23,7 +23,7 @@ contract EmergencyActivationCommittee is HashConsensus { address[] memory committeeMembers, uint256 executionQuorum, address emergencyProtectedTimelock - ) HashConsensus(owner, Durations.from(0)) { + ) HashConsensus(owner, Durations.ZERO) { EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; _addMembers(committeeMembers, executionQuorum); diff --git a/contracts/committees/EmergencyExecutionCommittee.sol b/contracts/committees/EmergencyExecutionCommittee.sol index 719ca409..72d03dc2 100644 --- a/contracts/committees/EmergencyExecutionCommittee.sol +++ b/contracts/committees/EmergencyExecutionCommittee.sol @@ -29,7 +29,7 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList { address[] memory committeeMembers, uint256 executionQuorum, address emergencyProtectedTimelock - ) HashConsensus(owner, Durations.from(0)) { + ) HashConsensus(owner, Durations.ZERO) { EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; _addMembers(committeeMembers, executionQuorum); diff --git a/contracts/committees/TiebreakerSubCommittee.sol b/contracts/committees/TiebreakerSubCommittee.sol index 4e6e0dc6..f69be1b7 100644 --- a/contracts/committees/TiebreakerSubCommittee.sol +++ b/contracts/committees/TiebreakerSubCommittee.sol @@ -27,7 +27,7 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { address[] memory committeeMembers, uint256 executionQuorum, address tiebreakerCoreCommittee - ) HashConsensus(owner, Durations.from(0)) { + ) HashConsensus(owner, Durations.ZERO) { TIEBREAKER_CORE_COMMITTEE = tiebreakerCoreCommittee; _addMembers(committeeMembers, executionQuorum);