Skip to content

Commit

Permalink
Squash commit: Pending DualGovernance state PR #127
Browse files Browse the repository at this point in the history
  • Loading branch information
bulbozaur committed Oct 30, 2024
1 parent ece9a84 commit d0d3ad9
Show file tree
Hide file tree
Showing 52 changed files with 4,792 additions and 1,040 deletions.
329 changes: 249 additions & 80 deletions contracts/DualGovernance.sol

Large diffs are not rendered by default.

76 changes: 0 additions & 76 deletions contracts/DualGovernanceConfigProvider.sol

This file was deleted.

166 changes: 99 additions & 67 deletions contracts/EmergencyProtectedTimelock.sol

Large diffs are not rendered by default.

261 changes: 204 additions & 57 deletions contracts/Escrow.sol

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions contracts/ImmutableDualGovernanceConfigProvider.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {Duration} from "./types/Duration.sol";
import {PercentD16} from "./types/PercentD16.sol";

import {IDualGovernanceConfigProvider} from "./interfaces/IDualGovernanceConfigProvider.sol";

import {DualGovernanceConfig} from "./libraries/DualGovernanceConfig.sol";

contract ImmutableDualGovernanceConfigProvider is IDualGovernanceConfigProvider {
using DualGovernanceConfig for DualGovernanceConfig.Context;

PercentD16 public immutable FIRST_SEAL_RAGE_QUIT_SUPPORT;
PercentD16 public immutable SECOND_SEAL_RAGE_QUIT_SUPPORT;

Duration public immutable MIN_ASSETS_LOCK_DURATION;

Duration public immutable VETO_SIGNALLING_MIN_DURATION;
Duration public immutable VETO_SIGNALLING_MAX_DURATION;
Duration public immutable VETO_SIGNALLING_MIN_ACTIVE_DURATION;
Duration public immutable VETO_SIGNALLING_DEACTIVATION_MAX_DURATION;

Duration public immutable VETO_COOLDOWN_DURATION;

Duration public immutable RAGE_QUIT_EXTENSION_PERIOD_DURATION;
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY;
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY;
Duration public immutable RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH;

constructor(DualGovernanceConfig.Context memory dualGovernanceConfig) {
dualGovernanceConfig.validate();

FIRST_SEAL_RAGE_QUIT_SUPPORT = dualGovernanceConfig.firstSealRageQuitSupport;
SECOND_SEAL_RAGE_QUIT_SUPPORT = dualGovernanceConfig.secondSealRageQuitSupport;

MIN_ASSETS_LOCK_DURATION = dualGovernanceConfig.minAssetsLockDuration;
VETO_SIGNALLING_MIN_DURATION = dualGovernanceConfig.vetoSignallingMinDuration;
VETO_SIGNALLING_MAX_DURATION = dualGovernanceConfig.vetoSignallingMaxDuration;

VETO_SIGNALLING_MIN_ACTIVE_DURATION = dualGovernanceConfig.vetoSignallingMinActiveDuration;
VETO_SIGNALLING_DEACTIVATION_MAX_DURATION = dualGovernanceConfig.vetoSignallingDeactivationMaxDuration;

VETO_COOLDOWN_DURATION = dualGovernanceConfig.vetoCooldownDuration;

RAGE_QUIT_EXTENSION_PERIOD_DURATION = dualGovernanceConfig.rageQuitExtensionPeriodDuration;
RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY = dualGovernanceConfig.rageQuitEthWithdrawalsMinDelay;
RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY = dualGovernanceConfig.rageQuitEthWithdrawalsMaxDelay;
RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH = dualGovernanceConfig.rageQuitEthWithdrawalsDelayGrowth;
}

function getDualGovernanceConfig() external view returns (DualGovernanceConfig.Context memory config) {
config.firstSealRageQuitSupport = FIRST_SEAL_RAGE_QUIT_SUPPORT;
config.secondSealRageQuitSupport = SECOND_SEAL_RAGE_QUIT_SUPPORT;

config.minAssetsLockDuration = MIN_ASSETS_LOCK_DURATION;
config.vetoSignallingMinDuration = VETO_SIGNALLING_MIN_DURATION;
config.vetoSignallingMaxDuration = VETO_SIGNALLING_MAX_DURATION;
config.vetoSignallingMinActiveDuration = VETO_SIGNALLING_MIN_ACTIVE_DURATION;
config.vetoSignallingDeactivationMaxDuration = VETO_SIGNALLING_DEACTIVATION_MAX_DURATION;

config.vetoCooldownDuration = VETO_COOLDOWN_DURATION;

config.rageQuitExtensionPeriodDuration = RAGE_QUIT_EXTENSION_PERIOD_DURATION;
config.rageQuitEthWithdrawalsMinDelay = RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY;
config.rageQuitEthWithdrawalsMaxDelay = RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY;
config.rageQuitEthWithdrawalsDelayGrowth = RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH;
}
}
3 changes: 2 additions & 1 deletion contracts/TimelockedGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ contract TimelockedGovernance is IGovernance {
}

