Era

ZKsync
FoundryLayer 2
500,000 USDC
View results
Submission Details
Severity: low
Valid

GovernorCountingFractional emitting CastVoteWithReason with ignored support parameter and wrong weight

Summary

When the function castVoteWithReasonAndParams is used to split votes, the event VoteCastWithParams with the support argument is emitted, although this is ignored in this case.

Vulnerability Details

GovernorCountingFractional supports splitting votes between Against/For/Abstain. To do so, _countVote checks if voteData is non-zero. If so, the split is parsed based on this data and the argument support is completely ignored. The function _castVote (within Governor: https://github.com/Cyfrin/2024-10-zksync/blob/cfc1251de29379a9548eeff1eea3c78267288356/zk-governance/l2-contracts/lib/openzeppelin-contracts/contracts/governance/Governor.sol#L581) calls _countVote and afterwards emits an event. If params has length zero, VoteCast is emitted with the support and weight parameters, which is correct when using GovernorCountingFractional (as it also allocates the whole weight to the chosen support value in this case).

However, when the params are non-zero, the event VoteCastWithParams is emitted with the same weight and support parameters. But these parameters are not directly related to the vote in this case. The weight is just the total weight (that can be arbitrarily split, even with multiple calls) and support is completely ignored. Note that the support value could even have invalid values in these events, as it is not verified in _countVoteFractional.

Impact

If an off-chain system (that tracks the voting progress or even makes decision automatically based on it, for instance with a Subgraph) just parses support and weight, it will lead to completely wrong result and would be easily gameable. For instance, someone with weight 10 could vote to times with vote 1 for "against", but always set the support parameter to "for". The off-chain system would then think that this were 100 votes "for", which is wrong. Setting invalid support parameters could also lead to crashes / errors in off-chain systems, as they might only expect the three possible enum values.

Even if an off-chain system is aware of these intricate details, actually parsing the vote result based on the events is hard: You need to decode the params byte array for every VoteCastWithParams event to get the correct votes.

Recommendations

It is recommended to introduce custom events within GovernorCountingFractional that emit the actual voting result directly. This will avoid errors in off-chain systems. The _castVote function could also be overwritten to prevent that these confusing events are emitted.

Updates

Lead Judging Commences

inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GovernorCountingFractional emitting CastVoteWithReason with ignored support parameter and wrong weight

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.