GovernorTimelockControl.sol 5.4 KB

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