# Can Recover Gobblers Burnt In Legendary Mint

Sacrificed Gobblers keep stale approvals; owner calls transferFrom(address(0), user, id) to revive burnt tokens and mint legendary Gobblers for free.

- Payout: Contest reward
- Severity: high
- Program: Art Gobblers
- Credited: philogy
- Disclosed: 2022-12-09
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-09-artgobblers-findings/issues/219
- Library page: https://bugbountylibrary.com/r/c4%3A2022-09-artgobblers%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:business-logic

**Target:** ArtGobblers ERC721 contract, mintLegendaryGobbler and transferFrom
**Root cause:** mintLegendaryGobbler burns sacrificed tokens without clearing their per-token approvals, and transferFrom does not reject from == address(0), so the stale approval lets the old owner re-mint the burnt token.
**Steps:**
1. Mint enough Gobblers to meet legendary cost (e.g. 69) and approve the user for each id.
2. Call `gobblers.mintLegendaryGobbler(ids)` to burn the sacrificed tokens and receive the legendary Gobbler.
3. Confirm burnt ids revert on `ownerOf` with NOT_MINTED.
4. Call `gobblers.transferFrom(address(0), user, ids[i])` for each id; stale approval passes the check and the token is revived to the user.
5. Repeat to recover all sacrificed Gobblers, effectively minting the legendary for free.
**How found:** Code review of mintLegendaryGobbler's burn loop noticed approvals were not reset, then checked transferFrom's handling of from == address(0) and found no guard, enabling revival of burnt tokens.
**Exploitation:** Owner sacrifices N Gobblers to mint a legendary, then revives each burnt Gobbler via transferFrom from address(0) using the un-cleared approval, recovering the sacrificed tokens at no cost beyond temporary liquidity (reducible via NFT flashloans).
**Insight:** When a burn path deletes ownership but not per-token approvals, test whether transferFrom(address(0), ...) can resurrect the token; ERC721 implementations should reject from == address(0) and clear approvals on burn.
