# GoldReserve: profit-claim logic drained via NFT address cycling

GoldReserve tracked claimed profit per address but computed entitlement from current ERC1155 balance, letting an attacker cycle NFTs through fresh addresses to claim the same profit repeatedly.

- Payout: Real-world hack
- Severity: high
- Program: GoldReserve
- Credited: DeFiHackLabs
- Disclosed: 2025-02-01
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-02/GoldReserve_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250201-goldreserve
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:accounting-error vuln:business-logic vuln:reward-distribution

**Target:** ERC1155 NFT profit-claim contract on BSC
**Root cause:** Claimed-profit accounting was keyed per address, while entitlement was derived from the caller's current ERC1155 balance, so transferring NFTs to a new address reset the claim state without changing the underlying entitlement.
**Steps:**
1. Flash-borrow 120 WBNB from Pancake V3 pool `0x172fcD41E0913e95784454622d1c3724f546f849`.
2. Unwrap WBNB to BNB; call `depositProfit{value: flashAmount - mintCost}()` to seed the profit pool.
3. Fund a holder address with `mintCost = mintPrice()*8` and call `mint(10, 8)` to acquire NFTs entitled to the deposited profit.
4. Call `claimProfit()` from holder, sweep BNB out.
5. Loop 21 times: `safeTransferFrom(holder, nextHolder, 10, 8, "")` then `claimProfit()` from the new holder and sweep.
6. Transfer 1 NFT to a final holder and claim again.
7. Re-wrap BNB, repay flash loan plus fee; keep >12 BNB profit.
**How found:** Not stated; the analysis notes the mismatch between per-address claimed-profit tracking and balance-derived entitlement, implying the attacker spotted that moving NFTs to a new address resets claim state.
**Exploitation:** Attacker flash-borrowed 120 WBNB, deposited most as profit, minted 8 NFTs of id 10, then repeatedly transferred the same NFTs to freshly derived addresses and called claimProfit from each, sweeping the native BNB each time before repaying the flash loan.
**Escalation:** Repeated the transfer-and-claim cycle across 22+ derived addresses to multiply the single deposited profit into 12.74 BNB extracted.
**Insight:** When a protocol tracks 'already claimed' per address but computes entitlement from a transferable token balance, test whether transferring the token to a fresh address re-enables the claim; per-address state plus movable entitlement is a repeat-claim primitive.
