Borrowed-Execution Depth and Post-Fill Solvency Discipline

  • Name: borrowed-execution depth and post-fill solvency discipline

  • Category: protocol-design reference / leverage-route discipline / post-fill solvency boundary / positive-design companion to toxic-execution admission exploits

  • Summary: Borrow-backed execution should only be allowed when one shared risk envelope already covers the exact route the protocol will hit, the executable depth that route can really absorb, and the post-fill solvency state the protocol is willing to keep on its own balance sheet. The recurring failure is not merely trade too large; it is that protocols silently collapse three promotions that deserve to stay separate: some mark or policy said the trade may enter, the protocol can actually force this much borrowed size through the chosen venue path without authoring toxic flow, and the resulting position still deserves lender, vault, or treasury support once the real fill lands. bZx / Fulcrum and Rodeo preserve two clean shapes of that mistake: a final health check that could be skipped after catastrophic venue impact, and an oracle-shaped strategy admission flow that still let borrowed funds route into a thin venue whose real executable depth never supported the published solvency story.

  • Why this note exists:

    • Several exploit families become easier to prevent once the reviewer asks what exact route-depth and post-fill object was the protocol willing to finance with shared funds?
    • Teams often have a decent pre-trade mark, quote, or strategy gate, but they still let execution routing, slippage semantics, and post-fill health live in partially separate modules.
    • Reviewers also flatten entry is allowed, the route can really absorb this borrowed size, and the resulting position deserves to survive into one vague comfort claim that the trade looked healthy.
    • The useful design question is often not did we have a health check somewhere? but why was any borrowed route allowed to move shared funds before one exact route-complete post-fill solvency story had already become unavoidable?

Fast route inside this family

  • bZx / Fulcrum is the clean protocol-authored toxic fill plus skipped final health check anchor: the system itself borrowed ETH, routed size through shallow Uniswap liquidity via Kyber, and then admitted the already-underwater short because shouldLiquidate() was short-circuited.
  • Rodeo Finance is the clean oracle-conditioned toxic admission anchor: a manipulable strategy-admission mark said entry was fine, but the real borrowed execution path through the same thin market could not support the resulting post-fill health story.
  • Stay here when the sharper design question is not only what mark or branch was wrong? but how should a leverage or strategy system keep route admission, executable depth, and post-fill solvency fused into one financeable truth object before shared funds move?

What this note means by borrowed-execution discipline

  • A borrowed execution is any flow where protocol funds, lender funds, vault inventory, treasury inventory, or other shared balance-sheet assets are deployed into an external route before the user has fully paid for the resulting position.
  • Executable depth means the real worst-case venue capacity of the exact route the protocol will hit: venue mix, pool depth, fee tiers, hop order, slippage limits, callback semantics, and same-venue feedback loops included.
  • Post-fill solvency means the health of the resulting position at the prices and balances the protocol actually created through that execution, not at a pre-trade permissioning mark or cleaner quoted path.

Three borrowed-route promotions healthy reviewers should not collapse

  1. A policy, oracle, or route gate said entry was admissible at all
  • A collateral rule, strategy whitelist, TWAP, quote sanity check, or leverage cap may say this trade may start.
  • That only answers the weakest question: some upstream policy allowed the attempt.
  1. The protocol can actually execute that borrowed route at this size without authoring toxic flow
  • This stronger question is about real route depth, hop composition, venue coupling, same-venue self-impact, and whether protocol-borrowed size is too large for the actual liquidity path.
  • Many systems fail here: the entry mark looks fine, but the real route cannot absorb borrowed size without producing a catastrophically bad fill.
  1. The resulting post-fill position still deserves shared balance-sheet support
  • Even if the route completes, the protocol must still prove that the final position is healthy at the realized fill and under realistic unwind assumptions.
  • This is the still-stronger promotion: should the system keep this position live after seeing what its own execution actually did?

Most expensive toxic-admission exploits collapse those three promotions into one vague statement that the trade or strategy looked healthy. Healthy review keeps them separate on purpose.

The main rules healthy borrowed-execution paths should obey

1. One financed route should imply one route-complete risk envelope

  • If the protocol is willing to lend, mint against, or otherwise finance the trade, the same risk object should already include the actual venue path, executable depth assumptions, slippage ceiling, and post-fill health test.
  • The dangerous shape is policy marked it admissible, router chose something nearby, and health was checked later on weaker semantics.

