Multi-Estimator Monotonicity and Selector-Switch Discipline

  • Name: multi-estimator monotonicity and selector-switch discipline
  • Category: AMM-and-solvency reference / estimator-selection checklist / selector-state monotonicity boundary
  • Summary: Some protocols compute one economic quantity from several candidate estimators — two liquidity estimates, several reserve-value estimates, fallback price branches, or other local views of the same object — and then pick one with min, max, or another selector rule. Those designs are not safe merely because each estimator looks conservative in isolation. They are only safe if teams keep three questions separate: are these branches really measuring the same economic object?, which branch is authoritative right now?, and which downstream rights may immediately spend against that authority? A design fails when selector changes are modeled as a helper detail instead of part of the state machine, and when a reachable sequence can first push the selected estimator artificially low or high and later flip the selector onto a different branch that partially reverses the distortion in a tradeable way. Healthy systems treat which estimator is authoritative right now? as a security boundary, not a harmless implementation detail.
  • Why this note exists:
    • Bunni V2 preserves the sharp negative exemplar: a locally conservative rounding choice pushed one liquidity estimate artificially low, then a later swap flipped the AMM onto the other estimate and monetized the rebound.
    • Many reviews still ask only is each branch individually conservative? instead of the harder question what happens when the protocol is allowed to switch branches under attacker-shaped state?
    • The useful design habit is to review one shared economic object together with its estimator set, selector rule, transition conditions, and downstream consumers.

What this note means by multi-estimator monotonicity

  • Multi-estimator design means the protocol derives one supposedly shared economic quantity from more than one candidate calculation.
    • Examples: liquidityEstimate0 and liquidityEstimate1, primary and fallback price paths, several basket-NAV views, or separate reserve-side estimates that are supposed to describe one pool state.
  • Selector rule means the protocol then decides which estimate becomes authoritative for pricing, minting, redemption, or solvency logic.
    • Common forms: min, max, use branch A unless zero, prefer branch B after threshold, or switch when ratio crosses X.
  • Monotonicity discipline means the protocol proves that reachable selector changes cannot create a tradeable rebound, free convexity, or other economic discontinuity that lets the attacker benefit from moving the authoritative branch and then moving it back.

Three estimator-authority questions reviewers should not collapse

1. Are these branches actually measuring the same economic object?

  • Before arguing about min, max, or fallback order, reviewers need one explicit sentence for what all candidate estimators are trying to describe.
  • two ways to estimate active liquidity, two views of reserve-backed collateral value, or primary and fallback paths for one collateral price object are coherent answers.
  • If the branches are not really interchangeable views of one shared object, selector logic is already being asked to hide a modeling problem.

2. Which branch is authoritative right now?

  • The next question is not whether a branch exists, but which branch currently controls pricing, minting, redemption, liquidation, or reserve accounting.
  • This is where threshold crossings, dust states, zero or sentinel behavior, and fallback conditions become security policy rather than implementation detail.
  • Bunni is the clean reminder that branch A is currently conservative was not enough; the exploit path mattered because the attacker could later move authority back onto branch B.

3. Which downstream rights may spend against that authority immediately?

  • Even if the protocol can justify why one branch is authoritative now, that still does not answer what money-moving paths should be live against it.
  • Swaps, borrows, redemptions, liquidations, reserve refreshes, or share issuance may deserve different distrust windows once selector disagreement becomes large or branch authority has just changed.
  • The dangerous collapse is selector flipped becoming the same event as freshly selected branch may now move reserves at full size.

Three selector-rebound promotions healthy reviews should not collapse

1. One branch may be locally conservative

  • A branch can round down, haircut harder, or otherwise publish a lower estimate than its sibling and still look prudent in isolation.
  • That is only a branch-local fact. It does not yet mean the protocol has found a globally safe solvency object.

2. The selector may promote that branch-local underestimate into canonical shared-object truth

  • Once min, fallback, or threshold logic chooses that branch, the protocol is no longer merely observing a conservative estimate.
  • It has decided that this branch now defines the economic object other code should believe.
  • This is the promotion many reviews understate: a cheap local distortion becomes far more dangerous once selector policy turns it into canonical pricing, liquidity, or collateral truth.

