Beatland Festival

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

Missing nonReentrant Guard on attendPerformance Allows Potential Reentrancy via ERC777 or Malicious Contracts Impact

Root + Impact

Description

  • The attendPerformance function mints BEAT tokens to the user. However, it lacks a nonReentrant modifier or similar protection. If the BeatToken contract is replaced with a malicious or ERC777-compliant contract, reentrancy into attendPerformance may be possible, which could bypass hasAttended or lastCheckIn guards before state is updated, allowing users to mint BEAT repeatedly in a single transaction.

function attendPerformance(uint256 performanceId) external {
require(isPerformanceActive(performanceId), "Performance is not active");
require(hasPass(msg.sender), "Must own a pass");
require(!hasAttended[performanceId][msg.sender], "Already attended this performance");
require(block.timestamp >= lastCheckIn[msg.sender] + COOLDOWN, "Cooldown period not met");
hasAttended[performanceId][msg.sender] = true;
lastCheckIn[msg.sender] = block.timestamp;
uint256 multiplier = getMultiplier(msg.sender);
@> BeatToken(beatToken).mint(msg.sender, performances[performanceId].baseReward * multiplier);
}

Risk

Likelihood:

  • Requires BEAT to be ERC777-compliant or a malicious contract.

  • Requires performance to be active and cooldown met.

  • Needs a crafted contract as msg.sender to reenter.

Impact:

  • Could allow attackers to mint excessive BEAT tokens by reentering attendPerformance during the same execution context.

  • May break intended game mechanics or inflate BEAT supply.

Proof of Concept

Calls attendPerformance normally.
In the callback of the BEAT mint (e.g., tokensReceived if ERC777), reenters attendPerformance again before the first call finishes.
Since state changes (e.g., hasAttended) may not be enforced properly under reentrancy, the second call may also succeed.
This cycle continues, minting more BEAT than allowed.
This is only possible if BeatToken is an ERC777 token or a user-supplied contract that calls back into FestivalPass during minting.

Recommended Mitigation

+ import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
+ contract FestivalPass is ERC1155, Ownable2Step, IFestivalPass, ReentrancyGuard {
- function attendPerformance(uint256 performanceId) external {
+ function attendPerformance(uint256 performanceId) external nonReentrant {
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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