GovernorCountingSimple.sol 3.3 KB

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