GovernorCountingSimple.sol 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../Governor.sol";
  4. /**
  5. * @dev Extension of {Governor} for simple, 3 options, vote counting.
  6. *
  7. * _Available since v4.3._
  8. */
  9. abstract contract GovernorCountingSimple is Governor {
  10. /**
  11. * @dev Supported vote types. Matches Governor Bravo ordering.
  12. */
  13. enum VoteType {
  14. Against,
  15. For,
  16. Abstain
  17. }
  18. struct ProposalVote {
  19. uint256 againstVotes;
  20. uint256 forVotes;
  21. uint256 abstainVotes;
  22. mapping(address => bool) hasVoted;
  23. }
  24. mapping(uint256 => ProposalVote) private _proposalVotes;
  25. /**
  26. * @dev See {IGovernor-COUNTING_MODE}.
  27. */
  28. // solhint-disable-next-line func-name-mixedcase
  29. function COUNTING_MODE() public pure virtual override returns (string memory) {
  30. return "support=bravo&quorum=for,abstain";
  31. }
  32. /**
  33. * @dev See {IGovernor-hasVoted}.
  34. */
  35. function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
  36. return _proposalVotes[proposalId].hasVoted[account];
  37. }
  38. /**
  39. * @dev Accessor to the internal vote counts.
  40. */
  41. function proposalVotes(uint256 proposalId)
  42. public
  43. view
  44. virtual
  45. returns (
  46. uint256 againstVotes,
  47. uint256 forVotes,
  48. uint256 abstainVotes
  49. )
  50. {
  51. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  52. return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);
  53. }
  54. /**
  55. * @dev See {Governor-_quorumReached}.
  56. */
  57. function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
  58. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  59. return
  60. quorum(proposalSnapshot(proposalId)) <=
  61. proposalvote.againstVotes + proposalvote.forVotes + proposalvote.abstainVotes;
  62. }
  63. /**
  64. * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be scritly over the againstVotes.
  65. */
  66. function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
  67. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  68. return proposalvote.forVotes > proposalvote.againstVotes;
  69. }
  70. /**
  71. * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
  72. */
  73. function _countVote(
  74. uint256 proposalId,
  75. address account,
  76. uint8 support,
  77. uint256 weight
  78. ) internal virtual override {
  79. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  80. require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already casted");
  81. proposalvote.hasVoted[account] = true;
  82. if (support == uint8(VoteType.Against)) {
  83. proposalvote.againstVotes += weight;
  84. } else if (support == uint8(VoteType.For)) {
  85. proposalvote.forVotes += weight;
  86. } else if (support == uint8(VoteType.Abstain)) {
  87. proposalvote.abstainVotes += weight;
  88. } else {
  89. revert("GovernorVotingSimple: invalid value for enum VoteType");
  90. }
  91. }
  92. }