AMM Invariant Unit-Consistency and Fork-Equivalence Discipline

  • Name: AMM invariant unit-consistency and fork-equivalence discipline
  • Category: AMM core-math reference / fork-equivalence checklist / invariant-review note / pool-math rollout discipline
  • Summary: Healthy AMM teams do not review fee constants, precision multipliers, and invariant guards as separate local edits. They treat the swap path as one solvency proof: the same economic quantity must survive from post-trade balance adjustment to the final invariant check without unit drift, copied-literal divergence, or half-upgraded fee bases. In the canonical Uranium failure, balanceAdjusted = balance * 10000 - amountIn * 16 was still checked against reserve0 * reserve1 * 1000**2, so the final guard literally compared different unit systems and granted about 100x false slack before any real trade economics were considered. This note preserves the positive-design companion to constant-product guard failure when the practical question becomes what should a protocol do before forking or modifying battle-tested pool math so one denominator edit does not become fleet-wide reserve fiction?

Why this note exists

  • AMM fork incidents are often narrated as just a typo, but the more durable lesson is that the pool’s solvency proof was no longer owned as one object.
  • Uranium Finance is the clean preserved exemplar: the fork changed Uniswap v2-style fee-adjusted balance scaling from 1000-based math to 10000-based math, but left the final invariant threshold at 1000**2, so the guard stopped proving reserve solvency at all.
  • Teams frequently inherit a battle-tested AMM and then make small product edits — fee-base changes, precision widening, protocol-fee rewiring, stable-curve coefficient updates, helper extraction, gas optimization, or multi-pool rollout changes — without re-deriving the economic proof those constants originally participated in.
  • The missing healthy-side question is therefore not only did we fuzz swaps? but how do we keep one invariant object, one unit system, and one reference-equivalence claim legible from math derivation through live rollout?

What this note means by invariant unit-consistency and fork equivalence

  • Invariant unit-consistency means every term participating in the AMM’s solvency guard still measures the same economic quantity in the same unit system after fees, normalization, decimal scaling, and rounding conventions are applied.
  • Fork equivalence means that if a protocol claims its AMM remains economically equivalent to a parent design such as Uniswap v2 except for some named parameter change, it can prove that claim with derivation, differential testing, and rollout discipline rather than branding.
  • The design target is not never customize AMM core math. It is never customize core math without making the new proof obligation explicit, testable, and operationally bounded.

Three solvency promotions healthy AMM teams should not collapse

  1. Some invariant-shaped state object exists
  • The pool can compute fee-adjusted balances, an invariant term, or a post-trade threshold comparison object.
  • This is only the weakest fact: the swap path produced a solvency-looking number.
  1. That computed object deserves to count as canonical pool-solvency truth
  • The harder question is whether every multiplier, denominator, precision basis, and threshold term still lives in one unit system and still proves the same economic object the pool claims to preserve.
  • Uranium-style failures happen here: the pool still has a final guard, but the guard no longer measures the same quantity the protocol thinks it does.
  1. That accepted solvency truth deserves this much live reserve authority
  • Even if the math is believed coherent, the protocol still decides how much inventory one accepted post-swap state may move before canaries, caps, pauses, or other containment intervene.
  • This is where staged rollout, pool-family grouping, and runtime outflow bounds become part of the design rather than mere incident response.

Healthy AMM review gets materially better once teams stop flattening those three promotions into one sentence like the invariant check is still there.

The six questions a healthy AMM-core change should answer

1. What exact invariant object is the pool trying to preserve?

  • Reviewers should be able to say what the pool is protecting in one sentence: constant product, stableswap balance, concentrated-liquidity liquidity accounting, or another explicit post-trade solvency relation.
  • We only changed fees is not a mathematical statement. The real question is what quantity the final guard is still supposed to certify after that change.
  • If different helpers, fee branches, or precision paths now imply slightly different invariant objects, the design is already drifting.

