Summary
In ContestManager.sol::createContest
doesn't check the rewards and totalRewards, this make ClaimCut may revert because of the overflow when player call the ClaimCut
Vulnerability Details
In ContestManager.sol::createContest
, the sum of all the players’rewards
function createContest(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards)
public
onlyOwner
returns (address)
{
Pot pot = new Pot(players, rewards, token, totalRewards);
contests.push(address(pot));
contestToTotalRewards[address(pot)] = totalRewards;
return address(pot);
}
POC
As show in follow code,The totalRewards
of ContestManager is 2, and the reward of players[player1] is 3, when the player1 call claimCut
, there is a overflow.
function testClosePot_chollima() public mintAndApproveTokens {
vm.startPrank(user);
contest = ContestManager(conMan).createContest(players, rewards, IERC20(ERC20Mock(weth)), 2);
ContestManager(conMan).fundContest(0);
vm.stopPrank();
uint256 balanceBefore = ERC20Mock(weth).balanceOf(contest);
console.log("The contest Before balance is: ", balanceBefore);
vm.startPrank(player1);
vm.expectRevert();
Pot(contest).claimCut();
vm.stopPrank();
}
also, it’s better to check the players’ length and the rewards’length.
Impact
In some situation, the player claimCut could be revert because of overflow.
Tools Used
manual
Recommendations
modify the createContest.
function createContest(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards)
public
onlyOwner
returns (address)
{
if (players.length != rewards.length) {
revert();
}
uint256 rewardsSum;
for (uint256 i = 0; i < rewards.length; i++) {
rewardsSum += rewards[i];
}
if (rewardsSum > totalRewards) {
revert();
}
Pot pot = new Pot(players, rewards, token, totalRewards);
contests.push(address(pot));
contestToTotalRewards[address(pot)] = totalRewards;
return address(pot);
}