Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GovernorCountingFractionalUpgradeable

Inherits: Initializable, GovernorUpgradeable

Extension of {Governor} for fractional voting. Similar to {GovernorCountingSimple}, this contract is a votes counting module for {Governor} that supports 3 options: Against, For, Abstain. Additionally, it includes a fourth option: Fractional, which allows voters to split their voting power amongst the other 3 options. Votes cast with the Fractional support must be accompanied by a params argument that is three packed uint128 values representing the weight the delegate assigns to Against, For, and Abstain respectively. For those votes cast for the other 3 options, the params argument must be empty. This is mostly useful when the delegate is a contract that implements its own rules for voting. These delegate-contracts can cast fractional votes according to the preferences of multiple entities delegating their voting power. Some example use cases include: Voting from tokens that are held by a DeFi pool Voting from an L2 with tokens held by a bridge Voting privately from a shielded pool using zero knowledge proofs. Based on ScopeLift's https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol[GovernorCountingFractional] Available since v5.1.

State Variables

VOTE_TYPE_FRACTIONAL

uint8 internal constant VOTE_TYPE_FRACTIONAL = 255;

GovernorCountingFractionalStorageLocation

bytes32 private constant GovernorCountingFractionalStorageLocation =
    0xd073797d8f9d07d835a3fc13195afeafd2f137da609f97a44f7a3aa434170800;

Functions

_getGovernorCountingFractionalStorage

function _getGovernorCountingFractionalStorage() private pure returns (GovernorCountingFractionalStorage storage $);

__GovernorCountingFractional_init

function __GovernorCountingFractional_init() internal onlyInitializing;

__GovernorCountingFractional_init_unchained

function __GovernorCountingFractional_init_unchained() internal onlyInitializing;

COUNTING_MODE

module:voting

*A description of the possible support values for {castVote} and the way these votes are counted, meant to be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of key-value pairs that each describe one aspect, for example support=bravo&quorum=for,abstain. There are 2 standard keys: support and quorum.

  • support=bravo refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in GovernorBravo.
  • quorum=bravo means that only For votes are counted towards quorum.
  • quorum=for,abstain means that both For and Abstain votes are counted towards quorum. If a counting module makes use of encoded params, it should include this under a params key with a unique name that describes the behavior. For example:
  • params=fractional might refer to a scheme where votes are divided fractionally between for/against/abstain.
  • params=erc721 might refer to a scheme where specific NFTs are delegated to vote. NOTE: The string can be decoded by the standard https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[URLSearchParams] JavaScript class.*
function COUNTING_MODE() public pure virtual override returns (string memory);

hasVoted

module:voting

Returns whether account has cast a vote on proposalId.

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

usedVotes

Get the number of votes already cast by account for a proposal with proposalId. Useful for integrations that allow delegates to cast rolling, partial votes.

function usedVotes(uint256 proposalId, address account) public view virtual returns (uint256);

proposalVotes

Get current distribution of votes for a given proposal.

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

_quorumReached

Amount of votes already cast passes the threshold limit.

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. Executing this function consumes (part of) the delegate's weight on the proposal. This weight can be distributed amongst the 3 options (Against, For, Abstain) by specifying a fractional support. This counting module supports two vote casting modes: nominal and fractional.

  • Nominal: A nominal vote is cast by setting support to one of the 3 bravo options (Against, For, Abstain).
  • Fractional: A fractional vote is cast by setting support to type(uint8).max (255). Casting a nominal vote requires params to be empty and consumes the delegate's full remaining weight on the proposal for the specified support option. This is similar to the {GovernorCountingSimple} module and follows the VoteType enum from Governor Bravo. As a consequence, no vote weight remains unspent so no further voting is possible (for this proposalId and this account). Casting a fractional vote consumes a fraction of the delegate's remaining weight on the proposal according to the weights the delegate assigns to each support option (Against, For, Abstain respectively). 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). This format can be produced using: abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes)) NOTE: Consider that fractional voting restricts the number of casted votes (in each category) to 128 bits. Depending on how many decimals the underlying token has, a single voter may require to split their vote into multiple vote operations. For precision higher than ~30 decimals, large token holders may require a potentially large number of calls to cast all their votes. The voter has the possibility to cast all the remaining votes in a single operation using the traditional "bravo" vote.*
function _countVote(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes memory params)
    internal
    virtual
    override
    returns (uint256);

Errors

GovernorExceedRemainingWeight

A fractional vote params uses more votes than are available for that user.

error GovernorExceedRemainingWeight(address voter, uint256 usedVotes, uint256 remainingWeight);

Structs

ProposalVote

struct ProposalVote {
    uint256 againstVotes;
    uint256 forVotes;
    uint256 abstainVotes;
    mapping(address voter => uint256) usedVotes;
}

GovernorCountingFractionalStorage

Note: storage-location: erc7201:openzeppelin.storage.GovernorCountingFractional

struct GovernorCountingFractionalStorage {
    mapping(uint256 proposalId => ProposalVote) _proposalVotes;
}