Several lower-severity issues. Each is individually best-practice / robustness / edge-case, but several compound the High and Medium findings reported separately.
Unchecked ERC20 return values — Pot.sol (i_token.transfer in claimCut / closePot / _transferReward) and ContestManager.fundContest (transferFrom) ignore the bool return. A token that returns false instead of reverting would mis-account (credit/claim without moving funds). Use SafeERC20.
No players.length == rewards.length check in the Pot constructor — a mismatch either reverts at deploy (DoS) or silently truncates the reward set.
No rescue/withdraw path anywhere — combined with the rounding/denominator issues, any residual balance (especially the ~90% stranded when nobody claims) is permanently unrecoverable.
fundContest has no double-funding guard — the owner can fund the same contest repeatedly, over-transferring tokens with no accounting of what was already sent.
Pot is never funded at construction (the i_token.transfer is commented out); nothing on-chain ties funding to the lifecycle, so an unfunded Pot makes claimCut/closePot revert on transfer.
Whole-distribution DoS — closePot's loop reverts entirely if any one claimant cannot receive the token (e.g. a blocklist token), blocking the payout for everyone.
Dead reward <= 0 check on a uint256 (true only when reward == 0); the constructor also has no zero-address or duplicate-player guard, and duplicate players inflate i_players.length, worsening the denominator bug.
Likelihood:
Most require a specific trigger — a non-reverting or blocklist token, an owner input mistake (mismatched arrays, double funding), or a zero/duplicate address — rather than an arbitrary attacker, so each is individually low likelihood.
Impact:
Individually low (best-practice / robustness / edge-case griefing), but several compound the High/Medium findings: the unchecked transfers, the absent rescue path, and duplicate players all amplify the fund-loss issues reported separately.
Illustrative snippets from the in-scope code — these are unchecked / dead-code paths, no exploit transaction required:
Use SafeERC20 for all token moves; validate players.length == rewards.length, reject zero addresses and duplicate players; add a rescue/sweep; guard fundContest against re-funding; fund the Pot as part of creation; and prefer pull-payments (or skip-on-failure) in the distribution loop.
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.