Collateral Membership Truth as a Single Security Object
- Name: collateral membership truth as a single security object
- Category: lending-safety reference / solvency-state design note / collateral-eligibility control-surface checklist / callback-and-helper path discipline
- Summary: Healthy lending systems do not treat
use as collateral,entered market,vault asset is still pledged, or similar flags as loose UI metadata. They treat collateral membership as one security object: the exact account or vault, the exact asset set currently allowed to support debt, the exact debt and liquidation state that still depends on that set, the exact mutation lane allowed to change it, and the exact post-edit solvency snapshot that proves the new set is economically real. The crucial ladder stays explicit too:the account or vault still holds some asset,the protocol still treats that asset as canonical collateral membership truth for this debt state, and only laterborrow, withdraw, liquidation, or management flows may keep spending against that membership truth. This note exists to keep that positive design target explicit instead of leaving readers to infer it only by inverting incidents like Rari / Fei Fuse, Omni, Sturdy, or Arcadia. - Why this note exists:
- Several lending incidents do not fail because balances were forged; they fail because the protocol first treated an asset as supporting debt and then, through a callback, helper, liquidation side path, or stale read, let itself forget that same dependency before settlement finished.
- Modern protocols often spread
which assets support this debt right now?across market-membership flags, collateral toggles, vault managers, liquidation modules, and oracle-sensitive helpers. The useful design question is what one object should have stayed coherent across all of them. - The exploit corpus keeps rediscovering the same lesson: if collateral membership can change under weaker assumptions than borrow, withdraw, liquidation, or rescue paths rely on, the protocol is already operating with two incompatible solvency stories.
Three collateral-membership promotions reviewers should not collapse
-
The account or vault still holds the asset
- This is the narrow inventory or custody fact.
- It only answers
is the asset still here right now?
-
The protocol still treats that asset as canonical collateral membership truth
- This is the stronger solvency claim that the asset is still part of the exact set backing this account’s live debt, liquidation state, or vault obligations.
- It answers
does this asset still count toward solvency for this exact debt story?
-
Downstream flows may still spend against that collateral-membership truth
- This is stronger again: borrow, withdraw, liquidation, rescue, migration, or manager paths are still allowed to rely on that membership answer when they move value.
- It answers
may the rest of the protocol still act as if that collateral relation is economically real right now?
Healthy systems answer those questions separately. They do not let the asset is still present silently imply the asset still backs debt, and they do not let the asset still backs debt silently imply every downstream flow may keep acting on that fact while the membership edit is mid-flight.
The six joints a healthy collateral-membership object should keep fused
-
Canonical account or vault identity
- The protocol needs one exact answer to which account, vault, or position the collateral-membership change belongs.
- A membership toggle is not safe merely because some caller has collateral-management authority in the abstract; it must be bound to one specific solvency subject.
- This is the joint that matters when helper contracts, liquidation paths, or callbacks can rebound a membership edit onto the wrong account or onto an account whose debt state was computed earlier in the stack.
-
Exact asset set currently supporting debt
- The object must bind which assets presently count toward solvency, not just which assets the account owns.
- Healthy systems do not let
owns token Xandtoken X still backs debtdrift by call order, helper route, or callback timing. - This is the joint Rari / Fei Fuse lost when ETH-send reentry allowed
exitMarket()before the borrow that depended on that market had finalized.
-
Debt and liquidation dependence snapshot
- The object must bind what debt, borrow limit, liquidation eligibility, or auction state still depends on that collateral set.
collateral disabledis not a meaningful state transition unless the protocol simultaneously knows whether the dependent debt was reduced, migrated, or still live.- This is the joint Omni lost when ERC-721 receiver callbacks could run before
usingAsCollateralcleanup and then resume into stale writes that no longer described the real debt relation.
-
Authorized mutation lane
- The object must bind which exact path is allowed to change collateral membership: borrow setup, explicit collateral toggle, liquidation unwind, migration helper, vault-management action, or emergency exit.
- Healthy systems do not let side paths mutate collateral truth under looser reentrancy, oracle, or phase assumptions than the main solvency paths.
- This is the joint Sturdy and Arcadia make vivid: the collateral-membership surface was reachable through helper or liquidation contexts that operated on weaker assumptions than the balance sheet demanded.
-
Stage-specific mutation timing
- The object must bind when collateral membership is allowed to change within a flow.
disable collateral sometime during this broader operationis weaker thandisable collateral only after debt, prices, balances, and outbound deliveries are settled enough that the new set is final.- If a callback, liquidation sidecar, or optimistic manager can observe or modify the object mid-transition, the protocol is authenticating the wrong stage.
-
Post-edit solvency proof
- The object must bind one authoritative post-edit health check based on settled balances, settled debt, settled prices, and the final collateral set.
- Healthy systems do not let stale debt, stale prices, cached balances, or temporary management assumptions stand in for the new balance sheet.
- This is the joint read-only-reentrancy variants lose when a temporary mark exists only long enough to authorize detaching some other asset from solvency.
What sound design looks like
-
One account or vault, one collateral set, one debt-dependence story
- The protocol should be able to answer
which assets support this debt right now?from one canonical state object rather than reconstructing the answer from balances plus scattered booleans and helper-local assumptions. - The sharper positive-design habit is to keep three claims distinct even when the same asset still sits in the account:
asset is present,asset still counts as collateral membership truth, anddownstream flows may still spend against that membership truth.
- The protocol should be able to answer
-
Collateral membership changes under the same perimeter as borrowing and withdrawal
- If borrow, withdraw, liquidation, and oracle-sensitive flows need a guard, then collateral toggles, market exits, migration helpers, vault managers, and liquidation side effects should inherit that same guard.
- Side paths should not get a weaker solvency boundary merely because they look operational or administrative.
-
Membership retires before external delivery or sibling re-interpretation
- If an asset is leaving through an ETH send, ERC-20 / ERC-777 transfer, ERC-721 / ERC-1155 safe transfer, helper callback, or optimistic management route, the protocol should already know whether that asset still counts toward solvency before outside code or sibling modules can act on it.
-
One post-edit health snapshot is authoritative
- After any membership mutation, health should be recomputed from a settled snapshot that includes the new collateral set, not from transient oracle values, cached debt, or balances that only existed inside a callback window.
-
Transitional states are explicit and non-overlappable
- If the system intentionally allows a temporary undercollateralized or partially migrated state, that phase should be explicit, machine-checkable, and closed to unrelated liquidation, withdrawal, or collateral-disablement rights.
-
The clean target is stronger than
eventual health passes- No callback, stale-read window, liquidation side path, or helper should ever create a world where debt is still real but the protocol’s collateral-membership story has already forgotten which assets that debt depended on.
Useful positive design shapes
1. One canonical collateral-membership ledger
- Keep one authoritative per-account or per-vault object for collateral membership rather than parallel booleans spread across receipt tokens, reserve configs, vault managers, and helper-local caches.
- Borrow, withdraw, liquidation, toggle, and migration code should all mutate that same object or a strictly derived view of it.
2. Membership edits as solvency-critical state transitions
- Treat
exitMarket,setUsingAsCollateral, collateral toggles, and equivalent helpers as balance-sheet operations rather than preference changes. - Require the same guardrail stack as borrow / withdraw: reentrancy protection, safe oracle context, stage checks, and immediate post-edit health validation.
3. Phase-locked collateral mutation
- Represent account state explicitly as phases such as
steady,borrow in flight,withdraw in flight,liquidation in flight, ormigration in flight. - Disallow collateral-membership edits from any other lane while one of those phases is active unless the protocol is deliberately consuming the same phase object.
4. Configure first, deliver second for collateral release
- When collateral leaves the system, retire or seal the collateral-membership relation before callback-capable delivery happens.
- This is especially important for safe-transfer NFT collateral, refunding ETH, or helper paths that forward assets out mid-operation.
5. One post-edit solvency recomputation surface
- Recompute health from one settled source of balances, debt, and prices immediately after any membership change.
- If same-transaction or callback-window prices are not trustworthy enough for that recomputation, quarantine the mutation until they are.
6. Transitional solvency modes that shrink authority
- If a vault manager, migration tool, or liquidation engine needs temporary flexibility, encode that as a separate mode that narrows who may act and what they may mutate.
- Transitional modes should never silently preserve normal collateral-disablement or withdrawal rights.
Design questions worth asking first
- What exact object answers
which assets support this debt right nowfor this account or vault? - Which modules are allowed to mutate that object, and do they all inherit the same safety perimeter as borrow and withdraw?
- Can any external callback, refund path, receiver hook, or helper self-call run before the membership transition is final?
- After a membership edit, what exact post-edit health computation proves the new collateral set is real rather than merely locally convenient?
- If the protocol supports temporary undercollateralization or staged migration, what closes unrelated liquidation, toggle, and withdrawal rights during that phase?
Red flags that usually mean the protocol is authenticating the wrong collateral object
exitMarket, collateral toggles, or vault collateral setters protected by weaker guards than borrow or withdraw- membership booleans stored in one module while debt, liquidation, or ownership truth lives elsewhere with no shared phase object
- callbacks or helper routes that deliver collateral out before
usingAsCollateralor equivalent state is final - post-edit health checks that reuse stale prices, stale debt, or cached balances from earlier in the same transaction
- deprecated collateral-management paths still live after newer guardrails were added elsewhere
- liquidation or migration modules allowed to clear or rewrite debt while assets are already outside the account or vault
Failure-prevention checklist
- Define one canonical collateral-membership object per account or vault and document every code path allowed to mutate it.
- Preserve the three-step ladder explicitly in code and reviews:
asset still present,asset still counts as collateral membership truth for this debt, anddownstream flows may still spend against that truthare different promotions, not one vagueposition still has collateralconclusion. - Put every membership mutation path behind the same reentrancy, oracle-safety, pause, and settled-state assumptions used by borrow, withdraw, and liquidation.
- Treat market exits, collateral toggles, vault collateral setters, liquidation side effects, migration helpers, and emergency exits as solvency-critical operations rather than convenience actions.
- Finalize or seal collateral-membership state before any callback-capable outbound delivery, including ETH sends, safe NFT transfers, router callbacks, or helper-forwarded transfers.
- Recompute health from one post-edit snapshot immediately after any membership change; do not rely on stale debt, stale prices, or optimistic temporary state.
- Remove or hard-disable deprecated collateral-mutator entrypoints once newer guardrails exist.
- Make temporary-management or migration phases explicit and non-overlappable with unrelated liquidation, withdrawal, or collateral-disablement rights.
- Fuzz malicious receivers, sibling entrypoints, collateral toggles, and liquidation helpers against in-flight borrow / withdraw / migration paths, including read-only reentrancy windows.
- Add blast-radius limits such as isolated markets, borrow caps, collateral-disablement cool-downs, and emergency pause scope over membership-changing functions.
- Preserve enough operator telemetry to reconstruct every collateral-membership edit, including which path performed it and what debt still depended on the asset at that moment.
Audit prompts
- What exact state object determines whether an asset currently counts toward solvency for this account or vault?
- Which functions can mutate that object, including deprecated, low-traffic, or helper-only paths?
- Are all of those functions guarded by the same reentrancy, oracle, phase, and pause assumptions as borrow, withdraw, redeem, and liquidation?
- Can any callback-capable surface reach a membership mutator while debt, balances, or liquidation state are mid-transition?
- After a membership edit, does the protocol recompute health from a coherent snapshot or from stale marks and cached state?
- Can liquidation, rescue, migration, or management modules erase or migrate debt while collateral assets are temporarily out of the account?
- Does any path allow an attacker to use a transient price or temporary balance only to disable a different collateral asset that they later withdraw at normal prices?
- If an account has live debt right now, what exact proof prevents the protocol from forgetting one required collateral asset before that debt is reduced or closed?
- What negative tests prove that no nested call can make the protocol first honor an asset as collateral and then silently stop counting it before settlement finishes?
- If the system intentionally supports transitional undercollateralization, what exact rights are removed during that phase and where is that enforced?
Lessons that should already be standard
Use as collateralis part of solvency truth, not wallet preference metadata.Asset is still in the account,asset still backs this debt, andother flows may still spend against that collateral relationare three different security claims.- Collateral membership deserves the same paranoia as borrow and liquidation code because it decides which assets debt is allowed to spend against.
- Side paths are where these bugs survive. A protocol can harden borrow logic and still fail through one legacy toggle, liquidation side effect, or migration helper.
- Callback safety is not only about token hooks. Any path that lets collateral leave before membership truth is final is opening a solvency hole.
- Read-only reentrancy is often most dangerous when it authorizes detaching some other asset from solvency rather than stealing directly through the manipulated price itself.
- A protocol should be able to answer
which assets support this debt right now?from one settled object. If the answer depends on call ordering across modules, the design is already fragile. - Temporary undercollateralization needs an explicit mode and narrowed authority, not a social assumption that no one will touch the position during the gap.
- The right design bar is stronger than
health passed at the end of the transaction; debt and collateral membership should never belong to different moments in time.
Negative exemplar cluster: what broken collateral-membership truth looks like
- Fei Fuse is the classic
real debt, stale market-membership storyexemplar: ETH-send reentry letexitMarket()run before the borrow that still depended on that market had fully settled. - Omni Protocol is the clean safe-transfer version: NFT collateral left through receiver hooks before
usingAsCollateralstate was truly final, and stale cleanup later erased a renewed debt dependency. - Sturdy is the strong read-only-reentrancy version: a temporary mark mattered mainly because it let the attacker disable another collateral asset under false premises.
- Arcadia is the optimistic-management version: liquidation logic and management flow no longer agreed on which assets still needed to support the debt.
How to use this note with the exploit corpus
- Start here when the sharper design question is
what one collateral-membership object should have stayed coherent while this lending system borrowed, withdrew, liquidated, or migrated value? - Use Collateral-membership desynchronization when the exploit-side question is still the recurring bug class.
- Use this note when the follow-up becomes
what exact account / asset-set / debt-dependence / mutation-lane / phase / post-edit solvency object should the protocol have authenticated instead? - Pair with helper-path-invariant-reuse-and-fail-closed-discipline when the decisive failure was that a collateral helper or legacy path operated on weaker assumptions than the main path.
- Pair with receiver-hook-staged-delivery-and-single-accounting-ownership when callback-bearing collateral delivery was the decisive stage boundary.
- Pair with safe-read-surface-discipline or delayed-snapshots-and-same-block-quarantine when transient marks were what made the bad membership edit look permissible.
- Pair with self-liquidation monetization when the attacker profits by controlling the liquidation side of the false collateral story they just created.
Internal linkages
- Core exploit-side family: collateral-membership-desynchronization.
- Adjacent callback-delivery companion: receiver-hook-staged-delivery-and-single-accounting-ownership.
- Adjacent helper-side companion: helper-path-invariant-reuse-and-fail-closed-discipline.
- Adjacent safe-read companions: safe-read-surface-discipline and delayed-snapshots-and-same-block-quarantine.
- Adjacent monetization family: self-liquidation-monetization.
- Best current negative exemplars: Fei Fuse, Omni Protocol, Sturdy, Arcadia.
Control surface
-
The decisive control surface is the protocol’s answer to one question:
which exact assets still support this exact debt right now? -
That answer is only healthy when account identity, asset set, debt dependence, mutation lane, stage, and post-edit solvency proof all remain one object.
-
Lending systems fail this control surface when one path borrows against an asset and another path, under weaker assumptions, silently teaches the protocol to forget the same dependency before settlement finishes.
-
Sources:
- collateral-membership-desynchronization
- helper-path-invariant-reuse-and-fail-closed-discipline
- receiver-hook-staged-delivery-and-single-accounting-ownership
- safe-read-surface-discipline
- delayed-snapshots-and-same-block-quarantine
- rari-capital-fei-fuse-pools-reentrancy-2022-04-30
- omni-protocol-doodles-nftx-safe-transfer-double-reentrancy-2022-07-10
- sturdy-finance-balancer-wsteth-weth-read-only-reentrancy-collateral-toggle-bypass-2023-06-12
- arcadia-finance-vaultmanagementaction-liquidation-reentrancy-drain-2023-07-10
-
Last reviewed: 2026-07-30 UTC