Abstract: multi-pool sandwich risk is not just local slippage
Modern DeFi price-manipulation risk is no longer well described by a single AMM pool and a simple before-after sandwich. The higher-risk pattern is a multi-pool sandwich combined with flash-loan-funded liquidation-boundary distortion: a short-lived liquidity vector affects AMM reserves, oracle sampling, collateral valuation, derivative indexes, and liquidation eligibility within the same execution window. The attacker does not need a long-term position. The protocol failure happens when an abnormal transient price becomes an irreversible liquidation, route execution, or refund valuation. This article builds a defensive model using Uniswap V2/V3, Curve-style stable swap behavior, TWAP oracles, oracle freshness, and lending-protocol health factors. The core idea is to replace single-pool slippage checks with a vector model: AMM price impact becomes a Jacobian over correlated price sources, and route execution is guarded by slippage value-at-risk, oracle confidence states, and cross-protocol circuit breakers. For AllSwap-style cross-chain exchange, the goal is not to predict every MEV opportunity. The goal is to avoid treating a distorted short-window price as a reliable quote or refund basis.
Scope: defensive modeling, not attack construction
This is a defensive protocol and routing-risk analysis. It does not provide sandwich scripts, transaction ordering templates, pool-selection procedures, or instructions for attacking real systems. The system roles are AMM pools, lending protocols, oracle networks, liquidators, MEV builders, searchers, cross-chain routers, users, and risk contracts. The adversary is assumed to have access to short-term liquidity or flash loans, to submit multiple transactions inside one execution window, to observe public mempools or builder order flow, and to exploit timing differences between protocols. The adversary is not assumed to forge oracle signatures, bypass consensus rules, or modify deployed contract code.
The distinction matters. A single-pool sandwich primarily changes the user's execution price. A multi-pool manipulation changes what other protocols believe the price is. If a lending protocol derives collateral value from one AMM path, a derivatives protocol updates margin from another index, and a router prices execution from a third route, the price vector is no longer independent. One pool's temporary displacement can propagate through TWAP windows, oracle caches, liquidation thresholds, synthetic asset indexes, and cross-chain route states. A defensive system does not need prices to be perfectly stable. It needs abnormal, short-lived, non-executable prices to avoid triggering irreversible settlement actions.
Cross-chain exchange adds time as another risk dimension. Source-chain quote, target-chain execution, bridge confirmation, refund window, and oracle update are not synchronous. A route can be safe when quoted and unsafe when executed. A TWAP can be adequate for one local chain but stale for a cross-chain path that waits through bridge finality. AllSwap's route model therefore needs to reason about price impact, finality delay, and refund attribution in the same state machine.
Multi-pool price impact model
Start with a Uniswap V2-style constant-product pool. Ignoring fees for intuition:
```text x * y = k p = y / x ```
The relevant security quantity is the local derivative of price with respect to trade size, after accounting for reserve direction, fee, and integer rounding. Uniswap V3 changes the shape: liquidity is concentrated inside tick ranges, so local price impact depends on active liquidity near the current tick, not on nominal total value locked. Curve-style stable swap systems provide lower slippage near balance, but the curve becomes steeper when the pool moves away from its intended equilibrium. "The pool is large" is not a sufficient safety condition. The question is whether there is enough executable depth in the relevant price interval.
For multiple pools and protocols, define a price-state vector:
```text P = (p_amm1, p_amm2, p_curve, p_lending_oracle, p_perp_index) Q = (q_1, q_2, ..., q_n) J = dP / dQ ```
`Q` is the vector of trades or state changes across pools and protocols. `J` is the price-sensitivity matrix. Single-pool defense checks one local derivative. Multi-pool defense checks the directionality of the matrix. If a relatively small trade vector moves several price components in the same risk direction, liquidation eligibility can be amplified. If collateral price decreases, debt-asset price increases, and a margin index moves in the same window, the health factor can deteriorate nonlinearly.
A generic lending health condition can be written as:
```text H = collateral_value(P) * liquidation_threshold - debt_value(P) liquidatable if H is not positive ```
The defensive quantity is `dH / dQ`. If a trade vector can move `H` from positive to non-positive inside one short window and the value naturally reverts a few blocks later, the system is exposed to transient-price liquidation. The loss is not just "a liquidation happened." The loss is that an irreversible settlement action accepted a price state that did not represent durable market depth.
TWAP and oracle-cache lag
TWAP oracles are widely used to reduce single-block manipulation risk. Uniswap V2's cumulative price oracle requires observers to compare cumulative prices over time. Uniswap V3 exposes observation windows and tick accumulators. The common idea is to transform spot price into a time average. But TWAP is a trade-off, not a complete defense.
A longer window raises the cost of short-term manipulation but reacts more slowly to real market movement. A shorter window reacts faster but becomes more sensitive to transient shocks. Risk appears when lending protocols, derivatives protocols, and routers use different windows. One protocol may believe the market recovered while another still reads the lagged low price. A liquidation module may trigger on a short window while collateral valuation confirms with a longer one. The result is not a simple stale price; it is a semantic split between state machines.
Oracle caches create the same class of issue. Chainlink's data-feed guidance emphasizes source selection, liquidity, market coverage, and update behavior. Lending protocols such as Aave and Maker maintain their own boundaries between oracle modules and liquidation logic. If a consumer only checks that a price exists, but not when it was updated, how far it deviates from alternate sources, what market depth supports it, and whether a fallback route is active, a stale or low-confidence price becomes an accepted state. A flash loan does not need to break oracle signatures. It may only need to exploit how the consumer reads price state.
A defensive price reader should not return only `price`. It should return:
```text price, timestamp, source_set, deviation, liquidity_depth, confidence_state ```
`confidence_state` can be `normal`, `stale`, `thinLiquidity`, `deviated`, or `circuitBreaker`. Liquidation, cross-chain quoting, and refund valuation should not collapse those states into one number. Price is an input. Price quality is the risk variable.
Liquidation boundaries and slippage VaR
Single-asset liquidation is usually described as collateral value falling or debt value rising until the health factor crosses a threshold. Multi-pool risk turns that line into a surface. Collateral assets, debt assets, LP tokens, synthetic assets, and wrapped cross-chain assets may share liquidity sources or oracle paths. The health factor becomes:
```text H(P_1, P_2, ..., P_m, t, chain_state) ```
`t` is the time window. `chain_state` includes finality, bridge condition, and execution delay. A first-order approximation is:
```text Delta H approximately equals gradient(H) dot Delta P ```
If a price-shock vector `Delta P` can push `Delta H` close to the liquidation boundary in a short window, protection should activate before the liquidation occurs. The value-at-risk here is not a direct copy of traditional finance VaR. It is protocol-level slippage VaR: given current executable liquidity, oracle confidence, and cross-chain delay, how much price displacement can a route or position absorb before settlement becomes unsafe?
Defenses can be layered. The first layer is pre-trade limiting: when path-level `slippage VaR` exceeds a threshold, reduce trade size or split execution. The second layer is pre-liquidation delay: when liquidation is triggered by abnormal price state, require a second source, a second TWAP window, or a short confirmation delay. The third layer is cross-protocol circuit breaking: when several related assets deviate together, pause new risk exposure or large cross-chain releases while preserving refunds and exit paths.
These designs have costs. Delaying liquidation can increase bad debt. Limiting order size can reduce capital efficiency. Multi-source oracle policies add governance and operational complexity. Good engineering does not stop at "add TWAP" or "use a safer oracle." It specifies who pays the cost and how users exit during abnormal states.
Oracle-consumer invariants
Many price incidents are not pure oracle failures. They are consumer failures: the consuming protocol treats price as a context-free number. A robust oracle consumer should maintain at least four invariants.
The first is a time invariant. Prices used for liquidation, quoting, or refund valuation must fall inside an allowed freshness window, and that window should be shorter than the irreversible settlement window of the business action. The second is a source-consistency invariant. If the primary source, fallback source, and AMM-derived price diverge beyond a threshold, the system enters a degraded state rather than blindly selecting one source.
The third is a depth invariant. The market depth behind the quoted price must cover the relevant trade or position size. An oracle can report a correct median price while the actual execution route cannot fill near that price. For a router, that price has little execution meaning. The fourth is a directional invariant. If collateral price moves down while debt-asset price moves up, liquidation risk should be amplified because the risk vector is aligned with the health factor's most sensitive direction.
These invariants should exist both off-chain and on-chain. The off-chain router can run richer correlation models and path selection. The on-chain contract should enforce hard safety thresholds: freshness, maximum deviation, maximum trade size, and circuit-breaker state. If every decision remains off-chain, users cannot verify that risk controls were applied. If every decision is pushed on-chain, gas and data availability limit the model. A pragmatic split is: off-chain systems compute risk scores; on-chain contracts enforce non-bypassable minimum conditions.
Cross-chain pre-execution price gates
Cross-chain exchange has one failure surface that local swaps do not: quote and execution do not occur in one atomic context. After the source-chain payment or lock is complete, the target chain may wait for bridge confirmation, queueing, reorg tolerance, relayer availability, and route rebalancing. If the target side does not re-check price quality immediately before execution, the route may carry an old quote into a new risk state.
This differs from ordinary slippage protection. Slippage protection checks the execution price. A price-quality gate checks whether the execution price comes from a healthy market. A pre-execution gate can check five conditions: whether effective depth still covers the order, whether short and long TWAP windows diverge, whether external oracle data is stale, whether correlated assets are moving abnormally together, and whether bridge or target-chain delay is elevated.
If any condition fails, the action should not become an uncontrolled failed trade. It should enter a controlled branch: re-quote, reduce size, wait for the next price window, or trigger refund. This avoids a gray zone where the price is untrusted but the system still attempts execution.
Refund valuation also needs a gate. If an order is not executed because of abnormal price state, the refund should not depend on a single distorted timestamp. A better design records the original quote context, source-chain paid asset, target-chain intended asset, failure reason, and verifiable timestamp, then applies product rules for original-asset refund, stable-asset refund, or delayed recovery. The key is to separate price anomaly from user intent so that a transient market distortion does not rewrite asset ownership.
Detection signals and defensive state machine
Multi-pool risk signals can be grouped into on-chain, price, and execution categories. On-chain signals include directional trades across related pools in one short window, abnormal reserve movement, rapid LP share movement, and many positions clustering near liquidation boundaries. Price signals include AMM price diverging from external sources, short TWAP diverging from long TWAP, and sudden elasticity changes in low-depth intervals. Execution signals include liquidation transactions failing unusually often, routes re-quoting repeatedly, and target-chain execution observing a materially different price state than the source-chain quote.
A defensive state machine can be:
```text normal, elevatedRisk, guardedExecution, circuitBreaker, recovery ```
`normal` executes standard quotes. `elevatedRisk` reduces per-order size and shortens quote validity. `guardedExecution` requires a fallback price source, a second TWAP, or a larger slippage buffer. `circuitBreaker` pauses new risk exposure while preserving refunds, cancellation, and low-risk exits. `recovery` requires price deviation, liquidity depth, and oracle freshness to return inside thresholds. It should not rely only on manual admin intervention. Recovery conditions also need to be logged for later audit.
The difficult part is false positives. During real market volatility, overly conservative circuit breakers harm users. During a manipulation window, overly loose controls settle wrong prices. A more robust policy is tiered response: limit first, delay second, switch route third, pause only last. Each level should have observable activation and recovery conditions.
AllSwap relevance: quote, execution, and refund are separate states
AllSwap's core use case is cross-chain exchange and route aggregation. Multi-pool price risk affects three different decisions: whether the quote is trustworthy, whether target-chain execution remains inside safe slippage, and whether a failed order can be refunded under an explainable valuation rule. A cross-chain route that reads price only at source-chain quote time may propagate a transiently distorted price to users.
The route layer can split price state into stages: `quoteObserved`, `liquidityReserved`, `oracleChecked`, `targetExecutionReady`, `releaseConfirmed`, and `refundPriced`. Each stage should record price source, update time, slippage VaR, route depth, and chain-finality state. If any stage becomes `deviated` or `stale`, the system should not continue pretending the original quote is deterministic. It should re-quote, limit execution, or move into refund handling.
This is why the lowest-fee route is not always the best route. A cheap path that crosses thin liquidity, a short TWAP, a pool with recent LP migration, or a target-chain stale oracle can carry higher real risk than the visible fee suggests. AllSwap can express that risk in route scoring without exposing a full matrix to users. Executability, refund certainty, and price quality should influence path selection alongside fees.
The implementation detail is that route scoring should be stateful. A route should not only store expected output and fee. It should store the price source, the executable depth used for the quote, the time at which each source was observed, the bridge-finality assumption, and the retry or refund policy if the target-side price gate fails. That record gives the system a deterministic reason for every later action: execute, re-quote, wait, lower size, or refund. Without that record, incident handling becomes a conversation about intent rather than a checkable state transition.
Limits should also be scoped to the risk source. A global daily cap is too coarse for price-quality risk. More useful controls are per-asset, per-route, per-oracle-source, per-target-chain, and per-depth-bucket limits. For example, a route can remain open for small stablecoin swaps while large trades through the same pool require a longer confirmation window. A route can keep refunds available while disabling fresh executions. A path can be acceptable when the primary and fallback oracle agree, but downgraded when only one source is fresh. These controls preserve user exit while reducing exposure to transient wrong prices.
The router should record negative evidence as well as positive evidence. A route that did not execute because the short TWAP and long TWAP diverged should store that reason. A refund caused by stale target-chain oracle data should store the source and timestamp. This matters because cross-chain users do not observe every internal market check. The product needs to explain why an order moved from execution to refund without revealing sensitive route internals or creating a new manipulation surface. Auditable logs also help separate market volatility from routing faults during post-incident review.
For non-custodial products, failure attribution is the key user-facing property. If target-chain price quality is abnormal and execution pauses, the user needs to know which chain holds the funds, which status the order is in, whether refund is available, and which pricing rule applies. The risk system's goal is not perfect completion. It is verifiable, explainable asset state when completion is unsafe.
Open problems
First, DeFi lacks a standard data structure for correlated price risk. Each protocol can describe its own oracle or pool, but there is no common way to express that two price sources are risk-correlated.
Second, TWAP window selection remains a hard trade-off. A short window is easier to manipulate; a long window lags real market moves. Cross-chain finality delay makes that trade-off worse.
Third, real-time on-chain VaR is expensive. Computing a full multi-pool Jacobian and liquidation surface costs gas and data. Production systems need approximations, cached risk buckets, and tiered thresholds.
Fourth, circuit breakers can be misused. Automatic guards reduce attack surface, but opaque recovery rules can become tools for censorship, delay, or selective execution.
Fifth, user interfaces still lack language for price quality. Showing a price is simple. Showing its depth, freshness, deviation, execution meaning, and refund implication is much harder.
References
[1] Uniswap V2 Whitepaper, Hayden Adams et al., 2020, https://app.uniswap.org/whitepaper.pdf
[2] Uniswap V3 Whitepaper, Hayden Adams et al., 2021, https://uniswap.org/whitepaper-v3.pdf
[3] Uniswap V2 Oracles Documentation, Uniswap, https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles
[4] Uniswap V3 Oracle Library Documentation, Uniswap, https://docs.uniswap.org/contracts/v3/reference/core/libraries/Oracle
[5] Curve StableSwap NG Oracle Documentation, Curve Finance, https://docs.curve.finance/stableswap-exchange/stableswap-ng/pools/oracles/
[6] Aave Price Oracle Documentation, Aave, https://aave.com/docs/developers/smart-contracts/oracles
[7] Chainlink Data Feed Selection Documentation, Chainlink, https://docs.chain.link/data-feeds/selecting-data-feeds
[8] Flash Boys 2.0: Frontrunning in Decentralized Exchanges, Daian et al., 2019, https://arxiv.org/abs/1904.05234
[9] Flashot: A Snapshot of Flash Loan Attack on DeFi Ecosystem, Qin et al., 2021, https://arxiv.org/abs/2102.00626
[10] SoK: Decentralized Finance Security and Privacy, 2022, https://arxiv.org/abs/2208.13035
[11] MakerDAO Oracle Module Documentation, MakerDAO, https://docs.makerdao.com/smart-contract-modules/oracle-module
FAQ
How is a multi-pool sandwich different from a normal sandwich attack?
A normal sandwich mostly affects one user's execution price in one pool. Multi-pool sandwich risk concerns how price displacement propagates across AMMs, oracles, lending protocols, and liquidation logic, potentially turning a short-lived wrong price into irreversible settlement.
Does TWAP fully prevent flash-loan price manipulation?
No. TWAP raises manipulation cost but introduces lag. Short windows remain sensitive to shocks, while long windows react slowly to real market moves. Consumers still need freshness, deviation, liquidity-depth, and fallback checks.
What is slippage VaR in this article?
Slippage VaR is a protocol-level estimate of how much price displacement a route or position can absorb under current liquidity, oracle confidence, and cross-chain delay. It is a risk-control approximation, not a direct copy of traditional finance VaR.
Why does AllSwap need to care about multi-pool price risk?
Cross-chain exchange separates quote, target execution, and refund timing. If a route relies on thin liquidity, stale oracles, or abnormal TWAP conditions, the cheapest route can create higher execution-failure and refund uncertainty.
Sources & references
- Uniswap V2 Whitepaper
- Uniswap V3 Whitepaper
- Uniswap V2 Oracles Documentation
- Uniswap V3 Oracle Library Documentation
- Curve StableSwap NG Oracle Documentation
- Aave Price Oracle Documentation
- Chainlink Data Feed Selection Documentation
- Flash Boys 2.0
- Flashot: Flash Loan Attack on DeFi Ecosystem
- SoK: Decentralized Finance Security and Privacy
- MakerDAO Oracle Module Documentation


