@venusprotocol/governance-contracts 1.1.0-dev.2 → 1.1.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/artifacts/build-info/52cd2a2ed6764b7fce3ff5a23ca8a581.json +1 -0
- package/artifacts/contracts/Governance/GovernorBravoDelegate.sol/GovernorBravoDelegate.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoDelegator.sol/GovernorBravoDelegator.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorAlphaInterface.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateInterface.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV2.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoEvents.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/TimelockInterface.dbg.json +1 -1
- package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/XvsVaultInterface.dbg.json +1 -1
- package/artifacts/contracts/legacy/GovernorBravoDelegateV1.sol/GovernorBravoDelegateV1.dbg.json +4 -0
- package/artifacts/contracts/legacy/GovernorBravoDelegateV1.sol/GovernorBravoDelegateV1.json +1143 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.dbg.json +4 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.json +278 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.dbg.json +4 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.json +56 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoEventsV1.dbg.json +4 -0
- package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoEventsV1.json +306 -0
- package/contracts/legacy/GovernorBravoDelegateV1.sol +528 -0
- package/contracts/legacy/GovernorBravoInterfaces.sol +176 -0
- package/deployments/bscmainnet/AccessControlManager.json +285 -0
- package/deployments/bscmainnet.json +7167 -0
- package/deployments/bsctestnet/AccessControlManager.json +364 -0
- package/deployments/bsctestnet.json +6437 -0
- package/deployments/sepolia.json +369 -0
- package/package.json +1 -1
- package/artifacts/build-info/97a3124320e74f843bc59439c75c258d.json +0 -1
- package/deployments/deployments.json +0 -13981
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
pragma solidity ^0.5.16;
|
|
2
|
+
pragma experimental ABIEncoderV2;
|
|
3
|
+
|
|
4
|
+
import "./GovernorBravoInterfaces.sol";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @title GovernorBravoDelegateV1
|
|
8
|
+
* @dev This contract is the first deployed implementation GovernorBravo.
|
|
9
|
+
* It is included here for testing purposes because it has a different signature for the ProposalCreated event and Proposal struct
|
|
10
|
+
*/
|
|
11
|
+
contract GovernorBravoDelegateV1 is GovernorBravoDelegateStorageV1, GovernorBravoEventsV1 {
|
|
12
|
+
/// @notice The name of this contract
|
|
13
|
+
string public constant name = "Venus Governor Bravo";
|
|
14
|
+
|
|
15
|
+
/// @notice The minimum setable proposal threshold
|
|
16
|
+
uint public constant MIN_PROPOSAL_THRESHOLD = 150000e18; // 150,000 Xvs
|
|
17
|
+
|
|
18
|
+
/// @notice The maximum setable proposal threshold
|
|
19
|
+
uint public constant MAX_PROPOSAL_THRESHOLD = 300000e18; //300,000 Xvs
|
|
20
|
+
|
|
21
|
+
/// @notice The minimum setable voting period
|
|
22
|
+
uint public constant MIN_VOTING_PERIOD = 20 * 60 * 3; // About 3 hours, 3 secs per block
|
|
23
|
+
|
|
24
|
+
/// @notice The max setable voting period
|
|
25
|
+
uint public constant MAX_VOTING_PERIOD = 20 * 60 * 24 * 14; // About 2 weeks, 3 secs per block
|
|
26
|
+
|
|
27
|
+
/// @notice The min setable voting delay
|
|
28
|
+
uint public constant MIN_VOTING_DELAY = 1;
|
|
29
|
+
|
|
30
|
+
/// @notice The max setable voting delay
|
|
31
|
+
uint public constant MAX_VOTING_DELAY = 20 * 60 * 24 * 7; // About 1 week, 3 secs per block
|
|
32
|
+
|
|
33
|
+
/// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed
|
|
34
|
+
uint public constant quorumVotes = 600000e18; // 600,000 = 2% of Xvs
|
|
35
|
+
|
|
36
|
+
/// @notice The EIP-712 typehash for the contract's domain
|
|
37
|
+
bytes32 public constant DOMAIN_TYPEHASH =
|
|
38
|
+
keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
|
|
39
|
+
|
|
40
|
+
/// @notice The EIP-712 typehash for the ballot struct used by the contract
|
|
41
|
+
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @notice Used to initialize the contract during delegator contructor
|
|
45
|
+
* @param timelock_ The address of the Timelock
|
|
46
|
+
* @param xvsVault_ The address of the XvsVault
|
|
47
|
+
* @param votingPeriod_ The initial voting period
|
|
48
|
+
* @param votingDelay_ The initial voting delay
|
|
49
|
+
* @param proposalThreshold_ The initial proposal threshold
|
|
50
|
+
*/
|
|
51
|
+
function initialize(
|
|
52
|
+
address timelock_,
|
|
53
|
+
address xvsVault_,
|
|
54
|
+
uint votingPeriod_,
|
|
55
|
+
uint votingDelay_,
|
|
56
|
+
uint proposalThreshold_,
|
|
57
|
+
address guardian_
|
|
58
|
+
) public {
|
|
59
|
+
require(address(timelock) == address(0), "GovernorBravo::initialize: can only initialize once");
|
|
60
|
+
require(msg.sender == admin, "GovernorBravo::initialize: admin only");
|
|
61
|
+
require(timelock_ != address(0), "GovernorBravo::initialize: invalid timelock address");
|
|
62
|
+
require(xvsVault_ != address(0), "GovernorBravo::initialize: invalid xvs address");
|
|
63
|
+
require(
|
|
64
|
+
votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD,
|
|
65
|
+
"GovernorBravo::initialize: invalid voting period"
|
|
66
|
+
);
|
|
67
|
+
require(
|
|
68
|
+
votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY,
|
|
69
|
+
"GovernorBravo::initialize: invalid voting delay"
|
|
70
|
+
);
|
|
71
|
+
require(
|
|
72
|
+
proposalThreshold_ >= MIN_PROPOSAL_THRESHOLD && proposalThreshold_ <= MAX_PROPOSAL_THRESHOLD,
|
|
73
|
+
"GovernorBravo::initialize: invalid proposal threshold"
|
|
74
|
+
);
|
|
75
|
+
require(guardian_ != address(0), "GovernorBravo::initialize: invalid guardian");
|
|
76
|
+
|
|
77
|
+
timelock = TimelockInterface(timelock_);
|
|
78
|
+
xvsVault = XvsVaultInterface(xvsVault_);
|
|
79
|
+
votingPeriod = votingPeriod_;
|
|
80
|
+
votingDelay = votingDelay_;
|
|
81
|
+
proposalThreshold = proposalThreshold_;
|
|
82
|
+
proposalMaxOperations = 10;
|
|
83
|
+
guardian = guardian_;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold
|
|
88
|
+
* @param targets Target addresses for proposal calls
|
|
89
|
+
* @param values Eth values for proposal calls
|
|
90
|
+
* @param signatures Function signatures for proposal calls
|
|
91
|
+
* @param calldatas Calldatas for proposal calls
|
|
92
|
+
* @param description String description of the proposal
|
|
93
|
+
* @return Proposal id of new proposal
|
|
94
|
+
*/
|
|
95
|
+
function propose(
|
|
96
|
+
address[] memory targets,
|
|
97
|
+
uint[] memory values,
|
|
98
|
+
string[] memory signatures,
|
|
99
|
+
bytes[] memory calldatas,
|
|
100
|
+
string memory description
|
|
101
|
+
) public returns (uint) {
|
|
102
|
+
// Reject proposals before initiating as Governor
|
|
103
|
+
require(initialProposalId != 0, "GovernorBravo::propose: Governor Bravo not active");
|
|
104
|
+
require(
|
|
105
|
+
xvsVault.getPriorVotes(msg.sender, sub256(block.number, 1)) > proposalThreshold,
|
|
106
|
+
"GovernorBravo::propose: proposer votes below proposal threshold"
|
|
107
|
+
);
|
|
108
|
+
require(
|
|
109
|
+
targets.length == values.length &&
|
|
110
|
+
targets.length == signatures.length &&
|
|
111
|
+
targets.length == calldatas.length,
|
|
112
|
+
"GovernorBravo::propose: proposal function information arity mismatch"
|
|
113
|
+
);
|
|
114
|
+
require(targets.length != 0, "GovernorBravo::propose: must provide actions");
|
|
115
|
+
require(targets.length <= proposalMaxOperations, "GovernorBravo::propose: too many actions");
|
|
116
|
+
|
|
117
|
+
uint latestProposalId = latestProposalIds[msg.sender];
|
|
118
|
+
if (latestProposalId != 0) {
|
|
119
|
+
ProposalState proposersLatestProposalState = state(latestProposalId);
|
|
120
|
+
require(
|
|
121
|
+
proposersLatestProposalState != ProposalState.Active,
|
|
122
|
+
"GovernorBravo::propose: one live proposal per proposer, found an already active proposal"
|
|
123
|
+
);
|
|
124
|
+
require(
|
|
125
|
+
proposersLatestProposalState != ProposalState.Pending,
|
|
126
|
+
"GovernorBravo::propose: one live proposal per proposer, found an already pending proposal"
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
uint startBlock = add256(block.number, votingDelay);
|
|
131
|
+
uint endBlock = add256(startBlock, votingPeriod);
|
|
132
|
+
|
|
133
|
+
proposalCount++;
|
|
134
|
+
Proposal memory newProposal = Proposal({
|
|
135
|
+
id: proposalCount,
|
|
136
|
+
proposer: msg.sender,
|
|
137
|
+
eta: 0,
|
|
138
|
+
targets: targets,
|
|
139
|
+
values: values,
|
|
140
|
+
signatures: signatures,
|
|
141
|
+
calldatas: calldatas,
|
|
142
|
+
startBlock: startBlock,
|
|
143
|
+
endBlock: endBlock,
|
|
144
|
+
forVotes: 0,
|
|
145
|
+
againstVotes: 0,
|
|
146
|
+
abstainVotes: 0,
|
|
147
|
+
canceled: false,
|
|
148
|
+
executed: false
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
proposals[newProposal.id] = newProposal;
|
|
152
|
+
latestProposalIds[newProposal.proposer] = newProposal.id;
|
|
153
|
+
|
|
154
|
+
emit ProposalCreated(
|
|
155
|
+
newProposal.id,
|
|
156
|
+
msg.sender,
|
|
157
|
+
targets,
|
|
158
|
+
values,
|
|
159
|
+
signatures,
|
|
160
|
+
calldatas,
|
|
161
|
+
startBlock,
|
|
162
|
+
endBlock,
|
|
163
|
+
description
|
|
164
|
+
);
|
|
165
|
+
return newProposal.id;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @notice Queues a proposal of state succeeded
|
|
170
|
+
* @param proposalId The id of the proposal to queue
|
|
171
|
+
*/
|
|
172
|
+
function queue(uint proposalId) external {
|
|
173
|
+
require(
|
|
174
|
+
state(proposalId) == ProposalState.Succeeded,
|
|
175
|
+
"GovernorBravo::queue: proposal can only be queued if it is succeeded"
|
|
176
|
+
);
|
|
177
|
+
Proposal storage proposal = proposals[proposalId];
|
|
178
|
+
uint eta = add256(block.timestamp, timelock.delay());
|
|
179
|
+
for (uint i = 0; i < proposal.targets.length; i++) {
|
|
180
|
+
queueOrRevertInternal(
|
|
181
|
+
proposal.targets[i],
|
|
182
|
+
proposal.values[i],
|
|
183
|
+
proposal.signatures[i],
|
|
184
|
+
proposal.calldatas[i],
|
|
185
|
+
eta
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
proposal.eta = eta;
|
|
189
|
+
emit ProposalQueued(proposalId, eta);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function queueOrRevertInternal(
|
|
193
|
+
address target,
|
|
194
|
+
uint value,
|
|
195
|
+
string memory signature,
|
|
196
|
+
bytes memory data,
|
|
197
|
+
uint eta
|
|
198
|
+
) internal {
|
|
199
|
+
require(
|
|
200
|
+
!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))),
|
|
201
|
+
"GovernorBravo::queueOrRevertInternal: identical proposal action already queued at eta"
|
|
202
|
+
);
|
|
203
|
+
timelock.queueTransaction(target, value, signature, data, eta);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @notice Executes a queued proposal if eta has passed
|
|
208
|
+
* @param proposalId The id of the proposal to execute
|
|
209
|
+
*/
|
|
210
|
+
function execute(uint proposalId) external {
|
|
211
|
+
require(
|
|
212
|
+
state(proposalId) == ProposalState.Queued,
|
|
213
|
+
"GovernorBravo::execute: proposal can only be executed if it is queued"
|
|
214
|
+
);
|
|
215
|
+
Proposal storage proposal = proposals[proposalId];
|
|
216
|
+
proposal.executed = true;
|
|
217
|
+
for (uint i = 0; i < proposal.targets.length; i++) {
|
|
218
|
+
timelock.executeTransaction(
|
|
219
|
+
proposal.targets[i],
|
|
220
|
+
proposal.values[i],
|
|
221
|
+
proposal.signatures[i],
|
|
222
|
+
proposal.calldatas[i],
|
|
223
|
+
proposal.eta
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
emit ProposalExecuted(proposalId);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold
|
|
231
|
+
* @param proposalId The id of the proposal to cancel
|
|
232
|
+
*/
|
|
233
|
+
function cancel(uint proposalId) external {
|
|
234
|
+
require(state(proposalId) != ProposalState.Executed, "GovernorBravo::cancel: cannot cancel executed proposal");
|
|
235
|
+
|
|
236
|
+
Proposal storage proposal = proposals[proposalId];
|
|
237
|
+
require(
|
|
238
|
+
msg.sender == guardian ||
|
|
239
|
+
msg.sender == proposal.proposer ||
|
|
240
|
+
xvsVault.getPriorVotes(proposal.proposer, sub256(block.number, 1)) < proposalThreshold,
|
|
241
|
+
"GovernorBravo::cancel: proposer above threshold"
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
proposal.canceled = true;
|
|
245
|
+
for (uint i = 0; i < proposal.targets.length; i++) {
|
|
246
|
+
timelock.cancelTransaction(
|
|
247
|
+
proposal.targets[i],
|
|
248
|
+
proposal.values[i],
|
|
249
|
+
proposal.signatures[i],
|
|
250
|
+
proposal.calldatas[i],
|
|
251
|
+
proposal.eta
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
emit ProposalCanceled(proposalId);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @notice Gets actions of a proposal
|
|
260
|
+
* @param proposalId the id of the proposal
|
|
261
|
+
* @return targets, values, signatures, and calldatas of the proposal actions
|
|
262
|
+
*/
|
|
263
|
+
function getActions(
|
|
264
|
+
uint proposalId
|
|
265
|
+
)
|
|
266
|
+
external
|
|
267
|
+
view
|
|
268
|
+
returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas)
|
|
269
|
+
{
|
|
270
|
+
Proposal storage p = proposals[proposalId];
|
|
271
|
+
return (p.targets, p.values, p.signatures, p.calldatas);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @notice Gets the receipt for a voter on a given proposal
|
|
276
|
+
* @param proposalId the id of proposal
|
|
277
|
+
* @param voter The address of the voter
|
|
278
|
+
* @return The voting receipt
|
|
279
|
+
*/
|
|
280
|
+
function getReceipt(uint proposalId, address voter) external view returns (Receipt memory) {
|
|
281
|
+
return proposals[proposalId].receipts[voter];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* @notice Gets the state of a proposal
|
|
286
|
+
* @param proposalId The id of the proposal
|
|
287
|
+
* @return Proposal state
|
|
288
|
+
*/
|
|
289
|
+
function state(uint proposalId) public view returns (ProposalState) {
|
|
290
|
+
require(
|
|
291
|
+
proposalCount >= proposalId && proposalId > initialProposalId,
|
|
292
|
+
"GovernorBravo::state: invalid proposal id"
|
|
293
|
+
);
|
|
294
|
+
Proposal storage proposal = proposals[proposalId];
|
|
295
|
+
if (proposal.canceled) {
|
|
296
|
+
return ProposalState.Canceled;
|
|
297
|
+
} else if (block.number <= proposal.startBlock) {
|
|
298
|
+
return ProposalState.Pending;
|
|
299
|
+
} else if (block.number <= proposal.endBlock) {
|
|
300
|
+
return ProposalState.Active;
|
|
301
|
+
} else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < quorumVotes) {
|
|
302
|
+
return ProposalState.Defeated;
|
|
303
|
+
} else if (proposal.eta == 0) {
|
|
304
|
+
return ProposalState.Succeeded;
|
|
305
|
+
} else if (proposal.executed) {
|
|
306
|
+
return ProposalState.Executed;
|
|
307
|
+
} else if (block.timestamp >= add256(proposal.eta, timelock.GRACE_PERIOD())) {
|
|
308
|
+
return ProposalState.Expired;
|
|
309
|
+
} else {
|
|
310
|
+
return ProposalState.Queued;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @notice Cast a vote for a proposal
|
|
316
|
+
* @param proposalId The id of the proposal to vote on
|
|
317
|
+
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
|
|
318
|
+
*/
|
|
319
|
+
function castVote(uint proposalId, uint8 support) external {
|
|
320
|
+
emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), "");
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @notice Cast a vote for a proposal with a reason
|
|
325
|
+
* @param proposalId The id of the proposal to vote on
|
|
326
|
+
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
|
|
327
|
+
* @param reason The reason given for the vote by the voter
|
|
328
|
+
*/
|
|
329
|
+
function castVoteWithReason(uint proposalId, uint8 support, string calldata reason) external {
|
|
330
|
+
emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), reason);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @notice Cast a vote for a proposal by signature
|
|
335
|
+
* @dev External function that accepts EIP-712 signatures for voting on proposals.
|
|
336
|
+
*/
|
|
337
|
+
function castVoteBySig(uint proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external {
|
|
338
|
+
bytes32 domainSeparator = keccak256(
|
|
339
|
+
abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this))
|
|
340
|
+
);
|
|
341
|
+
bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));
|
|
342
|
+
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
|
|
343
|
+
address signatory = ecrecover(digest, v, r, s);
|
|
344
|
+
require(signatory != address(0), "GovernorBravo::castVoteBySig: invalid signature");
|
|
345
|
+
emit VoteCast(signatory, proposalId, support, castVoteInternal(signatory, proposalId, support), "");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* @notice Internal function that caries out voting logic
|
|
350
|
+
* @param voter The voter that is casting their vote
|
|
351
|
+
* @param proposalId The id of the proposal to vote on
|
|
352
|
+
* @param support The support value for the vote. 0=against, 1=for, 2=abstain
|
|
353
|
+
* @return The number of votes cast
|
|
354
|
+
*/
|
|
355
|
+
function castVoteInternal(address voter, uint proposalId, uint8 support) internal returns (uint96) {
|
|
356
|
+
require(state(proposalId) == ProposalState.Active, "GovernorBravo::castVoteInternal: voting is closed");
|
|
357
|
+
require(support <= 2, "GovernorBravo::castVoteInternal: invalid vote type");
|
|
358
|
+
Proposal storage proposal = proposals[proposalId];
|
|
359
|
+
Receipt storage receipt = proposal.receipts[voter];
|
|
360
|
+
require(receipt.hasVoted == false, "GovernorBravo::castVoteInternal: voter already voted");
|
|
361
|
+
uint96 votes = xvsVault.getPriorVotes(voter, proposal.startBlock);
|
|
362
|
+
|
|
363
|
+
if (support == 0) {
|
|
364
|
+
proposal.againstVotes = add256(proposal.againstVotes, votes);
|
|
365
|
+
} else if (support == 1) {
|
|
366
|
+
proposal.forVotes = add256(proposal.forVotes, votes);
|
|
367
|
+
} else if (support == 2) {
|
|
368
|
+
proposal.abstainVotes = add256(proposal.abstainVotes, votes);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
receipt.hasVoted = true;
|
|
372
|
+
receipt.support = support;
|
|
373
|
+
receipt.votes = votes;
|
|
374
|
+
|
|
375
|
+
return votes;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* @notice Sets the new governance guardian
|
|
380
|
+
* @param newGuardian the address of the new guardian
|
|
381
|
+
*/
|
|
382
|
+
function _setGuardian(address newGuardian) external {
|
|
383
|
+
require(msg.sender == guardian || msg.sender == admin, "GovernorBravo::_setGuardian: admin or guardian only");
|
|
384
|
+
require(newGuardian != address(0), "GovernorBravo::_setGuardian: cannot live without a guardian");
|
|
385
|
+
address oldGuardian = guardian;
|
|
386
|
+
guardian = newGuardian;
|
|
387
|
+
|
|
388
|
+
emit NewGuardian(oldGuardian, newGuardian);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* @notice Admin function for setting the voting delay
|
|
393
|
+
* @param newVotingDelay new voting delay, in blocks
|
|
394
|
+
*/
|
|
395
|
+
function _setVotingDelay(uint newVotingDelay) external {
|
|
396
|
+
require(msg.sender == admin, "GovernorBravo::_setVotingDelay: admin only");
|
|
397
|
+
require(
|
|
398
|
+
newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY,
|
|
399
|
+
"GovernorBravo::_setVotingDelay: invalid voting delay"
|
|
400
|
+
);
|
|
401
|
+
uint oldVotingDelay = votingDelay;
|
|
402
|
+
votingDelay = newVotingDelay;
|
|
403
|
+
|
|
404
|
+
emit VotingDelaySet(oldVotingDelay, votingDelay);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @notice Admin function for setting the voting period
|
|
409
|
+
* @param newVotingPeriod new voting period, in blocks
|
|
410
|
+
*/
|
|
411
|
+
function _setVotingPeriod(uint newVotingPeriod) external {
|
|
412
|
+
require(msg.sender == admin, "GovernorBravo::_setVotingPeriod: admin only");
|
|
413
|
+
require(
|
|
414
|
+
newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD,
|
|
415
|
+
"GovernorBravo::_setVotingPeriod: invalid voting period"
|
|
416
|
+
);
|
|
417
|
+
uint oldVotingPeriod = votingPeriod;
|
|
418
|
+
votingPeriod = newVotingPeriod;
|
|
419
|
+
|
|
420
|
+
emit VotingPeriodSet(oldVotingPeriod, votingPeriod);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* @notice Admin function for setting the proposal threshold
|
|
425
|
+
* @dev newProposalThreshold must be greater than the hardcoded min
|
|
426
|
+
* @param newProposalThreshold new proposal threshold
|
|
427
|
+
*/
|
|
428
|
+
function _setProposalThreshold(uint newProposalThreshold) external {
|
|
429
|
+
require(msg.sender == admin, "GovernorBravo::_setProposalThreshold: admin only");
|
|
430
|
+
require(
|
|
431
|
+
newProposalThreshold >= MIN_PROPOSAL_THRESHOLD && newProposalThreshold <= MAX_PROPOSAL_THRESHOLD,
|
|
432
|
+
"GovernorBravo::_setProposalThreshold: invalid proposal threshold"
|
|
433
|
+
);
|
|
434
|
+
uint oldProposalThreshold = proposalThreshold;
|
|
435
|
+
proposalThreshold = newProposalThreshold;
|
|
436
|
+
|
|
437
|
+
emit ProposalThresholdSet(oldProposalThreshold, proposalThreshold);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @notice Initiate the GovernorBravo contract
|
|
442
|
+
* @dev Admin only. Sets initial proposal id which initiates the contract, ensuring a continuous proposal id count
|
|
443
|
+
* @param governorAlpha The address for the Governor to continue the proposal id count from
|
|
444
|
+
*/
|
|
445
|
+
function _initiate(address governorAlpha) external {
|
|
446
|
+
require(msg.sender == admin, "GovernorBravo::_initiate: admin only");
|
|
447
|
+
require(initialProposalId == 0, "GovernorBravo::_initiate: can only initiate once");
|
|
448
|
+
proposalCount = GovernorAlphaInterface(governorAlpha).proposalCount();
|
|
449
|
+
initialProposalId = proposalCount;
|
|
450
|
+
timelock.acceptAdmin();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* @notice Set max proposal operations
|
|
455
|
+
* @dev Admin only.
|
|
456
|
+
* @param proposalMaxOperations_ Max proposal operations
|
|
457
|
+
*/
|
|
458
|
+
function _setProposalMaxOperations(uint proposalMaxOperations_) external {
|
|
459
|
+
require(msg.sender == admin, "GovernorBravo::_setProposalMaxOperations: admin only");
|
|
460
|
+
uint oldProposalMaxOperations = proposalMaxOperations;
|
|
461
|
+
proposalMaxOperations = proposalMaxOperations_;
|
|
462
|
+
|
|
463
|
+
emit ProposalMaxOperationsUpdated(oldProposalMaxOperations, proposalMaxOperations_);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
|
|
468
|
+
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
|
|
469
|
+
* @param newPendingAdmin New pending admin.
|
|
470
|
+
*/
|
|
471
|
+
function _setPendingAdmin(address newPendingAdmin) external {
|
|
472
|
+
// Check caller = admin
|
|
473
|
+
require(msg.sender == admin, "GovernorBravo:_setPendingAdmin: admin only");
|
|
474
|
+
|
|
475
|
+
// Save current value, if any, for inclusion in log
|
|
476
|
+
address oldPendingAdmin = pendingAdmin;
|
|
477
|
+
|
|
478
|
+
// Store pendingAdmin with value newPendingAdmin
|
|
479
|
+
pendingAdmin = newPendingAdmin;
|
|
480
|
+
|
|
481
|
+
// Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
|
|
482
|
+
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
|
|
487
|
+
* @dev Admin function for pending admin to accept role and update admin
|
|
488
|
+
*/
|
|
489
|
+
function _acceptAdmin() external {
|
|
490
|
+
// Check caller is pendingAdmin and pendingAdmin ≠ address(0)
|
|
491
|
+
require(
|
|
492
|
+
msg.sender == pendingAdmin && msg.sender != address(0),
|
|
493
|
+
"GovernorBravo:_acceptAdmin: pending admin only"
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
// Save current values for inclusion in log
|
|
497
|
+
address oldAdmin = admin;
|
|
498
|
+
address oldPendingAdmin = pendingAdmin;
|
|
499
|
+
|
|
500
|
+
// Store admin with value pendingAdmin
|
|
501
|
+
admin = pendingAdmin;
|
|
502
|
+
|
|
503
|
+
// Clear the pending value
|
|
504
|
+
pendingAdmin = address(0);
|
|
505
|
+
|
|
506
|
+
emit NewAdmin(oldAdmin, admin);
|
|
507
|
+
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function add256(uint256 a, uint256 b) internal pure returns (uint) {
|
|
511
|
+
uint c = a + b;
|
|
512
|
+
require(c >= a, "addition overflow");
|
|
513
|
+
return c;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function sub256(uint256 a, uint256 b) internal pure returns (uint) {
|
|
517
|
+
require(b <= a, "subtraction underflow");
|
|
518
|
+
return a - b;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function getChainIdInternal() internal pure returns (uint) {
|
|
522
|
+
uint chainId;
|
|
523
|
+
assembly {
|
|
524
|
+
chainId := chainid()
|
|
525
|
+
}
|
|
526
|
+
return chainId;
|
|
527
|
+
}
|
|
528
|
+
}
|