GovernorTimelockCompound.sol 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorTimelockCompound.sol)
  3. pragma solidity ^0.8.19;
  4. import {IGovernorTimelock} from "./IGovernorTimelock.sol";
  5. import {IGovernor, Governor} from "../Governor.sol";
  6. import {SafeCast} from "../../utils/math/SafeCast.sol";
  7. import {ICompoundTimelock} from "../../vendor/compound/ICompoundTimelock.sol";
  8. import {IERC165} from "../../interfaces/IERC165.sol";
  9. import {Address} from "../../utils/Address.sol";
  10. /**
  11. * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
  12. * the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be
  13. * the admin of the timelock for any operation to be performed. A public, unrestricted,
  14. * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock.
  15. *
  16. * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
  17. * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  18. * inaccessible.
  19. *
  20. * _Available since v4.3._
  21. */
  22. abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
  23. ICompoundTimelock private _timelock;
  24. /// @custom:oz-retyped-from mapping(uint256 => GovernorTimelockCompound.ProposalTimelock)
  25. mapping(uint256 => uint256) private _proposalTimelocks;
  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. constructor(ICompoundTimelock timelockAddress) {
  34. _updateTimelock(timelockAddress);
  35. }
  36. /**
  37. * @dev See {IERC165-supportsInterface}.
  38. */
  39. function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) {
  40. return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId);
  41. }
  42. /**
  43. * @dev Overridden version of the {Governor-state} function with added support for the `Queued` and `Expired` state.
  44. */
  45. function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
  46. ProposalState currentState = super.state(proposalId);
  47. if (currentState != ProposalState.Succeeded) {
  48. return currentState;
  49. }
  50. uint256 eta = proposalEta(proposalId);
  51. if (eta == 0) {
  52. return currentState;
  53. } else if (block.timestamp >= eta + _timelock.GRACE_PERIOD()) {
  54. return ProposalState.Expired;
  55. } else {
  56. return ProposalState.Queued;
  57. }
  58. }
  59. /**
  60. * @dev Public accessor to check the address of the timelock
  61. */
  62. function timelock() public view virtual override returns (address) {
  63. return address(_timelock);
  64. }
  65. /**
  66. * @dev Public accessor to check the eta of a queued proposal
  67. */
  68. function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
  69. return _proposalTimelocks[proposalId];
  70. }
  71. /**
  72. * @dev Function to queue a proposal to the timelock.
  73. */
  74. function queue(
  75. address[] memory targets,
  76. uint256[] memory values,
  77. bytes[] memory calldatas,
  78. bytes32 descriptionHash
  79. ) public virtual override returns (uint256) {
  80. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  81. ProposalState currentState = state(proposalId);
  82. if (currentState != ProposalState.Succeeded) {
  83. revert GovernorUnexpectedProposalState(
  84. proposalId,
  85. currentState,
  86. _encodeStateBitmap(ProposalState.Succeeded)
  87. );
  88. }
  89. uint256 eta = block.timestamp + _timelock.delay();
  90. _proposalTimelocks[proposalId] = eta;
  91. for (uint256 i = 0; i < targets.length; ++i) {
  92. if (_timelock.queuedTransactions(keccak256(abi.encode(targets[i], values[i], "", calldatas[i], eta)))) {
  93. revert GovernorAlreadyQueuedProposal(proposalId);
  94. }
  95. _timelock.queueTransaction(targets[i], values[i], "", calldatas[i], eta);
  96. }
  97. emit ProposalQueued(proposalId, eta);
  98. return proposalId;
  99. }
  100. /**
  101. * @dev Overridden execute function that run the already queued proposal through the timelock.
  102. */
  103. function _execute(
  104. uint256 proposalId,
  105. address[] memory targets,
  106. uint256[] memory values,
  107. bytes[] memory calldatas,
  108. bytes32 /*descriptionHash*/
  109. ) internal virtual override {
  110. uint256 eta = proposalEta(proposalId);
  111. if (eta == 0) {
  112. revert GovernorNotQueuedProposal(proposalId);
  113. }
  114. Address.sendValue(payable(_timelock), msg.value);
  115. for (uint256 i = 0; i < targets.length; ++i) {
  116. _timelock.executeTransaction(targets[i], values[i], "", calldatas[i], eta);
  117. }
  118. }
  119. /**
  120. * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
  121. * been queued.
  122. */
  123. function _cancel(
  124. address[] memory targets,
  125. uint256[] memory values,
  126. bytes[] memory calldatas,
  127. bytes32 descriptionHash
  128. ) internal virtual override returns (uint256) {
  129. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  130. uint256 eta = proposalEta(proposalId);
  131. if (eta > 0) {
  132. // update state first
  133. delete _proposalTimelocks[proposalId];
  134. // do external call later
  135. for (uint256 i = 0; i < targets.length; ++i) {
  136. _timelock.cancelTransaction(targets[i], values[i], "", calldatas[i], eta);
  137. }
  138. }
  139. return proposalId;
  140. }
  141. /**
  142. * @dev Address through which the governor executes action. In this case, the timelock.
  143. */
  144. function _executor() internal view virtual override returns (address) {
  145. return address(_timelock);
  146. }
  147. /**
  148. * @dev Accept admin right over the timelock.
  149. */
  150. // solhint-disable-next-line private-vars-leading-underscore
  151. function __acceptAdmin() public {
  152. _timelock.acceptAdmin();
  153. }
  154. /**
  155. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  156. * must be proposed, scheduled, and executed through governance proposals.
  157. *
  158. * For security reasons, the timelock must be handed over to another admin before setting up a new one. The two
  159. * operations (hand over the timelock) and do the update can be batched in a single proposal.
  160. *
  161. * Note that if the timelock admin has been handed over in a previous operation, we refuse updates made through the
  162. * timelock if admin of the timelock has already been accepted and the operation is executed outside the scope of
  163. * governance.
  164. * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
  165. */
  166. function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance {
  167. _updateTimelock(newTimelock);
  168. }
  169. function _updateTimelock(ICompoundTimelock newTimelock) private {
  170. emit TimelockChange(address(_timelock), address(newTimelock));
  171. _timelock = newTimelock;
  172. }
  173. }