123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v5.0.0) (governance/extensions/GovernorCountingSimple.sol)
- pragma solidity ^0.8.20;
- import {Governor} from "../Governor.sol";
- /**
- * @dev Extension of {Governor} for simple, 3 options, vote counting.
- */
- abstract contract GovernorCountingSimple is Governor {
- /**
- * @dev Supported vote types. Matches Governor Bravo ordering.
- */
- enum VoteType {
- Against,
- For,
- Abstain
- }
- struct ProposalVote {
- uint256 againstVotes;
- uint256 forVotes;
- uint256 abstainVotes;
- mapping(address voter => bool) hasVoted;
- }
- mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
- /**
- * @dev See {IGovernor-COUNTING_MODE}.
- */
- // solhint-disable-next-line func-name-mixedcase
- function COUNTING_MODE() public pure virtual override returns (string memory) {
- return "support=bravo&quorum=for,abstain";
- }
- /**
- * @dev See {IGovernor-hasVoted}.
- */
- function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
- return _proposalVotes[proposalId].hasVoted[account];
- }
- /**
- * @dev Accessor to the internal vote counts.
- */
- function proposalVotes(
- uint256 proposalId
- ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) {
- ProposalVote storage proposalVote = _proposalVotes[proposalId];
- return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
- }
- /**
- * @dev See {Governor-_quorumReached}.
- */
- function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
- ProposalVote storage proposalVote = _proposalVotes[proposalId];
- return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
- }
- /**
- * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
- */
- function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
- ProposalVote storage proposalVote = _proposalVotes[proposalId];
- return proposalVote.forVotes > proposalVote.againstVotes;
- }
- /**
- * @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
- */
- function _countVote(
- uint256 proposalId,
- address account,
- uint8 support,
- uint256 totalWeight,
- bytes memory // params
- ) internal virtual override returns (uint256) {
- ProposalVote storage proposalVote = _proposalVotes[proposalId];
- if (proposalVote.hasVoted[account]) {
- revert GovernorAlreadyCastVote(account);
- }
- proposalVote.hasVoted[account] = true;
- if (support == uint8(VoteType.Against)) {
- proposalVote.againstVotes += totalWeight;
- } else if (support == uint8(VoteType.For)) {
- proposalVote.forVotes += totalWeight;
- } else if (support == uint8(VoteType.Abstain)) {
- proposalVote.abstainVotes += totalWeight;
- } else {
- revert GovernorInvalidVoteType();
- }
- return totalWeight;
- }
- }
|