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

"Inaccurate Reward Distribution in VotingBooth Contract Results in Unintended Ether Loss"

Summary

The contract suffers from a critical vulnerability in the reward distribution mechanism during the _distributeRewards process. The flaw arises from an inaccurate calculation of the rewardPerVoter, where the total rewards are divided by the combined number of votes ('For' and 'Against'). This oversight leads to an unequal distribution of ETH rewards among voters, with excess ETH being locked in the contract. The vulnerability undermines the core functionality of the contract, impacting the fairness and reliability of the voting reward system.

Vulnerability Details

In the _distributeRewards function, the calculation of rewardPerVoter is flawed. The division of totalRewards by totalVotes is used to determine the reward for each voter. However, this approach results in an inaccurate distribution, as it fails to consider the distinction between For and Against votes. The flawed logic leads to an uneven distribution of rewards, leaving excess ETH locked in the contract.

Impact

The impact of this vulnerability is significant, affecting the fairness and reliability of the voting reward system. As a consequence, voters receive an incorrect share of the rewards, leading to potential disputes and a loss of trust in the contract's intended functionality. Additionally, the excess ETH locked in the contract may be perceived as an economic inefficiency.

Tools Used

The analysis was conducted through manual code review and testing scenarios, including a test case designed to demonstrate the flawed reward distribution.

function testVotePassesAndMoneyIsSent() public {
vm.prank(address(0x1));
booth.vote(true);
vm.prank(address(0x2));
booth.vote(true);
vm.prank(address(0x3));
booth.vote(false);
assert(!booth.isActive() );
// shoud fail
vm.expectRevert();
assert(address(booth).balance == 0);
}

Recommendations

To address this vulnerability, the contract's reward distribution mechanism should be redesigned. The calculation of rewardPerVoter needs to account for the total number of voters who voted For the proposal rather than considering all votes collectively. A more accurate calculation would involve dividing totalRewards by totalVotesFor. Additionally, it is recommended to handle any remainder in a controlled manner to avoid leaving excess ETH locked in the contract.

Example Fix:

uint256 rewardPerVoter = totalRewards / totalVotesFor;
// Distribute rewards to voters 'For' the proposal
for (uint256 i; i < totalVotesFor; ++i) {
_sendEth(s_votersFor[i], rewardPerVoter);
}

By making these adjustments, the contract can ensure a fair and accurate distribution of rewards based on the number of votes 'For' the proposal.

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.