Approval-Funded Route Authority as a Single Security Object
- Name: approval-funded route authority as a single security object
- Category: router-security reference / approval-funded settlement design note / route-local caller-right binding checklist / wallet-spender authorization reference
- Summary: ERC-20 allowance does not by itself authorize a router, aggregator, or callback-driven adapter to spend from a wallet on any route it can decode. Healthy approval-funded systems keep one narrower route authority object intact above raw allowance: which approved spender surface may act, for which source wallet, on which exact route or stage, toward which exact counterparty and recipient semantics, under which selector / callback / settlement meaning, for which bounded token set and amounts, and how many times. This note exists to keep that approval-funded route object explicit. The secure design target is not
the router has allowance, but one route-local authorization object that binds spender identity, source wallet, committed route stage, allowed external counterparties, settlement meaning, and consumption semantics before anytransferFrom()or approval-funded callback settlement happens. It is also useful for preserving a three-step review ladder that teams still collapse too often:this spender surface is reachable,this exact route stage may exercise that reach, andthis route stage still deserves this much live spend authority under the current mode. Just as importantly, if only one emergency router path, operator-assisted completion lane, or fallback adapter remains live, that surviving approval-funded path should inherit a smaller payer, destination, and counterparty budget than healthy-mode routing rather than silently becoming ordinary spend authority because it is the only path left. - Why this note exists:
- The corpus already has strong negative notes for arbitrary call token-approval drain, callback-origin authentication failure, and the stripped-down approval-rights exposure family.
- It also already has a broader positive-design note in spender authority truth as a single security object.
- What was still worth preserving explicitly is the middle layer for approval-funded routers and adapters: once a spender surface is not just a raw helper but a route interpreter, what exact object should have kept
who may spend,why this route may spend,which callback or downstream counterparty may demand payment, andwhere funds may end upfused together before any allowance-backed transfer or settlement step.
The route authority object a healthy approval-funded system should keep fused
An approval-funded router is safest when it can point to one object that answers all of these together:
-
Approved spender surface identity
- Which exact contract, facet, adapter, or module is allowed to exercise the wallet approval?
- If the protocol uses diamonds, plugin routers, bridge adapters, or callback-heavy helper modules, which reachable surface is actually consuming allowance on this route?
-
Source-wallet and payer scope
- Which wallet, smart account, DSA, vault, or other delegated user-controlled account is permitted to fund this route?
- Is that source authenticated by
msg.sender, permit scope, signed route intent, internal vault ownership, a precommitted payer field written to trusted local state, or an acting-account binding that survives through proxy-style helper flows? - Dough-style deleverage incidents are the useful warning here:
the protocol can already manage this user proxyis not enough; the route authority object still has to prove which exact acting account is allowed to fund this unwind branch before downstream calldata can spend from it.
-
Exact route identity and stage meaning
- Which route, quote, or execution plan is being honored, and which stage of that route is live right now?
Some swap is executingis not enough once approvals are involved; the spender needs one narrower route-local meaning.
-
Allowed external counterparties and selectors
- Which pools, routers, bridge adapters, helper contracts, or selectors is this route actually allowed to touch?
- This is the field Transit, Dexible, Revert, Socket, Dough, and LI.FI-style bugs lost when attacker-shaped route data still chose the external call surface.
- Socket makes the point especially clean: even after the gateway fallback had already resolved
0x00000196to the wrapped-token helper, the route still letswapExtraDataredefine the selector family and economic meaning of that route id.
-
Callback / settlement counterparty binding
- If a later callback or settlement consumer can claim funds, which exact pool, pair, market, or resolver is allowed to do that for this route stage?
- This is the field Primitive, Sushi RouteProcessor2, and ParaSwap-style bugs lost when a fake pool or spoofed settlement caller could impersonate the expected counterparty.
-
Recipient and payout semantics
- Where may value ultimately go: protocol custody, a named pool, a bridge escrow, a route-local settlement bucket, or the user-specified final recipient?
- Safe design does not let raw calldata silently redefine whether a spend is funding a swap step, repaying a callback debt, or simply transferring tokens to an attacker.
-
Token / amount bounds and consumption semantics
- Which tokens and maximum amounts does this route authority permit, and is the authority single-use, stage-limited, or multi-step with explicit consumption?
- Standing ERC-20 allowance may be broad for UX reasons, but the route authority object should usually be much narrower than that raw capacity.
Three approval-funded routing questions reviewers should not collapse
1. Is the spender surface even reachable?
- This is the raw
allowance / permit / delegated-spend capability existsquestion. - It answers whether a router, facet, helper, or callback-settlement surface can pull from the wallet at all.
- It does not yet answer whether the current route is allowed to exercise that capability.
2. Does this exact route stage get to exercise that reach?
- This is the narrower
payer, route stage, canonical counterparty, recipient meaning, and target / selector family stayed boundquestion. - It is the review step Transit, Dexible, Socket, LI.FI, ParaSwap, Primitive, and Sushi RouteProcessor2 ultimately lost in different ways.
- A system can have a reachable approved spender and still fail here because attacker-shaped route bytes, callback metadata, or fast-path helpers redefine who gets paid, which counterparty is canonical, or which external program the spender may touch.
3. Even if the route stage is authentic, how much live authority does it deserve right now?
- This is the
budget / payer scope / destination reach / counterparty freedom under the current operating modequestion. - Healthy-mode routing, degraded routing, manual completion, and emergency fallback should not all inherit the same approval-funded authority object just because they share one spender surface.
- The important control is not merely
leave one route alive; it isshrink the surviving route's live spend authority on purpose when the trust boundary has narrowed.
What sound design looks like
1. Raw allowance and route authority are modeled separately
The wallet approved this routeris only the base layer.- A second object must answer
why may this exact route or stage exercise that approval now? - If the protocol cannot name that second object, it is already too close to generic approval-drain failure.
2. Route bytes should not be the only custody boundary
- Offchain-generated route data, nested adapter payloads, and callback calldata may describe a route, but they should not alone define who can spend from whom and to which counterparties.
- Healthy systems bind those facts to trusted local state, typed route commitments, allowlisted target/selector sets, or signed user intents before any allowance-backed transfer occurs.
3. External call freedom must stay narrower than spender authority
- A router that can spend approved tokens should almost never be free to call arbitrary targets or selectors inside the same step.
- Safe design keeps
who may spend approved balancesandwhich external programs this route may touchfused into one verified route authority object.
4. Callback settlement should consume precommitted route-local payer state
- If a pool, resolver, or bridge callback can demand payment, the callback should consume payer, token, and stage meaning that were committed before external control left.
- Approval-funded settlement is dangerous when the callback itself gets to define who pays or which counterparty is owed.
5. Recipient meaning should be derived from route state where possible
- A spend intended to fund
this swap,this bridge leg, orthis deleverage stepshould derive its recipient semantics from committed route state rather than from attacker-shapedtofields alone. transferFrom(victim, arbitraryRecipient, amount)should never be just one alternative interpretation of ordinary route data.
6. Route authority should usually be one-shot or stage-scoped
- If the protocol means one swap, one bridge leg, one deleverage, or one callback settlement, it should consume one route-local authorization object even if the wallet’s underlying ERC-20 allowance remains larger.
- This is the practical way to stop stale approvals from becoming generic reusable route fuel.
7. Surviving fallback approval lanes should become smaller lanes
- If one manual completion path, emergency adapter, or last-trusted router branch stays live during incident response or degraded mode, that branch should lose ordinary healthy-mode payer scope, destination reach, counterparty freedom, and approval reuse.
This is the only route we still trust enough to keep operatingshould meanthis route now has a smaller route authority object and smaller loss budget, notthis route may keep spending with the old broad wallet and inventory semantics because it is all we have left.
Useful positive design shapes
1. Signed or typed route intents that commit spender-relevant fields
- A route intent should commit at least source wallet, input token, max input amount, expected counterparty set or route family, recipient semantics, and expiry / nonce.
- The spender then proves that live execution is one permitted interpretation of that intent rather than merely one thing possible with the wallet’s allowance.
2. Target-and-selector binding on every approval-funded branch
- Allowlist both the contract and the function family each step may call.
- If inner calldata can choose another helper, bridge, or token contract, route authority has already split away from spender authority.
3. Precommitted callback slots for approval-funded settlement
- Before invoking a callback-capable pool or helper, record one stage-local object that binds expected caller, payer, token semantics, and remaining amount.
- The callback then proves it is consuming that exact slot, not just some ambient
router is in executionstate.
4. Route-local payout buckets
- Keep route-funded assets and route-funded debt in one route-local accounting bucket.
- A later settlement step should draw only from that committed bucket, not from whatever balance or wallet approval happens to still be reachable.
5. Distinct authorization for direct wallet pulls versus downstream settlement
- A router may need both
pull approved input from walletandsettle callback debt to canonical poolcapabilities. - Safe design treats these as different route stages with different authorized counterparties and different consumption rules, not one ambient spender privilege.
6. Degraded-mode approval envelopes with narrower authority
- If a protocol falls back to one emergency helper, one operator-assisted completion path, or one remaining router family, the committed approval-funded route object for that mode should shrink on purpose.
- Healthy degraded mode usually means fewer callable targets, fewer destination classes, no broad callback replay, smaller payer scope, and lower per-window token budgets than ordinary routing.
- The important design move is not merely
keep one approved route working; it iskeep only a consciously smaller approval-funded route authority alive while trust is weaker.
Design questions worth asking first
- Which exact contract surface will exercise user ERC-20 approvals on this route?
- What exact object proves the source wallet is meant to fund this route, not merely that it has a standing allowance?
- Which targets and selectors may this route call, and where is that bound?
- If a callback later demands payment, what exact state written before the external call proves who the canonical counterparty and payer are?
- Could any route branch reinterpret a spend as an arbitrary transfer to a different recipient or helper?
- When the protocol means one swap, one bridge leg, or one deleverage, what route-local object gets consumed so the same wallet approval cannot back a different route later?
Red flags
The router already has allowanceused as if that answered why this exact route may spend it- attacker-shaped target addresses or selectors on approval-funded paths
- callback settlement that reconstructs payer or pool meaning from callback bytes alone
- route systems where the same spender surface can mean
normal swap,bridge leg,rescue helper,migration pull, orarbitrary callwith only loosely checked mode flags - route accounting that settles from ambient router balances or arbitrary approved wallets instead of route-local funding buckets
- stale infinite allowances acting as the only remaining permission boundary once one router branch becomes too generic
Failure-prevention checklist
- Keep one route-local authorization object above raw ERC-20 allowance, and make every approval-funded execution path prove the same bounded spender, source wallet, counterparty set, stage meaning, recipient semantics, and token / amount limits before any value moves.
- Centralize target and selector validation for approval-funded execution, then forbid new facets, helpers, adapters, or callback fast paths from bypassing that gate on any externally reachable branch.
- Treat callback settlement as a separate authorization stage: record the canonical pool / pair / market, payer, asset semantics, and remaining amount in trusted local state before control leaves, and consume only that committed state on callback.
- Bind route meaning to typed intents, signed route commitments, allowlisted route families, or trusted local state rather than letting nested calldata alone decide who pays, which helper is called, or where tokens end up.
- Separate
pull approved input from wallet,pay canonical callback debt, andforward proceeds to recipientinto distinct stage-scoped permissions instead of one ambient spender privilege. - Constrain approval-funded execution by exact contract and exact function family, not just broad module ownership or
trusted routerstatus. - Keep route-funded assets and approval-funded debt inside route-local buckets so a malformed path cannot settle from arbitrary wallet approvals or ambient router balances.
- Pre-commit degraded-mode route policy too: if only one fallback router path, emergency helper, or operator-assisted completion lane remains live, automatically narrow payer scope, destination reach, callback counterparty freedom, and per-window token budget instead of preserving healthy-mode authority by default.
- Make route authority one-shot or explicitly consumable per hop / stage, and clear it on success, revert, or abandonment so stale approvals cannot be reused against a different route later.
- Fuzz and adversarially test helper-bypass, fake-pool, fake-callback, route-array substitution, selector drift, diamond-facet regression, and stale-context reuse cases as first-class wallet-drain scenarios.
- Review upgrades for
security middleware inheritance, not just business logic correctness: every new approval-consuming entrypoint should prove it still passes through the same route-authentication and target-binding machinery as the old path.
Audit prompts
- What exact object proves this approved spender may exercise allowance for this route right now rather than merely because the wallet once approved the router?
- Which contracts, facets, selectors, pools, bridge adapters, or helper modules can an attacker still choose on an approval-funded path, and where is that freedom bounded?
- If only one fallback router branch, manual completion lane, or emergency helper survives during degraded operation, what exact payer scope, destination classes, selector families, and per-window token budget disappear automatically — and which ones dangerously survive just because the same spender surface is still reachable?
- If a callback later demands payment, what trusted state written before the external call proves the canonical counterparty, payer, token semantics, and route stage being settled?
- Can any route branch reinterpret
swap fundingasarbitrary transfer,bridge funding,rescue, ormigrationusing only mode flags or attacker-shaped nested calldata? - Do all approval-consuming entrypoints share the same allowlist, selector checks, route-intent validation, and payer-binding logic, or does one helper / facet / fast path escape the common gate?
- Is route authority consumed once per stage, and what clears it on revert, retry, partial fill, or abandoned execution?
- If ordinary routing degrades to one emergency helper, one manual completion path, or one surviving router family, what exact payer scope, destination set, callback counterparty set, and approval budget disappear automatically?
- Could a fake pool, counterfeit adapter, or attacker-controlled helper still become the apparent canonical counterparty by shaping callback bytes, route arrays, or offchain-generated metadata?
- Where does the system distinguish
wallet being charged,router inventory being spent, androute-local proceeds being settled, and can those payer semantics collapse into one ambient spend surface? - What telemetry would reveal approval-funded route drift early: unexpected selectors, new external targets, callback callers outside canonical factories, payer substitutions, or route stages paying from wallets that never initiated the live hop?
- During upgrade review, what proves every new approval-consuming path still inherits the shared target / selector / callback / payer discipline rather than calling the low-level swap helper directly?
Lessons that should already be standard
- Wallet allowance or proxy-local delegated spend authority is not route intent. A healthy router has to prove a narrower route-local authorization object before spending approved funds.
Trusted routeris not a sufficient control. The question is which exact route, stage, payer, counterparty, and selector the trusted router is allowed to exercise.- Callback payment is just another approval-consuming route stage; it needs the same committed counterparty and payer truth as the initial wallet pull.
- The most dangerous approval-drain bugs often come from one helper, facet, or fast path that bypassed the shared middleware developers assumed every route used.
- Route bytes that both describe execution and define spend authority are custody-critical objects, not mere integration plumbing.
- Infinite approvals magnify blast radius, but they only become drains when route authority, target binding, or settlement meaning already failed first.
The spender is oursdoes not help if the spender can still be induced to speak in the attacker’s route language.Approved spender is reachableis not the same thing asthis exact route stage is authentic, and even that is not the same thing asthis stage still deserves ordinary spend authority right now.Only live approved route leftis not the same thing asthis route still deserves ordinary spend authority. Weaker live workflow should imply a smaller route authority object, not continuity at the old budget.- Approval-funded systems stay safest when they can answer one machine-checkable question at every step:
why may this exact route stage spend from this exact wallet toward this exact counterparty right now?
Negative exemplar cluster
- Transit Swap preserves the
outer bridge looked constrained, inner approval-funded helper was still attacker-steerablevariant. - Dexible preserves the
user-supplied route arrays chose both spender and execution targetvariant. - Seneca Chamber preserves the stripped-down
operation array still exposed generic callee.call()variant, where the approval-funded route object collapsed before any rich offchain routing story was even needed. - Revert Finance V3Utils preserves the
offchain route metadata became onchain approval authorityvariant. - Socket WrappedTokenSwapperImpl, Dough Finance, and LI.FI GasZipFacet preserve the
one route branch skipped the middleware that was supposed to keep approval-funded execution narrowfamily; Socket is the clearestroute id was fixed, but route meaning still was notexemplar inside that cluster. - Primitive Finance, Sushi RouteProcessor2, and ParaSwap Augustus V6 preserve the callback-settlement side where route authority failed to keep the canonical paying counterparty fused to the route stage.
- Bancor and Beanstalk TokenFacet are the sharper stripped-down cousins where no rich route object was needed at all because the already-approved spender directly exposed its own pull helper.
Where this note stops
- Use spender authority truth as a single security object when the sharper design question is the general one above any router:
what one approval-exercise object should an approved spender prove before it may pull from a wallet at all? - Use route commitment across callback frame and settlement envelope when the sharper design question is the full end-to-end routing problem across callback frames and downstream settlement envelopes, not specifically the allowance-backed spender boundary.
- Use approval-rights exposure when no meaningful route interpretation was required and the approved spender simply exposed its own pull primitive.
- Use arbitrary call token-approval drain when the negative classification question matters more than the positive design target and the decisive failure was a too-generic approval-funded execution surface.
- Use callback-origin authentication failure when the negative classification question is specifically
which callback counterparty was wrongly trusted to claim settlement?
How to use this note with the corpus
- Start here when the sharper question is
what exact route-local authorization object should have existed above raw ERC-20 allowance before a router, aggregator, or callback-driven adapter was allowed to spend? - Pair with arbitrary call token-approval drain when the exploit already proved a router stayed too generic and the next question is how the approval-funded route should have been bounded.
- Pair with callback-origin authentication failure when the exploit already proved a fake pool or spoofed callback counterparty could claim settlement and the next question is how route-local spender authority should have pinned the paying counterparty.
- Pair with spender authority truth as a single security object when you need the broader spender-boundary checklist above both direct helpers and richer route interpreters.
Internal linkages
- Broader approval boundary companion: spender-authority-truth-security-object.
- Negative generic-router family: arbitrary-call-token-approval-drain.
- Negative callback-settlement family: callback-origin-authentication-failure.
- Negative stripped-down spender-helper family: exposed-token-pull-helper-approval-rights-exposure.
- Broader route-stage companion: route-commitment-across-callback-frame-and-settlement-envelope.
- Settlement-side companion: settlement-envelope-truth-security-object.
- Surviving-lane containment companions: request-origination-lane-separation-and-scoped-shutdown-discipline and post-authentication-bounded-loss-design.
- Best concrete exemplar cluster: Transit Swap, Dexible, Seneca Chamber, Revert Finance V3Utils, Socket WrappedTokenSwapperImpl, Dough Finance, LI.FI GasZipFacet, Primitive Finance, Sushi RouteProcessor2, and ParaSwap Augustus V6.
Control surface
-
The decisive control surface is not the ERC-20 approval alone.
-
It is the full approval-funded route authority object: spender surface identity, source wallet, committed route and stage, allowed targets and selectors, canonical callback or settlement counterparty, recipient semantics, and one explicit consumption rule.
-
Approval-funded systems stay safest when they keep that narrower route authority object machine-checkable above the wallet’s raw allowance state, so
approved spendernever silently degrades intogeneric route-funded drainer. -
Sources:
- spender-authority-truth-security-object
- route-commitment-across-callback-frame-and-settlement-envelope
- settlement-envelope-truth-security-object
- arbitrary-call-token-approval-drain
- callback-origin-authentication-failure
- exposed-token-pull-helper-approval-rights-exposure
- transit-swap-routing-bridge-claimtokens-arbitrary-call-approval-drain-2022-10-01
- dexible-selfswap-router-validation-approval-drain-2023-02-17
- seneca-chamber-performoperations-arbitrary-call-approval-drain-2024-02-28
- revert-finance-v3utils-dynamic-swaprouter-arbitrary-call-approval-drain-2023-02-18
- socket-wrappedtokenswapperimpl-performaction-arbitrary-call-approval-drain-2024-01-16
- dough-finance-connectordeleverageparaswap-flashloanreq-unvalidated-paraswap-calldata-approval-drain-2024-07-12
- li-fi-gaszipfacet-arbitrary-call-infinite-approval-drain-2024-07-16
- primitive-finance-connectors-fake-option-flash-swap-callback-approval-drain-whitehack-2021-02-22
- sushiswap-routeprocessor2-fake-pool-callback-approval-drain-2023-04-09
- paraswap-augustus-v6-uniswapv3swapcallback-fake-pool-approval-drain-2024-03-20
-
Last reviewed: 2026-07-25 UTC