GovernorTimelockControl.sol 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.3.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 {SafeCast} from "../../utils/math/SafeCast.sol";
  7. /**
  8. * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a
  9. * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The
  10. * {Governor} needs the proposer (and ideally the executor and canceller) roles for the {Governor} to work properly.
  11. *
  12. * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
  13. * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  14. * inaccessible from a proposal, unless executed via {Governor-relay}.
  15. *
  16. * WARNING: Setting up the TimelockController to have additional proposers or cancelers besides the governor is very
  17. * risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing
  18. * operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance
  19. * proposals that have been approved by the voters, effectively executing a Denial of Service attack.
  20. */
  21. abstract contract GovernorTimelockControl is Governor {
  22. TimelockController private _timelock;
  23. mapping(uint256 proposalId => bytes32) private _timelockIds;
  24. /**
  25. * @dev Emitted when the timelock controller used for proposal execution is modified.
  26. */
  27. event TimelockChange(address oldTimelock, address newTimelock);
  28. /**
  29. * @dev Set the timelock.
  30. */
  31. constructor(TimelockController timelockAddress) {
  32. _updateTimelock(timelockAddress);
  33. }
  34. /**
  35. * @dev Overridden version of the {Governor-state} function that considers the status reported by the timelock.
  36. */
  37. function state(uint256 proposalId) public view virtual override returns (ProposalState) {
  38. ProposalState currentState = super.state(proposalId);
  39. if (currentState != ProposalState.Queued) {
  40. return currentState;
  41. }
  42. bytes32 queueid = _timelockIds[proposalId];
  43. if (_timelock.isOperationPending(queueid)) {
  44. return ProposalState.Queued;
  45. } else if (_timelock.isOperationDone(queueid)) {
  46. // This can happen if the proposal is executed directly on the timelock.
  47. return ProposalState.Executed;
  48. } else {
  49. // This can happen if the proposal is canceled directly on the timelock.
  50. return ProposalState.Canceled;
  51. }
  52. }
  53. /**
  54. * @dev Public accessor to check the address of the timelock
  55. */
  56. function timelock() public view virtual returns (address) {
  57. return address(_timelock);
  58. }
  59. /// @inheritdoc IGovernor
  60. function proposalNeedsQueuing(uint256) public view virtual override returns (bool) {
  61. return true;
  62. }
  63. /**
  64. * @dev Function to queue a proposal to the timelock.
  65. */
  66. function _queueOperations(
  67. uint256 proposalId,
  68. address[] memory targets,
  69. uint256[] memory values,
  70. bytes[] memory calldatas,
  71. bytes32 descriptionHash
  72. ) internal virtual override returns (uint48) {
  73. uint256 delay = _timelock.getMinDelay();
  74. bytes32 salt = _timelockSalt(descriptionHash);
  75. _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, salt);
  76. _timelock.scheduleBatch(targets, values, calldatas, 0, salt, delay);
  77. return SafeCast.toUint48(block.timestamp + delay);
  78. }
  79. /**
  80. * @dev Overridden version of the {Governor-_executeOperations} function that runs the already queued proposal
  81. * through the timelock.
  82. */
  83. function _executeOperations(
  84. uint256 proposalId,
  85. address[] memory targets,
  86. uint256[] memory values,
  87. bytes[] memory calldatas,
  88. bytes32 descriptionHash
  89. ) internal virtual override {
  90. // execute
  91. _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, _timelockSalt(descriptionHash));
  92. // cleanup for refund
  93. delete _timelockIds[proposalId];
  94. }
  95. /**
  96. * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it has already
  97. * been queued.
  98. */
  99. // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
  100. // well behaved (according to TimelockController) and this will not happen.
  101. // slither-disable-next-line reentrancy-no-eth
  102. function _cancel(
  103. address[] memory targets,
  104. uint256[] memory values,
  105. bytes[] memory calldatas,
  106. bytes32 descriptionHash
  107. ) internal virtual override returns (uint256) {
  108. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  109. bytes32 timelockId = _timelockIds[proposalId];
  110. if (timelockId != 0) {
  111. // cancel
  112. _timelock.cancel(timelockId);
  113. // cleanup
  114. delete _timelockIds[proposalId];
  115. }
  116. return proposalId;
  117. }
  118. /**
  119. * @dev Address through which the governor executes action. In this case, the timelock.
  120. */
  121. function _executor() internal view virtual override returns (address) {
  122. return address(_timelock);
  123. }
  124. /**
  125. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  126. * must be proposed, scheduled, and executed through governance proposals.
  127. *
  128. * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
  129. */
  130. function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
  131. _updateTimelock(newTimelock);
  132. }
  133. function _updateTimelock(TimelockController newTimelock) private {
  134. emit TimelockChange(address(_timelock), address(newTimelock));
  135. _timelock = newTimelock;
  136. }
  137. /**
  138. * @dev Computes the {TimelockController} operation salt.
  139. *
  140. * It is computed with the governor address itself to avoid collisions across governor instances using the
  141. * same timelock.
  142. */
  143. function _timelockSalt(bytes32 descriptionHash) private view returns (bytes32) {
  144. return bytes20(address(this)) ^ descriptionHash;
  145. }
  146. }