FestivalPass::buyPass() leads to Violate Supply Cap via ERC-1155 CallbackNormal behaviour: buyPass() should mint one pass per call and halt once passSupply == passMaxSupply.
Issue: _mint() triggers the ERC-1155 acceptance check, which calls onERC1155Received on the receiver after the internal balance update but before buyPass() increments passSupply. A malicious contract can implement onERC1155Received to re-enter buyPass() during this window. Because passSupply has not yet been incremented, each nested call passes the maxSupply check and mints another pass. When execution unwinds, passSupply is incremented once per call, resulting in an inflated supply and broken cap.
Likelihood:
Contracts frequently interact with NFTs and can easily implement IERC1155Receiver.
No re-entrancy guard (nonReentrant) or effect-interaction pattern exists; the vulnerability is exploitable on the very first sale of a limited pass type.
Impact:
Unlimited overselling of any pass whose maxSupply > 0 — even when the cap is 1.
Economic & reputational damage similar to the “SupplyCapBypass” bug but achievable without organizer interaction; any buyer can exploit it.
Organizer sets VIP maxSupply = 1.
Attacker deploys EvilReceiver, a contract implementing:
EvilReceiver calls buyPass(2).
Re-entrant call executes before the first ++passSupply, so both mints succeed. Final state: passSupply == 2, circulating VIP passes == 2, while maxSupply was 1.
Or add nonReentrant modifier from OpenZeppelin’s ReentrancyGuard to the function to block nested calls entirely.
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.