GovernorCompatibilityBravo.sol 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../../utils/Counters.sol";
  4. import "../../utils/math/SafeCast.sol";
  5. import "../extensions/IGovernorTimelock.sol";
  6. import "../extensions/GovernorProposalThreshold.sol";
  7. import "../Governor.sol";
  8. import "./IGovernorCompatibilityBravo.sol";
  9. /**
  10. * @dev Compatibility layer that implements GovernorBravo compatibility on to of {Governor}.
  11. *
  12. * This compatibility layer includes a voting system and requires a {IGovernorTimelock} compatible module to be added
  13. * through inheritance. It does not include token bindings, not does it include any variable upgrade patterns.
  14. *
  15. * NOTE: When using this module, you may need to enable the Solidity optimizer to avoid hitting the contract size limit.
  16. *
  17. * _Available since v4.3._
  18. */
  19. abstract contract GovernorCompatibilityBravo is
  20. IGovernorTimelock,
  21. IGovernorCompatibilityBravo,
  22. Governor,
  23. GovernorProposalThreshold
  24. {
  25. using Counters for Counters.Counter;
  26. using Timers for Timers.BlockNumber;
  27. enum VoteType {
  28. Against,
  29. For,
  30. Abstain
  31. }
  32. struct ProposalDetails {
  33. address proposer;
  34. address[] targets;
  35. uint256[] values;
  36. string[] signatures;
  37. bytes[] calldatas;
  38. uint256 forVotes;
  39. uint256 againstVotes;
  40. uint256 abstainVotes;
  41. mapping(address => Receipt) receipts;
  42. bytes32 descriptionHash;
  43. }
  44. mapping(uint256 => ProposalDetails) private _proposalDetails;
  45. // solhint-disable-next-line func-name-mixedcase
  46. function COUNTING_MODE() public pure virtual override returns (string memory) {
  47. return "support=bravo&quorum=bravo";
  48. }
  49. // ============================================== Proposal lifecycle ==============================================
  50. /**
  51. * @dev See {IGovernor-propose}.
  52. */
  53. function propose(
  54. address[] memory targets,
  55. uint256[] memory values,
  56. bytes[] memory calldatas,
  57. string memory description
  58. ) public virtual override(IGovernor, Governor, GovernorProposalThreshold) returns (uint256) {
  59. _storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description);
  60. return super.propose(targets, values, calldatas, description);
  61. }
  62. /**
  63. * @dev See {IGovernorCompatibilityBravo-propose}.
  64. */
  65. function propose(
  66. address[] memory targets,
  67. uint256[] memory values,
  68. string[] memory signatures,
  69. bytes[] memory calldatas,
  70. string memory description
  71. ) public virtual override returns (uint256) {
  72. _storeProposal(_msgSender(), targets, values, signatures, calldatas, description);
  73. return propose(targets, values, _encodeCalldata(signatures, calldatas), description);
  74. }
  75. /**
  76. * @dev See {IGovernorCompatibilityBravo-queue}.
  77. */
  78. function queue(uint256 proposalId) public virtual override {
  79. ProposalDetails storage details = _proposalDetails[proposalId];
  80. queue(
  81. details.targets,
  82. details.values,
  83. _encodeCalldata(details.signatures, details.calldatas),
  84. details.descriptionHash
  85. );
  86. }
  87. /**
  88. * @dev See {IGovernorCompatibilityBravo-execute}.
  89. */
  90. function execute(uint256 proposalId) public payable virtual override {
  91. ProposalDetails storage details = _proposalDetails[proposalId];
  92. execute(
  93. details.targets,
  94. details.values,
  95. _encodeCalldata(details.signatures, details.calldatas),
  96. details.descriptionHash
  97. );
  98. }
  99. function cancel(uint256 proposalId) public virtual override {
  100. ProposalDetails storage details = _proposalDetails[proposalId];
  101. require(
  102. _msgSender() == details.proposer || getVotes(details.proposer, block.number - 1) < proposalThreshold(),
  103. "GovernorBravo: proposer above threshold"
  104. );
  105. _cancel(
  106. details.targets,
  107. details.values,
  108. _encodeCalldata(details.signatures, details.calldatas),
  109. details.descriptionHash
  110. );
  111. }
  112. /**
  113. * @dev Encodes calldatas with optional function signature.
  114. */
  115. function _encodeCalldata(string[] memory signatures, bytes[] memory calldatas)
  116. private
  117. pure
  118. returns (bytes[] memory)
  119. {
  120. bytes[] memory fullcalldatas = new bytes[](calldatas.length);
  121. for (uint256 i = 0; i < signatures.length; ++i) {
  122. fullcalldatas[i] = bytes(signatures[i]).length == 0
  123. ? calldatas[i]
  124. : abi.encodeWithSignature(signatures[i], calldatas[i]);
  125. }
  126. return fullcalldatas;
  127. }
  128. /**
  129. * @dev Store proposal metadata for later lookup
  130. */
  131. function _storeProposal(
  132. address proposer,
  133. address[] memory targets,
  134. uint256[] memory values,
  135. string[] memory signatures,
  136. bytes[] memory calldatas,
  137. string memory description
  138. ) private {
  139. bytes32 descriptionHash = keccak256(bytes(description));
  140. uint256 proposalId = hashProposal(targets, values, _encodeCalldata(signatures, calldatas), descriptionHash);
  141. ProposalDetails storage details = _proposalDetails[proposalId];
  142. if (details.descriptionHash == bytes32(0)) {
  143. details.proposer = proposer;
  144. details.targets = targets;
  145. details.values = values;
  146. details.signatures = signatures;
  147. details.calldatas = calldatas;
  148. details.descriptionHash = descriptionHash;
  149. }
  150. }
  151. // ==================================================== Views =====================================================
  152. /**
  153. * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
  154. */
  155. function proposalThreshold()
  156. public
  157. view
  158. virtual
  159. override(IGovernorCompatibilityBravo, GovernorProposalThreshold)
  160. returns (uint256);
  161. /**
  162. * @dev See {IGovernorCompatibilityBravo-proposals}.
  163. */
  164. function proposals(uint256 proposalId)
  165. public
  166. view
  167. virtual
  168. override
  169. returns (
  170. uint256 id,
  171. address proposer,
  172. uint256 eta,
  173. uint256 startBlock,
  174. uint256 endBlock,
  175. uint256 forVotes,
  176. uint256 againstVotes,
  177. uint256 abstainVotes,
  178. bool canceled,
  179. bool executed
  180. )
  181. {
  182. id = proposalId;
  183. eta = proposalEta(proposalId);
  184. startBlock = proposalSnapshot(proposalId);
  185. endBlock = proposalDeadline(proposalId);
  186. ProposalDetails storage details = _proposalDetails[proposalId];
  187. proposer = details.proposer;
  188. forVotes = details.forVotes;
  189. againstVotes = details.againstVotes;
  190. abstainVotes = details.abstainVotes;
  191. ProposalState status = state(proposalId);
  192. canceled = status == ProposalState.Canceled;
  193. executed = status == ProposalState.Executed;
  194. }
  195. /**
  196. * @dev See {IGovernorCompatibilityBravo-getActions}.
  197. */
  198. function getActions(uint256 proposalId)
  199. public
  200. view
  201. virtual
  202. override
  203. returns (
  204. address[] memory targets,
  205. uint256[] memory values,
  206. string[] memory signatures,
  207. bytes[] memory calldatas
  208. )
  209. {
  210. ProposalDetails storage details = _proposalDetails[proposalId];
  211. return (details.targets, details.values, details.signatures, details.calldatas);
  212. }
  213. /**
  214. * @dev See {IGovernorCompatibilityBravo-getReceipt}.
  215. */
  216. function getReceipt(uint256 proposalId, address voter) public view virtual override returns (Receipt memory) {
  217. return _proposalDetails[proposalId].receipts[voter];
  218. }
  219. /**
  220. * @dev See {IGovernorCompatibilityBravo-quorumVotes}.
  221. */
  222. function quorumVotes() public view virtual override returns (uint256) {
  223. return quorum(block.number - 1);
  224. }
  225. // ==================================================== Voting ====================================================
  226. /**
  227. * @dev See {IGovernor-hasVoted}.
  228. */
  229. function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
  230. return _proposalDetails[proposalId].receipts[account].hasVoted;
  231. }
  232. /**
  233. * @dev See {Governor-_quorumReached}. In this module, only forVotes count toward the quorum.
  234. */
  235. function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
  236. ProposalDetails storage details = _proposalDetails[proposalId];
  237. return quorum(proposalSnapshot(proposalId)) < details.forVotes;
  238. }
  239. /**
  240. * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be scritly over the againstVotes.
  241. */
  242. function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
  243. ProposalDetails storage details = _proposalDetails[proposalId];
  244. return details.forVotes > details.againstVotes;
  245. }
  246. /**
  247. * @dev See {Governor-_countVote}. In this module, the support follows Governor Bravo.
  248. */
  249. function _countVote(
  250. uint256 proposalId,
  251. address account,
  252. uint8 support,
  253. uint256 weight
  254. ) internal virtual override {
  255. ProposalDetails storage details = _proposalDetails[proposalId];
  256. Receipt storage receipt = details.receipts[account];
  257. require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already cast");
  258. receipt.hasVoted = true;
  259. receipt.support = support;
  260. receipt.votes = SafeCast.toUint96(weight);
  261. if (support == uint8(VoteType.Against)) {
  262. details.againstVotes += weight;
  263. } else if (support == uint8(VoteType.For)) {
  264. details.forVotes += weight;
  265. } else if (support == uint8(VoteType.Abstain)) {
  266. details.abstainVotes += weight;
  267. } else {
  268. revert("GovernorCompatibilityBravo: invalid vote type");
  269. }
  270. }
  271. }