Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Festival Contract Single-Use Limitation Leading to Token Ecosystem Fragmentation

Root + Impact

The BeatToken contract can only be linked to one festival contract permanently, creating a fragmented token ecosystem where each festival requires a separate token deployment, breaking token continuity and utility.

Description

  • The normal behavior should allow the BeatToken to be reused across multiple festivals or events, maintaining token value and ecosystem continuity

  • The current implementation permanently locks the token to a single festival contract address, preventing any future reuse or multi-festival integration

function setFestivalContract(address _festival) external onlyOwner {
@> require(festivalContract == address(0), "Festival contract already set"); // Prevents any future updates
festivalContract = _festival;
}
function mint(address to, uint256 amount) external {
@> require(msg.sender == festivalContract, "Only_Festival_Mint"); // Only one contract can mint
_mint(to, amount);
}

Risk

Likelihood:

  • Any festival organizer wanting to create multiple events will encounter this limitation immediately

  • The project documentation indicates this is a known issue that will occur in every multi-festival scenario

Impact:

  • Token holders lose accumulated value when new festivals require new token deployments

  • Memorabilia and rewards from different festivals cannot be traded in a unified ecosystem

  • Increased deployment and operational costs for organizers

  • Poor user experience due to managing multiple token types

Proof of Concept

// Deploy BeatToken and FestivalPass for first festival
BeatToken beatToken = new BeatToken();
FestivalPass festival1 = new FestivalPass(address(beatToken), organizer);
beatToken.setFestivalContract(address(festival1));
// Users earn BEAT tokens during festival1
// Festival1 ends, organizer wants to create festival2
// This will REVERT - cannot reuse the same BeatToken
FestivalPass festival2 = new FestivalPass(address(beatToken), organizer);
// beatToken.setFestivalContract(address(festival2)); // REVERTS: "Festival contract already set"
// Organizer forced to deploy new token, fragmenting ecosystem
BeatToken beatToken2 = new BeatToken();
FestivalPass festival2 = new FestivalPass(address(beatToken2), organizer);
beatToken2.setFestivalContract(address(festival2));
// Now users have beatToken (festival1) and beatToken2 (festival2)
// Cannot use festival1 tokens for festival2 memorabilia

Recommended Mitigation

- require(festivalContract == address(0), "Festival contract already set");
- festivalContract = _festival;
+ mapping(address => bool) public authorizedFestivals;
+
+ function addFestivalContract(address _festival) external onlyOwner {
+ require(_festival != address(0), "Invalid festival address");
+ authorizedFestivals[_festival] = true;
+ emit FestivalAdded(_festival);
+ }
+
+ function removeFestivalContract(address _festival) external onlyOwner {
+ authorizedFestivals[_festival] = false;
+ emit FestivalRemoved(_festival);
+ }
function mint(address to, uint256 amount) external {
- require(msg.sender == festivalContract, "Only_Festival_Mint");
+ require(authorizedFestivals[msg.sender], "Unauthorized_Festival");
_mint(to, amount);
}
function burnFrom(address from, uint256 amount) external {
- require(msg.sender == festivalContract, "Only_Festival_Burn");
+ require(authorizedFestivals[msg.sender], "Unauthorized_Festival");
_burn(from, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.