MyCut

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

Users can claim rewards after the 90-day deadline, harming other claimants and the owner.

Root + Impact

claimCut() has no block.timestamp check. Users can claim rewards after 90 days until the owner calls closePot(). These late-claimed rewards should have been distributed between the owner and the claimants who claimed on time.

Severity

Medium

Likelihood

Medium

Description

  • claimCut() should only allow claiming rewards within a 90-day window. After that period, no one should be able to claim.

  • However, no time check is implemented. This allows claiming after 90 days, breaking the intended protocol behavior and preventing the owner and on-time claimants from receiving their share of unclaimed rewards.

function claimCut() public {
@> // missing check: if (block.timestamp > i_deployedAt + 90 days) revert();
address player = msg.sender;
uint256 reward = playersToRewards[player];
if (reward <= 0) {
revert Pot__RewardNotFound();
}
playersToRewards[player] = 0;
remainingRewards -= reward;
claimants.push(player);
_transferReward(player, reward);
}

Risk

Likelihood:

  • Occurs in every deployed Pot contract. No complex attack required.

Impact:

  • Breaks the intended behavior described in the documentation.

  • The owner and on-time claimants lose part of the unclaimed rewards, or remainingRewards can even reach 0.

Proof of Concept

This test shows how a player can call claimCut() after 90 days, causing remainingRewards to reach 0 and the owner to receive nothing.

function test_Players_Can_ClaimCut_After_Deadline() public {
// There are 4 players, 1 weth each
// 3 players call claimCut() before the deadline
address[3] memory pClaim = [player1, player3, player4];
for (uint256 i; i < pClaim.length; i++) {
vm.prank(pClaim[i]);
pot.claimCut();
}
// Advance time past 90 days
vm.warp(block.timestamp + 90 days + 5);
uint256 remaninRewardsBefore = pot.getRemainingRewards();
// remainingRewards before player2 claims after the deadline
console.log("remainingRewards within deadline:", remaninRewardsBefore);
// Player2 calls claimCut() after the deadline
vm.prank(player2);
pot.claimCut();
uint256 remaninRewardsAfter = pot.getRemainingRewards();
// remainingRewards after player2 claims after the deadline
console.log("remainingRewards after deadline:", remaninRewardsAfter);
// Owner closes the pot
vm.prank(ownerContest);
contest.closeContest(address(pot));
// ContestManager balance is 0 - owner receives nothing
assertEq(weth.balanceOf(address(contest)), 0);
}
Logs:
remainingRewards within deadline: 1000000000000000000
remainingRewards after deadline: 0

Recommended Mitigation

Add a time check to prevent players from claiming after the 90-day deadline.

+ error Pot__ClaimPeriodOver();
function claimCut() public {
+ if (block.timestamp > i_deployedAt + 90 days) revert Pot__ClaimPeriodOver();
address player = msg.sender;
uint256 reward = playersToRewards[player];
if (reward <= 0) {
revert Pot__RewardNotFound();
}
playersToRewards[player] = 0;
remainingRewards -= reward;
claimants.push(player);
_transferReward(player, reward);
}
Updates

Lead Judging Commences

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