# NFTFloorOracle's assets will use old prices if added back after removal

NFTFloorOracle's delete of assetFeederMap leaves nested feederPrice mapping intact, so re-added assets reuse stale prices, misvaluing NFTs and risking wrongful liquidations.

- Payout: Contest reward
- Severity: medium
- Program: ParaSpace
- Credited: hyh
- Disclosed: 2023-04-27
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-11-paraspace-findings/issues/459
- Library page: https://bugbountylibrary.com/r/c4%3A2022-11-paraspace%3AM-15
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:liquidation vuln:oracle-manipulation

**Target:** NFTFloorOracle price oracle contract
**Root cause:** Solidity `delete` on a struct does not recurse into nested mappings, so `feederPrice` survives `delete assetFeederMap[_asset]`; re-adding the asset reuses old feeder prices.
**Steps:**
1. Call `_removeAsset(asset)`: `delete assetFeederMap[_asset]` clears registered/index but leaves nested `feederPrice` mapping intact.
2. Later call `_addAsset(asset)`: only `registered` and `index` are reset; old `feederPrice` entries remain.
3. `_combine()` reads `feederRegistrar.feederPrice[feeders[i]]`; if `updatedAt` within `config.expirationPeriod`, stale twaps are aggregated as valid.
4. Median of stale prices becomes the asset price, misvaluing collateral.
**How found:** Code reading of `_removeAsset` and the `FeederRegistrar` struct; recognized Solidity delete semantics do not clear nested mappings, then traced `_combine` to confirm stale prices are consumed.
**Exploitation:** Requires asset removal then re-addition while feeder prices remain within expirationPeriod; stale/corrupted prices feed `_combine`, producing incorrect NFT valuation that can trigger liquidation of healthy accounts.
**Insight:** When auditing oracle/registry contracts, check every `delete` of a struct containing nested mappings — Solidity skips mappings, so per-feeder/per-user state persists across remove/re-add cycles and can be silently reused.
