Skip to content

Commit

Permalink
Merge branch 'lidofinance:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
qian-hu authored Sep 30, 2024
2 parents ef214c7 + 1ffa251 commit 2fcc925
Show file tree
Hide file tree
Showing 70 changed files with 7,355 additions and 1,291 deletions.
346 changes: 262 additions & 84 deletions contracts/DualGovernance.sol

Large diffs are not rendered by default.

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

This file was deleted.

215 changes: 138 additions & 77 deletions contracts/EmergencyProtectedTimelock.sol

Large diffs are not rendered by default.

263 changes: 205 additions & 58 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;
}
}
10 changes: 7 additions & 3 deletions contracts/TimelockedGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ contract TimelockedGovernance is IGovernance {
/// @dev Submits a proposal to the timelock.
/// @param calls An array of ExternalCall structs representing the calls to be executed in the proposal.
/// @return proposalId The ID of the submitted proposal.
function submitProposal(ExternalCall[] calldata calls) external returns (uint256 proposalId) {
function submitProposal(
ExternalCall[] calldata calls,
string calldata metadata
) external returns (uint256 proposalId) {
_checkCallerIsGovernance();
return TIMELOCK.submit(TIMELOCK.getAdminExecutor(), calls);
return TIMELOCK.submit(TIMELOCK.getAdminExecutor(), calls, metadata);
}

/// @dev Schedules a submitted proposal.
Expand All @@ -50,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)
);
}
}
38 changes: 29 additions & 9 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 @@ -17,14 +20,16 @@ enum ProposalType {
/// @notice This contract allows a committee to vote on and execute emergency proposals
/// @dev Inherits from HashConsensus for voting mechanisms and ProposalsList for proposal management
contract EmergencyExecutionCommittee is HashConsensus, ProposalsList {
error ProposalDoesNotExist(uint256 proposalId);

address public immutable EMERGENCY_PROTECTED_TIMELOCK;

constructor(
address owner,
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 @@ -37,11 +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 @@ -66,10 +72,22 @@ 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 > IEmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK).getProposalsCount()
) {
revert ProposalDoesNotExist(proposalId);
}
}

/// @dev Encodes the proposal data and generates the proposal key for an emergency execution
/// @param proposalId The ID of the proposal to encode
/// @return proposalData The encoded proposal data
Expand Down Expand Up @@ -114,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
Loading

0 comments on commit 2fcc925

Please sign in to comment.