Reproduced Exploit

Yield Ninja withdraw accounting — AuditVault 19123

withdraw burns shares but fails to debit the corresponding assets.

Nov 2022Otherlogic2 min read

Chain

Other

Category

logic

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: 19123. Standalone Foundry PoC and full write-up: 19123-yield-ninja-withdraw-accounting_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/logic/incorrect-state-transition · vuln/arithmetic/precision-loss

Reproduction: Fully local synthetic reduction. Run forge test -vvv in this folder; no live RPC is required.

Key info#

FieldValue
ProtocolAudit finding 19123
ImpactHigh
LossReduced invariant reproduced; no live funds moved
Attacker EOAConfigured synthetic caller
Attack contractExploit
Attack txLocal Foundry Exploit.attack() call
Chain · block · dateEthereum model · block 1 · synthetic
Bug classSee vulnerability-class tags above
Vulnerable contractVulnerable in test/19123-yield-ninja-withdraw-accounting.sol
Attack contractExploit
CompilerSolidity 0.8.24
ReproductionLocal reduced model

TL;DR#

withdraw burns shares but fails to debit the corresponding assets.

Background#

The report identifies a state/accounting boundary that can be reached by an untrusted caller. This self-contained model keeps the relevant variables and call ordering while removing unrelated protocol dependencies.

The vulnerable code#

The minimized victim and attack contracts are in test/19123-yield-ninja-withdraw-accounting.sol. The marked operation is executed by Exploit.attack() and asserted by the Foundry test.

Root cause#

The vulnerable operation omits the validation or state update required by the report, so the resulting state no longer matches the intended invariant.

Preconditions#

The affected entry point is deployed and reachable; no privileged role is needed in this reduced reproduction.

Attack walkthrough#

  1. Deploy the reduced victim from Exploit.
  2. Execute the reported call sequence.
  3. Assert the resulting state mismatch in test_exploit.

Diagrams#

flowchart TD A[Attacker] --> B[Vulnerable entry point] B --> C[Missing check or state update] C --> D[Incorrect state / denial of service]

Remediation#

Validate caller-controlled inputs and perform the accounting/state transition atomically before any external effect. Add a regression test for the reported invariant.

How to reproduce#

BASH
forge test -vvv

Sources#

Reference: AuditVault finding 19123


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.