MyCut

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

fundContest uses array index with no bounds check — out-of-range index panics with unhelpful error and valid-but-wrong index silently funds the wrong pot

Root + Impact

Description

  • fundContest(uint256 index) is designed to transfer tokens to the pot at position index in the contests array. Contest addresses are stored sequentially by creation order and referenced by position.

  • There is no bounds check on index. An out-of-range value triggers a Solidity array out-of-bounds panic (0x32) rather than a descriptive custom error. More critically, a valid but incorrect index silently funds the wrong pot — a particularly hazardous failure mode given that the owner calling this function likely intends to fund a specific newly-created contest.

function fundContest(uint256 index) public onlyOwner {
// no bounds check — panics with 0x32 if index >= contests.length
Pot pot = Pot(contests[index]);
// ...
token.transferFrom(msg.sender, address(pot), contestToTotalRewards[address(pot)]);
}

Risk

Likelihood:

  • The onlyOwner restriction limits the attack surface to configuration mistakes rather than adversarial misuse. Off-by-one errors in contest index selection are common when managing multiple contests from scripts or UIs.

  • There is no double-funding protection — calling fundContest twice with the same index silently over-funds the pot.

Impact:

  • Out-of-range index: generic panic revert with no information about what went wrong.

  • Valid-but-wrong index: a different pot receives the tokens intended for the new contest. The misrouted tokens are not automatically recoverable, and the intended pot remains unfunded while appearing deployed.

Proof of Concept

Place this test in test/ and run forge test --match-test testOutOfRangeIndexPanicsWithNoCustomError. The test demonstrates that passing an out-of-range index to fundContest() triggers a generic array-out-of-bounds panic rather than a descriptive custom error, giving callers no actionable revert reason.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
import {ContestManager} from "src/ContestManager.sol";
import {MockERC20} from "test/mocks/MockERC20.sol";
contract L12Test is Test {
MockERC20 token;
ContestManager cm;
address owner = address(0x1);
function setUp() public {
token = new MockERC20();
vm.prank(owner);
cm = new ContestManager();
}
function testOutOfRangeIndexPanicsWithNoCustomError() public {
// No contests created yet; contests.length == 0
token.mint(owner, 100e18);
vm.startPrank(owner);
token.approve(address(cm), 100e18);
vm.expectRevert(); // generic 0x32 panic, not a custom error
cm.fundContest(0); // index 0 is out of range
vm.stopPrank();
}
}

Recommended Mitigation

Add an explicit bounds check require(index < contests.length, ContestManager__InvalidIndex()) before the array access so callers receive a meaningful revert message on invalid input.

+ error ContestManager__InvalidIndex();
function fundContest(uint256 index) public onlyOwner {
+ if (index >= contests.length) revert ContestManager__InvalidIndex();
Pot pot = Pot(contests[index]);
// ...
}
Updates

Lead Judging Commences

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