Skip to content

Commit

Permalink
Merge branch 'develop' into develop-archive-sorted-through
Browse files Browse the repository at this point in the history
  • Loading branch information
Psirex committed Nov 29, 2024
2 parents f7b34ef + 7ca533f commit 59f35d4
Show file tree
Hide file tree
Showing 11 changed files with 496 additions and 55 deletions.
47 changes: 39 additions & 8 deletions contracts/EmergencyProtectedTimelock.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

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

import {IOwnable} from "./interfaces/IOwnable.sol";
import {IEmergencyProtectedTimelock} from "./interfaces/IEmergencyProtectedTimelock.sol";
Expand Down Expand Up @@ -32,17 +32,23 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock {
// ---

/// @notice The parameters for the sanity checks.
/// @param minExecutionDelay The minimum allowable duration for the combined after-submit and after-schedule delays.
/// @param maxAfterSubmitDelay The maximum allowable delay before a submitted proposal can be scheduled for execution.
/// @param maxAfterScheduleDelay The maximum allowable delay before a scheduled proposal can be executed.
/// @param maxEmergencyModeDuration The maximum time the timelock can remain in emergency mode.
/// @param maxEmergencyProtectionDuration The maximum time the emergency protection mechanism can be activated.
struct SanityCheckParams {
Duration minExecutionDelay;
Duration maxAfterSubmitDelay;
Duration maxAfterScheduleDelay;
Duration maxEmergencyModeDuration;
Duration maxEmergencyProtectionDuration;
}

/// @notice Represents the minimum allowed time that must pass between the submission of a proposal and its execution.
/// @dev The minimum permissible value for the sum of `afterScheduleDelay` and `afterSubmitDelay`.
Duration public immutable MIN_EXECUTION_DELAY;

/// @notice The upper bound for the delay required before a submitted proposal can be scheduled for execution.
Duration public immutable MAX_AFTER_SUBMIT_DELAY;

Expand Down Expand Up @@ -72,13 +78,29 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock {
// Constructor
// ---

constructor(SanityCheckParams memory sanityCheckParams, address adminExecutor) {
constructor(
SanityCheckParams memory sanityCheckParams,
address adminExecutor,
Duration afterSubmitDelay,
Duration afterScheduleDelay
) {
MIN_EXECUTION_DELAY = sanityCheckParams.minExecutionDelay;
MAX_AFTER_SUBMIT_DELAY = sanityCheckParams.maxAfterSubmitDelay;
MAX_AFTER_SCHEDULE_DELAY = sanityCheckParams.maxAfterScheduleDelay;
MAX_EMERGENCY_MODE_DURATION = sanityCheckParams.maxEmergencyModeDuration;
MAX_EMERGENCY_PROTECTION_DURATION = sanityCheckParams.maxEmergencyProtectionDuration;

_timelockState.setAdminExecutor(adminExecutor);

if (afterSubmitDelay > Durations.ZERO) {
_timelockState.setAfterSubmitDelay(afterSubmitDelay, MAX_AFTER_SUBMIT_DELAY);
}

if (afterScheduleDelay > Durations.ZERO) {
_timelockState.setAfterScheduleDelay(afterScheduleDelay, MAX_AFTER_SCHEDULE_DELAY);
}

_timelockState.checkExecutionDelay(MIN_EXECUTION_DELAY);
}

// ---
Expand Down Expand Up @@ -132,13 +154,22 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock {
_timelockState.setGovernance(newGovernance);
}

/// @notice Configures the delays for submitting and scheduling proposals, within defined upper bounds.
/// @param afterSubmitDelay The delay required before a submitted proposal can be scheduled.
/// @param afterScheduleDelay The delay required before a scheduled proposal can be executed.
function setupDelays(Duration afterSubmitDelay, Duration afterScheduleDelay) external {
/// @notice Sets the delay required to pass from the submission of a proposal before it can be scheduled for execution.
/// Ensures that the new delay value complies with the defined sanity check bounds.
/// @param newAfterSubmitDelay The delay required before a submitted proposal can be scheduled.
function setAfterSubmitDelay(Duration newAfterSubmitDelay) external {
_checkCallerIsAdminExecutor();
_timelockState.setAfterSubmitDelay(newAfterSubmitDelay, MAX_AFTER_SUBMIT_DELAY);
_timelockState.checkExecutionDelay(MIN_EXECUTION_DELAY);
}

/// @notice Sets the delay required to pass from the scheduling of a proposal before it can be executed.
/// Ensures that the new delay value complies with the defined sanity check bounds.
/// @param newAfterScheduleDelay The delay required before a scheduled proposal can be executed.
function setAfterScheduleDelay(Duration newAfterScheduleDelay) external {
_checkCallerIsAdminExecutor();
_timelockState.setAfterSubmitDelay(afterSubmitDelay, MAX_AFTER_SUBMIT_DELAY);
_timelockState.setAfterScheduleDelay(afterScheduleDelay, MAX_AFTER_SCHEDULE_DELAY);
_timelockState.setAfterScheduleDelay(newAfterScheduleDelay, MAX_AFTER_SCHEDULE_DELAY);
_timelockState.checkExecutionDelay(MIN_EXECUTION_DELAY);
}

/// @notice Transfers ownership of the executor contract to a new owner.
Expand Down
17 changes: 14 additions & 3 deletions contracts/libraries/TimelockState.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ library TimelockState {
// ---

error CallerIsNotGovernance(address caller);
error InvalidGovernance(address value);
error InvalidAfterSubmitDelay(Duration value);
error InvalidAfterScheduleDelay(Duration value);
error InvalidGovernance(address governance);
error InvalidAdminExecutor(address adminExecutor);
error InvalidExecutionDelay(Duration executionDelay);
error InvalidAfterSubmitDelay(Duration afterSubmitDelay);
error InvalidAfterScheduleDelay(Duration afterScheduleDelay);

// ---
// Events
Expand Down Expand Up @@ -122,4 +123,14 @@ library TimelockState {
revert CallerIsNotGovernance(msg.sender);
}
}

/// @notice Checks that the combined after-submit and after-schedule delays meet the minimum required execution delay.
/// @param self The context of the Timelock State library library.
/// @param minExecutionDelay The minimum required delay between proposal submission and execution.
function checkExecutionDelay(Context storage self, Duration minExecutionDelay) internal view {
Duration executionDelay = self.afterScheduleDelay + self.afterSubmitDelay;
if (executionDelay < minExecutionDelay) {
revert InvalidExecutionDelay(executionDelay);
}
}
}
2 changes: 1 addition & 1 deletion docs/plan-b.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ Resets the `governance` address to the `EMERGENCY_GOVERNANCE` value defined in t
* MUST be called by the Emergency Execution Committee address.

### Admin functions
The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setupDelays`). These functions MUST be called by the [Admin Executor](#) address.
The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setAfterSubmitDelay`, `setAfterScheduleDelay`). These functions MUST be called by the [Admin Executor](#) address.

## Contract: `Executor`
Executes calls resulting from governance proposals' execution. Every protocol permission or role protected by the TG, as well as the permission to manage these roles/permissions, should be assigned exclusively to instances of this contract.
Expand Down
2 changes: 1 addition & 1 deletion docs/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ Resets the `governance` address to the `EMERGENCY_GOVERNANCE` value defined in t

### Admin functions

The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setupDelays`). These functions MUST be called by the [Admin Executor](#Administrative-actions) address, basically routing any such changes through the Dual Governance mechanics.
The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setAfterSubmitDelay`, `setAfterScheduleDelay`). These functions MUST be called by the [Admin Executor](#Administrative-actions) address, basically routing any such changes through the Dual Governance mechanics.

## Contract: ImmutableDualGovernanceConfigProvider.sol

Expand Down
3 changes: 3 additions & 0 deletions scripts/deploy/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {IAragonVoting} from "contracts/interfaces/IAragonVoting.sol";
import {Duration} from "contracts/types/Duration.sol";
import {PercentD16} from "contracts/types/PercentD16.sol";

// TODO: choose better value for MIN_EXECUTION_DELAY
uint256 constant DEFAULT_MIN_EXECUTION_DELAY = 0 seconds;
uint256 constant DEFAULT_AFTER_SUBMIT_DELAY = 3 days;
uint256 constant DEFAULT_MAX_AFTER_SUBMIT_DELAY = 45 days;
uint256 constant DEFAULT_AFTER_SCHEDULE_DELAY = 3 days;
Expand Down Expand Up @@ -45,6 +47,7 @@ bytes32 constant CHAIN_NAME_HOLESKY_HASH = keccak256(bytes("holesky"));
bytes32 constant CHAIN_NAME_HOLESKY_MOCKS_HASH = keccak256(bytes("holesky-mocks"));

struct DeployConfig {
Duration MIN_EXECUTION_DELAY;
Duration AFTER_SUBMIT_DELAY;
Duration MAX_AFTER_SUBMIT_DELAY;
Duration AFTER_SCHEDULE_DELAY;
Expand Down
12 changes: 4 additions & 8 deletions scripts/deploy/ContractsDeployment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,14 @@ library DGContractsDeployment {
return new EmergencyProtectedTimelock({
adminExecutor: address(adminExecutor),
sanityCheckParams: EmergencyProtectedTimelock.SanityCheckParams({
minExecutionDelay: dgDeployConfig.MIN_EXECUTION_DELAY,
maxAfterSubmitDelay: dgDeployConfig.MAX_AFTER_SUBMIT_DELAY,
maxAfterScheduleDelay: dgDeployConfig.MAX_AFTER_SCHEDULE_DELAY,
maxEmergencyModeDuration: dgDeployConfig.MAX_EMERGENCY_MODE_DURATION,
maxEmergencyProtectionDuration: dgDeployConfig.MAX_EMERGENCY_PROTECTION_DURATION
})
}),
afterSubmitDelay: dgDeployConfig.AFTER_SUBMIT_DELAY,
afterScheduleDelay: dgDeployConfig.AFTER_SCHEDULE_DELAY
});
}

Expand Down Expand Up @@ -322,13 +325,6 @@ library DGContractsDeployment {
address dualGovernance,
DeployConfig memory dgDeployConfig
) internal {
adminExecutor.execute(
address(timelock),
0,
abi.encodeCall(
timelock.setupDelays, (dgDeployConfig.AFTER_SUBMIT_DELAY, dgDeployConfig.AFTER_SCHEDULE_DELAY)
)
);
adminExecutor.execute(address(timelock), 0, abi.encodeCall(timelock.setGovernance, (dualGovernance)));
adminExecutor.transferOwnership(address(timelock));
}
Expand Down
4 changes: 4 additions & 0 deletions scripts/deploy/JsonConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {PercentsD16} from "contracts/types/PercentD16.sol";
import {
DeployConfig,
LidoContracts,
DEFAULT_MIN_EXECUTION_DELAY,
DEFAULT_AFTER_SUBMIT_DELAY,
DEFAULT_MAX_AFTER_SUBMIT_DELAY,
DEFAULT_AFTER_SCHEDULE_DELAY,
Expand Down Expand Up @@ -75,6 +76,9 @@ contract DGDeployJSONConfigProvider is Script {
string memory jsonConfig = loadConfigFile();

config = DeployConfig({
MIN_EXECUTION_DELAY: Durations.from(
stdJson.readUintOr(jsonConfig, ".MIN_EXECUTION_DELAY", DEFAULT_MIN_EXECUTION_DELAY)
),
AFTER_SUBMIT_DELAY: Durations.from(
stdJson.readUintOr(jsonConfig, ".AFTER_SUBMIT_DELAY", DEFAULT_AFTER_SUBMIT_DELAY)
),
Expand Down
Loading

0 comments on commit 59f35d4

Please sign in to comment.