/// @dev Cancels all pending proposals that have not been executed.
function cancelAllPendingProposals() external {
function cancelAllPendingProposals() external returns (bool) {
_checkCallerIsGovernance();
TIMELOCK.cancelAllNonExecutedProposals();
return true;
}

/// @dev Checks if the msg.sender is the governance address.
Expand Down
13 changes: 8 additions & 5 deletions contracts/committees/EmergencyActivationCommittee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ pragma solidity 0.8.26;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {HashConsensus} from "./HashConsensus.sol";
import {ITimelock} from "../interfaces/ITimelock.sol";
import {Duration, Durations} from "../types/Duration.sol";
import {Durations} from "../types/Duration.sol";
import {Timestamp} from "../types/Timestamp.sol";

import {IEmergencyProtectedTimelock} from "../interfaces/IEmergencyProtectedTimelock.sol";

import {HashConsensus} from "./HashConsensus.sol";

/// @title Emergency Activation Committee Contract
/// @notice This contract allows a committee to approve and execute an emergency activation
/// @dev Inherits from HashConsensus to utilize voting and consensus mechanisms
Expand All @@ -21,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);
Expand Down Expand Up @@ -52,7 +54,8 @@ contract EmergencyActivationCommittee is HashConsensus {
function executeActivateEmergencyMode() external {
_markUsed(EMERGENCY_ACTIVATION_HASH);
Address.functionCall(
EMERGENCY_PROTECTED_TIMELOCK, abi.encodeWithSelector(ITimelock.activateEmergencyMode.selector)
EMERGENCY_PROTECTED_TIMELOCK,
abi.encodeWithSelector(IEmergencyProtectedTimelock.activateEmergencyMode.selector)
);
}
}
29 changes: 19 additions & 10 deletions contracts/committees/EmergencyExecutionCommittee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
pragma solidity 0.8.26;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {Durations} from "../types/Duration.sol";
import {Timestamp} from "../types/Timestamp.sol";

import {IEmergencyProtectedTimelock} from "../interfaces/IEmergencyProtectedTimelock.sol";

import {HashConsensus} from "./HashConsensus.sol";
import {ProposalsList} from "./ProposalsList.sol";
import {ITimelock} from "../interfaces/ITimelock.sol";
import {Timestamp} from "../types/Timestamp.sol";
import {Durations} from "../types/Duration.sol";

