GovernorTimelockControl.sol 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorTimelockControl.sol)
  3. pragma solidity ^0.8.20;
  4. import {IGovernor, Governor} from "../Governor.sol";
  5. import {TimelockController} from "../TimelockController.sol";
  6. import {IERC165} from "../../interfaces/IERC165.sol";
  7. import {SafeCast} from "../../utils/math/SafeCast.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. abstract contract GovernorTimelockControl is Governor {
  23. TimelockController private _timelock;
  24. mapping(uint256 proposalId => bytes32) private _timelockIds;
  25. /**
  26. * @dev Emitted when the timelock controller used for proposal execution is modified.
  27. */
  28. event TimelockChange(address oldTimelock, address newTimelock);
  29. /**
  30. * @dev Set the timelock.
  31. */
  32. constructor(TimelockController timelockAddress) {
  33. _updateTimelock(timelockAddress);
  34. }
  35. /**
  36. * @dev Overridden version of the {Governor-state} function that considers the status reported by the timelock.
  37. */
  38. function state(uint256 proposalId) public view virtual override returns (ProposalState) {
  39. ProposalState currentState = super.state(proposalId);
  40. if (currentState != ProposalState.Queued) {
  41. return currentState;
  42. }
  43. bytes32 queueid = _timelockIds[proposalId];
  44. if (_timelock.isOperationPending(queueid)) {
  45. return ProposalState.Queued;
  46. } else if (_timelock.isOperationDone(queueid)) {
  47. // This can happen if the proposal is executed directly on the timelock.
  48. return ProposalState.Executed;
  49. } else {
  50. // This can happen if the proposal is canceled directly on the timelock.
  51. return ProposalState.Canceled;
  52. }
  53. }
  54. /**
  55. * @dev Public accessor to check the address of the timelock
  56. */
  57. function timelock() public view virtual returns (address) {
  58. return address(_timelock);
  59. }
  60. /**
  61. * @dev Function to queue a proposal to the timelock.
  62. */
  63. function _queueOperations(
  64. uint256 proposalId,
  65. address[] memory targets,
  66. uint256[] memory values,
  67. bytes[] memory calldatas,
  68. bytes32 descriptionHash
  69. ) internal virtual override returns (uint48) {
  70. uint256 delay = _timelock.getMinDelay();
  71. bytes32 salt = _timelockSalt(descriptionHash);
  72. _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, salt);
  73. _timelock.scheduleBatch(targets, values, calldatas, 0, salt, delay);
  74. return SafeCast.toUint48(block.timestamp + delay);
  75. }
  76. /**
  77. * @dev Overridden version of the {Governor-_executeOperations} function that runs the already queued proposal through
  78. * the timelock.
  79. */
  80. function _executeOperations(
  81. uint256 proposalId,
  82. address[] memory targets,
  83. uint256[] memory values,
  84. bytes[] memory calldatas,
  85. bytes32 descriptionHash
  86. ) internal virtual override {
  87. // execute
  88. _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, _timelockSalt(descriptionHash));
  89. // cleanup for refund
  90. delete _timelockIds[proposalId];
  91. }
  92. /**
  93. * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
  94. * been queued.
  95. */
  96. // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
  97. // well behaved (according to TimelockController) and this will not happen.
  98. // slither-disable-next-line reentrancy-no-eth
  99. function _cancel(
  100. address[] memory targets,
  101. uint256[] memory values,
  102. bytes[] memory calldatas,
  103. bytes32 descriptionHash
  104. ) internal virtual override returns (uint256) {
  105. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  106. bytes32 timelockId = _timelockIds[proposalId];
  107. if (timelockId != 0) {
  108. // cancel
  109. _timelock.cancel(timelockId);
  110. // cleanup
  111. delete _timelockIds[proposalId];
  112. }
  113. return proposalId;
  114. }
  115. /**
  116. * @dev Address through which the governor executes action. In this case, the timelock.
  117. */
  118. function _executor() internal view virtual override returns (address) {
  119. return address(_timelock);
  120. }
  121. /**
  122. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  123. * must be proposed, scheduled, and executed through governance proposals.
  124. *
  125. * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
  126. */
  127. function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
  128. _updateTimelock(newTimelock);
  129. }
  130. function _updateTimelock(TimelockController newTimelock) private {
  131. emit TimelockChange(address(_timelock), address(newTimelock));
  132. _timelock = newTimelock;
  133. }
  134. /**
  135. * @dev Computes the {TimelockController} operation salt.
  136. *
  137. * It is computed with the governor address itself to avoid collisions across governor instances using the
  138. * same timelock.
  139. */
  140. function _timelockSalt(bytes32 descriptionHash) private view returns (bytes32) {
  141. return bytes20(address(this)) ^ descriptionHash;
  142. }
  143. }