MyCut

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

[H-1] `Pot::constructor` assigns rewards according to place in `Pot::i_players` and `Pot::i_rewards`

[H-1] Pot::constructor assigns rewards according to place in Pot::i_players and Pot::i_rewards

Description

Pot::constructor uses a for loop to assign players' rewards to mapping Pot::playersToRewards, according to i's place in both Pot::i_players and Pot::i_rewards, which removes any element of a game. Additionally, this method requires that an equal number of players and rewards are given in the respective arrays.

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;
// i_token.transfer(address(this), i_totalRewards);
@> for (uint256 i = 0; i < i_players.length; i++) {
@> playersToRewards[i_players[i]] = i_rewards[i];
@> }
}

Risk

Likelihood:

This is guaranteed to happen every time a contest is created.

Impact:

  • The impact is that the players are given rewards based on their placement within the array players passed to Pot::constructor and the placement of rewards in the array rewards passed to Pot::constructor.

  • This reduces any kind of game element to the contest. It is simply a convoluted way of distributing rewards to players whose rewards are already predetermined.

Proof of Concept

Below we use the testing suite with our test function TestMyCut::testRewardsAreAssignedToPlayers to verify that a player's reward is directly correlated with their placement within their players array and rewards array.

We see that the player at position 0, player1, has a reward that is the 0th element in rewards, and the player at position 1, player2, has a reward that is at position 1 in rewards.

The test function passes.

// global var of rewards
uint256[] rewards = [3, 1];
function testRewardsAreAssignedToPlayers() public mintAndApproveTokens {
// Arrange
vm.startPrank(user);
contest = ContestManager(conMan).createContest(
players,
rewards,
IERC20(ERC20Mock(weth)),
totalRewards
);
ContestManager(conMan).fundContest(0);
vm.stopPrank();
uint256 player1BalanceBefore = ERC20Mock(weth).balanceOf(player1);
uint256 player2BalanceBefore = ERC20Mock(weth).balanceOf(player2);
console.log("Player1 balance before: ", player1BalanceBefore);
console.log("Player2 balance before: ", player2BalanceBefore);
uint256 firstReward = rewards[0];
uint256 secondReward = rewards[1];
console.log("first reward", firstReward);
console.log("second reward", secondReward);
// Act
vm.startPrank(player1);
Pot(contest).claimCut();
vm.stopPrank();
vm.startPrank(player2);
Pot(contest).claimCut();
vm.stopPrank();
// Assert
// get players' balance after
uint256 player1BalanceAfter = ERC20Mock(weth).balanceOf(player1);
uint256 player2BalanceAfter = ERC20Mock(weth).balanceOf(player2);
console.log("Player1 balance after: ", player1BalanceAfter);
console.log("Player2 balance after: ", player2BalanceAfter);
// assert that players' rewards are equal to the corresponding uint256 in the array i_rewards
assertEq(firstReward, player1BalanceAfter);
assertEq(secondReward, player2BalanceAfter);
}

Recommended Mitigation

We recommend that a different way of distributing rewards to players be devised so that an element of a game is retained. We recommend deleting the for loop.

- for (uint256 i = 0; i < i_players.length; i++) {
- playersToRewards[i_players[i]] = i_rewards[i];
- }
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour 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!