NORMAL BEHAVIOUR:
When finalizing the event, the contract should compute the total shares for the winning country in a gas-bounded, reliable manner (constant time or bounded iterations), or use an aggregation model that avoids looping across an unbounded user list inside a single transaction.
PROBLEM :
_getWinnerShares() iterates over usersAddress (which grows with each joinEvent) and increments a storage variable totalWinnerShares inside the loop. Because usersAddress can be arbitrarily large and duplicates are possible, this function is unbounded and can exceed block gas limits. If setWinner() calls _getWinnerShares() and gas is exceeded, setWinner() will revert — the contract owner cannot finalize the winner and finalizedVaultAsset is not set, meaning withdraw() cannot succeed. An attacker can spam joinEvent() (or join multiple times if duplicates allowed) to permanently prevent finalization.
Likelihood:
High: any large real user base creates many entries; duplicates amplify the issue.
High: an attacker with small deposits can spam joinEvent or exploit lack of hasJoined to create many entries cheaply.
Impact:
Owner cannot call setWinner() as it will revert due to gas exhaustion → finalizedVaultAsset never set → withdraw() cannot be executed by winners → funds locked.
if _getWinnerShares() partially succeeds or is callable multiple times without reset, totalWinnerShares may be incorrectly inflated, leading to wrong payouts.
Contract expects to iterate userAddress length N.
If N is large enough such that gasPerIteration *N > block gas limit (~30M), the loop will run out of gas and revert.
Attacker can, from a single EOAs or many low-value deposits, call joinEvent() repeatedly (if duplicate protection missing) to increase userAddress length to N causing setWinner() to revert.
Primary strategy (best): Maintain per-country aggregate share counts during join — O(1) updates — eliminate need to iterate at finalization. Also prevent duplicate joins.
The _getWinnerShares() function is intended to iterate through all users and sum their shares for the winning country, returning the total.
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.