MyCut

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

`claimCut` has no 90-day deadline check, so players can claim after the window and even after `closePot`, breaking the time-boxed distribution

Description

Normal behavior: authorized claimants have 90 days to claim; after that the manager closes the pot and the remainder is split among those who claimed in time. Claiming should only be possible during the 90-day window.

Specific issue: claimCut never checks block.timestamp - i_deployedAt < 90 days. A player can therefore claim their original cut at any time, including after the window has closed and after closePot has already run its distribution. closePot also never zeroes remainingRewards, so a late claimCut still finds a non-zero playersToRewards[player], decrements the stale remainingRewards, and pulls tokens from whatever balance is left in the pot (including the funds left locked by finding #1), corrupting the intended accounting and racing the close distribution.

function claimCut() public {
address player = msg.sender;
uint256 reward = playersToRewards[player]; // @> no window check
if (reward <= 0) { revert Pot__RewardNotFound(); }
playersToRewards[player] = 0;
remainingRewards -= reward;
claimants.push(player);
_transferReward(player, reward);
}

Risk

Likelihood:

  • Any player who missed the window can call claimCut afterwards; nothing prevents it.

Impact:

  • The "claim within 90 days or forfeit to in-time claimants" rule is unenforceable; late claimers still take their cut, undermining the incentive design and the post-close balance, and can cause closePot/late-claim transfers to revert on insufficient balance.

Proof of Concept

A player who never claimed calls claimCut after block.timestamp has passed the 90-day mark (and even after closePot); the call succeeds and transfers their reward, proving the window is not enforced.

function test_ClaimAfterDeadline() public {
vm.warp(block.timestamp + 91 days); // window is over
uint256 before = token.balanceOf(players[2]);
vm.prank(players[2]); pot.claimCut(); // should be rejected, but succeeds
assertGt(token.balanceOf(players[2]), before);
}

Recommended Mitigation

Reject claims once the window has elapsed.

function claimCut() public {
+ if (block.timestamp - i_deployedAt >= 90 days) revert Pot__StillOpenForClaim();
address player = msg.sender;
uint256 reward = playersToRewards[player];
...
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!