3. A later path may still monetize the rebound when authority moves again

  • Even after a conservative branch has been selected, the system still needs to ask what happens when a later trade, withdrawal, mint, or state transition pushes authority back toward a different branch.
  • If downstream consumers can still trade, redeem, borrow, or liquidate against that rebound immediately, then conservative now was only temporary underpricing waiting for a monetizable reversal.
  • The dangerous collapse is the protocol first picked the lower estimate, so we were safe becoming the same story as a later selector move could not possibly manufacture spendable value.

The main design rules

1. Name the one shared economic object before reviewing the branches

  • Reviewers should be able to state plainly what all candidate estimators are trying to approximate.
  • A healthy review sentence looks like:
    • estimate0 and estimate1 are both candidate views of total active liquidity
    • primary and fallback branches are both candidate views of the same collateral price object
  • If the team cannot name that shared object clearly, it is too early to reason about whether min or max is safe.

2. Treat the selector as part of the protocol state machine

  • The security question is not only is estimator A safe? or is estimator B safe?
  • It is also under what reachable state transitions does authority move from A to B, and what economic rights are still live immediately after that switch?
  • Selector state matters whenever the protocol lets one branch become temporary truth for:
    • swap pricing
    • share issuance or burn pricing
    • collateral valuation
    • reserve refresh or NAV publication
    • liquidation thresholds
  • If the switch itself is not modeled, the protocol is likely proving local branch safety while missing global path dependence.

3. Local conservatism is not enough

  • Use the smaller estimate often sounds safe.
  • Use the larger estimate can also sound safe in reserve-protection or haircut logic.
  • Both claims are incomplete unless the team proves what happens after the selected branch is later replaced by another branch under attacker-controlled state transitions.
  • The real question is whether the protocol ever lets an attacker:
    1. distort one estimator cheaply,
    2. make that distorted branch authoritative,
    3. trigger a selector flip,
    4. trade, mint, redeem, or liquidate against the resulting rebound.

4. Bound or quarantine selector flips when branch disagreement becomes large

  • Large estimator disagreement is not just a numeric detail; it often means the protocol has left its normal operating domain.
  • Healthy designs should consider:
    • pausing or narrowing dangerous actions when estimator spread exceeds a bound
    • delaying activation of a new branch
    • requiring reconciliation before swaps, borrows, or redemptions continue
    • applying the more pessimistic state to all downstream consumers until the disagreement is resolved
    • introducing hysteresis so tiny oscillations or attacker-shaped dust states cannot flip the authoritative branch cheaply
  • Selector flips are free and immediate is often the hidden exploit primitive.

5. Keep branch changes and downstream money-moving rights separated when possible

  • If a selector flip can immediately change live pricing or solvency truth, the protocol has collapsed which branch is currently authoritative? and who may trade against that authority? into the same step.
  • Safer shapes include:
    • publish branch disagreement now, but delay downstream use
    • let withdrawals proceed but freeze swaps
    • let observation update, but keep collateral logic on the old bounded branch until a cooldown passes
    • require a reconciliation path that recomputes one canonical state before regular trading resumes
  • This is the selector-switch cousin of broader publication-authority problems.

6. Test reversible attacker paths, not just steady-state correctness

  • Many multi-estimator systems look fine under forward-only tests.
  • The exploit often appears only when the attacker can:
    • push one estimator into a dust or edge state,
    • make the protocol select it,
    • perform a later action that changes which estimator is chosen,
    • and immediately unwind against the rebound.
  • Good tests therefore need to cover distort -> select -> flip -> cash out, not just one operation at a time.

What sound design looks like

1. One canonical object, many views, explicit selector policy

  • The protocol can say:
    • what shared object the estimators represent,
    • why several estimators exist,
    • what the selector rule is,
    • what exact branch transitions are allowed,
    • and which downstream consumers are allowed to trust the selected branch.
  • If those answers live only in scattered comments or operator intuition, the selector boundary is underdesigned.
  • A good spec or review doc should make it obvious which question it is answering: same object, current authoritative branch, or downstream rights allowed to trust that branch.

