Beatland Festival

AI First Flight #4
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

L-2: Critical addresses can be set to `address(0)` without validation

Root + Impact

Deployment and admin functions assign beatToken, organizer, and festivalContract without zero-address checks. A single misconfiguration bricks organizer actions or all BEAT mint/burn paths.

Description

  • Normal behavior: constructor wires BeatToken and organizer; owner later sets festivalContract on BeatToken exactly once.

  • None of these assignments validate address(0), so a typo in deployment or setOrganizer permanently locks configuration.

// src/FestivalPass.sol
constructor(address _beatToken, address _organizer) ERC1155("ipfs://beatdrop/{id}") Ownable(msg.sender){
setOrganizer(_organizer);
// @> No require(_beatToken != address(0))
beatToken = _beatToken;
}
function setOrganizer(address _organizer) public onlyOwner {
// @> No zero check
organizer = _organizer;
}
// src/BeatToken.sol
function setFestivalContract(address _festival) external onlyOwner {
require(festivalContract == address(0), "Festival contract already set");
// @> No require(_festival != address(0))
festivalContract = _festival;
}

Risk

Likelihood:

  • Owner calls setOrganizer(address(0)) by mistake, or deploy script passes a zero address.

  • Owner calls setFestivalContract(address(0)) before verifying the address.

Impact:

  • onlyOrganizer functions become unreachable (organizer is zero).

  • BeatToken.mint / burnFrom always revert (msg.sender must be festivalContract).

  • Protocol requires redeployment; one-shot setFestivalContract cannot be fixed without new token.

Proof of Concept

function test_L02_setOrganizerToZeroAddressBricksConfig() public {
festivalPass.setOrganizer(address(0));
assertEq(festivalPass.organizer(), address(0));
// Previous organizer can no longer configure passes
vm.prank(organizer);
vm.expectRevert("Only organizer can call this");
festivalPass.configurePass(1, GENERAL_PRICE, 100);
}

Recommended Mitigation

+ error ZeroAddress();
constructor(address _beatToken, address _organizer) ... {
+ if (_beatToken == address(0) || _organizer == address(0)) revert ZeroAddress();
setOrganizer(_organizer);
beatToken = _beatToken;
}
function setOrganizer(address _organizer) public onlyOwner {
+ if (_organizer == address(0)) revert ZeroAddress();
organizer = _organizer;
}
function setFestivalContract(address _festival) external onlyOwner {
require(festivalContract == address(0), "Festival contract already set");
+ require(_festival != address(0), "Zero address");
festivalContract = _festival;
}
function withdraw(address target) external onlyOwner {
+ require(target != address(0), "Zero address");
// ...
}
Updates

Lead Judging Commences

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