@venusprotocol/governance-contracts 0.0.1

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