Beatland Festival

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

Immutable BeatToken Address Configuration

Root + Impact

Description

  • The FestivalPass constructor accepts a _beatToken address parameter but stores it as a public address variable without any setter function to modify it if incorrectly configured during deployment.

//@> address public beatToken;
address public organizer;
...
//@> constructor(address _beatToken, address _organizer) ERC1155("ipfs://beatdrop/{id}") Ownable(msg.sender) {
setOrganizer(_organizer);
//@> beatToken = _beatToken;
}

Risk

Likelihood:

  • Reason 1: This is primarily a deployment configuration error rather than an actively exploitable vulnerability

  • Reason 2: Requires the deployer to make a mistake during contract deployment

  • Reason 3: Requires human error during the deployment process

Impact:

  • Impact 1: If the wrong _beatToken address is provided during deployment, the contract will be permanently linked to an incorrect or non-existent token contract.

  • Impact 2: This would completely break core protocol functionality:

  • Impact 3: The entire tokenomics and reward system would be non-functional

  • Impact 4: Users would lose access to earned rewards and bonuses

  • Impact 5: This represents a complete failure of the protocol's core value proposition

Proof of Concept

This test demonstrates the core vulnerability by:

  1. Deploying with Wrong Address: Creates a new FestivalPass contract with an incorrect beatToken address (0x1234567890123456789012345678901234567890)

  1. Verifying the Problem: Confirms that the wrong address is permanently stored in the contract

  1. Testing Core Functionality Failures:

  • VIP Pass Purchase: When a user buys a VIP pass, the contract tries to mint 5 BEAT tokens to the user by calling BeatToken(beatToken).mint(msg.sender, bonus). Since beatToken points to a wrong address, this call fails.

  • Performance Attendance: When users attend performances, the contract tries to mint reward tokens. This also fails due to the wrong address.

  • Memorabilia Redemption: When users redeem memorabilia, the contract tries to burn BEAT tokens using BeatToken(beatToken).burnFrom(msg.sender, collection.priceInBeat). This fails as well.

  1. No Recovery Path: The test demonstrates that there's no way to fix this - no setter function exists to change the beatToken address.

function test_Vulnerability_ImmutableBeatTokenAddress() public {
// Deploy a new FestivalPass with an incorrect beatToken address
address incorrectBeatToken = address(0x1234567890123456789012345678901234567890);
FestivalPass vulnerableFestivalPass = new FestivalPass(incorrectBeatToken, organizer);
// Verify the incorrect address is set
assertEq(vulnerableFestivalPass.beatToken(), incorrectBeatToken);
vm.prank(organizer);
vulnerableFestivalPass.configurePass(2, VIP_PRICE, 1);
// Try to buy a VIP pass - this will fail because the incorrect address doesn't have mint function
vm.prank(user1);
vm.expectRevert(); // Will revert when trying to call mint on incorrect address
vulnerableFestivalPass.buyPass{value: VIP_PRICE}(2);
// Try to attend a performance - this will also fail
vm.prank(organizer);
uint256 perfId = vulnerableFestivalPass.createPerformance(block.timestamp + 1 hours, 2 hours, 100e18);
vm.warp(block.timestamp + 90 minutes);
vm.prank(user1);
vm.expectRevert(); // Will revert when trying to call mint on incorrect address
vulnerableFestivalPass.attendPerformance(perfId);
// Try to redeem memorabilia - this will also fail
vm.prank(organizer);
uint256 collectionId =
vulnerableFestivalPass.createMemorabiliaCollection("Test Collection", "ipfs://test", 100e18, 10, true);
vm.prank(user1);
vm.expectRevert(); // Will revert when trying to call burnFrom on incorrect address
vulnerableFestivalPass.redeemMemorabilia(collectionId);
// There is NO way to fix this - no setter function exists
// The contract is permanently broken if the wrong address is used during deployment
}

Recommended Mitigation

Setter function to set a valid address after deployment with an onlyOwner modifier to restrict access rights to the owner only.

+ function setBeatToken(address _beatToken) external onlyOwner {
+ beatToken = _beatToken;
+ }
Updates

Lead Judging Commences

inallhonesty Lead Judge 26 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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