GovernorTimelockCompoundUpgradeable.sol 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorTimelockCompound.sol)
  3. pragma solidity ^0.8.0;
  4. import "./IGovernorTimelockUpgradeable.sol";
  5. import "../GovernorUpgradeable.sol";
  6. import "../../utils/math/SafeCastUpgradeable.sol";
  7. import "../../proxy/utils/Initializable.sol";
  8. /**
  9. * https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[Compound's timelock] interface
  10. */
  11. interface ICompoundTimelockUpgradeable {
  12. receive() external payable;
  13. // solhint-disable-next-line func-name-mixedcase
  14. function GRACE_PERIOD() external view returns (uint256);
  15. // solhint-disable-next-line func-name-mixedcase
  16. function MINIMUM_DELAY() external view returns (uint256);
  17. // solhint-disable-next-line func-name-mixedcase
  18. function MAXIMUM_DELAY() external view returns (uint256);
  19. function admin() external view returns (address);
  20. function pendingAdmin() external view returns (address);
  21. function delay() external view returns (uint256);
  22. function queuedTransactions(bytes32) external view returns (bool);
  23. function setDelay(uint256) external;
  24. function acceptAdmin() external;
  25. function setPendingAdmin(address) external;
  26. function queueTransaction(
  27. address target,
  28. uint256 value,
  29. string memory signature,
  30. bytes memory data,
  31. uint256 eta
  32. ) external returns (bytes32);
  33. function cancelTransaction(
  34. address target,
  35. uint256 value,
  36. string memory signature,
  37. bytes memory data,
  38. uint256 eta
  39. ) external;
  40. function executeTransaction(
  41. address target,
  42. uint256 value,
  43. string memory signature,
  44. bytes memory data,
  45. uint256 eta
  46. ) external payable returns (bytes memory);
  47. }
  48. /**
  49. * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
  50. * the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be
  51. * the admin of the timelock for any operation to be performed. A public, unrestricted,
  52. * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock.
  53. *
  54. * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
  55. * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  56. * inaccessible.
  57. *
  58. * _Available since v4.3._
  59. */
  60. abstract contract GovernorTimelockCompoundUpgradeable is Initializable, IGovernorTimelockUpgradeable, GovernorUpgradeable {
  61. using SafeCastUpgradeable for uint256;
  62. using TimersUpgradeable for TimersUpgradeable.Timestamp;
  63. struct ProposalTimelock {
  64. TimersUpgradeable.Timestamp timer;
  65. }
  66. ICompoundTimelockUpgradeable private _timelock;
  67. mapping(uint256 => ProposalTimelock) private _proposalTimelocks;
  68. /**
  69. * @dev Emitted when the timelock controller used for proposal execution is modified.
  70. */
  71. event TimelockChange(address oldTimelock, address newTimelock);
  72. /**
  73. * @dev Set the timelock.
  74. */
  75. function __GovernorTimelockCompound_init(ICompoundTimelockUpgradeable timelockAddress) internal onlyInitializing {
  76. __GovernorTimelockCompound_init_unchained(timelockAddress);
  77. }
  78. function __GovernorTimelockCompound_init_unchained(ICompoundTimelockUpgradeable timelockAddress) internal onlyInitializing {
  79. _updateTimelock(timelockAddress);
  80. }
  81. /**
  82. * @dev See {IERC165-supportsInterface}.
  83. */
  84. function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, GovernorUpgradeable) returns (bool) {
  85. return interfaceId == type(IGovernorTimelockUpgradeable).interfaceId || super.supportsInterface(interfaceId);
  86. }
  87. /**
  88. * @dev Overriden version of the {Governor-state} function with added support for the `Queued` and `Expired` status.
  89. */
  90. function state(uint256 proposalId) public view virtual override(IGovernorUpgradeable, GovernorUpgradeable) returns (ProposalState) {
  91. ProposalState status = super.state(proposalId);
  92. if (status != ProposalState.Succeeded) {
  93. return status;
  94. }
  95. uint256 eta = proposalEta(proposalId);
  96. if (eta == 0) {
  97. return status;
  98. } else if (block.timestamp >= eta + _timelock.GRACE_PERIOD()) {
  99. return ProposalState.Expired;
  100. } else {
  101. return ProposalState.Queued;
  102. }
  103. }
  104. /**
  105. * @dev Public accessor to check the address of the timelock
  106. */
  107. function timelock() public view virtual override returns (address) {
  108. return address(_timelock);
  109. }
  110. /**
  111. * @dev Public accessor to check the eta of a queued proposal
  112. */
  113. function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
  114. return _proposalTimelocks[proposalId].timer.getDeadline();
  115. }
  116. /**
  117. * @dev Function to queue a proposal to the timelock.
  118. */
  119. function queue(
  120. address[] memory targets,
  121. uint256[] memory values,
  122. bytes[] memory calldatas,
  123. bytes32 descriptionHash
  124. ) public virtual override returns (uint256) {
  125. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  126. require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful");
  127. uint256 eta = block.timestamp + _timelock.delay();
  128. _proposalTimelocks[proposalId].timer.setDeadline(eta.toUint64());
  129. for (uint256 i = 0; i < targets.length; ++i) {
  130. require(
  131. !_timelock.queuedTransactions(keccak256(abi.encode(targets[i], values[i], "", calldatas[i], eta))),
  132. "GovernorTimelockCompound: identical proposal action already queued"
  133. );
  134. _timelock.queueTransaction(targets[i], values[i], "", calldatas[i], eta);
  135. }
  136. emit ProposalQueued(proposalId, eta);
  137. return proposalId;
  138. }
  139. /**
  140. * @dev Overriden execute function that run the already queued proposal through the timelock.
  141. */
  142. function _execute(
  143. uint256 proposalId,
  144. address[] memory targets,
  145. uint256[] memory values,
  146. bytes[] memory calldatas,
  147. bytes32 /*descriptionHash*/
  148. ) internal virtual override {
  149. uint256 eta = proposalEta(proposalId);
  150. require(eta > 0, "GovernorTimelockCompound: proposal not yet queued");
  151. AddressUpgradeable.sendValue(payable(_timelock), msg.value);
  152. for (uint256 i = 0; i < targets.length; ++i) {
  153. _timelock.executeTransaction(targets[i], values[i], "", calldatas[i], eta);
  154. }
  155. }
  156. /**
  157. * @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
  158. * been queued.
  159. */
  160. function _cancel(
  161. address[] memory targets,
  162. uint256[] memory values,
  163. bytes[] memory calldatas,
  164. bytes32 descriptionHash
  165. ) internal virtual override returns (uint256) {
  166. uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
  167. uint256 eta = proposalEta(proposalId);
  168. if (eta > 0) {
  169. for (uint256 i = 0; i < targets.length; ++i) {
  170. _timelock.cancelTransaction(targets[i], values[i], "", calldatas[i], eta);
  171. }
  172. _proposalTimelocks[proposalId].timer.reset();
  173. }
  174. return proposalId;
  175. }
  176. /**
  177. * @dev Address through which the governor executes action. In this case, the timelock.
  178. */
  179. function _executor() internal view virtual override returns (address) {
  180. return address(_timelock);
  181. }
  182. /**
  183. * @dev Accept admin right over the timelock.
  184. */
  185. // solhint-disable-next-line private-vars-leading-underscore
  186. function __acceptAdmin() public {
  187. _timelock.acceptAdmin();
  188. }
  189. /**
  190. * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
  191. * must be proposed, scheduled, and executed through governance proposals.
  192. *
  193. * For security reasons, the timelock must be handed over to another admin before setting up a new one. The two
  194. * operations (hand over the timelock) and do the update can be batched in a single proposal.
  195. *
  196. * Note that if the timelock admin has been handed over in a previous operation, we refuse updates made through the
  197. * timelock if admin of the timelock has already been accepted and the operation is executed outside the scope of
  198. * governance.
  199. * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
  200. */
  201. function updateTimelock(ICompoundTimelockUpgradeable newTimelock) external virtual onlyGovernance {
  202. _updateTimelock(newTimelock);
  203. }
  204. function _updateTimelock(ICompoundTimelockUpgradeable newTimelock) private {
  205. emit TimelockChange(address(_timelock), address(newTimelock));
  206. _timelock = newTimelock;
  207. }
  208. /**
  209. * This empty reserved space is put in place to allow future versions to add new
  210. * variables without shifting down storage in the inheritance chain.
  211. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  212. */
  213. uint256[48] private __gap;
  214. }