0
# Governance
1
2
OpenZeppelin Contracts provides a comprehensive governance framework enabling decentralized decision-making through on-chain voting mechanisms, proposal management, and timelock controllers for secure governance operations.
3
4
## Core Imports
5
6
Import governance contracts using Solidity import statements:
7
8
```solidity
9
import "@openzeppelin/contracts/governance/Governor.sol";
10
import "@openzeppelin/contracts/governance/TimelockController.sol";
11
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
12
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
13
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
14
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
15
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
16
```
17
18
## Capabilities
19
20
### Governor Framework
21
22
Core governance system providing flexible on-chain governance with proposal management, voting mechanisms, and execution capabilities.
23
24
```solidity { .api }
25
abstract contract Governor is Context, ERC165, EIP712, IGovernor {
26
function name() public view virtual returns (string memory);
27
function version() public view virtual returns (string memory);
28
function hashProposal(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) public pure virtual returns (uint256);
29
function state(uint256 proposalId) public view virtual returns (ProposalState);
30
function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);
31
function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);
32
function proposalThreshold() public view virtual returns (uint256);
33
function votingDelay() public view virtual returns (uint256);
34
function votingPeriod() public view virtual returns (uint256);
35
function quorum(uint256 blockNumber) public view virtual returns (uint256);
36
function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);
37
function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);
38
function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description) public virtual returns (uint256);
39
function execute(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) public payable virtual returns (uint256);
40
function cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) public virtual returns (uint256);
41
function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256);
42
function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) public virtual returns (uint256);
43
function castVoteWithReasonAndParams(uint256 proposalId, uint8 support, string calldata reason, bytes memory params) public virtual returns (uint256);
44
function castVoteBySig(uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) public virtual returns (uint256);
45
function castVoteWithReasonAndParamsBySig(uint256 proposalId, uint8 support, string calldata reason, bytes memory params, uint8 v, bytes32 r, bytes32 s) public virtual returns (uint256);
46
}
47
```
48
49
#### Proposal States
50
51
```solidity { .api }
52
enum ProposalState {
53
Pending,
54
Active,
55
Canceled,
56
Defeated,
57
Succeeded,
58
Queued,
59
Expired,
60
Executed
61
}
62
```
63
64
#### Events
65
66
```solidity { .api }
67
event ProposalCreated(uint256 proposalId, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description);
68
event ProposalCanceled(uint256 proposalId);
69
event ProposalExecuted(uint256 proposalId);
70
event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
71
event VoteCastWithParams(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason, bytes params);
72
```
73
74
### Timelock Controller
75
76
Timelock mechanism for governance operations ensuring a delay between proposal approval and execution for security and transparency.
77
78
```solidity { .api }
79
contract TimelockController is AccessControl {
80
function isOperation(bytes32 id) public view virtual returns (bool registered);
81
function isOperationPending(bytes32 id) public view virtual returns (bool pending);
82
function isOperationReady(bytes32 id) public view virtual returns (bool ready);
83
function isOperationDone(bytes32 id) public view virtual returns (bool done);
84
function getTimestamp(bytes32 id) public view virtual returns (uint256 timestamp);
85
function getMinDelay() public view virtual returns (uint256 duration);
86
function hashOperation(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash);
87
function hashOperationBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash);
88
function schedule(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual;
89
function scheduleBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual;
90
function cancel(bytes32 id) public virtual;
91
function execute(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public payable virtual;
92
function executeBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public payable virtual;
93
function updateDelay(uint256 newDelay) external virtual;
94
}
95
```
96
97
#### Timelock Roles
98
99
```solidity { .api }
100
bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
101
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
102
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
103
bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
104
```
105
106
#### Events
107
108
```solidity { .api }
109
event CallScheduled(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay);
110
event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
111
event Cancelled(bytes32 indexed id);
112
event MinDelayChange(uint256 oldDuration, uint256 newDuration);
113
```
114
115
### Governor Extensions
116
117
#### Governor Settings
118
119
Configurable governance parameters for voting delay, voting period, and proposal threshold.
120
121
```solidity { .api }
122
abstract contract GovernorSettings is Governor {
123
function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance;
124
function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance;
125
function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance;
126
}
127
```
128
129
#### Governor Counting Simple
130
131
Simple counting mechanism supporting Against, For, and Abstain votes.
132
133
```solidity { .api }
134
abstract contract GovernorCountingSimple is Governor {
135
function COUNTING_MODE() public pure virtual override returns (string memory);
136
function proposalVotes(uint256 proposalId) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes);
137
}
138
```
139
140
#### Governor Votes
141
142
Integration with vote-enabled tokens (like ERC20Votes) for determining voting power.
143
144
```solidity { .api }
145
abstract contract GovernorVotes is Governor {
146
constructor(IVotes _token);
147
function token() public view virtual returns (IVotes);
148
}
149
```
150
151
#### Governor Votes Quorum Fraction
152
153
Quorum calculation based on a fraction of the total token supply.
154
155
```solidity { .api }
156
abstract contract GovernorVotesQuorumFraction is GovernorVotes {
157
function quorumNumerator() public view virtual returns (uint256);
158
function quorumDenominator() public view virtual returns (uint256);
159
function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance;
160
}
161
```
162
163
#### Governor Timelock Control
164
165
Integration between Governor and TimelockController for delayed execution.
166
167
```solidity { .api }
168
abstract contract GovernorTimelockControl is Governor {
169
constructor(TimelockController _timelock);
170
function timelock() public view virtual override returns (address);
171
function proposalEta(uint256 proposalId) public view virtual override returns (uint256);
172
function queue(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) public virtual returns (uint256);
173
}
174
```
175
176
#### Governor Prevent Late Quorum
177
178
Prevents late quorum manipulation by extending the voting period when quorum is reached near the deadline.
179
180
```solidity { .api }
181
abstract contract GovernorPreventLateQuorum is Governor {
182
function lateQuorumVoteExtension() public view virtual returns (uint64);
183
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256);
184
function setLateQuorumVoteExtension(uint64 newVoteExtension) external virtual onlyGovernance;
185
}
186
```
187
188
#### Governor Proposal Threshold
189
190
Sets minimum voting power required to create proposals, preventing spam.
191
192
```solidity { .api }
193
abstract contract GovernorProposalThreshold is Governor {
194
function proposalThreshold() public view virtual override returns (uint256);
195
}
196
```
197
198
#### Governor Votes Comp
199
200
Compound-compatible voting weight extraction from ERC20VotesComp tokens.
201
202
```solidity { .api }
203
abstract contract GovernorVotesComp is Governor {
204
constructor(ERC20VotesComp _token);
205
function token() public view virtual returns (IERC20);
206
function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256);
207
}
208
```
209
210
#### Governor Timelock Compound
211
212
Integration with Compound-style timelock for legacy compatibility.
213
214
```solidity { .api }
215
abstract contract GovernorTimelockCompound is Governor {
216
constructor(TimelockInterface _timelock);
217
function timelock() public view virtual override returns (address);
218
function proposalEta(uint256 proposalId) public view virtual override returns (uint256);
219
}
220
```
221
222
#### Governor Compatibility Bravo
223
224
Full compatibility layer providing GovernorBravo interface for existing integrations.
225
226
```solidity { .api }
227
abstract contract GovernorCompatibilityBravo is Governor, GovernorTimelockControl {
228
function propose(address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public virtual returns (uint256);
229
function queue(uint256 proposalId) public virtual;
230
function execute(uint256 proposalId) public payable virtual;
231
function cancel(uint256 proposalId) public virtual;
232
function getActions(uint256 proposalId) external view virtual returns (address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas);
233
function getReceipt(uint256 proposalId, address voter) external view virtual returns (Receipt memory);
234
}
235
```
236
237
## Usage Example
238
239
### Basic DAO Setup
240
241
```solidity
242
pragma solidity ^0.8.0;
243
244
import "@openzeppelin/contracts/governance/Governor.sol";
245
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
246
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
247
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
248
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
249
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
250
251
contract MyDAO is
252
Governor,
253
GovernorSettings,
254
GovernorCountingSimple,
255
GovernorVotes,
256
GovernorVotesQuorumFraction,
257
GovernorTimelockControl
258
{
259
constructor(
260
IVotes _token,
261
TimelockController _timelock,
262
uint256 _votingDelay,
263
uint256 _votingPeriod,
264
uint256 _proposalThreshold,
265
uint256 _quorumPercentage
266
)
267
Governor("MyDAO")
268
GovernorSettings(_votingDelay, _votingPeriod, _proposalThreshold)
269
GovernorVotes(_token)
270
GovernorVotesQuorumFraction(_quorumPercentage)
271
GovernorTimelockControl(_timelock)
272
{}
273
274
function votingDelay() public view override(IGovernor, GovernorSettings) returns (uint256) {
275
return super.votingDelay();
276
}
277
278
function votingPeriod() public view override(IGovernor, GovernorSettings) returns (uint256) {
279
return super.votingPeriod();
280
}
281
282
function quorum(uint256 blockNumber) public view override(IGovernor, GovernorVotesQuorumFraction) returns (uint256) {
283
return super.quorum(blockNumber);
284
}
285
286
function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
287
return super.proposalThreshold();
288
}
289
}
290
```
291
292
### Creating and Executing Proposals
293
294
```solidity
295
// Create a proposal
296
address[] memory targets = new address[](1);
297
uint256[] memory values = new uint256[](1);
298
bytes[] memory calldatas = new bytes[](1);
299
300
targets[0] = address(treasury);
301
values[0] = 0;
302
calldatas[0] = abi.encodeWithSelector(Treasury.withdraw.selector, recipient, amount);
303
304
uint256 proposalId = governor.propose(
305
targets,
306
values,
307
calldatas,
308
"Proposal #1: Withdraw funds from treasury"
309
);
310
311
// Vote on the proposal (after voting delay)
312
governor.castVote(proposalId, 1); // 1 = For
313
314
// Queue the proposal (if using timelock)
315
governor.queue(
316
targets,
317
values,
318
calldatas,
319
keccak256(bytes("Proposal #1: Withdraw funds from treasury"))
320
);
321
322
// Execute the proposal (after timelock delay)
323
governor.execute(
324
targets,
325
values,
326
calldatas,
327
keccak256(bytes("Proposal #1: Withdraw funds from treasury"))
328
);
329
```
330
331
## Governance Best Practices
332
333
1. **Voting Power**: Use vote-enabled tokens (ERC20Votes) to determine voting power
334
2. **Quorum**: Set appropriate quorum thresholds to ensure legitimacy
335
3. **Timelock**: Use timelock delays to allow for community review and emergency responses
336
4. **Proposal Threshold**: Set reasonable proposal thresholds to prevent spam
337
5. **Voting Period**: Balance adequate deliberation time with operational efficiency
338
6. **Emergency Procedures**: Implement emergency mechanisms for critical vulnerabilities
339
340
## Integration with Token Voting
341
342
```solidity
343
pragma solidity ^0.8.0;
344
345
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
346
347
contract GovernanceToken is ERC20Votes {
348
constructor() ERC20("GovernanceToken", "GOV") EIP712("GovernanceToken", "1") {
349
_mint(msg.sender, 1000000 * 10**18);
350
}
351
352
function _afterTokenTransfer(address from, address to, uint256 amount) internal override(ERC20Votes) {
353
super._afterTokenTransfer(from, to, amount);
354
}
355
356
function _mint(address to, uint256 amount) internal override(ERC20Votes) {
357
super._mint(to, amount);
358
}
359
360
function _burn(address account, uint256 amount) internal override(ERC20Votes) {
361
super._burn(account, amount);
362
}
363
}
364
```
365
366
## Error Handling
367
368
Governance contracts may revert with various errors:
369
370
- **Governor**: `GovernorAlreadyCastVote(address voter)`, `GovernorDisabledDeposit()`, `GovernorInvalidProposalLength(uint256 targets, uint256 calldatas, uint256 values)`, etc.
371
- **TimelockController**: `TimelockInsufficientDelay(uint256 delay, uint256 minDelay)`, `TimelockInvalidOperation(bytes32 operationId)`, etc.
372
- **Access Control**: Standard AccessControl errors for role-based permissions