Not a point-drain — a contagion. Exposure-BFS, finally centre stage. ~15 min.
Builds on: L16 · L40 · L26Anchor: a stablecoin loses its pegNew: multi-hop contagion, attenuated
The last three traces followed value leaving one target. A depeg is different in kind: one node's price
collapses and the damage ripples outward — to everything holding it, lending against it, or allocated to those
markets, fading with distance. This is the one trace that puts exposure-BFS (L16/L40) in the lead, and the one
where the graph's value as a network — not a pile of cells — is the whole point.
The scenario
A yield-bearing stable FT loses its peg — its price drops ~40% in a block. FT is held by holders directly,
used as collateral in lending market M (at 75% LTV), and vault V has 40% of its capital allocated to
M. The peg breaks once; we watch the shock travel.
The reframe: contagion, not extraction
L50–L52 asked "how much can an attacker take?" A depeg asks "how far does the loss spread, and how strongly?"
That's the Bardoscia financial-contagion model exposure-BFS implements (L16): a weight starts at 1.0 at FT and is
multiplied by each edge's transmission weight every hop, so a node three hops away feels a tremor, not the full
quake. RiskUSD = weight × node price. No attacker, no cell — just a shock decaying across the network.
The cascade — multiplicative decay, hop by hop
The shock leaves FT and attenuates by the real transmission coefficient on each edge (L40 — LTV for lending, allocation
share for vault allocation, 1.0 for direct holdings):
1.0FT depegs
×0.75LENDING_ COLLATERAL (LTV)
0.75market M
×0.40VAULT_ ALLOCATION (share)
0.30vault V
×…further hops
↓minDelta
So vault V carries weight 0.30 of FT's depeg (1.0 × 0.75 × 0.40); its RiskUSD = 0.30 × V's price.
Direct FT holders feel it at ×1.0 (a HOLDS edge transmits fully). The walk is bounded by minDelta = 1e-6 (paths that
decay below it die) and MaxBFSDepth = 6 — the same self-limiting traversal from L16.
A subtlety you now know (L40)
You might expect the shock to flow through the pool that holds FT — but POOL_ASSET / VAULT_ASSET /
WRAP_UNWRAP carriers are weight 0.0: they're topology, not transmission. Exposure rides the value-bearing
edges — HOLDS (the pool's LP holders feel it directly), LENDING_COLLATERAL, VAULT_ALLOCATION — not the
structural carriers. Knowing which edges propagate (and which are weight-0) is exactly what L40 was for.
The trace — the peg breaks at block N
1
FT's price collapses.L1 · L7 · L26
the depeg shows up as a price move (a sell-off crashing FT's pools, and/or the oracle reporting the lower price); the price/NAV refresher reads FT's new usd_price.
2
Cross-source agrees — it's a real depeg, not a glitch.L26 validateCrossSource checks FT's new price against an independent source; a genuine depeg shows everywhere, so the prices agree and the new (low) price is stamped. (A lone-source crash with peers still at peg would be rejected as a likely bad feed — the L52 defense, inverted.)
The defense distinguishes a true depeg from a manipulated feed.
3
Revalue every FT position.L26 · L36
FT is SADD'd to price-dirty → the PriceDirtyDrainer recomputes every HOLDS edge's usd_value at the new price. Holders' FT positions, and the FT legs of pools, mark down.
RPC-economy: price stamped once, the recompute is graph-side (no per-holder RPC).
4
Exposure-BFS re-propagates — only the delta cone.L16 · L40 · L23 ComputeForNodes recomputes exposure for the nodes the delta touched: the weight flows out from FT, ×edge-weight per hop. M lands at 0.75, V at 0.30, and so on until minDelta / depth-6 stop it.
RPC-economy: incremental — only FT's exposure cone recomputes, not the whole graph (L23 delta-driven).
5
Max-over-paths, if V is reachable two ways.L16 · L46
say V also holds FT directly (a HOLDS path, weight 1.0) and via M (0.30). V's exposure is the max (1.0), not the sum — the strongest single path is the honest measure.
Combinator: max-over-paths — anti-double-count, exactly L46's rule for overlapping exposure.
6
Conservation holds — repriced, not vanished.L29 · L32 Σ HOLDS(FT) in units still ≈ totalSupply — FT didn't disappear, its price fell. The conservation check (which sums raw quantities, not USD) stays green; only USD values moved.
A depeg is a price event; conservation is on quantities, so it correctly doesn't fire.
7
Rules fire across the cone; alerts deliver.L12 · L45 · L15 · L18
rules thresholded on RiskUSD / exposure for M, V, and other affected nodes trip — potentially several alerts, one per affected customer's scope, each fire-once-debounced and msg-id-deduped.
Idempotency: a multi-node cascade can fire many rules, but each (rule,node) fires once per breach.
What made this trace different
The first three followed a single target. This one followed a front — a shock moving through the graph, its strength
set by the edges it crosses, its reach bounded by decay. Exposure-BFS is the only engine that answers "if X fails, who
else is hurt and by how much?", and the answer is a number per node, attenuated by LTV and allocation share. The graph
isn't a list of risks; it's a network across which risk flows.
The trace set, complete
Shape
Star engine
The number
L50 NAV
point — redeem supply
at_risk cells (model B)
at_stake = full supply
L51 pool drain
point — sweep a venue
exit-liquidity v2
extractable ≪ at_stake
L52 oracle borrow
point — borrow other asset
oracle bridger + model A
min(at_stake×LTV, other_borrowable)
L53 depeg
network — contagion
exposure-BFS
weight × price, per node, decaying
Four traces, the whole machine exercised
Three point-attacks across the at_risk taxonomy, and one network contagion across the exposure graph. Between them you've
driven every major engine — cells, extractable, exit liquidity, the oracle bridger, exposure-BFS — through real attacks,
end to end, applying all four cross-cutting lenses each time. There isn't a part of risk-graph-indexer you can't now pick
up, follow, and reason about. That is, in full, what "understand it deeply, end to end" meant.
Run it yourself
1. How is a depeg fundamentally different from the L50–L52 attacks the system models?
2. FT depegs; market M lends against it at 75% LTV; vault V allocates 40% to M. What exposure weight does V carry to FT's failure?
3. Why does the cascade not propagate through a POOL_ASSET edge from FT to a pool?
4. At step 2, the cross-source check stamps the new low price rather than rejecting it (unlike L52). Why?
5. At step 4, exposure-BFS recomputes only FT's delta cone, not the whole graph. Which lens is that?
6. Vault V reaches FT both directly (HOLDS, weight 1.0) and via M (0.30). What's V's exposure?
7. After the depeg, verify_balance_conservation stays green. Why doesn't a 40% price crash trip it?
8. A depeg can fire several alerts at once (M, V, other affected nodes). How does the system avoid a storm of duplicates?
↳ Ask your teacher
Try: "Show me where ComputeForNodes picks the delta cone to recompute." ·
"How deep does a realistic cascade reach before minDelta kills it?" ·
"If FT is a wrapped LST, does WRAP_UNWRAP really block propagation?" ·
"Quiz me cold: a new attack, name the star engine and the number." ·
"Where would second-order effects (a vault's own LPs) show up?"
What you can now do
Trace a depeg as a contagion: a shock decaying multiplicatively across value-bearing edges.
Compute a multi-hop exposure weight (LTV × allocation share × …) and the resulting RiskUSD.
Explain why structural carriers are weight-0 and which edges actually transmit.
Apply max-over-paths, the price-dirty revalue, incremental cone recompute, and quantity-based conservation.
Place all four traces in one taxonomy — three point-attacks + one network contagion — and pick the star engine for any new scenario.
The journey, fully realized
Fifty-three lessons: every subsystem, every mechanism, the algorithms and their parameters, the language idioms, four
unifying disciplines, and four end-to-end traces that drove the whole machine through real attacks. You set out to
understand risk-graph-indexer deeply, end to end, before contributing — point-attacks and contagions alike, from a raw
log to a human, with every number derivable to source. That understanding is yours. Phase 2, and its on-ramp, wait
whenever you decide.