MyCut

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

## M-1 — No closed state and no claim upper time bound

Root + Impact

The 90-day window is enforced only in closePot. claimCut has neither an upper time bound nor a closed-state check, so it is callable forever. Because close pays residual only to the claimants set, a player can claim after day 90 but before close (front-running it) to enter that set. Players who never claimed before the close are then locked out because the pot no longer holds enough to pay their reward.

Description

// src/Pot.sol
function claimCut() public {
address player = msg.sender;
uint256 reward = playersToRewards[player];
if (reward <= 0) {
revert Pot__RewardNotFound();
}
// @> no block.timestamp check, no closed flag
playersToRewards[player] = 0;
remainingRewards -= reward;
claimants.push(player); // @> joining the claimant set unlocks residual share
_transferReward(player, reward);
}

Risk

Likelihood: Any player can time a claim after the window and immediately before close.

Impact: Value extraction by ordering; late claimants' rewards become unpayable (revert on insufficient balance).

Proof of Concept

// test/Exploits.t.sol
function testClaimAllowedAfterWindow() public {
Pot pot = _createFundClose(100e18, 100e18, 200e18);
vm.warp(block.timestamp + 365 days);
vm.prank(alice);
pot.claimCut(); // succeeds despite the 90-day claim window
assertEq(token.balanceOf(alice), 100e18);
}
​
function testLateClaimantRevertsAfterClose() public {
uint256 total = 200e18;
Pot pot = _createFundClose(100e18, 100e18, total);
​
vm.prank(alice);
pot.claimCut();
​
vm.warp(block.timestamp + 91 days);
vm.prank(owner);
manager.closeContest(address(pot));
​
assertEq(pot.checkCut(bob), 100e18);
vm.prank(bob);
vm.expectRevert();
pot.claimCut();
}

Recommended Mitigation

function claimCut() public {
+ if (i_closed) revert Pot__Closed();
+ if (block.timestamp - i_deployedAt >= 90 days) revert Pot__ClaimWindowOver();
address player = msg.sender;
...
}

Updates

Lead Judging Commences

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