2. Estimator disagreement is a first-class alarm condition

  • When branch spread becomes extreme, the protocol should not continue acting as though it still has ordinary high-confidence pricing or liquidity truth.
  • Large disagreement should often mean some combination of:
    • capped trading,
    • delayed settlement,
    • quarantined collateral usage,
    • or forced reconciliation.

3. Selector switches should be monotonic with respect to value extraction

  • A healthy system should prove that switching authoritative branches cannot by itself create value for an attacker.
  • Said another way: if branch A understated and branch B later replaces it, the transition should not create a profit surface that downstream swap, mint, or redeem logic still honors.
  • The sharper version is that branch A was locally conservative is still not enough unless the protocol can also show that selecting A, later leaving A, and then spending against the rebound never manufactures executable value.
  • If the protocol cannot prove this directly, it should assume selector changes need containment.

4. Dust states and branch singularities need explicit handling

  • Many selector bugs appear only when one branch approaches zero, infinity, or a degenerate denominator.
  • Healthy systems explicitly guard:
    • near-zero balances
    • branch outputs that collapse to 0 or 1
    • pathological denominators
    • sudden branch inversions caused by tiny state moves
  • Edge-state branch logic is part of the solvency surface, not a harmless numerical tail.

Negative exemplar cluster

  • liquidity-rebound sandwich drain (2025-09-02) — Bunni computed total liquidity from token0-side and token1-side estimates and chose the smaller one. Tiny withdrawals pushed the token0-side estimate artificially low; a later swap made the token0-side estimate explode and flipped authority back to the token1-side estimate; the attacker sandwiched that rebound.
  • The preserved lesson is not merely rounding was wrong. It is selector-switch economics were not reviewed as one security object with the branch-level arithmetic.

Detection heuristics

  • Fuzz sequences that intentionally create large disagreement between candidate estimators, then attempt an immediate selector flip and unwind.
  • Track the selector as explicit state during tests; do not only inspect final numeric outputs.
  • Assert that profitable roundtrips do not emerge from distort estimator A -> switch to estimator B -> trade -> revert toward normal.
  • Test dust, near-zero, and branch-singularity states even if they seem operationally unlikely.
  • Differential-test against a simpler reconciled model that uses one canonical economic object and compare downstream outcomes, not just local branch outputs.

Red flags

  • We use min/max, so the rule is automatically conservative.
  • Each branch is safe in isolation.
  • The selector is just an implementation detail.
  • If one estimate gets weird, the other one will take over.
  • A later branch flip only restores normal pricing.
  • comments that reason about one operation locally while ignoring multi-step branch-switch sequences

Failure-prevention checklist

  • Name the shared economic object explicitly in code comments, specs, and review docs before discussing individual estimators. If reviewers cannot state what all candidate branches are trying to measure, they cannot reason about selector safety.
  • Treat selector choice as state, not a helper expression. Log, test, and review the exact conditions under which authority moves from estimator A to estimator B, including whether the switch can happen intra-transaction or same-block before downstream rights are curtailed.
  • Bound or quarantine large estimator disagreement. When branch spread exceeds a plausible operating range, narrow or pause the money-moving actions that consume the selected output instead of letting the selector keep flipping under attacker-shaped state.
  • Add hysteresis, cooldowns, or one-way reconciliation where appropriate so tiny state changes, dust balances, or denominator singularities cannot repeatedly toggle the authoritative branch.
  • Separate branch publication from branch monetization when possible. A protocol can observe disagreement immediately while delaying swaps, borrows, redemptions, or collateral recognition until one canonical state is re-established.
  • Test specifically for conservative branch first, monetizable rebound later. If the argument for safety starts with we always take the lower estimate or we always take the higher haircut, reviewers should require a composed-path proof that later selector changes cannot refund the attacker through a different branch.
  • Test full reversible attacker paths, not only single-operation safety. Coverage should include distort -> select -> flip -> cash out -> unwind across dust states, near-zero balances, and branch outputs near zero or infinity.
  • Differential-test against a simpler canonical model that computes one reconciled economic object, then compare downstream outcomes rather than only local branch arithmetic.
  • Treat branch singularities as first-class solvency surfaces. Explicitly guard near-zero denominators, zero-liquidity ranges, branch outputs that collapse to zero, and thresholds where the selector can change authority abruptly.
  • Document which downstream consumers are allowed to trust the selected branch: swap pricing, share issuance, redemption, liquidation, reserve reporting, collateral valuation, or dashboard-only presentation. The more rights the branch carries, the stricter selector discipline needs to be.
  • Require incident-response and operator playbooks to say what happens when estimator disagreement spikes in production: who gets paged, which actions are disabled, and how the system returns to one trusted state.

