Normally, cancelParticipation() should remove a participant from the event and adjust all related state variables accordingly.
The current implementation burns the participant's shares and refunds their staked assets, but it does not remove the participant from usersAddress, does not decrement totalParticipantShares, and does not clear userSharesToCountry, which can lead to incorrect winner share calculations and inflated totals.
Likelihood:
Users cancel their participation before the event start and then the _getWinnerShares() function is called after the event ends.
Users can deposit, join, cancel, and rejoin multiple times, leading to duplicate entries in usersAddress.
Impact:
Overestimation of totalWinnerShares or totalParticipantShares.
Incorrect payouts to winners due to canceled participants still being counted.
Potential manipulation of the system by repeatedly joining/canceling.
Update usersAddress to remove canceled participants.
Adjust totalParticipantShares when a user cancels.
Clear userSharesToCountry for that user.
Consider using a mapping-based replacement for usersAddress to make removal O(1) and reduce gas cost for large events.
Note: Using a mapping-based structure such as mapping(address => bool) joined or mapping(address => uint256) userIndex could replace the usersAddress array to allow constant-time removal, improving gas efficiency for large participant sets.
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.