GovernorCountingSimple.sol 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorCountingSimple.sol)
  3. pragma solidity ^0.8.19;
  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(
  43. uint256 proposalId
  44. ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
  45. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  46. return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
  47. }
  48. /**
  49. * @dev See {Governor-_quorumReached}.
  50. */
  51. function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
  52. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  53. return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
  54. }
  55. /**
  56. * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
  57. */
  58. function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
  59. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  60. return proposalVote.forVotes > proposalVote.againstVotes;
  61. }
  62. /**
  63. * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
  64. */
  65. function _countVote(
  66. uint256 proposalId,
  67. address account,
  68. uint8 support,
  69. uint256 weight,
  70. bytes memory // params
  71. ) internal virtual override {
  72. ProposalVote storage proposalVote = _proposalVotes[proposalId];
  73. require(!proposalVote.hasVoted[account], "GovernorVotingSimple: vote already cast");
  74. proposalVote.hasVoted[account] = true;
  75. if (support == uint8(VoteType.Against)) {
  76. proposalVote.againstVotes += weight;
  77. } else if (support == uint8(VoteType.For)) {
  78. proposalVote.forVotes += weight;
  79. } else if (support == uint8(VoteType.Abstain)) {
  80. proposalVote.abstainVotes += weight;
  81. } else {
  82. revert("GovernorVotingSimple: invalid value for enum VoteType");
  83. }
  84. }
  85. }