The issue emerges after a proposal's approval during the voter reward calculation process. It stems from the formula used to calculate the reward per voter, which is the division of total rewards by the total number of votes. This total vote count is the sum of totalVotesFor and totalVotesAgainst.
https://github.com/Cyfrin/2023-12-Voting-Booth/blob/main/src/VotingBooth.sol#L172
uint256 totalVotes = totalVotesFor + totalVotesAgainst;
The total reward is divided by the sum of totalVotesFor and totalVotesAgainst, inadvertently including voters ineligible for rewards.
https://github.com/Cyfrin/2023-12-Voting-Booth/blob/main/src/VotingBooth.sol#L192
uint256 rewardPerVoter = totalRewards / totalVotes;
Consider a practical scenario: A proposal is funded with 10 ether and 7 voters are allowed to vote. It passes with 3 'for' votes and 1 'against' vote. According to the formula, the reward per voter is calculated as 2.5 ether (10 ether / 4 votes). This results in each 'for' voter receiving 2.5 ether, leaving 2.5 ether unclaimed. Due to the lack of a withdrawal mechanism in the VotingBooth contract, this remaining reward becomes inaccessible and is effectively locked within the contract.
Import console and StdInvariant inside VotingBoothTest.t.sol:
Copy and paste the following inside VotingBoothTest.t.sol::VotingBoothTest::setUp
Copy and paste the function invariant_testAllMoneySentAfterProposalPassesOrReturnedAfterDefeated() inside VotingBoothTest.t.sol::VotingBoothTest
Run forge test --mt invariant_testAllMoneySentAfterProposalPassesOrReturnedAfterDefeated -vv in the terminal.
'for' voters rewards are diluted and the residual rewards are locked in the VotingBooth contract.
Foundry
Consider calculating the reward per voter by dividing the total rewards by the total 'for' votes to avoid leaving unallocated funds locked in the 'VotingBooth' contract.
If the 'for' voters rewards dilution is intentional, implement a withdraw function that can be called by the owner after the proposal ends.
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.