The formula used in _distributeRewards() to calculate rewards when a proposal is passed is incorrect. Voters may be rewarded less than they should be. Ether may be left in the contract with no way to get it back.
According to the rules of the VotingBooth contract, the reward is distributed among the for voters if the proposal passes. for voters are the only recipients of the Ether reward. Each for voter receives an equal share of the reward.
The test testVotePassesAndMoneyIsSent() shows that the rules of the contract are being followed when the quorum has been reached and when all the voters voted in favour of the proposal. However, if we write a fuzzing test (see Recommendation #2) or change testVotePassesAndMoneyIsSent(), e.g. like this:
It will fail.
The error occurs because the reward distribution formula is not entirely correct. The expression:
Takes into account all the votes. However only for votes must count. A similar error is encountered during the last voter's reward calculation:
The error causes those who for-voted to receive less Ether than they should. For example, if 3 of 5 voted in favour, they get totalRewards / 5 ETH, although they should get totalRewards / 3 ETH. This also results in some of the ether remaining in the smart contract. See the example with comments below:
To correct the error totalVotes must be replaced by totalVotesFor (see Recommendation #1).
Once the fix is in place, it's also safe to remove the totalVotes variable because it's not being used anywhere else in the code.
High:
Voters might not be rewarded as expected by the rules.
It will not be possible to retrieve any ether left in the contract.
Manual check
Fuzzing test
Formula for rewardPerVoter must be changed in two places:
Integrate fuzzing tests into the test suite. For example, the following fuzzing test can be used to easily find the vulnerability by using automatic substitution of different combinations of boolean values in vote1, vote2 and vote3 during each test run:
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.