Governor.sol 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts v4.4.1 (governance/Governor.sol)
  3. pragma solidity ^0.8.0;
  4. import "../utils/cryptography/ECDSA.sol";
  5. import "../utils/cryptography/draft-EIP712.sol";
  6. import "../utils/introspection/ERC165.sol";
  7. import "../utils/math/SafeCast.sol";
  8. import "../utils/Address.sol";
  9. import "../utils/Context.sol";
  10. import "../utils/Timers.sol";
  11. import "./IGovernor.sol";
  12. /**
  13. * @dev Core of the governance system, designed to be extended though various modules.
  14. *
  15. * This contract is abstract and requires several function to be implemented in various modules:
  16. *
  17. * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}
  18. * - A voting module must implement {getVotes}
  19. * - Additionanly, the {votingPeriod} must also be implemented
  20. *
  21. * _Available since v4.3._
  22. */
  23. abstract contract Governor is Context, ERC165, EIP712, IGovernor {
  24. using SafeCast for uint256;
  25. using Timers for Timers.BlockNumber;
  26. bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
  27. struct ProposalCore {
  28. Timers.BlockNumber voteStart;
  29. Timers.BlockNumber voteEnd;
  30. bool executed;
  31. bool canceled;
  32. }
  33. string private _name;
  34. mapping(uint256 => ProposalCore) private _proposals;
  35. /**
  36. * @dev Restrict access to governor executing address. Some module might override the _executor function to make
  37. * sure this modifier is consistant with the execution model.
  38. */
  39. modifier onlyGovernance() {
  40. require(_msgSender() == _executor(), "Governor: onlyGovernance");
  41. _;
  42. }
  43. /**
  44. * @dev Sets the value for {name} and {version}
  45. */
  46. constructor(string memory name_) EIP712(name_, version()) {
  47. _name = name_;
  48. }
  49. /**
  50. * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
  51. */
  52. receive() external payable virtual {
  53. require(_executor() == address(this));
  54. }
  55. /**
  56. * @dev See {IERC165-supportsInterface}.
  57. */
  58. function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
  59. return interfaceId == type(IGovernor).interfaceId || super.supportsInterface(interfaceId);
  60. }
  61. /**
  62. * @dev See {IGovernor-name}.
  63. */
  64. function name() public view virtual override returns (string memory) {
  65. return _name;
  66. }
  67. /**
  68. * @dev See {IGovernor-version}.
  69. */
  70. function version() public view virtual override returns (string memory) {
  71. return "1";
  72. }
  73. /**
  74. * @dev See {IGovernor-hashProposal}.
  75. *
  76. * The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array
  77. * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
  78. * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
  79. * advance, before the proposal is submitted.
  80. *
  81. * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
  82. * same proposal (with same operation and same description) will have the same id if submitted on multiple governors
  83. * accross multiple networks. This also means that in order to execute the same operation twice (on the same
  84. * governor) the proposer will have to change the description in order to avoid proposal id conflicts.
  85. */
  86. function hashProposal(
  87. address[] memory targets,
  88. uint256[] memory values,
  89. bytes[] memory calldatas,
  90. bytes32 descriptionHash
  91. ) public pure virtual override returns (uint256) {
  92. return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
  93. }
  94. /**
  95. * @dev See {IGovernor-state}.
  96. */
  97. function state(uint256 proposalId) public view virtual override returns (ProposalState) {
  98. ProposalCore memory proposal = _proposals[proposalId];
  99. if (proposal.executed) {
  100. return ProposalState.Executed;
  101. } else if (proposal.canceled) {
  102. return ProposalState.Canceled;
  103. } else if (proposal.voteStart.getDeadline() >= block.number) {
  104. return ProposalState.Pending;
  105. } else if (proposal.voteEnd.getDeadline() >= block.number) {
  106. return ProposalState.Active;
  107. } else if (proposal.voteEnd.isExpired()) {
  108. return
  109. _quorumReached(proposalId) && _voteSucceeded(proposalId)
  110. ? ProposalState.Succeeded
  111. : ProposalState.Defeated;
  112. } else {
  113. revert("Governor: unknown proposal id");
  114. }
  115. }
  116. /**
  117. * @dev See {IGovernor-proposalSnapshot}.
  118. */
  119. function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
  120. return _proposals[proposalId].voteStart.getDeadline();
  121. }
  122. /**
  123. * @dev See {IGovernor-proposalDeadline}.
  124. */
  125. function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
  126. return _proposals[proposalId].voteEnd.getDeadline();
  127. }
  128. /**
  129. * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
  130. */
  131. function proposalThreshold() public view virtual returns (uint256) {
  132. return 0;
  133. }
  134. /**
  135. * @dev Amount of votes already cast passes the threshold limit.
  136. */
  137. function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
  138. /**
  139. * @dev Is the proposal successful or not.
  140. */
  141. function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
  142. /**
  143. * @dev Register a vote with a given support and voting weight.
  144. *
  145. * Note: Support is generic and can represent various things depending on the voting system used.
  146. */
  147. function _countVote(
  148. uint256 proposalId,
  149. address account,
  150. uint8 support,
  151. uint256 weight
  152. ) internal virtual;
  153. /**
  154. * @dev See {IGovernor-propose}.
  155. */
  156. function propose(
  157. address[] memory targets,
  158. uint256[] memory values,
  159. bytes[] memory calldatas,
  160. string memory description
  161. ) public virtual override returns (uint256) {
  162. require(
  163. getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
  164. "GovernorCompatibilityBravo: proposer votes below proposal threshold"
  165. );
  166. uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
  167. require(targets.length == values.length, "Governor: invalid proposal length");
  168. require(targets.length == calldatas.length, "Governor: invalid proposal length");
  169. require(targets.length > 0, "Governor: empty proposal");
  170. ProposalCore storage proposal = _proposals[proposalId];
  171. require(proposal.voteStart.isUnset(), "Governor: proposal already exists");
  172. uint64 snapshot = block.number.toUint64() + votingDelay().toUint64();
  173. uint64 deadline = snapshot + votingPeriod().toUint64();
  174. proposal.voteStart.setDeadline(snapshot);
  175. proposal.voteEnd.setDeadline(deadline);
  176. emit ProposalCreated(
  177. proposalId,
  178. _msgSender(),
  179. targets,
  180. values,
  181. new string[](targets.length),
  182. calldatas,
  183. snapshot,
  184. deadline,
  185. description
  186. );
  187. return proposalId;
  188. }
  189. /**
  190. * @dev See {IGovernor-execute}.
  191. */
  192. function execute(
  193. address[] memory targets,
  194. uint256[] memory values,
  195. bytes[] memory calldatas,
  196. bytes32 descriptionHash
  197. ) public payable virtual override returns (uint256) {
  198. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  199. ProposalState status = state(proposalId);
  200. require(
  201. status == ProposalState.Succeeded || status == ProposalState.Queued,
  202. "Governor: proposal not successful"
  203. );
  204. _proposals[proposalId].executed = true;
  205. emit ProposalExecuted(proposalId);
  206. _execute(proposalId, targets, values, calldatas, descriptionHash);
  207. return proposalId;
  208. }
  209. /**
  210. * @dev Internal execution mechanism. Can be overriden to implement different execution mechanism
  211. */
  212. function _execute(
  213. uint256, /* proposalId */
  214. address[] memory targets,
  215. uint256[] memory values,
  216. bytes[] memory calldatas,
  217. bytes32 /*descriptionHash*/
  218. ) internal virtual {
  219. string memory errorMessage = "Governor: call reverted without message";
  220. for (uint256 i = 0; i < targets.length; ++i) {
  221. (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
  222. Address.verifyCallResult(success, returndata, errorMessage);
  223. }
  224. }
  225. /**
  226. * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
  227. * canceled to allow distinguishing it from executed proposals.
  228. *
  229. * Emits a {IGovernor-ProposalCanceled} event.
  230. */
  231. function _cancel(
  232. address[] memory targets,
  233. uint256[] memory values,
  234. bytes[] memory calldatas,
  235. bytes32 descriptionHash
  236. ) internal virtual returns (uint256) {
  237. uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
  238. ProposalState status = state(proposalId);
  239. require(
  240. status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,
  241. "Governor: proposal not active"
  242. );
  243. _proposals[proposalId].canceled = true;
  244. emit ProposalCanceled(proposalId);
  245. return proposalId;
  246. }
  247. /**
  248. * @dev See {IGovernor-castVote}.
  249. */
  250. function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {
  251. address voter = _msgSender();
  252. return _castVote(proposalId, voter, support, "");
  253. }
  254. /**
  255. * @dev See {IGovernor-castVoteWithReason}.
  256. */
  257. function castVoteWithReason(
  258. uint256 proposalId,
  259. uint8 support,
  260. string calldata reason
  261. ) public virtual override returns (uint256) {
  262. address voter = _msgSender();
  263. return _castVote(proposalId, voter, support, reason);
  264. }
  265. /**
  266. * @dev See {IGovernor-castVoteBySig}.
  267. */
  268. function castVoteBySig(
  269. uint256 proposalId,
  270. uint8 support,
  271. uint8 v,
  272. bytes32 r,
  273. bytes32 s
  274. ) public virtual override returns (uint256) {
  275. address voter = ECDSA.recover(
  276. _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
  277. v,
  278. r,
  279. s
  280. );
  281. return _castVote(proposalId, voter, support, "");
  282. }
  283. /**
  284. * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
  285. * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
  286. *
  287. * Emits a {IGovernor-VoteCast} event.
  288. */
  289. function _castVote(
  290. uint256 proposalId,
  291. address account,
  292. uint8 support,
  293. string memory reason
  294. ) internal virtual returns (uint256) {
  295. ProposalCore storage proposal = _proposals[proposalId];
  296. require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");
  297. uint256 weight = getVotes(account, proposal.voteStart.getDeadline());
  298. _countVote(proposalId, account, support, weight);
  299. emit VoteCast(account, proposalId, support, weight, reason);
  300. return weight;
  301. }
  302. /**
  303. * @dev Address through which the governor executes action. Will be overloaded by module that execute actions
  304. * through another contract such as a timelock.
  305. */
  306. function _executor() internal view virtual returns (address) {
  307. return address(this);
  308. }
  309. }