MyCut

AI First Flight #8
Beginner FriendlyFoundry
EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

Pot Can Be Closed Multiple Times Resulting in Duplicate Reward Distribution.

Root + Impact

Description

Function https://github.com/CodeHawks-Contests/ai-mycut/blob/819134663950999ca5ab29a91eeceddb80274743/src/Pot.sol#L49 contains no state variable indicating that the pot has already been finalized.
function can therefore be called repeatedly.
Each execution performs:
manager fee transfer
redistribution to all claimants
using the same remainingRewards value.
Since remainingRewards is never updated after redistribution, every subsequent call attempts to distribute the same rewards again.
// Root cause in the codebase with @> marks to highlight the relevant section

Risk

Likelihood:


Impact:

If sufficient tokens exist inside the contract (accidental transfers, fee-on-transfer behavior, or malicious deposits), claimants can repeatedly receive redistribution rewards.
The function violates the protocol invariant that a contest should only be finalized once.

Proof of Concept

remainingRewards = 1000
claimants = [Alice, Bob]
Owner calls
closePot()
Alice and Bob receive redistribution.
Owner calls
closePot()
again.
Alice and Bob receive redistribution again.
The contract has no protection against repeated execution.
function test_closePotTwice() public {
address contests;
uint256 player2BalB4 = weth.balanceOf(player2);
console.log("Player 2 Initial Balance:", player2BalB4);
vm.startPrank(owner);
contests = _contestManager.createContest(players, rewards, IERC20(ERC20Mock(weth)), 4);
_contestManager.fundContest(0);
vm.stopPrank();
vm.warp(100 days);
vm.startPrank(player2);
Pot(contests).claimCut();
vm.stopPrank();
vm.startPrank(owner);
_contestManager.closeContest(contests);
vm.stopPrank();
vm.startPrank(owner);
_contestManager.closeContest(contests);
vm.stopPrank();
uint256 player2BalAF = weth.balanceOf(player2);
console.log("Player2 Balancing After Pot closed:", player2BalAF);
assertGt(player2BalAF, player2BalB4);
}

Recommended Mitigation

Introduce a finalized flag, before performing any transfers.
bool public closed; + add this code
require(!closed); + add this code
closed = true; + add this code
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 1 day ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!