Concentrated-Liquidity Boundary Coherence and Reverse-Path Discipline
- Name: concentrated-liquidity boundary coherence and reverse-path discipline
- Category: AMM reference / concentrated-liquidity solvency-boundary note / swap-math invariant checklist
- Summary: A healthy concentrated-liquidity AMM does not merely compute plausible prices. It keeps one security object intact across every swap step: current price, current tick, active liquidity, boundary-cross side effects, and any auxiliary liquidity layers all need to agree about which side of each tick boundary the pool is actually on. Just as importantly, it keeps three boundary-state promotions separate:
price moved near or across a boundary,the engine published one semantic answer about which side of that boundary is active, and only laterdownstream paths may spend against that answer as real liquidity truth. This note exists to preserve the positive-design target behind exploits like KyberSwap Elastic: if a pool can end one step withprice says crossedwhileliquidity accounting says not crossed, the market can briefly trade against liquidity that does not exist. The reverse path then becomes the cash-out rail. - Why this note exists:
- tick-liquidity-desynchronization preserves the failure family, but it is useful to state the affirmative design target explicitly: what should a custom CLAMM prove before anyone trusts it with real liquidity?
- Concentrated-liquidity exploit writeups often stop at
rounding error,precision loss, orcustom math bug, which is too soft to guide design review. - The sharper recurring lesson is that swap math, boundary-cross control flow, reverse-swap behavior, and custom liquidity overlays must all preserve one coherent boundary state.
The core design rule
In a CLAMM, price, tick, and active liquidity are one security object. Any step that lets them disagree should revert, not settle.
Healthy designs should not let these become separable:
the engine thinks the tick was not crossedthe final price landed beyond that tickthe active-liquidity update will be deferred until later
If those statements can all be true at once, the later swap path may monetize fictitious liquidity.
Three boundary-state promotions reviewers should not collapse
-
Price approached or even numerically crossed a boundary
- The pool computed a post-step
sqrtP, implied tick, or other geometric position close to or beyond the next initialized boundary. - This is only a geometric observation about where one arithmetic path landed. It is not yet the same thing as
the semantic boundary state changed cleanlyornew liquidity is now spendable.
- The pool computed a post-step
-
The engine published one semantic answer about which side of the boundary is active
- The protocol decided whether the tick was crossed, which liquidity set is active, and which auxiliary-liquidity state now belongs to the live market.
- This is already a stronger claim than
price moved somewhere near the boundary, but it is still not automatically the same thing asevery downstream path may immediately trade against that answer at full size.
-
Downstream swap and reverse-path consumers may spend against that boundary answer
- The pool now lets the next step, the reverse swap, fee logic, or any other money-moving consumer honor the freshly published boundary state as real liquidity truth.
- This is where many CLAMM failures actually pay: the engine did not merely compute or publish an incoherent boundary answer, it let later flow spend against it before any fail-closed check stopped settlement.
The recurring design target is to answer three separate questions cleanly: where did price land geometrically?, what exact semantic boundary state did the engine publish?, and which downstream paths were actually allowed to spend against that publication?
The four joints a healthy CLAMM must keep fused
-
Boundary decision and final-price computation
- The same authoritative logic should determine both
did the swap cross the target tick?andwhat is the resulting post-step price? - If control flow decides crossing in one branch while another branch separately computes
nextSqrtP, the implementation has already created a seam where rounding, truncation, or off-by-one logic can desynchronize state. - A healthy pool makes
not crossedandprice remained on the same sidethe same statement.
- The same authoritative logic should determine both
-
Boundary position and active-liquidity updates
- Crossing a tick is not just a price event. It is also a liquidity-activation event.
- The pool must never carry a state where price-derived boundary position says one liquidity set should be active while the accounting ledger still has the previous set live.
- This is the exact seam that turns arithmetic mistakes into spendable depth.
-
Auxiliary liquidity layers and core swap invariants
- Reinvestment liquidity, fee liquidity, hook-adjusted balances, linked-list traversal helpers, and other custom layers are not side features.
- If they influence step pricing, they are inside the same solvency boundary as base liquidity and tick-cross logic.
- A healthy design proves that these layers cannot move price in ways the crossing logic and reverse path do not understand.
-
Forward-path and reverse-path consistency
- A pool is not safe just because the forward step appears locally plausible.
- The immediate reverse swap is part of the same security proof, because many boundary-state bugs only become profitable when the reverse path activates liquidity, applies fee state, or traverses ticks under corrupted assumptions.
- Healthy CLAMMs should treat
swap then near-immediate inverse swapas a core solvency invariant, not just a regression test.
What sound design looks like
-
Observation, semantic boundary publication, and spend authority stay distinct until the engine can fuse them safely
- A healthy CLAMM can tolerate price moving close to a boundary only if it refuses to let geometric output, semantic boundary state, and spendable liquidity truth drift apart.
- The design goal is not merely
compute a plausible next price; it isonly publish and monetize one boundary state the engine can still defend.
-
One canonical statement of where the pool is relative to the next boundary
- Price-derived tick, cached current tick, target tick, and post-step liquidity state should all describe the same side of the same boundary.
- No helper should be allowed to preserve a stale boundary interpretation after the main price move is known.
-
One monotonic boundary policy per direction
- Exact-in, exact-out, token0-for-token1, and token1-for-token0 paths should all preserve a monotonic rule: non-crossing logic must under-reach or exactly reach the boundary, never silently overshoot it.
- Conservative under-reach is annoying; silent overshoot is a solvency bug.
-
One coherent liquidity ledger across custom layers
- Base liquidity and any synthetic or fee-derived liquidity should participate in boundary logic under a single consistency story.
- If a custom layer can influence price without being reflected identically in activation and deactivation logic, the pool is already maintaining two ledgers for one market.
-
One fail-closed response to impossible geometry
- If a swap step ends in a state that cannot happen under the pool’s own invariants, the system should revert rather than carry that impossible geometry into later fee accounting, reversals, or user-visible pricing.
We'll reconcile on the next stepis not a safe CLAMM policy.
-
One adversarial model that treats vacuum zones as normal
- Zero-base-liquidity regions, narrow attacker-controlled ranges, and one-wei-from-crossing boundary states should be first-class test conditions.
- They are not pathological corners; they are where an attacker can cheapest force the pool to reveal incoherent accounting.
Useful positive design shapes
1. One source of truth for step completion and boundary crossing
- The clean design target from Uniswap-v3-style math is that swap-step completion and tick-cross semantics share one coherent boundary story.
- The reusable point is not
copy Uniswap blindly; it isdo not let custom control flow and custom price math answer the same boundary question differently. - If a fork needs custom liquidity layers or step formulas, it should preserve the same single-authority property explicitly.
2. Differential testing against a simpler reference model
- A production CLAMM may need optimized math, but a security review still benefits from a slower model that enforces
price/tick/liquiditycoherence directly. - The reusable design move is to treat the reference model as an oracle for impossible geometry, especially around
amountToCross ± 1, zero-base-liquidity states, and immediate reversals. - This is often the fastest way to catch custom-step logic that still produces plausible average prices while violating boundary semantics.
3. Reverse-path solvency as a launch gate
- Healthy teams should require proof that a swap followed by its inverse cannot create value through boundary handling alone.
- The reusable lesson from KyberSwap Elastic is that forward-path correctness without reverse-path coherence is not correctness.
- This deserves launch-blocking status for any CLAMM with custom step math, reinvestment liquidity, or nontrivial tick traversal.
4. Production invariant checks on impossible state
- Boundary coherence checks belong in live code for custom CLAMMs, not only in audits.
- The reusable idea is simple: if the implementation ever derives a post-step state where
not crossedcoexists withprice already beyond boundary, revert immediately. - Cheap runtime guards are often a better trade than trusting an optimized path to remain perfect under all boundary states forever.
5. Vacuum-zone and attacker-range testing as standard coverage
- A healthy test harness should intentionally construct the ugly states auditors usually hand-wave past: no base liquidity, narrow attacker-owned range, custom auxiliary liquidity still present, one-wei-short swap amount, and immediate reversal.
- The reusable point is that CLAMM security depends on how the engine behaves when almost no honest liquidity exists near the next meaningful boundary.
Design questions worth asking first
- What exact code path determines
crossedversusnot crossed, and can any downstream math or helper produce a post-step price that contradicts that answer? - If a swap is one wei short of the nominal crossing amount, what invariant proves the resulting price stayed on the same side of the boundary in all directions and modes?
- Which custom liquidity layers influence price, and where is it proven that they cannot desynchronize activation logic from price motion?
- Can the pool ever end a step with price-derived tick, cached tick, and active-liquidity ledger describing different boundary positions?
- What specific tests prove that an immediate reverse swap cannot add liquidity twice, traverse the same boundary twice, or otherwise monetize stale boundary state?
- Where does the engine distinguish
price geometry landed near or beyond the boundary,the semantic crossed/not-crossed answer was published, andthe next swap leg may already spend against that answer as real liquidity truth? - What happens in vacuum zones where base liquidity is zero but auxiliary liquidity terms remain positive or attacker-shaped liquidity controls the next active range?
- If an invariant fails mid-step, does the pool revert, or can it persist a partially updated state that later swaps will trust?
- Has the implementation been differential-tested against a simpler model around
amountToCross - 1,amountToCross, andamountToCross + 1across many ticks and liquidity densities?
Red flags that usually mean the CLAMM is relying on folklore
It is only a precision issuewhen the precision issue can move state across a boundary- custom fee or reinvestment liquidity participates in price math, but reviewers cannot explain in one sentence how crossing logic stays coherent with it
- reverse-swap tests are sparse or treated as optimization coverage rather than solvency coverage
- zero-liquidity or near-zero-liquidity ranges are dismissed as unrealistic even though attackers can deliberately create them
- production code assumes impossible intermediate states will self-heal on the next swap
- the implementation cannot assert directly that
not crossedimpliesprice stayed on the same side - the security argument depends on several cached tick notions staying aligned without one explicit invariant check proving they did
Failure-prevention checklist
- Keep one authoritative boundary decision path per direction. The code that decides
crossedversusnot crossedshould be the same code that constrains the post-step price range, rather than one helper deciding control flow while another helper later computes a contradictorynextSqrtP. - Assert the non-crossing invariant directly in code and tests: if a step claims it did not cross the next tick, the resulting price must still lie on the same side of that boundary under every direction, exact-in/exact-out mode, and rounding branch.
- Couple boundary crossing to liquidity activation atomically. Price movement, tick advancement, liquidity-net application, fee-growth updates, and any custom reinvestment or overlay-liquidity adjustments should settle as one state transition or revert together.
- Treat custom liquidity layers as treasury logic, not surface polish. If reinvestment liquidity, virtual liquidity, hooks, fee layers, or traversal helpers influence price, they must participate in the same coherence proof as base liquidity and tick-cross logic.
- Make reverse-path solvency a launch gate. For boundary-sensitive pools,
swap -> near-immediate inverse swapshould be a first-class invariant proving that no stale boundary state, double activation, or fictitious depth can be monetized. - Differential-test against a simpler geometric model. Optimized production math should be checked against a slower reference implementation that enforces
price / tick / active-liquiditycoherence explicitly, especially aroundamountToCross ± 1, dust liquidity, and vacuum zones. - Fail closed on impossible geometry. If the engine derives
not crossedplusprice already beyond boundary, or any equivalent split-brain state, it should revert immediately instead of carrying that contradiction into later swaps or fee accounting. - Distinguish geometric output from spendable boundary truth. The engine should make it explicit in code and tests that
price moved near or even beyond boundary X,boundary X was semantically crossed, andlater paths may already spend against the new liquidity setare separate claims that only collapse when the invariants proving them have all passed. - Give zero-liquidity and near-zero-liquidity regions explicit policy. Dust states, one-sided ranges, empty-base-liquidity spans, and attacker-controlled narrow ranges should not inherit ordinary path assumptions by accident.
- Instrument boundary coherence in production. Track transitions where price moves close to a boundary without a matching liquidity-net change, and alert on unusual reverse-path profitability or repeated edge-state oscillation.
- Treat upgrades to swap-step math, tick traversal, hook semantics, or auxiliary-liquidity accounting as balance-sheet changes. Re-run coherence and reverse-path suites before shipping even when the patch looks like
just precisionorjust optimization.
Audit prompts
- What exact function or branch is authoritative for
crossedversusnot crossed, and can any later math still compute a post-step price that contradicts that answer? - For
amountToCross - 1,amountToCross, andamountToCross + 1, what invariant proves the pool stays on the expected side of the boundary in both swap directions and both exact-in/exact-out modes? - Can any custom liquidity layer influence price movement without participating identically in tick activation, liquidity-net updates, and reverse-path accounting?
- Is there any reachable state where price-derived tick, cached current tick, next initialized tick, and active-liquidity ledger can describe different boundary positions at the end of one step?
- What concrete tests prove that an immediate inverse swap cannot monetize stale tick state, double-count auxiliary liquidity, or traverse a boundary under a different interpretation than the forward leg used?
- How does the engine behave when base liquidity is zero or dust-sized near the next boundary but auxiliary liquidity terms remain positive?
- Are runtime guards present for impossible geometry, or is the design relying entirely on audit confidence that the optimized path can never desynchronize?
- Which rounding choices are justified only locally? Could any of them become globally unsafe once the reverse path, fee path, or boundary-activation path is considered?
- During upgrades or hook additions, where is the explicit assertion that new custom logic still preserves one coherent
price / tick / liquiditystory? - If an attacker can cheaply park the pool one wei short of crossing, what stops them from iterating that state until a later step trades against liquidity that should not be active?
Lessons that should already be standard
- In concentrated-liquidity systems, precision bugs are often boundary-truth bugs in disguise. The dangerous moment is not
math was slightly off; it ismath let price, tick, and active liquidity stop meaning the same state. - Reverse paths are part of the solvency proof, not post-launch QA. Many CLAMM exploits only become visible when the attacker can immediately trade back through the state the forward leg corrupted.
Price touched the boundary,the engine changed semantic boundary state, andlater flow may already spend against that stateare different claims. Good CLAMMs keep them separate until one coherent state transition proves they can safely collapse them.- Custom liquidity overlays inherit custody-grade review requirements the moment they influence price. Reinvestment or fee-liquidity layers are not harmless extras if swap math can trade against them.
Impossible geometry will self-heal on the next swapis not a safety model. If the pool cannot explain its own boundary state now, it should not keep settling.- Dust and vacuum zones are adversarially reachable operating states, not unrealistic tails. Attackers deliberately buy access to the cheapest boundary conditions.
- The safest CLAMMs are boring at the seam: one boundary decision, one post-step price interpretation, one active-liquidity ledger, and one reverse path that cannot cash out disagreement.
- When teams say
it is just a rounding issue, reviewers should immediately ask whether that rounding choice can move the pool across a tick, change which liquidity is live, or alter what the reverse path can extract.
How to use this note with the exploit corpus
- Start here when the sharper question is
what should a healthy concentrated-liquidity engine keep fused so one boundary mistake cannot become fictitious liquidity? - Drop into liquidity desynchronization when the decisive failure is that boundary state, price state, and active liquidity actually came apart.
- Pair with directional-rounding-bias-roundtrip-non-invariance when the sharper question is whether biased rounding or asymmetrical swap math already lets forward and reverse paths create value before a full tick-state desync is visible.
- Pair with amm-invariant-scaling-mismatch when the sharper question is reserve or invariant scaling rather than concentrated-liquidity boundary handling.
- Pair with residual-liquidity-segregation-and-active-tvl-hygiene only when the issue has shifted from live boundary safety to how a legacy or degraded venue should present remaining balances and route quality.
Internal linkages
- Canonical exploit family: tick-liquidity-desynchronization.
- Adjacent arithmetic cousin: directional-rounding-bias-roundtrip-non-invariance.
- Adjacent invariant cousin: amm-invariant-scaling-mismatch.
- Best concrete case study: KyberSwap Elastic.
Control surface
-
The decisive control surface is the swap-step engine: boundary-cross decision logic, rounding direction, tick traversal, active-liquidity activation, and every custom liquidity layer that can influence price.
-
A concentrated-liquidity AMM is healthiest when all of those pieces still describe one geometric state instead of several nearby approximations that humans hope remain aligned.
-
The dangerous moment is not
a tiny math error happened; it isthe pool is now allowed to believe in and trade against liquidity that should not exist. -
Sources:
-
Last reviewed: 2026-07-28 UTC