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, andthe 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, andthe resulting position deserves to surviveinto one vague comfort claim that the tradelooked healthy. - The useful design question is often not
did we have a health check somewhere?butwhy was any borrowed route allowed to move shared funds before one exact route-complete post-fill solvency story had already become unavoidable?
- Several exploit families become easier to prevent once the reviewer asks
Fast route inside this family
- bZx / Fulcrum is the clean
protocol-authored toxic fill plus skipped final health checkanchor: the system itself borrowed ETH, routed size through shallow Uniswap liquidity via Kyber, and then admitted the already-underwater short becauseshouldLiquidate()was short-circuited. - Rodeo Finance is the clean
oracle-conditioned toxic admissionanchor: 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?buthow 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
- 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.
- 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.
- 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, andhealth 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()orshouldLiquidate()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 allowedandroute safe to financeare 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 failboundary 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 lateris not a reason to relaxhealthy 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 laterThis same-asset or helper branch does not need the expensive validationThe oracle / TWAP says strategy entry is safeThe router will find the best pathLiquidators can handle it if the position ends up weakThe 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 allowedis weaker thanthe route could absorb borrowed size, and that is weaker thanthe 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
- Start here when the sharper design question is how a leverage or strategy system should keep route admission, executable depth, and post-fill solvency fused before shared funds move.
- Pair with post-trade solvency validation bypass when the negative family is already clear and the design question is how to keep the financed route from outrunning the solvency proof.
- Pair with helper-path-invariant-reuse-and-fail-closed-discipline when helper branches, retries, or emergency paths are the reason the final health boundary became optional.
- Pair with collateral-admission-lag-and-borrow-side-quarantine when the deeper question is why a newly published price or strategy state gained borrow power too early.
- Pair with liquidation-capital-provenance-and-keeper-competition-assumptions when the protocol’s fallback safety story quietly assumes better stressed unwind liquidity or keeper depth than actually exists.
Internal linkages
- Negative-family companion: post-trade-solvency-validation-bypass.
- Canonical skipped-check exemplar: [[../incidents/lending-liquidations/bzx-fulcrum-eth-wbtc-margin-pump-shouldliquidate-bypass-2020-02-15|bZx / Fulcrum ETH-WBTC margin-pump
shouldLiquidate()bypass (2020-02-15)]]. - Canonical oracle-conditioned toxic-admission exemplar: ForceInvestment health-factor bypass (2023-07-11).
- Adjacent helper-path companion: helper-path-invariant-reuse-and-fail-closed-discipline.
- Adjacent fresh-admission companion: collateral-admission-lag-and-borrow-side-quarantine.
- Adjacent liquidation realism companion: liquidation-capital-provenance-and-keeper-competition-assumptions.
Control surface
-
The decisive control surface is the boundary where a protocol turns
entry may be attemptedintoshared funds may now hit this exact route at this sizeand then intothe resulting position may remain on the books. -
The sharper review split is three-layered: which marks may authorize consideration, which route objects may authorize financed execution, and which post-fill states may authorize continued balance-sheet support.
-
Healthy systems do not let routing, venue depth, and solvency live as three partially overlapping stories once borrowed execution begins.
-
Sources:
- post-trade-solvency-validation-bypass
- bzx-fulcrum-eth-wbtc-margin-pump-shouldliquidate-bypass-2020-02-15
- rodeo-finance-eth-unsheth-camelot-twap-manipulation-forceinvestment-health-factor-bypass-2023-07-11
- https://www.palkeo.com/en/projets/ethereum/bzx.html
- https://lev.liv.nev.org.uk/pub/bzx_debug.txt
- https://peckshield.medium.com/bzx-hack-full-disclosure-with-detailed-profit-analysis-e6b1fa9b18fc
- https://medium.com/@Rodeo_Finance/rodeo-post-mortem-overview-f35635c14101
- https://www.quillaudits.com/blog/hack-analysis/rodeo-finance-hack
-
Last reviewed: 2026-08-03 UTC