GovernorCountingSimple.sol 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
  60. }
  61. /**
  62. * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be scritly over the againstVotes.
  63. */
  64. function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
  65. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  66. return proposalvote.forVotes > proposalvote.againstVotes;
  67. }
  68. /**
  69. * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
  70. */
  71. function _countVote(
  72. uint256 proposalId,
  73. address account,
  74. uint8 support,
  75. uint256 weight
  76. ) internal virtual override {
  77. ProposalVote storage proposalvote = _proposalVotes[proposalId];
  78. require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already casted");
  79. proposalvote.hasVoted[account] = true;
  80. if (support == uint8(VoteType.Against)) {
  81. proposalvote.againstVotes += weight;
  82. } else if (support == uint8(VoteType.For)) {
  83. proposalvote.forVotes += weight;
  84. } else if (support == uint8(VoteType.Abstain)) {
  85. proposalvote.abstainVotes += weight;
  86. } else {
  87. revert("GovernorVotingSimple: invalid value for enum VoteType");
  88. }
  89. }
  90. }