# A previously timelocked NFT token becomes permanently stuck in vault if it’s ever moved back into the vault

Visor vault's transferERC721 skips deleting timelockERC721s, so a re-deposited NFT retains a stale recipient and becomes permanently locked.

- Payout: Audit contest
- Severity: high
- Program: Visor
- Found by: 0xRajeev
- Disclosed: 2021-08-30
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-05-visorfinance-findings/issues/35
- Library page: https://bugbountylibrary.com/r/c4%3A2021-05-visorfinance%3AH-01
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** ERC721 vault timelock/transfer logic
**Root cause:** transferERC721() performs the same expires/recipient checks as timeUnlockERC721() but never deletes timelockERC721s[key], leaving stale timelock and nftApprovals data for the tokenID.
**Steps:**
1. Alice calls `timeLockERC721()` on an NFT with delegate Eve as recipient.
2. Eve calls `transferERC721()` to move the NFT out without calling `timeUnlockERC721()` first.
3. Alice re-acquires the NFT and deposits it back into the vault without any timelock.
4. Stale `timelockERC721s`/`nftApprovals` still mark the NFT as timelocked to Eve; the L510 recipient check only permits Eve to transfer it out.
5. Alice cannot withdraw her own NFT unless Eve cooperates.
**How found:** Code review comparing transferERC721() against timeUnlockERC721(): both do the same expires/recipient checks, but transferERC721() omits the `delete timelockERC721s[...]` cleanup present at L572 of timeUnlockERC721().
**Exploitation:** Not an attacker-driven exploit; the flaw traps the NFT. The owner loses access unless the stale recipient (Eve) is still trusted and available to call transferERC721().
**Insight:** When two functions share identical access checks, diff their state-mutation side effects: a missing delete/cleanup in the alternate exit path leaves stale authorization data that resurfaces on re-entry of the same key.