2. What unit system does each term live in?

  • Every multiplier, denominator, decimal normalization, and precision basis in the swap path should belong to one readable unit map.
  • A constant such as 1000, 10000, 1e18, Q96, or BPS is never just a number in AMM core math; it is part of the proof that adjusted balances and threshold terms still describe the same quantity.
  • A healthy review asks what are the units on the left-hand side and right-hand side of the final guard now?, not merely did the edited lines compile?

3. What changed constants remain coupled as one proof?

  • The dangerous anti-pattern is duplicated literals or forked helpers whose constants used to agree by construction upstream but now require explicit coordinated change.
  • A changed-constants inventory should name every location participating in the same proof obligation: fee-adjusted balances, reserve-product thresholds, protocol-fee minting, quote helpers, invariant monitors, and any simulation code used to justify rollout.
  • If one edited constant has no explicit sibling map, reviewers are already relying on luck.

4. What reference model or parent design is this pool still claiming equivalence to?

  • When a team says this is Uniswap v2 with different fees or same pool, just more precision, that claim should be operationalized.
  • The implementation should have a reference harness proving where it is intentionally equivalent, where it is intentionally different, and what new edge states the divergence creates.
  • Equivalence claims without a differential test suite are mostly social comfort.

5. What runtime blast radius follows if the proof is wrong?

  • AMM core math bugs are usually fleet-wide because one pair or pool implementation fans out across many markets.
  • A safe design treats core pool-math rollout as protocol-wide change management: staged deployment, canary liquidity, outflow monitoring, pause controls, and clear understanding of how many pools inherit the same arithmetic.
  • One broken pair contract often means all pools sharing this bytecode are now a drain surface.

6. How does the system fail before reserve fiction becomes withdrawable value?

  • Mathematical proof and runtime containment should overlap.
  • Even if invariant math is believed sound, healthy systems still add practical blast-radius controls: staged activation, per-pool caps, monitoring for impossible reserve transitions, and fast pause or delist paths.
  • The goal is not to replace the invariant with guardrails; it is to stop one proof mistake from instantly turning every reserve into attacker inventory.

What sound design looks like

  • One invariant object stays explicit from derivation to code.
    • The protocol can name the exact economic quantity the pool preserves, and every edited line in swap math is justified against that same object rather than by local intuition.
  • One unit map exists for the whole solvency guard.
    • Fee bases, normalization constants, precision scales, and threshold terms are reviewed as one joined dimensional system rather than as scattered literals.
  • Equivalence claims are executable.
    • If the fork claims semantic closeness to an upstream AMM, differential tests and model comparisons make that claim concrete across ordinary and adversarial trades.
  • Core-math rollouts are staged like custody changes.
    • New pair logic, invariant edits, and fee-base changes launch behind canaries, limited liquidity, or constrained pool counts until live behavior proves consistent with the claimed math.
  • Runtime monitors look for impossible reserve state, not only outages.
    • The system alarms on suspicious reserve depletion, outlier swap acceptance, or other states the intended invariant should not admit.
  • The clean reviewer question is: after every edit, do both sides of the final solvency guard still measure the same quantity in the same unit system, and what evidence proves that answer?

Useful positive design shapes

1. A changed-constants ledger for core AMM math

  • Every AMM core change should ship with a short table listing each edited constant, every sibling location participating in the same proof, and the intended economic meaning of the new value.
  • This is the positive-design answer to we changed one denominator but forgot the other one.

2. Reference-model differential harnesses

  • Keep an executable parent-model comparison whenever the product claim is still economically the same AMM, with these named differences.
  • Differential tests should cover small inputs, extreme outputs, fee-on and fee-off branches, reserve depletion attempts, and edge-state rounding.
  • The point is not to prove the upstream is perfect; it is to make unintended divergence visible immediately.

3. Invariant property tests stated in economic terms

  • Test suites should assert reserve-solvency properties such as tiny input cannot buy nearly all opposite reserves and post-swap state still satisfies the intended invariant object.
  • Copying source expressions into tests is not enough if both code and tests share the same wrong literal.