Audit prompts

  • What exact shared economic object are these estimators meant to describe, and do all downstream consumers treat them as interchangeable views of that same object?
  • Under what reachable state transitions can the protocol switch from one authoritative estimator to another, and what money-moving rights remain live immediately after the switch?
  • Can an attacker cheaply push one estimator into a dust, near-zero, or pathological denominator state without paying the same economic cost the selected branch will later let them recover?
  • If branch A is chosen today because it is smaller or larger, what prevents a later action from flipping authority to branch B and partially reversing the distortion in a tradeable way?
  • Where does the review separately prove branch-local conservatism, selector-level promotion into canonical truth, and downstream inability to monetize a later rebound, instead of assuming the first one implies the other two?
  • Does the protocol merely assume min or max is conservative, or can it prove that selector flips cannot create free convexity, profitable rebounds, or temporary underpricing / overpricing surfaces?
  • When estimator disagreement becomes extreme, does the system continue admitting swaps, borrows, minting, redemption, or liquidation as though the shared object were still well defined?
  • Are selector transitions observable in logs, metrics, and tests, or would operators only notice a dangerous branch flip indirectly through price impact or solvency drift?
  • Which functions can publish, cache, sync, or otherwise make one estimator authoritative for downstream consumers, and can those writes be timed around attacker-shaped transient state?
  • Where does the protocol distinguish these branches still describe the same shared object, this branch is authoritative right now, and reserve-moving logic may immediately spend against that branch at full size?
  • Have reversible sequences been fuzzed across branch thresholds: amount - 1, amount, amount + 1, dust withdrawals, thin liquidity, partial harvests, and immediate inverse actions?
  • If a selector flip happened repeatedly over several blocks, what exact value could leave before governance or operators could intervene?

Lessons that should already be standard

  • Conservatism is path-dependent. A branch that looks safer in isolation can become the profit leg of an exploit once the protocol lets authority switch away from and back to it.
  • Locally conservative is not the same thing as globally safe once selected and still not the same thing as safe after a later selector rebound. Good reviews keep those promotions separate.
  • Which estimator is live right now? is part of the security boundary. Treating selector logic as a convenience helper is how local arithmetic reviews miss global economic exploits.
  • These branches describe one object, this branch currently wins, and downstream consumers may now spend against it are three different claims. Good reviews keep them separate instead of letting selector choice silently promote fresh branch authority into full monetary authority.
  • Large estimator disagreement is not ordinary noise. It is often the protocol’s strongest signal that its supposed single economic object has split into several attacker-shapable stories.
  • Branch flips deserve the same containment thinking as oracle updates, harvest publication, or governance-controlled parameter changes. The publication step and the monetization step should not collapse into one unchecked action.
  • Dust and near-singularity states are where selector bugs get cheap enough to exploit. If the design argument only works for deep, well-behaved balances, the design argument is incomplete.
  • Differential models are especially valuable here because they expose branch-switch economics even when each branch’s local arithmetic still looks plausible.
  • If operators cannot explain what they would do when estimator spread blows out in production, the system is probably over-trusting selector logic already.

Where this note stops

How to use this note with the exploit corpus

Internal linkages

Control surface