The quorum check in the vote function does not calculate properly causing premature distribution that will leave an unrecoverable balance of tokens stuck in the contract.
The conditional statement to end and distribute tokens is checked after each vote.
It requires total Current Votes divided by the total Allowed Voters be greater than 51%, however this does not establish a quorum.
Instead, it will end and distribute tokens after more than half of the voters have submitted a vote before reaching a quorum on position.
ie: if there are 5 voters so the votes should need 3 YES or 3 NO to conclude.
2 vote YES, 1 votes NO. 2 have not voted, the fourth vote can tie the standings 2-2 and a fifth vote would be required.
However, after 2 YES, 1 NO : 3 votes and 5 are voting so according to the conditional statement 3/5 would be >= 51% thus ending the voting booth.
*The reward gets distributed to the 2 YES votes but on calculating _distributeRewards(), 1 share of the distribution stays locked in the contract.
(simplified)
3 votes occurred so the total Reward is divided by 3.
Only the addresses that voted FOR are sent ETH, since they are included in the s_votersFor array but there are only 2 of them.
The third third remains locked in the contract.
The vote is ended prematurely, without reaching a true consensus.
If approved, a share of tokens will stay locked inside the contract with no way to recover them after distribution occurs.
Foundry
Depending on the intended functionality, to prevent tokens from getting stuck in the contract:
The denominator in rewardPerVoter formula should be changed to the length of the s_votersFor array.
Keep the denominator the same but send the final third, remaining balance, to the creator address when VotingBooth closes.
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.