@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.
Files changed (30) hide show
  1. package/README.md +11 -0
  2. package/artifacts/build-info/52cd2a2ed6764b7fce3ff5a23ca8a581.json +1 -0
  3. package/artifacts/contracts/Governance/GovernorBravoDelegate.sol/GovernorBravoDelegate.dbg.json +1 -1
  4. package/artifacts/contracts/Governance/GovernorBravoDelegator.sol/GovernorBravoDelegator.dbg.json +1 -1
  5. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorAlphaInterface.dbg.json +1 -1
  6. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateInterface.dbg.json +1 -1
  7. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.dbg.json +1 -1
  8. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV2.dbg.json +1 -1
  9. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.dbg.json +1 -1
  10. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/GovernorBravoEvents.dbg.json +1 -1
  11. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/TimelockInterface.dbg.json +1 -1
  12. package/artifacts/contracts/Governance/GovernorBravoInterfaces.sol/XvsVaultInterface.dbg.json +1 -1
  13. package/artifacts/contracts/legacy/GovernorBravoDelegateV1.sol/GovernorBravoDelegateV1.dbg.json +4 -0
  14. package/artifacts/contracts/legacy/GovernorBravoDelegateV1.sol/GovernorBravoDelegateV1.json +1143 -0
  15. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.dbg.json +4 -0
  16. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegateStorageV1.json +278 -0
  17. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.dbg.json +4 -0
  18. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoDelegatorStorage.json +56 -0
  19. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoEventsV1.dbg.json +4 -0
  20. package/artifacts/contracts/legacy/GovernorBravoInterfaces.sol/GovernorBravoEventsV1.json +306 -0
  21. package/contracts/legacy/GovernorBravoDelegateV1.sol +528 -0
  22. package/contracts/legacy/GovernorBravoInterfaces.sol +176 -0
  23. package/deployments/bscmainnet/AccessControlManager.json +285 -0
  24. package/deployments/bscmainnet.json +7167 -0
  25. package/deployments/bsctestnet/AccessControlManager.json +364 -0
  26. package/deployments/bsctestnet.json +6437 -0
  27. package/deployments/sepolia.json +369 -0
  28. package/package.json +1 -1
  29. package/artifacts/build-info/97a3124320e74f843bc59439c75c258d.json +0 -1
  30. 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
+ }