You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.2 KiB
Solidity
101 lines
3.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorCountingSimple.sol)
|
|
|
|
pragma solidity ^0.8.0;
|
|
|
|
import "../Governor.sol";
|
|
|
|
/**
|
|
* @dev Extension of {Governor} for simple, 3 options, vote counting.
|
|
*
|
|
* _Available since v4.3._
|
|
*/
|
|
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 => bool) hasVoted;
|
|
}
|
|
|
|
mapping(uint256 => 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 weight,
|
|
bytes memory // params
|
|
) internal virtual override {
|
|
ProposalVote storage proposalVote = _proposalVotes[proposalId];
|
|
|
|
require(!proposalVote.hasVoted[account], "GovernorVotingSimple: vote already cast");
|
|
proposalVote.hasVoted[account] = true;
|
|
|
|
if (support == uint8(VoteType.Against)) {
|
|
proposalVote.againstVotes += weight;
|
|
} else if (support == uint8(VoteType.For)) {
|
|
proposalVote.forVotes += weight;
|
|
} else if (support == uint8(VoteType.Abstain)) {
|
|
proposalVote.abstainVotes += weight;
|
|
} else {
|
|
revert("GovernorVotingSimple: invalid value for enum VoteType");
|
|
}
|
|
}
|
|
}
|