Skip to content

Fractional Governance Voting #2929

Open
@apbendi

Description

@apbendi

🧐 Motivation

We'd like to implement a version/extension of Governor that enables delegates to distribute their total voting weight fractionally across For/Against/Abstain. There are many possible uses for this, many of them related to allowing owners of governance tokens which are pooled to participate in Governance votes. Take, for example, cUNI community voting.

📝 Details

In current Governor implementations, a delegate assigns all their voting weight to a single choice: For/Against/Abstain. Specifically, this is implemented concretely in the _countVote implementation in GovernorCountingSimple.

We'd like to implement a version that enables the delegate to split their voting weight fractionally. For example, a delegate with a weight of 1,000 might assign 700 to For, 100 to Against, and 200 to Abstain.

One challenge with this idea is that it can't trivially be implemented as an extension to the existing Governor implementation or interface in the same way as GovernorCountingSimple.

Specifically, GovernorCountingSimple implements the virtual _countVotes method, which is itself called by the internals of the concrete Governor.

A hypothetical GovernorCountingFractional faces a challenge here, because there is no where in the signature of _countVotes method to include data about how to fractionalize the votes. The only available parameter is the support parameter, but as a uint8, it's not big enough to hold data about how to split votes between 3 discreet options.

Given this, we'd like some feedback on how we might go about implementing this feature in a way you'd be likely to accept. There are any number of options, but here are a few to consider:

  1. Change the signature of _countVote, and the castVote family of methods, to make support a uint256. With the extra bits, we could pack the vote counts/proportions for each options into the support parameter. This is an easy approach, with minimal surface are for the implementation, but the obvious downside is backwards compatibility as it changes the signatures.
  2. Extend Governor and add a new castWeightedVote family of methods. This works, and contains the fractional voting changes to a single new file, but it feels a bit hacky. The castWeightedVote methods added would exist on the inheriting class, but effectively "redo" much of the functionality from the base Governor. It eschews the benefits of using the inheritance pattern in the first place.
  3. Create a new IGovernorFractional interface and GovernorFractional implementation. In this version, the IGovernorFractional would extend and add fractional voting methods to the IGovernor interface. The GovernorFractional interface would implement the castWeightedVote methods. Finally, a GovernorFractionalCountingSimple implementation would provide a concrete implementation of a new, virtual _countFractionalVote method. Internally, the _countVote implementation could curry to the new _countFractionalVote method for backwards compatibility with the inherited, non-fractional voting methods.

We're totally open to feedback on this feature proposal, along with the best way to go about implement it. We believe this feature could be beneficial to many projects opting for OZ implementations of Governance. We're eager and willing to tackle the implementation ourselves and open a PR, but want to do it in a way that will fit with the rest of the library. Thanks in advance for your consideration!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions