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.