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

Wrong formula to calculate `rewardPerVoter` when proposal passed. Certain amount of ETH can remain in the contract forever

Summary

Wrong formula to calculate rewardPerVoter when proposal passed. Certain amount of ETH can remain in the contract forever

Vulnerability Details

In VotingBooth::_distributeRewards() function, in case the proposal passed, the eth reward should be distributed to all "For" voters equally. Hence the formula for calculating the rewardPerVoter should be as follows:

rewardPerVoter = totalRewards / totalVotesFor;

Instead it is as follows:

rewardPerVoter = totalRewards / totalVotes;

Impact

In case when:

  1. the proposal passed (there are more voters for than against) and

  2. there is at least one voter against

not all of the reward will be distributed to the "For" voters, and totalRewards/totalVotes * (totalVotes - totalVotesFor) of eth will remain in the contract after distribution is finished.

Tools Used

Changing the existing test function testVotePassesAndMoneyIsSent() so that address(0x3) votes against will cause the test to fail.
I additionally added console2.log to see the balances

function testVotePassesAndMoneyIsSent() public {
vm.prank(address(0x1));
booth.vote(true);
vm.prank(address(0x2));
booth.vote(true);
vm.prank(address(0x3));
+ booth.vote(false);
- booth.vote(true);
+ console2.log("Booth balance: ", address(booth).balance);
+ console2.log("Voter 1 balance: ", address(0x1).balance);
+ console2.log("Voter 2 balance: ", address(0x2).balance);
+ console2.log("Voter 3 balance: ", address(0x3).balance);
assert(!booth.isActive() && address(booth).balance == 0);
}

The result will be:

Booth balance: 3333333333333333333
Voter 1 balance: 3333333333333333333
Voter 2 balance: 3333333333333333334
Voter 3 balance: 0

Recommendations

Consider changing the following lines in the function _distributeRewards():

- uint256 totalVotes = totalVotesFor + totalVotesAgainst;
+ uint256 rewardPerVoter = totalRewards / totalVotesFor;
- uint256 rewardPerVoter = totalRewards / totalVotes;
if (i == totalVotesFor - 1) {
rewardPerVoter = Math.mulDiv(
totalRewards,
1,
+ totalVotesFor,
- totalVotes,
Math.Rounding.Ceil
);
}
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.