4. Canary pools and staged activation for new math

  • New pair bytecode or materially changed invariant math should reach production through bounded liquidity, low-count canary pools, or temporary outflow limits before full factory-wide rollout.
  • This is the operational companion to mathematical review: if the proof is wrong, the system loses one canary market, not the whole exchange.

5. Fleet-wide bytecode grouping and pause ownership

  • Operators should know which live pools share each math implementation and who can pause, migrate, or delist them if reserve behavior looks impossible.
  • A core AMM bug is rarely one-pool risk; healthy systems keep the fleet map explicit before launch.

6. Reserve-state anomaly monitoring

  • Monitoring should detect conditions the intended invariant should almost never permit: near-total one-sided reserve depletion after tiny inputs, abnormal outflow concentration, or swap outcomes far outside modeled bounds.
  • Good math should still be watched like custody code.

The minimum fork-review packet that should already exist

Before a modified AMM core goes live, a healthy team should be able to hand reviewers and operators one compact packet instead of making them reverse-engineer intent from diffs:

  1. One invariant note

    • The exact post-trade solvency relation the pool claims to preserve, written once in canonical form with units.
    • This is the artifact that answers what quantity are we still protecting after the fee / precision edit?
  2. One changed-constants map

    • Every edited literal, denominator, multiplier, normalization helper, or fee coefficient that participates in the same proof.
    • For each change, the packet should name the sibling locations that must stay synchronized.
  3. One reference-equivalence harness

    • Differential tests against the parent AMM or another explicit reference model for ordinary swaps, edge-state swaps, extreme amountOut requests, and reserve-depletion attempts.
    • If the fork intentionally diverges, the packet should say exactly where and why.
  4. One fleet map

    • Which factories, pair templates, or pool deployments inherit the edited math; which canaries go first; which pause or delist controls exist if the proof is wrong.
    • A core-AMM diff without this map is still an incident-response blind spot.
  5. One live anomaly budget

    • The concrete reserve, outflow, or price-transition conditions that should alarm immediately because the intended invariant ought to make them nearly impossible.
    • This is where the mathematical claim turns into operational detection.

The point of the packet is not bureaucracy. It is to force one proof object, one rollout story, and one incident-response surface to stay visible at the same time. Uranium-style failures usually happen when those three stories drift apart long before exploit day.

Design questions worth asking first

  • What exact invariant does this pool claim to preserve after the proposed fee or precision change?
  • Which constants, helpers, and threshold terms participate in that one proof obligation?
  • If the fork claims equivalence to an upstream AMM, what exact tests prove the claim and where are the intentional divergences documented?
  • Could a tiny input plus an extreme output request now satisfy the final guard because the left-hand side and right-hand side live in different unit systems?
  • How many live pools inherit this bytecode or math family immediately if the change ships?
  • What runtime limits or canaries contain loss if one arithmetic assumption is still wrong?

Red flags

  • It is just a fee-constant update.
  • The upstream proof still mostly applies.
  • We changed the math in one place because the other place looked unrelated.
  • The test suite passes when the tests reuse the same copied formula without a reference model.
  • Only one pair contract changed when the factory will stamp that logic across a fleet.
  • We can always pause later without a grouped map of which pools share the same core math.
  • The invariant check is still there as if presence alone proved it still measures the intended quantity.

Failure-prevention checklist

  • Keep three review questions explicit in design docs and rollout packets: what invariant-shaped object the swap path computes, why it still counts as canonical solvency truth, and how much reserve authority that accepted truth is allowed to carry.
  • Write the intended invariant in one canonical form, with units, before editing fee bases, normalization constants, precision scalars, or threshold terms.
  • Maintain a changed-constants ledger for every AMM core change, explicitly listing every location that participates in the same proof obligation.
  • Differential-test modified pool math against the upstream or reference model across ordinary swaps, extreme amountOut requests, small-input / large-output attacks, and reserve depletion attempts.
  • Add economic property tests that would fail even if code and tests shared the same bad literal: tiny inputs cannot buy nearly all opposite reserves, reserve products do not move into impossible states, and fee-adjusted post-swap balances still satisfy the intended invariant object.
  • Treat AMM core bytecode changes as protocol-wide risk. Stage rollout through canary pools, temporary liquidity caps, or restricted factory deployment before full propagation.
  • Keep a live bytecode-to-pool inventory so one arithmetic anomaly can immediately expand into the full affected pool set.
  • Monitor for impossible reserve transitions and outlier swap outcomes, not only failed transactions or uptime issues.
  • Give responders a narrow emergency path: pause the affected factory family, freeze new liquidity, delist front-end routing, or constrain outflows without waiting for a full protocol shutdown.
  • Require at least one reviewer to re-derive the economic meaning of the final guard after customization rather than only reviewing code diffs or gas changes.
  • Treat battle-tested upstream as a dependency to verify continuously, not as inherited immunity once the fork diverges.

