Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

VotersFor rewards is less than it should be and funds are locked forever due to bad logic implementation

Summary

VotersFor rewards is less than it should be and funds are locked forever due to bad logic implementation in the _distributeRewards() function called internally by vote(). The rewards are calculated as if they were going to be distributed to all the voters, not just the votersFor.

Vulnerability Details

  • Actors:

    • Victims: VotersFor when there are votersAgainst

    • Protocol: the VotingBooth contract

  • Exploit Scenario:

    • Initial State: The Protocol is deployed by its creator who sent 1 ETH as minimum funding and gave as argument a list of 5 voters. Hence when the 3rd voter votes, the voting will be considered complete.

    • Step 1: Victim#1 who is voters[0] in the PoC below votes for the proposal by calling booth.vote(true)

    • Step 2: voters[2] in the PoC below votes against the proposal by calling booth.vote(false)

    • Step 3: Victim#2 who is voters[2] in the PoC below votes for the proposal by calling booth.vote(true)

Impact

  • Outcome: victim#1 gets rewarded 0.33...33 ETH instead of 0.5 ETH and victim#2 gets rewarded 0.33...34 ETH instead of 0.5 ETH. The funds that have not been distributed will remain locked inside the protocol.

  • Implications: Funds will be locked inside the protocol and the voters who voted for the proposol will receive less than they deserve. In the PoC below I assumed the creator sends 1 ether which is the minimum funding, had he send more, the amount of funds locked would increase as well. Voters can predict how much they're owed as nothing is hashed and everything is available onchain and people can read the storage and know who voted for and who voted against the proposal. That would leave them angry at the protocol and the creator.

Tools Used

Manual Analysis and foundry

Recommendations

  • uint256 rewardPerVoter = totalRewards / totalVotes;

  • uint256 rewardPerVoter = totalRewards / totalVotesFor;

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

VotingBooth._distributeRewards(): Incorrect computation of rewardPerVoter

Support

FAQs

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