Quadratic voting

Hi guys,
I am implementing quadratic voting in addition to token weighted voting for a token and finding the ERC20Votes design flawed for that purpose. This is because in order to implement a different vote weight tally I will need to take out the moveVotingPower logic and tallies out of the token and refactor into a separate component. Even that is difficult as I will need to comply with the IVotes interface (in order to be able to use GovernorVotes in the governor. Complying with IVotes is impossible outside the token due to the delegate(address) function requirement which works with msg.sender only which in turn works within the token only.
Checking whether this was intended design? And also whether casting between a currently compatible interface and IVotes will be safe enough for future versions.

Can you explain in more depth how you plan to implement quadratic voting?

I don't see how taking moveVotingPower out of the token is possible, given that you need to trigger it in every token transfer.

Perhaps the design you're going for is so different that it shouldn't be based on ERC20Votes, or GovernorVotes even.

Yes I can best illustrate with an example for calculating quadratic voting power in a delegation enabled governance:
If person A holding X tokens and person B holding Y tokens have delegated their tokens to person C, person C's voting power in a QV vote should be calculated as square root(X)+square root(Y).

Are you sure you want the power to be sqrt(X)+sqrt(Y) and not sqrt(X+Y) ?

With your formula, if I have N tokens, I'm incentivized to create N wallets, give each wallet 1 token, and delegate all that to the same voter. IMO that is a bad incentive.

This is normal under the quadratic voting model. It's why it requires a sybil resistance mechanism. This is why Gitcoin for example has created Gitcoin Passport.

1 Like

Should that be part of the token logic ? It definitely feels like its more than ERC20+ERC5805

In ERC5808 you are bundling the concepts of delegation with that of token weight. Looking at it that way we could argue that OZ's implementation is only supporting delegation with 1-token-1-vote. However if you want to open the governance templates to be more flexible in calculating vote weights, I think it'll suffice to
a) Change IVotes to not rely on the implementation being within the token. This is only blocked by the delegate function. This will allow people to plug in alternate token implementations in the GovernorVotes except the token.
b) Not necessarily required but would be nice to unbundle the token from the voting implementation. Normally tokens aren't upgradable and vote counting mechanisms are.

My working implementation atm using as much of the OZ infrastructure as possible is here https://github.com/0xProject/protocol/pull/641

I don't think we expect IVotes to cover the full range of things that can be done with vote weight tracking and counting.

Our thinking is that if something doesn't fit in that interface, instead of using GovernorVotes you should go with writing your own alternative Votes module for the Governor, which basically means a custom _getVotes function that may not source from an IVotes token at all. In addition to that you could also have a custom Counting module (instead of GovenorCountingSimple). Have you looked into this approach as an alternative to customizing the voting token itself?

I will also point out the "params" system that can be used for more advanced Votes and Counting modules. This is for example how we can support ERC721 tokens that do not have vote tracking built in. (This is a module we will provide in the near future.) We don't have a guide for using params at the moment but I think it can be useful for quadratic voting.

The reason that delegation and token weight tracking are bundled together is to avoid an unbounded iteration through the list of delegators to add up delegated votes. Does this make sense?

I can surely reimplement the governor modules like GovernorVotes and GovenorCountingSimple but since I've already decomposed the ERC20Votes and IVotes that will leave me with almost no OOB OZ code, effectively meaning implementations of QV are not supported in OZ contracts library. I think it should be made clear in the docs that no other vote counting mechanisms are supported OOB except for 1-token-1-vote.

We are interested in supporting QV and other forms of vote counting out of the box, but needed more research to be done. What sybil resistance mechanism are you planning to use?