enum ProposalType {
EmergencyExecute,
Expand All @@ -26,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);
Expand All @@ -39,12 +42,12 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList {
/// @notice Votes on an emergency execution proposal
/// @dev Only callable by committee members
/// @param proposalId The ID of the proposal to vote on
/// @param _supports Indicates whether the member supports the proposal execution
function voteEmergencyExecute(uint256 proposalId, bool _supports) public {
/// @param _support Indicates whether the member supports the proposal execution
function voteEmergencyExecute(uint256 proposalId, bool _support) public {
_checkCallerIsMember();
_checkProposalExists(proposalId);
(bytes memory proposalData, bytes32 key) = _encodeEmergencyExecute(proposalId);
_vote(key, _supports);
_vote(key, _support);
_pushProposal(key, uint256(ProposalType.EmergencyExecute), proposalData);
}

Expand All @@ -69,14 +72,18 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList {
(, bytes32 key) = _encodeEmergencyExecute(proposalId);
_markUsed(key);
Address.functionCall(
EMERGENCY_PROTECTED_TIMELOCK, abi.encodeWithSelector(ITimelock.emergencyExecute.selector, proposalId)
EMERGENCY_PROTECTED_TIMELOCK,
abi.encodeWithSelector(IEmergencyProtectedTimelock.emergencyExecute.selector, proposalId)
);
}

/// @notice Checks if a proposal exists
/// @param proposalId The ID of the proposal to check
function _checkProposalExists(uint256 proposalId) internal view {
if (proposalId == 0 || proposalId > ITimelock(EMERGENCY_PROTECTED_TIMELOCK).getProposalsCount()) {
if (
proposalId == 0
|| proposalId > IEmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK).getProposalsCount()
) {
revert ProposalDoesNotExist(proposalId);
}
}
Expand Down Expand Up @@ -125,7 +132,9 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList {
function executeEmergencyReset() external {
bytes32 proposalKey = _encodeEmergencyResetProposalKey();
_markUsed(proposalKey);
Address.functionCall(EMERGENCY_PROTECTED_TIMELOCK, abi.encodeWithSelector(ITimelock.emergencyReset.selector));
Address.functionCall(
EMERGENCY_PROTECTED_TIMELOCK, abi.encodeWithSelector(IEmergencyProtectedTimelock.emergencyReset.selector)
);
}

/// @notice Encodes the proposal key for an emergency reset
Expand Down
39 changes: 22 additions & 17 deletions contracts/committees/HashConsensus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.26;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {Duration} from "../types/Duration.sol";
import {Timestamp, Timestamps} from "../types/Timestamp.sol";

Expand Down Expand Up @@ -57,10 +58,6 @@ abstract contract HashConsensus is Ownable {
revert HashAlreadyScheduled(hash);
}

if (approves[msg.sender][hash] == support) {
return;
}

approves[msg.sender][hash] = support;
emit Voted(msg.sender, hash, support);

Expand Down Expand Up @@ -127,19 +124,11 @@ abstract contract HashConsensus is Ownable {
/// function will revert. The quorum is also updated and must not be zero or greater than
/// the new total number of members.
/// @param membersToRemove The array of addresses to be removed from the members list.
/// @param newQuorum The updated minimum number of members required for executing certain operations.
function removeMembers(address[] memory membersToRemove, uint256 newQuorum) public {
/// @param executionQuorum The updated minimum number of members required for executing certain operations.
function removeMembers(address[] memory membersToRemove, uint256 executionQuorum) public {
_checkOwner();

for (uint256 i = 0; i < membersToRemove.length; ++i) {
if (!_members.contains(membersToRemove[i])) {
revert AccountIsNotMember(membersToRemove[i]);
}
_members.remove(membersToRemove[i]);
emit MemberRemoved(membersToRemove[i]);
}

_setQuorum(newQuorum);
_removeMembers(membersToRemove, executionQuorum);
}

/// @notice Gets the list of committee members
Expand Down Expand Up @@ -216,16 +205,32 @@ abstract contract HashConsensus is Ownable {
/// @param executionQuorum The minimum number of members required for executing certain operations.
function _addMembers(address[] memory newMembers, uint256 executionQuorum) internal {
for (uint256 i = 0; i < newMembers.length; ++i) {
if (_members.contains(newMembers[i])) {
if (!_members.add(newMembers[i])) {
revert DuplicatedMember(newMembers[i]);
}
_members.add(newMembers[i]);
emit MemberAdded(newMembers[i]);
}

_setQuorum(executionQuorum);
}

/// @notice Removes specified members from the contract and updates the execution quorum.
/// @dev This internal function removes multiple members from the contract. If any of the specified members are not
/// found in the members list, the function will revert. The quorum is also updated and must not be zero or
/// greater than the new total number of members.
/// @param membersToRemove The array of addresses to be removed from the members list.
/// @param executionQuorum The updated minimum number of members required for executing certain operations.
function _removeMembers(address[] memory membersToRemove, uint256 executionQuorum) internal {
for (uint256 i = 0; i < membersToRemove.length; ++i) {
if (!_members.remove(membersToRemove[i])) {
revert AccountIsNotMember(membersToRemove[i]);
}
emit MemberRemoved(membersToRemove[i]);
}

_setQuorum(executionQuorum);
}

/// @notice Gets the number of votes in support of a given hash
/// @dev Internal function to count the votes in support of a hash
/// @param hash The hash to check
Expand Down
6 changes: 4 additions & 2 deletions contracts/committees/ResealCommittee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ pragma solidity 0.8.26;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {Duration} from "../types/Duration.sol";
import {Timestamp} from "../types/Timestamp.sol";

import {IDualGovernance} from "../interfaces/IDualGovernance.sol";

import {HashConsensus} from "./HashConsensus.sol";
import {ProposalsList} from "./ProposalsList.sol";
import {Timestamp} from "../types/Timestamp.sol";
import {Duration} from "../types/Duration.sol";

/// @title Reseal Committee Contract
/// @notice This contract allows a committee to vote on and execute resealing proposals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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);

Expand Down
Loading

0 comments on commit d0d3ad9

Please sign in to comment.