GovernorTimelockControlUpgradeable.sol 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (governance/extensions/GovernorTimelockControl.sol)
  3. pragma solidity ^0.8.0;
  4. import "./IGovernorTimelockUpgradeable.sol";
  5. import "../GovernorUpgradeable.sol";
  6. import "../TimelockControllerUpgradeable.sol";
  7. import "../../proxy/utils/Initializable.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 introduces the risk that
  18. * approved governance proposals could be blocked by the other proposers, effectively executing a Denial of Service attack,
  19. * and therefore blocking access to governance-controlled assets.
  20. *
  21. * _Available since v4.3._
  22. */
  23. abstract contract GovernorTimelockControlUpgradeable is Initializable, IGovernorTimelockUpgradeable, GovernorUpgradeable {
  24. TimelockControllerUpgradeable private _timelock;
  25. mapping(uint256 => bytes32) private _timelockIds;
  26. /**
  27. * @dev Emitted when the timelock controller used for proposal execution is modified.
  28. */
  29. event TimelockChange(address oldTimelock, address newTimelock);
  30. /**
  31. * @dev Set the timelock.
  32. */
  33. function __GovernorTimelockControl_init(TimelockControllerUpgradeable timelockAddress) internal onlyInitializing {
  34. __Context_init_unchained();
  35. __ERC165_init_unchained();
  36. __IGovernor_init_unchained();
  37. __IGovernorTimelock_init_unchained();
  38. __GovernorTimelockControl_init_unchained(timelockAddress);
  39. }
  40. function __GovernorTimelockControl_init_unchained(TimelockControllerUpgradeable timelockAddress) internal onlyInitializing {
  41. _updateTimelock(timelockAddress);
  42. }
  43. /**
  44. * @dev See {IERC165-supportsInterface}.
  45. */
  46. function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, GovernorUpgradeable) returns (bool) {
  47. return interfaceId == type(IGovernorTimelockUpgradeable).interfaceId || super.supportsInterface(interfaceId);
  48. }
  49. /**
  50. * @dev Overriden version of the {Governor-state} function with added support for the `Queued` status.
  51. */
  52. function state(uint256 proposalId) public view virtual override(IGovernorUpgradeable, GovernorUpgradeable) returns (ProposalState) {
  53. ProposalState status = super.state(proposalId);
  54. if (status != ProposalState.Succeeded) {
  55. return status;
  56. }
  57. // core tracks execution, so we just have to check if successful proposal have been queued.
  58. bytes32 queueid = _timelockIds[proposalId];
  59. if (queueid == bytes32(0)) {
  60. return status;
  61. } else if (_timelock.isOperationDone(queueid)) {
  62. return ProposalState.Executed;
  63. } else if (_timelock.isOperationPending(queueid)) {
  64. return ProposalState.Queued;
  65. } else {
  66. return ProposalState.Canceled;
  67. }
  68. }
  69. /**
  70. * @dev Public accessor to check the address of the timelock
  71. */
  72. function timelock() public view virtual override returns (address) {
  73. return address(_timelock);
  74. }
  75. /**
  76. * @dev Public accessor to check the eta of a queued proposal
  77. */
  78. function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
  79. uint256 eta = _timelock.getTimestamp(_timelockIds[proposalId]);
  80. return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value
  81. }
  82. /**
  83. * @dev Function to queue a proposal to the timelock.
  84. */
  85. function queue(
  86. address[] memory targets,
  87. uint256[] memory values,
  88. bytes[] memory calldatas,
  89. bytes32 descriptionHash
  90. ) public virtual override returns (uint256) {
  91. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  92. require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful");
  93. uint256 delay = _timelock.getMinDelay();
  94. _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
  95. _timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);
  96. emit ProposalQueued(proposalId, block.timestamp + delay);
  97. return proposalId;
  98. }
  99. /**
  100. * @dev Overriden execute function that run the already queued proposal through the timelock.
  101. */
  102. function _execute(
  103. uint256, /* proposalId */
  104. address[] memory targets,
  105. uint256[] memory values,
  106. bytes[] memory calldatas,
  107. bytes32 descriptionHash
  108. ) internal virtual override {
  109. _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
  110. }
  111. /**
  112. * @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
  113. * been queued.
  114. */
  115. function _cancel(
  116. address[] memory targets,
  117. uint256[] memory values,
  118. bytes[] memory calldatas,
  119. bytes32 descriptionHash
  120. ) internal virtual override returns (uint256) {
  121. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  122. if (_timelockIds[proposalId] != 0) {
  123. _timelock.cancel(_timelockIds[proposalId]);
  124. delete _timelockIds[proposalId];
  125. }
  126. return proposalId;
  127. }
  128. /**
  129. * @dev Address through which the governor executes action. In this case, the timelock.
  130. */
  131. function _executor() internal view virtual override returns (address) {
  132. return address(_timelock);
  133. }
  134. /**
  135. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  136. * must be proposed, scheduled and executed using the {Governor} workflow.
  137. */
  138. function updateTimelock(TimelockControllerUpgradeable newTimelock) external virtual onlyGovernance {
  139. _updateTimelock(newTimelock);
  140. }
  141. function _updateTimelock(TimelockControllerUpgradeable newTimelock) private {
  142. emit TimelockChange(address(_timelock), address(newTimelock));
  143. _timelock = newTimelock;
  144. }
  145. uint256[48] private __gap;
  146. }