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

Incorrect Reward Distribution to 'For' Voters Locks Remaining Funds in the Contract

Summary

The VootingBooth::_distributeRewards function in the voting smart contract has an issue with the calculation of rewards, resulting in incorrect fund distribution to voters and potential funds getting locked in the contract indefinitely.

Vulnerability Details

The problematic code lies within the VootingBooth::_distributeRewards function, specifically in the calculation of rewardPerVoter. The current calculation divides the totalRewards by totalVotes, which includes all votes (both 'for' and 'against'). This miscalculation leads to incorrect reward distribution to 'for' voters.

Follow the steps below:

  1. Import StdInvariant from forge-std/StdInvariant.sol into VotingBoothTest.t.sol contract for invariant testing.

import { StdInvariant } from 'forge-std/StdInvariant.sol'
  1. Add the StdInvariant to the inheritance. Ensure that StdInvariant is the first in the inheritance chain to avoid Linearization of inheritance graph impossible error.

contract VotingBoothTest is StdInvariant, Test {}
  1. Introduce the following invariant test in the contract.

Code
function invariant_booth_balance_must_be_correct() public view {
if (booth.isActive()) {
assert(address(booth).balance == ETH_REWARD);
} else {
console.log("Voting Booth Balance: ", address(booth).balance);
assert(address(booth).balance == 0);
}
}
  1. The assertion will fail, demonstrating incomplete fund distribution to voters.

Impact

The incorrect calculation in rewardPerVoter impacts the allocation of funds to voters who voted 'for'. Consequently, the remaining funds might not be correctly distributed, potentially resulting in funds getting locked within the contract, as the issue affects the one-time use nature of the contract.

Tools Used

Foundry

Recommendations

  1. Revise the denominator of rewardPerVoter to totalVotesFor:

uint256 rewardPerVoter = totalRewards / totalVotesFor;
  1. Handling Dust:
    Adjust the last voter's reward to avoid leftover funds

if (i == totalVotesFor - 1) {
rewardPerVoter = address(this).balance
}
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.