MyCut

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

M-04 Missing Input Validation in createContest()

Root + Impact:

Description:

The createContest() function accepts players and rewards arrays but does not validate that they have the same length. This allows the owner to create a Pot with mismatched arrays, where players[i] may not have a corresponding rewards[i].

In the Pot constructor, the loop for (uint256 i = 0; i < i_players.length; i++) iterates over i_players.length and assigns playersToRewards[i_players[i]] = i_rewards[i]. If rewards.length < players.length, this will cause an out-of-bounds access and revert. If rewards.length > players.length, some rewards are ignored.

@> function createContest(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards)
public
onlyOwner
returns (address)
{
+ // Missing: require(players.length == rewards.length, "length mismatch");
Pot pot = new Pot(players, rewards, token, totalRewards);
contests.push(address(pot));
contestToTotalRewards[address(pot)] = totalRewards;
return address(pot);
}

Risk:

Likelihood: High - The owner may accidentally pass mismatched arrays; no validation exists.

Impact:

  • If rewards.length < players.length: Pot creation will revert (index out of bounds)

  • If rewards.length > players.length: Some rewards are ignored, and the totalRewards may not match sum of rewards

  • Economic invariants broken: rewards distribution may not match expected behavior

Proof of Concept:

This POC demonstrates that passing mismatched array lengths to createContest() causes the Pot constructor to revert (if rewards is shorter than players) or ignore some rewards (if rewards is longer).

function testExploitVulnerability() public {
// Create arrays with different lengths
address[] memory players = new address[](3);
players[0] = makeAddr("player1");
players[1] = makeAddr("player2");
players[2] = makeAddr("player3");
uint256[] memory rewards = new uint256[](2); // MISMATCH: only 2 rewards for 3 players
rewards[0] = 100 ether;
rewards[1] = 200 ether;
// Missing reward for player3!
// This should revert because rewards[2] doesn't exist
// But there's no validation in createContest()
vm.prank(owner);
vm.expectRevert(); // Expect revert due to out-of-bounds access in Pot constructor
contestManager.createContest(players, rewards, token, 300 ether);
console.log("BUG: Mismatched arrays cause revert in Pot constructor");
}

Recommended Mitigation:

Adding validation ensures that the players and rewards arrays have the same length before creating the Pot, preventing out-of-bounds access or ignored rewards.

function createContest(address[] memory players, uint256[] memory rewards, IERC20 token, uint256 totalRewards)
public
onlyOwner
returns (address)
{
+ require(players.length == rewards.length, "length mismatch");
+ require(players.length > 0, "no players");
+ require(totalRewards > 0, "no rewards");
Pot pot = new Pot(players, rewards, token, totalRewards);
contests.push(address(pot));
contestToTotalRewards[address(pot)] = totalRewards;
return address(pot);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 7 days 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!