closePot() reads remainingRewards to size the manager cut and the claimant cuts, but it never writes the variable (or any closed flag) back. The 90-day time check stays satisfied forever, so the owner can call closeContest on the same pot again and again. Every call pays a fresh 10% manager cut and a fresh round of claimant cuts computed from the original, stale remainingRewards, draining the leftover balance left behind by the distribution (which the divisor bug in this same function guarantees is substantial). One pot's closing distribution can be paid out three times in the verified PoC, limited only by the token balance physically remaining.
Likelihood: Medium - requires the trusted owner (or any automation driving it) to call close more than once, whether by mistake, by a duplicated transaction, or deliberately; the contract offers no protection at all against it.
Impact: Medium - the pot's remaining balance, which by the documented rules belongs to a single final distribution, can be paid out repeatedly to the manager and past claimants until it is gone, leaving nothing for the intended one-time settlement and corrupting the contest's final accounting.
Verified with Foundry (test passes). Same 100-token, 4-player pot, one claimant. The owner closes the pot three times. The manager cut of 7.5 is paid three times (22.5 total) and the claimant cut of 16.875 is paid three times, while getRemainingRewards() still reports the untouched 75 after all three closes.
Settle the state inside closePot: zero remainingRewards (and record a closed flag) before making the transfers, so any later call sees nothing left to distribute.
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.