Summary
There is possible for players to claim their rewards even after owner of protocol call closePot
function.
Vulnerability Details
According to protocol documentation, there is allowed for claimants 90 days to claim before the manager close the pot. However, there is no check for time passed inside the Pot:claimCut
function and due to another bugs in closePot
function, there will still be balance after pot is closed.
PoC
Add following to test file and run test.
function testPlayerCouldClaimAfterPotClosed() public mintAndApproveTokens {
address player3 = makeAddr("player3");
address player4 = makeAddr("player4");
address player5 = makeAddr("player5");
address player6 = makeAddr("player6");
address player7 = makeAddr("player7");
players = [player1, player2, player3, player4, player5, player6, player7];
rewards = [50, 20, 60, 40, 35, 55, 99];
totalRewards = 1000;
vm.startPrank(user);
contest = ContestManager(conMan).createContest(players, rewards, IERC20(ERC20Mock(weth)), totalRewards);
ContestManager(conMan).fundContest(0);
vm.stopPrank();
vm.prank(player1);
Pot(contest).claimCut();
vm.prank(player3);
Pot(contest).claimCut();
vm.warp(91 days);
vm.prank(user);
ContestManager(conMan).closeContest(contest);
vm.prank(player2);
Pot(contest).claimCut();
vm.prank(player6);
Pot(contest).claimCut();
}
Impact
Players could still claim their rewards when pot is closed.
Tools Used
Manual review.
Recommendations
Add some check to claimCut
function to prevent claiming after pot is closed.
++ error Pot__PotIsClosed();
function claimCut() public {
++ if (block.timestamp > i_deployedAt + 90 days) {
++ revert Pot__PotIsClosed();
++ }
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);
}