When a user calls cancelParticipation, they should be fully removed from the event. Their assets should be returned, their shares burned, and their entry in the winner-payout calculation should be erased.
The cancelParticipation function only burns the user's shares and returns their assets. It fails to clean up the userSharesToCountry mapping or remove the user from the usersAddress array. This leaves "ghost shares" in the system. When _getWinnerShares is called, it iterates over the usersAddress array and includes these ghost shares in the totalWinnerShares calculation, massively inflating the denominator and diluting the payout for all legitimate winners.
Likelihood:
This is a guaranteed side effect of normal user behavior. Any user who joins and then cancels will poison the share pool for their chosen country.
Impact:
Legitimate winners will receive a diluted payout, as the total pot is divided by an inflated totalWinnerShares. The portion of the payout corresponding to the "ghost shares" becomes permanently locked in the contract, unclaimable by anyone.
This PoC (test_cancelerSharesIfWinStillCounted) demonstrates the attack.
user1 deposits, joins country 0, and then calls cancelParticipation. user1 gets their money back, but their "ghost shares" remain in userSharesToCountry[user1][0] and their address remains in usersAddress.
user2 deposits and joins country 0.
The owner sets country 0 as the winner. _getWinnerShares is called.
The function loops usersAddress (containing user1 and user2) and adds both of their shares, even though user1's shares are "ghosts."
'When user2 withdraws, their payout is calculated with an inflated denominator (shares_user1 + shares_user2), so they only receive a fraction of the funds they are entitled to.
The only robust fix is to add state to track which countryId a user has joined, so cancelParticipation can fully clear their state.
CancelParticipation burns shares but leaves the address inside usersAddress and keeps userSharesToCountry populated.
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.