GovernorTimelockControl.sol 5.6 KB

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