Documentation
Contracts
GovernorCountingFractional.sol

GovernorCountingFractional

Git Source (opens in a new tab)

Inherits: Governor

Extension of Governor for 3 option fractional vote counting. When voting, a delegate may split their vote weight between Against/For/Abstain. This is most useful when the delegate is itself a contract, implementing its own rules for voting. By allowing a contract-delegate to split its vote weight, the voting preferences of many disparate token holders can be rolled up into a single vote to the Governor itself. Some example use cases include voting with tokens that are held by a DeFi pool, voting from L2 with tokens held by a bridge, or voting privately from a shielded pool using zero knowledge proofs.

State Variables

_proposalVotes

Mapping from proposal ID to vote tallies for that proposal.

mapping(uint256 => ProposalVote) private _proposalVotes;

_proposalVotersWeightCast

Mapping from proposal ID and address to the weight the address has cast on that proposal, e.g. _proposalVotersWeightCast[42][0xBEEF] would tell you the number of votes that 0xBEEF has cast on proposal 42.

mapping(uint256 => mapping(address => uint128)) private _proposalVotersWeightCast;

fractionalVoteNonce

Mapping from voter address to signature-based vote nonce. The voter's nonce increments each time a signature-based vote is cast with fractional voting params and must be included in the params as the last 16 bytes when signing for a fractional vote.

mapping(address => uint128) public fractionalVoteNonce;

_MASK_HALF_WORD_RIGHT

uint256 internal constant _MASK_HALF_WORD_RIGHT = 0xffffffffffffffffffffffffffffffff;

Functions

COUNTING_MODE

See IGovernor-COUNTING_MODE.

function COUNTING_MODE() public pure virtual override returns (string memory);

hasVoted

See IGovernor-hasVoted.

function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool);

voteWeightCast

Get the number of votes cast thus far on proposal proposalId by account account. Useful for integrations that allow delegates to cast rolling, partial votes.

function voteWeightCast(uint256 proposalId, address account) public view returns (uint128);

proposalVotes

Accessor to the internal vote counts.

function proposalVotes(uint256 proposalId)
  public
  view
  virtual
  returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes);

_quorumReached

See Governor-_quorumReached.

function _quorumReached(uint256 proposalId) internal view virtual override returns (bool);

_voteSucceeded

See Governor-_voteSucceeded. In this module, forVotes must be > againstVotes.

function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool);

_countVote

See Governor-_countVote.

Function that records the delegate's votes. If the voteData bytes parameter is empty, then this module behaves identically to GovernorBravo. That is, it assigns the full weight of the delegate to the support parameter, which follows the VoteType enum from Governor Bravo.

If the voteData bytes parameter is not zero, then it must be three packed uint128s, totaling 48 bytes, representing the weight the delegate assigns to Against, For, and Abstain respectively, i.e. abi.encodePacked(againstVotes, forVotes, abstainVotes). The sum total of the three decoded vote weights must be less than or equal to the delegate's remaining weight on the proposal, i.e. their checkpointed total weight minus votes already cast on the proposal.

See _countVoteNominal and _countVoteFractional for more details.

function _countVote(
  uint256 proposalId,
  address account,
  uint8 support,
  uint256 totalWeight,
  bytes memory voteData
) internal virtual override;

_countVoteNominal

Record votes with full weight cast for support. Because this function votes with the delegate's full weight, it can only be called once per proposal. It will revert if combined with a fractional vote before or after.

function _countVoteNominal(uint256 proposalId, address account, uint128 totalWeight, uint8 support)
  internal;

_countVoteFractional

Count votes with fractional weight. voteData is expected to be three packed uint128s, i.e. abi.encodePacked(againstVotes, forVotes, abstainVotes). This function can be called multiple times for the same account and proposal, i.e. partial/rolling votes are allowed. For example, an account with total weight of 10 could call this function three times with the following vote data:

  • against: 1, for: 0, abstain: 2
  • against: 3, for: 1, abstain: 0
  • against: 1, for: 1, abstain: 1

The result of these three calls would be that the account casts 5 votes AGAINST, 2 votes FOR, and 3 votes ABSTAIN on the proposal. Though partial, votes are still final once cast and cannot be changed or overridden. Subsequent partial votes simply increment existing totals. Note that if partial votes are cast, all remaining weight must be cast with _countVoteFractional: _countVoteNominal will revert.

function _countVoteFractional(
  uint256 proposalId,
  address account,
  uint128 totalWeight,
  bytes memory voteData
) internal;

_decodePackedVotes

Decodes three packed uint128's. Uses assembly because of a Solidity language limitation which prevents slicing bytes stored in memory, rather than calldata.

function _decodePackedVotes(bytes memory voteData)
  internal
  pure
  returns (uint128 againstVotes, uint128 forVotes, uint128 abstainVotes);

castVoteWithReasonAndParamsBySig

Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature. Emits a VoteCast or VoteCastWithParams event depending on the length of params.

If casting a fractional vote via params, the voter's current nonce must be appended to the params as the last 16 bytes and included in the signature. I.e., the params used when constructing the signature would be: abi.encodePacked(againstVotes, forVotes, abstainVotes, nonce) See fractionalVoteNonce and _castVote for more information.

function castVoteWithReasonAndParamsBySig(
  uint256 proposalId,
  uint8 support,
  string calldata reason,
  bytes memory params,
  uint8 v,
  bytes32 r,
  bytes32 s
) public virtual override returns (uint256);

Structs

ProposalVote

struct ProposalVote {
  uint128 againstVotes;
  uint128 forVotes;
  uint128 abstainVotes;
}