The VotingBooth contract pays the eth reward to for voters if the proposal was passed, but while calculating rewardPerVoter it also considers the against voters and as the protocol pays eth reward only to the for voters, the remaining amount of eth will get stuck in the VotingBooth contract as the eth reward was reduced by also considering against voters.
As the protocol only pays to the for voters on successful proposal, so the intended implementation should be to calculate reward by only considering for voters and not against voters.
The vulnerability lies inside the VotingBooth contract inside the _distributeRewards function at line 192 and 207 while calculating the rewards that is to be distributed to each for voter.
The function is intended to send eth only to the for voters (when the proposal is successful), but while calculating the rewardPerVoter it also considers the against voters as a result of which the eth to be distributed to each for voter is reduced by against voters and for voters will receive less amount of eth.
The total eth reward in the contract is divided by totalVotes which is a sum of both for voters and against voters, thus reducing the eth amount that is to be sent to the for voters and in the for loop eth is distributed to for voters (which is intended) but as a result of this there will be eth remaining in the contract and it will get permanently stuck in there and there is no way to retrieve it.
Due to wrong implemented _distributeRewards function, it calculates reward to be distributed to for voters also considering the against voters, leading to reduced amount of eth sent to for voters. Thus it will have a impact on the eth amount to be distributed to for voters and it will be less than the expected amount that is to be sent.
Also, as the reward per voter amount is reduced, there will be eth remaining in the VotingBooth contract and it will get permanently stuck in there and there is no way to rescue the remaining eth amount.
Create a new file VotingBoothInvariantTest.t.sol inside the Test folder and add the below test contract inside it.
Run the test:
Here it says the assertion failed. The remaining contract balance is expected to be 0 after voting ends but it is 0.4 eth
Manual Review, Foundry Test, Fuzzy Cat (Meow)
rewardPerVoter correctly by dividing the total rewards by total number of for voters.For line 192
For line 207
for voters by considering the against voters, then remaining balance should be sent back to the s_creatorTherefore consider sending eth to the creator inside the else statement which is at line 191 inside VotingBooth::_distributeRewards() function.
Add the below line just after the for loop inside the else statement discussed above.
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.