MyCut

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

Missing time validation allows Users to claim rewards after the 90-day period

Missing time validation allows Users to claim Rewards after the 90-day period

Description

The Pot::claimCut() function lacks a time-based validation. As a result, users can claim rewards even after the intended 90-day claim period has elapsed, violating the protocol’s business rules.

Vulnerability Details

The claimCut() function allows users to claim rewards without enforcing the protocol’s 90-day time limit :

function claimCut() public {
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); //no time limit verification
}

Because no timestamp or deadline check is performed, any user with a non-zero reward balance can successfully call claimCut() even after the intended claim period has expired.

This results in a violation of the protocol’s business logic and may lead to unintended reward distribution.

Impact details / Risk

Pot::claimCut() allow users to claim rewards after the 90-day period, reducing the rewards for timely claimants and the owner’s share, contrary to the protocol’s intended redistribution rules, and potentially hurting user trust.

References

https://github.com/CodeHawks-Contests/ai-mycut/blob/main/src/Pot.sol#L37

Recommended mitigation

Add a time-based check in Pot::claimCut() to ensure users can only claim rewards **within the intended 90-day window.

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

Proof of concept

We warp the blockchain timestamp beyond 90 days and then call claimCut() (with player1) to demonstrate that rewards can still be claimed after the intended claim period.

Add this function to your TestMyCut.t.sol file :

function testClaimAfter90Days() public mintAndApproveTokens {
vm.startPrank(user);
contest = ContestManager(conMan).createContest(players, rewards, IERC20(ERC20Mock(weth)), 4);
ContestManager(conMan).fundContest(0);
vm.stopPrank();
// player balance before
uint256 balanceBefore = ERC20Mock(weth).balanceOf(player1);
console.log("Current timestamp:", block.timestamp);
vm.warp(block.timestamp + 91 days);
console.log("Warped timestamp:", block.timestamp);
// player claims after 91 days
vm.startPrank(player1);
Pot(contest).claimCut();
vm.stopPrank();
// player balance after
uint256 balanceAfter = ERC20Mock(weth).balanceOf(player1);
assert(balanceAfter > balanceBefore);
}

Then run :

forge test --mt testClaimAfter90Days -vvvv
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!