Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Pass Transfer Enables Multiple Performance Attendance

Economic Loss + Unfair Advantage

Description

  • The system is designed so that each festival pass can attend each performance only once, with a 1-hour cooldown between any performance attendances to prevent rapid farming of BEAT token rewards.

  • However, attendance tracking is tied to user addresses rather than pass tokens, allowing the same pass to attend the same performance multiple times through strategic transfers between addresses.

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);
emit Attended(msg.sender, performanceId, performances[performanceId].baseReward * multiplier);
}

Risk

Likelihood:

  • Users can easily transfer ERC1155 passes to other addresses they control or collaborate with others

  • The attack requires no special technical knowledge, just basic understanding of NFT transfers

  • Economic incentive exists as users can earn multiple BEAT token rewards from single pass purchase

Impact:

  • Same pass can attend same performance unlimited times through different addresses, breaking the one-attendance-per-pass design

  • Cooldown mechanism can be bypassed by transferring passes between addresses

  • Excessive BEAT token minting beyond intended tokenomics, potentially devaluing the token

  • Unfair advantage for users who can afford multiple addresses or collaborate with others

Proof of Concept

// Scenario 1: Same pass, multiple attendances for the same performance
// Alice owns a VIP pass, attends Performance #1
alice.attendPerformance(1); // Gets 2x multiplier reward, hasAttended[1][alice] = true
// Alice transfers VIP pass to Bob
festivalPass.safeTransferFrom(alice, bob, VIP_PASS, 1, "");
// Bob can immediately attend the same performance with the same pass
bob.attendPerformance(1); // Gets another 2x multiplier reward
// This works because hasAttended[1][bob] = false (different address)

Recommended Mitigation

- remove this code
+ add this code
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unlimited beat farming by transferring passes to other addresses.

Support

FAQs

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