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

Tokens stuck after approval distribution

Summary

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.

Vulnerability Details

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.

if (totalCurrentVotes * 100 / s_totalAllowedVoters >= MIN_QUORUM) {
// mark voting as having been completed
s_votingComplete = true;
// distribute the voting rewards
_distributeRewards();
}

(simplified)

function _distributeRewards(){
uint256 rewardPerVoter = totalRewards / totalVotes;
_sendEth(s_votersFor[i], rewardPerVoter);
}

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.

Impact

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.

Tools Used

Foundry

Recommendations

Depending on the intended functionality, to prevent tokens from getting stuck in the contract:

  1. The denominator in rewardPerVoter formula should be changed to the length of the s_votersFor array.

  2. Keep the denominator the same but send the final third, remaining balance, to the creator address when VotingBooth closes.

Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice
TrillionX Submitter
over 1 year ago
0xnevi Lead Judge
over 1 year ago
TrillionX Submitter
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice
TrillionX Submitter
over 1 year ago
0xnevi Lead Judge
over 1 year ago

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.