Description
🧐 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:
- Change the signature of
_countVote
, and thecastVote
family of methods, to makesupport
a uint256. With the extra bits, we could pack the vote counts/proportions for each options into thesupport
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. - 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. ThecastWeightedVote
methods added would exist on the inheriting class, but effectively "redo" much of the functionality from the baseGovernor
. It eschews the benefits of using the inheritance pattern in the first place. - 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, aGovernorFractionalCountingSimple
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!