Attackers can use a single ERC1155 Pass to attend the same performance from multiple contracts, minting BEAT tokens multiple times illegitimately. This undermines the one-pass-per-attendee logic and enables infinite BEAT farming with a single pass, eventually leading to NFT redemption without economic cost.
A user holding an ERC1155 FestivalPass is allowed to call attendPerformance(performanceId), which verifies they hold a pass, checks cooldown and attendance status, and then mints BEAT tokens as a reward.
The contract checks pass ownership via hasPass(msg.sender) only once at the start of attendPerformance(). However, it does not lock the pass or verify ownership after the BEAT token mint. Because ERC1155 passes are transferrable during execution or immediately afterward, a user can:
Call attendPerformance() from one address (Contract A).
Transfer the pass to another contract (Contract B).
Repeat the process to farm BEAT tokens multiple times per performance using only one Festival Pass.
These BEAT tokens can then be used to redeem unlimited NFTs via redeemMemorabilia().
Attendance is tracked per address, not per pass/token ID.
Contracts can transfer ERC1155 tokens immediately after passing the hasPass check.
No lock or reference to token ownership duration.
Reason 1: This will occur whenever an attacker deploys multiple contracts and rotates ownership of a single pass among them.
Reason 2: All conditions inside attendPerformance are satisfied each time a new contract address receives the pass.
Impact 1: Attackers can mint unlimited BEAT tokens using a single pass spread across wallets/contracts.
Impact 2: Farmed BEAT tokens can be used to redeem limited-edition NFTs (redeemMemorabilia()), violating maximum supply constraints, devaluing NFTs, and collapsing collection scarcity.
Step-by-step attack outline:
Attacker deploys multiple contracts (e.g., Contract A, B, Cā¦).
Buys only 1 Festival Pass.
Calls attendPerformance() from Contract A.
After BEAT tokens are minted, transfers the ERC1155 pass to Contract B.
Calls attendPerformance() from Contract B.
Repeats the process N times, farming N Ć BEAT tokens.
Finally, uses redeemMemorabilia() to mint NFTs from the collected BEAT tokens.
1) Track Attendance by Token ID (not just msg.sender):
2) Pass Ownership Duration Lock: Enforce a minimum holding duration before a pass can be used.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.