Reproduced Exploit

ParaSpace — [H-01] Data corruption in NFTFloorOracle; Denial of Service

1. Remove feeder B (middle): last feeder C is swapped into B's slot. 2. feederPositionMap[C].index still says 2 while array length is 2. 3. removeFeeder(C) reads feeders[2] → out of bounds revert; C stuck forever.

Nov 2022Otheruntagged2 min read

Chain

Other

Category

untagged

Date

Nov 2022

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 25723-h-01-data-corruption-in-nftfloororacle-denial-of-service-cod. Standalone Foundry PoC and full write-up: 25723-h-01-data-corruption-in-nftfloororacle-denial-of-service-cod_exp in the evm-hack-registry mirror.


Vulnerability classes: missing index update · data-corruption · DoS

Reproduction: self-contained Foundry PoC with only forge-std — no fork. Full trace: output.txt.

AuditVault taxonomy: lang/solidity · platform/code4rena · severity/high · sector/lending · genome: missing-modifier · data-corruption/price-manipulation · dos-resistance


Key info#

ImpactHIGH — swap+pop without map fixup makes further feeder removals OOB-revert
ProtocolParaSpace
Vulnerable codeNFTFloorOracle._removeFeeder — no index update after swap
Bug classIncomplete swap-and-pop bookkeeping
FindingCode4rena 2022-11-paraspace · #25723 (H-01) · reporter csanuragjain
Compiler^0.8.24 (PoC)

TL;DR#

  1. Remove feeder B (middle): last feeder C is swapped into B's slot.
  2. feederPositionMap[C].index still says 2 while array length is 2.
  3. removeFeeder(C) reads feeders[2] → out of bounds revert; C stuck forever.

The vulnerable code#

SOLIDITY
feeders[feederIndex] = feeders[feeders.length - 1]; // @> VULN: no map update for moved feeder
// FIX: feederPositionMap[feeders[feederIndex]].index = feederIndex;
feeders.pop();

Diagrams#

flowchart TD A["Feeders A B C at 0 1 2"] --> B["removeFeeder B"] B --> C["Array becomes A C"] C --> D["Map still says C at 2"] D --> E["removeFeeder C OOB reverts"] E --> F["Dead feeder cannot be cleared"]

Impact#

Malfunctioning/malicious feeders cannot be removed after any middle-index removal; oracle integrity breaks over normal operations.

Remediation#

After swap, set feederPositionMap[feeders[feederIndex]].index = feederIndex before pop.

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.