VotingBooth
pays a reward to the for
voters if the proposal passes, otherwise refunds the reward to the creator. In order for the proposal to pass, it needs to have more for
votes than against
. The system of voting doesn't require a strict majority to pass the proposal, it just requires the quorum to be reached (enough people to vote).
The problem arises when the for
votes win, some voters voted against
, and the rewards are calculated. Instead of equally dividing the reward pot between the for voters, it is dividing the reward between all users that votes (even though only the ones that voted for
will end up receiving the reward). This wrong calculation of the rewards per voter could leave funds stuck in the contract.
The rewardPerVoter
calculation on line 192 of the VotingBooth.sol
(https://github.com/Cyfrin/2023-12-Voting-Booth/blob/a3241b1c530529a4f739f9462f720e8561ad45ca/src/VotingBooth.sol#L192) is incorrect. The rewards are divided between the total number of votes and not the "for" voters.
If the voting booth has at least one against
voter, the ETH reward paid out to for
voters will be less than the total reward amount held by the VotingBooth
contract and the missing balance will be permanently stuck inside the VotingBooth
contract.
Foundry.
Add the following test function to the VotingBoothTest.t.sol
file and run forge test -vvvv --mc VotingBoothTest --mt testExploit
to see the exploit steps and result.
Consider changing the rewardPerVoter
calculation on line 192 of the VotingBooth.sol
(https://github.com/Cyfrin/2023-12-Voting-Booth/blob/a3241b1c530529a4f739f9462f720e8561ad45ca/src/VotingBooth.sol#L192) as shown below so the rewards are divided between the "for" voters and not the total number of votes:
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.