Governor.sol 12 KB

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