Impact
The constructor of the Pot.sol does not verify that the totalRewards matches the sum of individual rewards. This could result in an incorrect funding scenario where the total amount allocated for rewards is less than the sum of all individual rewards specified. This discrepancy can lead to financial losses, disputes among users, or failures in reward distribution, undermining the contract's functionality and security.
Proof of Concept
Pot.sol:22@>
constructor(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards) {
i_players = players;
i_rewards = rewards;
i_token = token;
i_totalRewards = totalRewards;
remainingRewards = totalRewards;
i_deployedAt = block.timestamp;
for (uint256 i = 0; i < i_players.length; i++) {
playersToRewards[i_players[i]] = i_rewards[i];
}
}
Test1:
function testCanCreatePotEvenIfTheTotalRewardsIsLessThenIndivitualRewards() public mintAndApproveTokens {
console.log("Contest Manager Owner: ", ContestManager(conMan).owner());
console.log("msg.sender: ", msg.sender);
vm.startPrank(user);
contest = ContestManager(conMan).createContest(players, rewards, IERC20(ERC20Mock(weth)), 2);
totalContests = ContestManager(conMan).getContests();
vm.stopPrank();
assertEq(totalContests.length, 1);
}
Test2:
function testRewardDistributionFailsIfTotalRewardsIsBelowSumOfIndividualRewards() public mintAndApproveTokens {
console.log("Contest Manager Owner: ", ContestManager(conMan).owner());
console.log("msg.sender: ", msg.sender);
vm.startPrank(user);
contest = ContestManager(conMan).createContest(players, rewards, IERC20(ERC20Mock(weth)), 3);
totalContests = ContestManager(conMan).getContests();
vm.stopPrank();
assertEq(totalContests.length, 1);
vm.startPrank(user);
ContestManager(conMan).fundContest(0);
vm.stopPrank();
assertEq(ERC20Mock(weth).balanceOf(contest), 3);
vm.startPrank(player1);
Pot(contest).claimCut();
vm.stopPrank();
vm.startPrank(player2);
Pot(contest).claimCut();
vm.stopPrank();
}
Tools Used
Manual Analysis
Recommendation
Add a check in the constructor to verify that the sum of all individual rewards equals totalRewards.
constructor(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards) {
i_players = players;
i_rewards = rewards;
i_token = token;
i_totalRewards = totalRewards;
remainingRewards = totalRewards;
i_deployedAt = block.timestamp;
+ uint256 sumRewards = 0;
for (uint256 i = 0; i < i_players.length; i++) {
playersToRewards[i_players[i]] = i_rewards[i];
+ sumRewards += i_rewards[i];
}
+ if (sumRewards != totalRewards) {
+ revert("Total rewards do not match the sum of individual rewards.");
+ }
}