MyCut

First Flight #23
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Invalid

Users can claim there cut after 90 days as well breaking the main invariant of protocol

Summary

ClaimCut is meant to be called upto 90 days from the time, contest is created. Although lack of time check allows users to claim it any time i.e. after 90 days as well breaks the protocol intended behaviour.

Vulnerability Details

2024-08-MyCut/src/Pot.sol at main · Cyfrin/2024-08-MyCut (github.com)

function claimCut() public {
///@custom:audit no check if user is claiming within 90 days
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);
}

ClaimCut allows eligible users to claim there cut upto 90 days once contest is created. As afterwards remaining funds are meant to distributed as follows:

1) 10% to owner

2) 90% split among all claimants who claimed on time equally.

However, due to lack of check, users can claim the assigned rewards without the 90 days restriction breaking the protocol design.

POC

Add following test in existing test suite:

function testCanClaimCutAfter90Days() 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);
vm.warp(block.timestamp + 91 days);
vm.startPrank(player1);
Pot(contest).claimCut();
console.log("user has claimed after 90 days successfully");
vm.stopPrank();
// player balance after
uint256 balanceAfter = ERC20Mock(weth).balanceOf(player1);
assert(balanceAfter > balanceBefore);
}

then run forge test --mt testCanClaimCutAfter90Days -vv in the terminal, it will show following output:

[⠊] Compiling...
[⠘] Compiling 1 files with Solc 0.8.20
[⠃] Solc 0.8.20 finished in 1.75s
Compiler run successful!
Ran 1 test for test/TestMyCut.t.sol:TestMyCut
[PASS] testCanClaimCutAfter90Days() (gas: 833511)
Logs:
User Address: 0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D
Contest Manager Address 1: 0x7BD1119CEC127eeCDBa5DCA7d1Bd59986f6d7353
Minting tokens to: 0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D
Approved tokens to: 0x7BD1119CEC127eeCDBa5DCA7d1Bd59986f6d7353
user has claimed after 90 days successfully
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.32ms (437.08µs CPU time)

Impact

breaks protocol design

Tools Used

Manual Review

Recommendations

Add a strict time period, as per design, given below:

+ error Pot__ClaimIsClosed();
function claimCut() public {
+ if (block.timestamp - i_deployedAt > 90 days) {
+ revert Pot__ClaimIsClosed();
+ }
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

equious Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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