Closing a pot is meant to be a one-time finalization: take the manager cut and distribute the leftover, once. After that the pot should be closed. The problem is that closePot() never marks the pot as closed and never resets remainingRewards. Since remainingRewards keeps its value, the owner can call closePot (via ContestManager.closeContest) multiple times. Each call re-computes and re-transfers the manager cut and the claimant shares, draining the contract's balance far beyond the intended single distribution.
Likelihood:
The owner (ContestManager) can call closeContest -> closePot any number of times after the 90-day period; nothing prevents repeated calls.
Impact:
Each repeated call transfers the manager cut and claimant shares again, based on the stale remainingRewards, draining the pot's token balance.
Funds intended for a single distribution are paid out multiple times until the contract is emptied (later calls revert once balance is insufficient), corrupting all accounting.
Note: demonstrates that closePot has no "closed" flag and never resets remainingRewards, so closeContest -> closePot can be called repeatedly, re-paying the manager cut (and claimant shares) each time until the pot is drained. The missing state reset is evident from the source.
Reset remainingRewards to 0 after distribution (and/or add a closed boolean set once). This makes closePot idempotent and prevents repeated payouts.
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.