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.
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?