getActivePlayerIndex() returns 0 in two indistinguishable situations — the player genuinely at index 0, and "address is not a player at all" (lines 110-117):
The function's documented purpose is locating the index for refund(playerIndex). A UI or integration that looks up a non-player address receives 0 — the same value as a real index-0 player — and may then call refund(0). Instead of reverting on a bad lookup, the caller silently operates on the wrong player: whoever sits at index 0 gets their ticket refunded to someone else's msg.sender... and in fact refund(0) would then revert on the playerAddress == msg.sender check — but only by luck of the access control, not by the lookup failing loudly. Any future caller that trusts the index without re-validating acts on the wrong player with no warning.
Likelihood: Low — requires an integrator to trust the return value without a separate membership check.
Impact: Low — no direct fund loss inside the contract today, but a classic footgun: silent wrong-index operations instead of an explicit failure.
The Foundry test below demonstrates the ambiguity directly:
Test assertions and measured result (forge test --match-test test_PoC_L1_GetActivePlayerIndexAmbiguous):
Fail loudly on a missed lookup instead of returning a value that collides with a valid index. Reverting (or returning a sentinel like type(uint256).max that can never be a real index) turns the silent wrong-player footgun into an explicit, catchable failure — integrators can no longer accidentally act on index 0.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.