Audit prompts

  • What exact invariant-shaped object is the swap path computing, and is review accidentally treating the arithmetic returned a number as if that already proved pool solvency?
  • After every edit, do both sides of the final invariant guard still measure the same economic quantity in the same unit system?
  • Which duplicated literals or helper-level constants used to agree implicitly upstream but now require explicit coordinated maintenance?
  • If the fork claims semantic equivalence to an upstream AMM, what exact differential harness proves it for adversarial edge states rather than only happy-path swaps?
  • Can a small direct transfer plus a large amountOut request now pass the guard in a way the parent design would reject?
  • What runtime monitors would detect reserve states the intended invariant should never admit before the full pool fleet is drained?
  • How many pools inherit this math immediately, and where is the grouped incident-response plan for that shared bytecode family?
  • Did reviewers re-derive the guard from first principles after the customization, or did they only inspect whether the edited code looked locally plausible?
  • If one fee or precision constant changed tomorrow, what artifact would tell operators every other place that change must stay synchronized?
  • Even if the computed object is coherent, what staged rollout, canary, or outflow budget stops one accepted post-swap state from becoming fleet-wide reserve authority immediately?

Lessons that should already be standard

  • Small AMM math edits are not small risk. One denominator drift can invalidate the whole solvency proof.
  • The invariant check is still there collapses three different claims: a solvency-shaped object exists, that object still counts as canonical pool truth, and that accepted truth deserves immediate reserve authority.
  • Forked from a battle-tested AMM stops being a security property the moment the fork changes the proof obligation but keeps the parent brand halo.
  • A final invariant guard is only protective if both sides still measure the same thing. Presence of a require is not evidence of solvency.
  • Differential testing is not optional when the product claim is same pool, slightly different parameters.
  • Core pool-math changes are fleet changes. If the same pair code backs many pools, one arithmetic bug is already a portfolio-level incident.
  • Runtime guardrails are not a substitute for correct math, but they are still part of good design because AMM bugs tend to fail catastrophically and repetitively.
  • Reviewers should read AMM swap code as one security object: balance adjustments, fee bases, thresholds, helper math, and rollout policy all decide whether reserves remain money-good.

Negative exemplar cluster

  • Uranium Finance is the preserved canonical case: a fork changed the fee-adjusted balance scaling but left the final threshold on the old base, so the pool’s solvency guard became fiction and the attacker replayed the same primitive across 26 pools.
  • The preserved common lesson is not merely someone typoed 1000 vs 10000. It is the protocol stopped treating pool math as one joined proof obligation and had no staged rollout or fleet containment once that proof failed.

How this note complements the exploit corpus

  • Start here when the design question is what should a healthy AMM team do before modifying core pool math so one fee or precision edit does not desynchronize the invariant?
  • Pair with constant-product guard failure when the exploit-side question is the concrete drain pattern.
  • Compare with roundtrip-swap non-invariance when the pool still measures the same invariant object in principle but leaks value through edge-state rounding rather than outright unit drift.
  • Compare with liquidity desynchronization when the sharper failure is concentrated-liquidity state-boundary coherence rather than final-guard unit mismatch.
  • Pair with concentrated-liquidity-boundary-coherence-and-reverse-path-discipline when the design question shifts from forked constant-product pools to state coherence across concentrated-liquidity boundaries.

Internal linkages

Control surface