2. Route depth is part of solvency, not execution quality

  • A leverage engine that ignores its own market impact is not merely accepting bad UX; it is lending against an unreal position.
  • Worst-case executable depth belongs inside solvency admission, not in a separate trading module that only cares about fill quality.

3. A final health check is only real if no path can spend borrowed funds before it becomes unavoidable

  • The presence of isHealthy() or shouldLiquidate() in code is not enough.
  • The meaningful question is whether any helper branch, same-asset shortcut, strategy-specific path, asynchronous continuation, or branch-local assumption can route borrowed funds before the post-fill solvency proof becomes mandatory.

4. Permissioning marks should authorize investigation, not substitute for executable truth

  • TWAPs, oracle marks, strategy allowlists, and route quotes can decide whether a flow is even worth evaluating.
  • They should not by themselves authorize the protocol to deploy shared funds into the same thin venue whose real depth they have not yet proven.
  • Rodeo is the reminder that entry allowed and route safe to finance are different claims.

5. Opposite-side inventory is part of the threat model

  • If the protocol can shove a thin venue out of line with borrowed funds, a realistic attacker model includes someone already holding the other side and harvesting the distortion immediately.
  • A route that only looks safe because reviewers forgot the attacker can sell into the protocol’s own dislocation is not safe.

6. Helper paths and retries should inherit the same post-fill truth boundary

  • Batch leverage wrappers, strategy adapters, keeper retries, and asynchronous execution continuations should not get a weaker solvency standard than the direct user path.
  • If a route’s execution semantics differ, the burden should be to recompute the same post-fill truth under the new path or fail closed.

What sound design looks like

  • Reachability, route absorbency, and post-fill survival stay separate on purpose

    • A mark may allow the trade to be considered without proving the route can absorb borrowed size, and route completion still does not by itself prove the resulting position deserves shared balance-sheet support.
    • Healthy systems force those promotions to be explicit instead of letting a pre-trade green light silently stand in for all three.
  • One financed route uses one path-complete risk object

    • The exact route, size, venue mix, slippage assumptions, and resulting health test all describe the same executable object before funds move.
  • Worst-case executable depth dominates notional leverage rules

    • Collateral ratios and strategy caps are subordinate to the real route depth the protocol can finance without creating a born-underwater position.
  • Post-fill solvency is proven at the realized fill or a stricter bounded worst case

    • Healthy systems validate the position against the execution they actually authorized, not against a cleaner proxy mark that lived earlier in the call chain.
  • Toxic admission fails closed instead of relying on liquidation theater later

    • If the route cannot prove safe post-fill health, the protocol shrinks, delays, or rejects the trade rather than expecting keepers, backstops, or downstream arbitrage to socialize the mistake.
  • One admitted mistake is still survivable

    • Per-route caps, per-market caps, venue-aware notional ceilings, strict slippage bounds, and fast pauses stop one bad financed route from becoming systemwide bad debt.

Useful positive design shapes

1. Shared route-complete admission object

  • Build one internal object that includes route identity, size, venue path, slippage bounds, permissioning mark, and post-fill solvency outcome.
  • Let wrappers and routers feed that object into one canonical finance or fail boundary instead of re-checking different subsets in different modules.

2. Depth-aware leverage caps

  • Express leverage limits in terms of worst-case realizable depth on the actual route, not just collateral ratios or headline market price.
  • If the route changes, the cap should change with it automatically.

3. Worst-case fill before funds move

  • Require admission to simulate or bound the actual execution path tightly enough that the protocol can prove this trade is still solvent if we clear at the worst fill we are willing to tolerate.
  • If the route cannot supply that evidence, borrowed execution should not proceed.

4. Route-local blast-radius controls

  • Keep per-venue, per-hop, per-market, and per-strategy caps near the route itself.
  • Borrow-backed trading should not be able to concentrate balance-sheet risk into the thinnest reachable venue just because the aggregate protocol cap still looks conservative.

5. Same predicate for direct, helper, and asynchronous settlement

  • If a keeper, router retry, or delayed continuation can complete borrowed execution, it should have to satisfy the same post-fill solvency predicate as the synchronous path.
  • Completed later is not a reason to relax healthy enough to exist.

