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 year ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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

Give us feedback!