The GovernorCountingFractional.sol's
quorum logic is broken cause it attempts to only count for
votes for quorum but wrongly specifies it in the COUNTING MODE
First note that the L2 contracts attempt to extend the Governor.sol
in order to now support 3 options faction for vote counting.
This approach is also heavily inspired from Scopelift's scope, see
Now going to the implementation of GovernorCountingFractional
we can see that whereas Zksync claim this code has been copied there are some differences which we can see, for e.g in the implemented approach, only for
votes are counted to quorum, i.e:
This is unlike Scopelift's scope where both for
and abstain votes are counted towards quorum:
The above reason is why in scope lift's case the COUNTING_MODE
was specified as such:
Notice the "support=bravo&quorum=for,abstain¶ms=fractional"
i.e:
support=bravo
quorum=for,abstain
, and
params=fractional
This is correctly implemented, cause when we go to the official Openzeppelin documentation where this all has been inherited from we see the documentation below:
https://docs.openzeppelin.com/contracts/4.x/api/governance#IGovernor-COUNTING_MODE--
COUNTING_MODE() → string - public
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.
Evidently, we can see that whereas Scopelift correctly implements the options, i.e support=bravo
cause they want the three options (for, against and abstain) and also quorum=for,abstain
cause they count both for and abstain votes to quorum, see previously tagged Scopelift's snippet.
However in the case for Zksync we should have the quorum option to be bravo
cause only the for
votes are counted against quorum but this si wrongly implemented cause we have quorum=for
instead breaking the logic
See it in code snippets:
The counting mode against the quorum is wrong leading to wrong accounting of votes as the mode does not align with what's been used tor each quorum and breaks all external integration since the correct vote options can't be shown neither would the results be correctly shown.
Manual review
Apply these changes:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.