Users deposit assets and call joinEvent to select a country, appending their address to usersAddress for participant tracking.
The owner calls setWinner after the event to finalize the winner, calculating totalWinnerShares by looping over usersAddress in _getWinnerShares.
The issue is that joinEvent allows unrestricted repeated calls by the same user, bloating usersAddress with duplicates.
This bloat makes the loop in _getWinnerShares exceed transaction gas limits, causing setWinner to revert due to out-of-gas, preventing event finalization.
Likelihood: High
A user with a deposit repeatedly calls joinEvent before the event starts.
No checks prevent duplicates in usersAddress.
Impact: High
setWinner reverts due to out-of-gas, blocking winner declaration.
All vault assets remain locked indefinitely, preventing withdrawals or event resolution.
Add testDoSOnSetWinner to briVault.t.sol
To verify the cause is out-of-gas ,run forge test --mt testDoSOnSetWinner -vvvv
The mitigation introduces a hasJoined mapping to ensure each user can call joinEvent only once, preventing duplicates in usersAddress. If already joined, it reverts. After a successful join, it sets hasJoined[msg.sender] to true. This keeps the array bounded by unique participants, avoiding gas bloat in _getWinnerShares and enabling setWinner to succeed. For further optimization, consider removing the array if possible or using an enumerable set for uniqueness.
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.