# Vulnerability in burnToMint function allows double use of NFT

burnToMint mints the new NFT before burning the old one, letting a contract recipient reenter and sell the token that is then burned, duping the buyer.

- Payout: Contest reward
- Severity: medium
- Program: NextGen
- Credited: ast3ros
- Disclosed: 2024-01-08
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-10-nextgen-findings/issues/1597
- Library page: https://bugbountylibrary.com/r/c4%3A2023-10-nextgen%3AM-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:reentrancy

**Target:** NextGenCore.sol burnToMint / ERC721 _safeMint callback
**Root cause:** burnToMint calls _mintProcessing (which uses _safeMint, invoking the recipient's onERC721Received) before _burn, violating checks-effects-interactions and leaving the to-be-burned token still owned/transferable during the callback.
**Steps:**
1. Deploy two collections and call `initializeBurn(1,2,true)` so collection-1 tokens can be burned to mint collection-2 tokens.
2. Mint token `10000000000` of collection 1 to a malicious contract implementing `IERC721Receiver`.
3. Malicious contract lists token `10000000000` for sale; buyer `addr3` places an offer.
4. Call `hhMinter.burnToMint(1, 10000000000, 2, 100)`; during `_safeMint` of token `20000000000`, `onERC721Received` fires.
5. Inside the callback, `transferFrom(address(this), receiver, 10000000000)` sells the still-unburned token to the buyer.
6. After callback returns, `_burn(10000000000)` executes; attacker keeps new token `20000000000` and sale proceeds, buyer gets nothing.
**How found:** Code reading of burnToMint revealed mint-before-burn ordering; recognizing _mintProcessing uses _safeMint (external callback to recipient) exposed a reentrancy window to transfer the not-yet-burned token.
**Exploitation:** Attacker-controlled contract receives the minted token via _safeMint callback while the original token is still owned by it; it transfers/sells the original token to a buyer within the callback, then the outer function burns it, so the buyer pays but receives a burned token while the attacker keeps both the new NFT and the sale proceeds.
**Insight:** In burn-to-mint / migrate-style functions, check whether the new mint uses _safeMint before the burn; the ERC721Receiver callback lets a contract recipient act on the still-owned old token (sell/transfer) before it is destroyed.
