# Pawnfi: unverified NFT collateral lets attacker drain staked APE

Pawnfi failed to verify NFT collateral transfer, letting attacker borrow APE against an already-staked BAYC and re-stake/withdraw protocol APE for ~$820K.

- Payout: Real-world hack
- Severity: high
- Program: Pawnfi
- Analysis by: DeFiHackLabs
- Disclosed: 2023-06-17
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-06/Pawnfi_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230617-pawnfi
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:access-control vuln:accounting-error vuln:business-logic

**Target:** Pawnfi lending/staking contract (ApeStaking) with P-BAYC NFT collateral
**Root cause:** The protocol did not verify that the specified NFT was actually transferred when used as collateral for borrowing, so an NFT already staked in the APE Staking Pool could be reused as collateral.
**Steps:**
1. Flash-borrow `200_000 * 1e18` APE from Uniswap V3 pool `0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF`.
2. Mint sAPE via `sAPE.mint(APE.balanceOf(this))`, then mint isAPE via `isAPE.mint(sAPE.balanceOf(this))` and `Unitroller.enterMarkets([isAPE])`.
3. Borrow `1005 * 1e18` iPBAYC, approve PBAYC, call `PBAYC.randomTrade(1)` to obtain a BAYC NFT id.
4. `BAYC.setApprovalForAll(ApeStaking1, true)` and `ApeStaking1.setCollectRate(1e18)`.
5. Call `ApeStaking1.depositAndBorrowApeAndStake(depositInfo, stakingInfo, [], [])` with the BAYC id as mainTokenId and zero cash/borrow amounts.
6. Borrow ETH from CEther up to account liquidity via `borrowEth()`.
7. Loop 20 times: read `ApeStaking2.pools(1)` and `getTimeRangeBy(1, lastRewardsRangeIndex)`, then call `depositBorrowWithdrawApe(timeRange.capPerPosition)`.
8. Finally call `depositBorrowWithdrawApe(APE.balanceOf(PBAYC))` to withdraw protocol APE, then repay `200_000 * 1e18 + fee0` APE to the Uniswap pool.
**How found:** Analysis identified that the contract never checked NFT transfer on collateral use, and that re-staking protocol-held APE caused misattribution of deposits to the attacker.
**Exploitation:** Attacker flash-borrowed APE, supplied it as isAPE collateral, borrowed iPBAYC, and used a BAYC NFT already staked in the APE Staking Pool as collateral to borrow APE. The borrowed APE sat in the project contract; re-invoking depositAndBorrowApeAndStake caused the contract to stake those APE and misattribute them to the attacker, who then called withdrawApeCoin to extract them, netting ~$820K.
**Escalation:** Repeated deposit/borrow/withdraw cycles (20 iterations plus a final sweep of PBAYC's APE balance) amplified the drain.
**Insight:** When a lending contract custodies borrowed funds and later re-stakes them, check whether re-invoking the stake function credits those funds to the caller; also test reusing an NFT already locked in an external staking pool as collateral.

