GovernorTimelockControl.sol 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorTimelockControl.sol)
  3. pragma solidity ^0.8.19;
  4. import {IGovernorTimelock} from "./IGovernorTimelock.sol";
  5. import {IGovernor, Governor} from "../Governor.sol";
  6. import {TimelockController} from "../TimelockController.sol";
  7. import {IERC165} from "../../interfaces/IERC165.sol";
  8. /**
  9. * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a
  10. * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The
  11. * {Governor} needs the proposer (and ideally the executor) roles for the {Governor} to work properly.
  12. *
  13. * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
  14. * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  15. * inaccessible.
  16. *
  17. * WARNING: Setting up the TimelockController to have additional proposers besides the governor is very risky, as it
  18. * grants them powers that they must be trusted or known not to use: 1) {onlyGovernance} functions like {relay} are
  19. * available to them through the timelock, and 2) approved governance proposals can be blocked by them, effectively
  20. * executing a Denial of Service attack. This risk will be mitigated in a future release.
  21. *
  22. * _Available since v4.3._
  23. */
  24. abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
  25. TimelockController private _timelock;
  26. mapping(uint256 => bytes32) private _timelockIds;
  27. /**
  28. * @dev Emitted when the timelock controller used for proposal execution is modified.
  29. */
  30. event TimelockChange(address oldTimelock, address newTimelock);
  31. /**
  32. * @dev Set the timelock.
  33. */
  34. constructor(TimelockController timelockAddress) {
  35. _updateTimelock(timelockAddress);
  36. }
  37. /**
  38. * @dev See {IERC165-supportsInterface}.
  39. */
  40. function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) {
  41. return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId);
  42. }
  43. /**
  44. * @dev Overridden version of the {Governor-state} function with added support for the `Queued` state.
  45. */
  46. function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
  47. ProposalState currentState = super.state(proposalId);
  48. if (currentState != ProposalState.Succeeded) {
  49. return currentState;
  50. }
  51. // core tracks execution, so we just have to check if successful proposal have been queued.
  52. bytes32 queueid = _timelockIds[proposalId];
  53. if (queueid == bytes32(0)) {
  54. return currentState;
  55. } else if (_timelock.isOperationPending(queueid)) {
  56. return ProposalState.Queued;
  57. } else if (_timelock.isOperationDone(queueid)) {
  58. // This can happen if the proposal is executed directly on the timelock.
  59. return ProposalState.Executed;
  60. } else {
  61. // This can happen if the proposal is canceled directly on the timelock.
  62. return ProposalState.Canceled;
  63. }
  64. }
  65. /**
  66. * @dev Public accessor to check the address of the timelock
  67. */
  68. function timelock() public view virtual override returns (address) {
  69. return address(_timelock);
  70. }
  71. /**
  72. * @dev Public accessor to check the eta of a queued proposal
  73. */
  74. function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
  75. uint256 eta = _timelock.getTimestamp(_timelockIds[proposalId]);
  76. return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value
  77. }
  78. /**
  79. * @dev Function to queue a proposal to the timelock.
  80. */
  81. function queue(
  82. address[] memory targets,
  83. uint256[] memory values,
  84. bytes[] memory calldatas,
  85. bytes32 descriptionHash
  86. ) public virtual override returns (uint256) {
  87. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  88. ProposalState currentState = state(proposalId);
  89. if (currentState != ProposalState.Succeeded) {
  90. revert GovernorUnexpectedProposalState(
  91. proposalId,
  92. currentState,
  93. _encodeStateBitmap(ProposalState.Succeeded)
  94. );
  95. }
  96. uint256 delay = _timelock.getMinDelay();
  97. _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
  98. _timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);
  99. emit ProposalQueued(proposalId, block.timestamp + delay);
  100. return proposalId;
  101. }
  102. /**
  103. * @dev Overridden execute function that run the already queued proposal through the timelock.
  104. */
  105. function _execute(
  106. uint256 proposalId,
  107. address[] memory targets,
  108. uint256[] memory values,
  109. bytes[] memory calldatas,
  110. bytes32 descriptionHash
  111. ) internal virtual override {
  112. // execute
  113. _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
  114. // cleanup for refund
  115. delete _timelockIds[proposalId];
  116. }
  117. /**
  118. * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
  119. * been queued.
  120. */
  121. // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
  122. // well behaved (according to TimelockController) and this will not happen.
  123. // slither-disable-next-line reentrancy-no-eth
  124. function _cancel(
  125. address[] memory targets,
  126. uint256[] memory values,
  127. bytes[] memory calldatas,
  128. bytes32 descriptionHash
  129. ) internal virtual override returns (uint256) {
  130. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  131. bytes32 timelockId = _timelockIds[proposalId];
  132. if (timelockId != 0) {
  133. // cancel
  134. _timelock.cancel(timelockId);
  135. // cleanup
  136. delete _timelockIds[proposalId];
  137. }
  138. return proposalId;
  139. }
  140. /**
  141. * @dev Address through which the governor executes action. In this case, the timelock.
  142. */
  143. function _executor() internal view virtual override returns (address) {
  144. return address(_timelock);
  145. }
  146. /**
  147. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  148. * must be proposed, scheduled, and executed through governance proposals.
  149. *
  150. * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
  151. */
  152. function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
  153. _updateTimelock(newTimelock);
  154. }
  155. function _updateTimelock(TimelockController newTimelock) private {
  156. emit TimelockChange(address(_timelock), address(newTimelock));
  157. _timelock = newTimelock;
  158. }
  159. }