The ContestManager.fundContest() function is intended to be called once per contest to transfer totalRewards worth of ERC20 tokens from the admin into the Pot contract. The function should only allow a single funding operation per contest.
However, fundContest() has no state flag to prevent repeated calls. Each invocation transfers totalRewards tokens from the admin to the Pot, regardless of whether the Pot has already been funded. Since the Pot only distributes the original totalRewards amount through claimCut() and closePot(), any excess tokens transferred in subsequent calls are permanently locked in the Pot contract.
Likelihood: Medium
Requires the admin to call fundContest() more than once for the same contest index. While not expected behavior, there is no guard, no event emission, and no warning — an honest mistake or a UI bug could trigger this.
Impact: Medium
The excess transfer amount (totalRewards per extra call) is permanently locked. The Pot has no sweep function and its distribution logic only accounts for the original funded amount.
Severity: Medium
An admin creates a contest with 1000 USDC total rewards. They call fundContest(0) to fund it, then accidentally call fundContest(0) again (e.g., a UI retry after a timeout). The Pot now holds 2000 USDC, but only 1000 USDC is ever distributable through claimCut() and closePot(). The extra 1000 USDC is permanently locked.
Adding a boolean funding guard ensures each contest can only be funded once. This is a standard pattern for one-time operations and prevents both accidental and malicious re-funding.
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.