# EGGX: reentrancy in NFT claim check drains pool

EGGX claim contract's check() let attacker re-mint EGGX via flash-loaned pool balance, then dump into Uniswap V3 pool for ~2 ETH.

- Payout: Real-world hack
- Severity: medium
- Program: EGGX
- Analysis by: DeFiHackLabs
- Disclosed: 2024-02-20
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-02/EGGX_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240220-eggx
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:medium tech:evm tech:solidity technique:chained vuln:business-logic vuln:flash-loan vuln:reentrancy

**Target:** EGGX claim contract and Uniswap V3 EGGX/WETH pool
**Root cause:** The claim check() function re-mints EGGX for already-claimed NFT IDs without proper state validation, allowing repeated claims during a flash-loan callback.
**Steps:**
1. Fork mainnet at block 19252566.
2. Flash-borrow entire EGGX balance of pool 0x26be...944F via `pool.flash(this,0,EGGX.balanceOf(pool),data)`.
3. In `uniswapV3FlashCallback`, call `EGGXCliam.check(nftid)` repeatedly with batches of already-claimed NFT IDs (e.g. 30342,30319,...) to mint EGGX.
4. Repay pool with `EGGX.transfer(pool, pollbalance+fee1)`.
5. Swap remaining EGGX into pool via `pool.swap(this,false,amountSpecified,sqrtPriceLimitX96,0x61)` to extract WETH.
6. Collect ~2 ETH profit.
**How found:** Researcher noticed claim check() lacked idempotency on NFT IDs and could be invoked inside a flash callback to mint unbacked EGGX, then arbitraged against the pool.
**Exploitation:** Attacker flash-borrows the pool's EGGX, re-claims EGGX via check() on already-claimed NFT IDs, repays flash loan, then swaps the excess EGGX for WETH in the same Uniswap V3 pool, netting ~2 ETH.
**Insight:** When a claim/mint function takes an array of IDs, test whether re-submitting already-claimed IDs inside a flash-loan callback re-mints tokens; the pool holding the token is the natural exit liquidity.