Design questions worth asking first

  • What exact route object is the protocol financing with shared funds?
  • Which component proves that the actual route can absorb this borrowed size, not just that the strategy or collateral looked admissible?
  • Where is post-fill solvency proven, and can any branch move borrowed funds before that proof becomes unavoidable?
  • If the protocol itself pushes the market out of line, who can immediately stand on the other side of that distortion?
  • Which route, quote, oracle, or helper assumptions would still be trusted if downstream execution landed at the worst fill the protocol says it tolerates?

Red flags that usually mean borrowed execution has outrun solvency proof

  • The final health check runs later
  • This same-asset or helper branch does not need the expensive validation
  • The oracle / TWAP says strategy entry is safe
  • The router will find the best path
  • Liquidators can handle it if the position ends up weak
  • The route is usually deep enough

Failure-prevention checklist

  • Define one canonical route-complete admission object for every borrow-backed execution path: permissioning mark, exact route, executable depth assumptions, slippage ceiling, and post-fill solvency proof should live together.
  • Make post-fill health validation unavoidable before shared funds become economically committed. No helper branch, same-asset shortcut, strategy mode, retry path, or asynchronous continuation should be able to skip the same solvency proof.
  • Size leverage and strategy notional against realizable route depth on the actual venue path. If the protocol cannot clear the size without creating a born-underwater position, the route is unsafe regardless of headline collateral math.
  • Evaluate worst-case execution using the same route semantics the protocol will honor in production: venue mix, pool tier, callback path, hop order, and partial-fill behavior.
  • Treat oracle and TWAP gates as permissioning hints, not as proof that borrowed execution is safe. A mark can authorize evaluation without authorizing financing.
  • Model opposite-side inventory and same-transaction monetization explicitly. If the protocol can donate value to the other side of a pool through its own financed trade, assume the attacker can be waiting there.
  • Put route-local blast-radius limits under the financed path: per-route notional caps, per-venue caps, strategy-specific pauses, and slippage ceilings that actually protect the balance sheet rather than just user experience.
  • Force helper, router, and keeper paths to reuse the same post-fill solvency predicate as the direct path. If one path cannot prove the same thing, it should fail closed.
  • Monitor for impossible admissions: positions born near or below liquidation threshold, repeated extreme-slippage fills, or strategies whose health only survives at the permissioning mark instead of the realized fill.
  • Treat routing code as balance-sheet code whenever the protocol is lending into the route. Execution modules are not just UX plumbing once shared funds pay for the trade.

Audit prompts

  • What exact object says this borrow-backed trade may proceed, and does that same object also commit the route, size, and post-fill health proof?
  • At what exact line does the protocol prove this position is healthy after the real fill, and can any path move borrowed funds before that line becomes mandatory?
  • Which route assumptions are merely quoted or inferred, and which are actually bounded at execution time?
  • Does the protocol finance a route chosen by the same venue or market that also authored the permissioning mark?
  • If the attacker holds the opposite-side inventory, how much value can the protocol’s own order donate to them before the position becomes immediately liquidatable?
  • Are leverage caps expressed in notional terms only, or do they shrink with real route depth, venue concentration, and pool-specific liquidity?
  • Which same-asset, helper, or retry branches claim to be safer than the main path, and what exact evidence shows they cannot skip or weaken post-fill solvency validation?
  • If execution becomes partial, asynchronous, or keeper-completed, does the same post-fill solvency predicate still gate settlement?
  • What onchain or operator-side control limits damage if one route-depth assumption is wrong anyway?
  • Which tests prove that no newly opened financed position can start life below maintenance margin at the executions the protocol itself is allowed to create?

Lessons that should already be standard

  • Entry was allowed is weaker than the route could absorb borrowed size, and that is weaker than the resulting position deserved to survive.
  • Route depth is part of solvency whenever shared funds finance the trade.
  • A health check that can be skipped after borrowed execution is not a safety control; it is a postmortem note.
  • Oracle permissioning and execution routing are one security story once the protocol is willing to lend into the route.
  • Liquidation should contain honest positions that later deteriorate, not sanitize positions the protocol should never have admitted.
  • Same-asset or helper branches deserve more suspicion, not less. Many toxic-admission bugs hide behind code paths developers believed were obviously safe.
  • Routing modules are treasury code when they decide where borrowed funds hit the market.
  • The clean design target is stronger than most financed trades stay healthy: no borrow-backed route should need favorable drift, downstream subsidies, or lucky keeper behavior to justify the fill the protocol itself just created.

How to use this note with the exploit corpus

Internal linkages

Control surface