GovernorCompatibilityBravo.sol 9.6 KB

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