GovernorCompatibilityBravo.sol 9.8 KB

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