-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Expand file tree
/
Copy pathGovernorDelay.sol
More file actions
106 lines (91 loc) · 3.67 KB
/
GovernorDelay.sol
File metadata and controls
106 lines (91 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (governance/extensions/GovernorDelay.sol)
pragma solidity ^0.8.24;
import {IGovernor, Governor} from "../Governor.sol";
import {SafeCast} from "../../utils/math/SafeCast.sol";
import {Time} from "../../utils/types/Time.sol";
/**
* @dev Extension of {Governor} that adds a configurable delay to all successful proposals before they can be executed.
*
* This extension provides a simple way to add a delay to all proposals without requiring an external timelock contract.
* When a delay is set (greater than 0), all successful proposals must be queued and wait for the delay period to elapse
* before they can be executed.
*
* The delay is enforced by the Governor itself, unlike {GovernorTimelockControl} and {GovernorTimelockCompound} where
* the delay is enforced by an external timelock contract.
*
* NOTE: The delay is expressed in seconds and uses block.timestamp, regardless of the governor's clock mode. This is
* consistent with {proposalEta} which is documented to not follow ERC-6372 CLOCK_MODE and almost always be a timestamp.
*
* @custom:security-note This extension enforces delays at the Governor level. If you need more sophisticated delay
* mechanisms (e.g., cancellable operations, different delays per operation), consider using {GovernorTimelockAccess}
* with an {AccessManager}.
*/
abstract contract GovernorDelay is Governor {
using Time for *;
uint32 private _delay;
error GovernorUnmetDelay(uint256 proposalId, uint256 neededTimestamp);
event DelaySet(uint32 oldDelay, uint32 newDelay);
/**
* @dev Initialize the governor with an initial delay.
*/
constructor(uint32 initialDelay) {
_setDelay(initialDelay);
}
/**
* @dev Returns the delay in seconds that must elapse before a queued proposal can be executed.
*/
function delay() public view virtual returns (uint32) {
return _delay;
}
/**
* @dev Change the delay. This operation can only be performed through a governance proposal.
*
* Emits a {DelaySet} event.
*/
function setDelay(uint32 newDelay) public virtual onlyGovernance {
_setDelay(newDelay);
}
/**
* @dev Internal function to set the delay without access control.
*/
function _setDelay(uint32 newDelay) internal virtual {
emit DelaySet(_delay, newDelay);
_delay = newDelay;
}
/// @inheritdoc IGovernor
function proposalNeedsQueuing(uint256) public view virtual override returns (bool) {
return _delay > 0;
}
/**
* @dev Function to queue a proposal with the configured delay.
*/
function _queueOperations(
uint256 /* proposalId */,
address[] memory /* targets */,
uint256[] memory /* values */,
bytes[] memory /* calldatas */,
bytes32 /* descriptionHash */
) internal virtual override returns (uint48) {
if (_delay == 0) {
return 0;
}
return Time.timestamp() + _delay;
}
/**
* @dev Overridden version of the {Governor-_executeOperations} function that checks if the delay has elapsed.
*/
function _executeOperations(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override {
uint48 etaSeconds = SafeCast.toUint48(proposalEta(proposalId));
if (etaSeconds > 0 && block.timestamp < etaSeconds) {
revert GovernorUnmetDelay(proposalId, etaSeconds);
}
super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
}
}