# Owner of a position can prevent liquidation due to the onERC721Received callback

Borrower contract returns invalid selector from onERC721Received, making safeTransferFrom revert during liquidation and blocking liquidation of undercollateralized positions.

- Payout: Contest reward
- Severity: high
- Program: Revert Lend
- Credited: 0xjuan
- Disclosed: 2024-05-22
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-03-revert-lend-findings/issues/54
- Library page: https://bugbountylibrary.com/r/c4%3A2024-03-revert-lend%3AH-06
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos vuln:liquidation

**Target:** V3Vault liquidation / NonfungiblePositionManager ERC721 transfer
**Root cause:** _cleanupLoan uses nonfungiblePositionManager.safeTransferFrom to return the LP NFT to the owner, which invokes onERC721Received on the owner contract; a malicious owner returns an invalid selector causing the transfer (and thus liquidation) to revert.
**Steps:**
1. Deploy MaliciousBorrower contract whose onERC721Received returns `bytes4(0xdeadbeef)` when `from == vault`, else `msg.sig`.
2. Borrower creates position with NFT collateral and borrows max against collateralValue.
3. Mock DAI/USD oracle to 0 so debt > collateralValue, making position liquidatable.
4. Liquidator calls `vault.liquidate(...)` with approved USDC; `_cleanupLoan` calls `safeTransferFrom(address(this), owner, tokenId)` which reverts `ERC721: transfer to non ERC721Receiver implementer`.
5. Liquidation fails; bad debt accrues.
**How found:** Code-reading of _cleanupLoan's safeTransferFrom to owner and recognizing the ERC721 receiver callback gives the owner control over liquidation success.
**Exploitation:** Attacker borrows maximum against an LP NFT position from a contract that rejects ERC721 receipts from the vault; when price moves against them, any liquidation attempt reverts at the NFT return step, leaving protocol holding bad debt.
**Insight:** Any protocol that pushes an ERC721/ERC1155 to a user during settlement (liquidation, redemption, refund) hands that user a revert switch via the receiver hook; prefer pull-over-push (approve + user redeems) for adversarial counterparties.
