Price-Domain and Reciprocal-Range Discipline
- Name: price-domain and reciprocal-range discipline
- Category: oracle-and-solvency reference / dimensional-review checklist / reciprocal-boundary checklist
- Summary: Many lending incidents do not fail because the protocol had no price. They fail because the protocol never wrote down what price domain it expected, what reciprocal range it could safely support, or what states were impossible at the seam between oracle publication and borrow-side math. Healthy systems treat
asset / quoteidentity, decimal scale, reciprocal transform, and zero-floor behavior as one review object. This note exists to preserve the design rule that every solvency-critical price path should publish both the supported output units and the supported reciprocal range before the path is allowed to control borrowing, liquidation, or minting. - Why this note exists:
- Oracle incidents are often split too early into
wrong unitsversusinverse rounded to zero, even though both failures begin with one missing artifact: the protocol never made its supported price domain explicit. - Teams regularly verify freshness, liveness, and source identity without forcing themselves to say
what exact units does this path output?andwhat exact reciprocal range can downstream code safely consume? - The useful design habit is to review one end-to-end price object: upstream quantity, final normalized output, downstream reciprocal transform if any, and explicit impossible-state handling.
- Oracle incidents are often split too early into
What this note means by price-domain and reciprocal-range discipline
- Price-domain discipline means the protocol can state the exact final solvency object in plain terms:
this path returns <asset>/<quote> in <scale> after <specific transforms>. - Reciprocal-range discipline means the protocol can also state the downstream borrow-side domain:
if we invert that output as K / price, the supported upstream range is <X>, the supported reciprocal range is <Y>, and zero is impossible state. - The design goal is not just
normalize correctly. It ismake the supported semantic domain and the supported arithmetic domain explicit before balance-sheet logic trusts either one.
Three price-object promotions reviewers should not collapse
1. A source path can print some price-looking number
- A feed, wrapper adapter, composite oracle, or migration branch can return a nonzero integer that is locally well-formed.
- This only proves
some number exists. It does not yet prove the protocol has named the right economic object, the right quote asset, the right decimal scale, or a reciprocal domain the borrow side can safely consume.
2. The protocol can publish that number as final local solvency truth
- The next promotion is stronger: the system has decided that the branch output is already the canonical
asset / quoteobject it wants downstream code to trust. - This is where missing quote legs, decimal mismatches, wrapper-ratio confusion, and silent reciprocal-domain assumptions stop being integration trivia and become balance-sheet policy.
- A price path is already in danger when
some branch returned a numbersilently becomesthis is the final money-good mark for this market.
3. Downstream code may spend against that published truth
- The last promotion is that borrowing, liquidation, minting, redemption, reserve accounting, or health-factor logic is allowed to act on the published mark or its reciprocal transform.
- This is where many incidents actually pay: the protocol did not merely publish an unstable or mis-specified price object, it let a live balance-sheet path spend against it before any guard, quarantine, or de-recognition step intervened.
- Healthy reviews keep
number exists,number is the final solvency object, anddownstream code may already spend against itvisibly separate.
The main design rules
1. Write the final solvency object as dimensional algebra
- Reviewers should be able to say, on paper, what the final output means.
- A healthy oracle review artifact looks like:
- raw source:
cbETH / ETHat1e18 - quote leg:
ETH / USDat1e8 - final output:
cbETH / USDat1e18 - downstream consumer:
collateralValue = amount * price / 1e18
- raw source:
- If the team cannot write that sentence clearly, the price path is not ready for production.
2. Publish both the supported output units and the supported downstream transform
- Some paths end at the final market price. Others hand that price into
K / price,1 / exchangeRate, or another reciprocal normalization step. - The review object should therefore include both:
- semantic domain — what the number means
- arithmetic domain — what numeric range downstream code can safely consume
- This keeps teams from proving only
the feed is dimensionally rightwhile never asking whether the borrow engine can safely invert the result.
3. Treat dimensional correctness and reciprocal safety as one seam
- A price path can fail before inversion because the output is in the wrong unit domain.
- It can also fail after a locally correct output because reciprocal math floors the inverse to zero.
- Healthy design review checks both in one pass:
- are the units right?
- is the scale right?
- does the downstream transform preserve a nonzero safe range?
- what exact outputs are impossible and should revert?
4. Make impossible states explicit
price == 0is usually impossible state.inverse == 0is also usually impossible state.asset / quoteoutputs that differ by several orders of magnitude from the supported market domain may also be impossible state even if they are syntactically valid integers.- A healthy system does not leave those decisions implicit inside comments or operator folklore. It encodes them as guards, pauses, quarantines, or bounded fallbacks.
5. Review launch and migration paths against the same domain sheet
- The useful artifact is not only for new protocol design. It matters at:
- market launch
- oracle migration
- wrapper migration
- new collateral admission
- fallback-branch activation
- defensive-overlay rollout
- If a protocol needs a different unit interpretation or reciprocal bound after a migration, that is a balance-sheet change, not a mere implementation detail.
6. Fuzz for boundary crossing, not only for ordinary prices
- Good tests should push the output across both semantic and arithmetic edges:
- wrong quote leg
- wrong decimal exponent
- enormous but still representable wrapper prices
- reciprocal floor to zero
- The useful question is not only
does the number look right in normal conditions?butwhat exact guard fires first when the path leaves its supported domain?
What sound design looks like
- The protocol can say which promotion boundary it is crossing.
- Reviewers and operators can distinguish
a branch emitted a number,the system accepted that number as the final price object, andborrow / liquidation / mint logic may now spend against itinstead of collapsing those steps into one ambientprice updatedevent.
- Reviewers and operators can distinguish
- The protocol can name the final price object plainly.
- Example:
this path returns cbETH/USD scaled by 1e18is better thanthis path returns a normalized price.
- Example:
- The protocol can name the supported reciprocal domain plainly.
- Example:
the borrow engine inverts this as 1e36 / price and rejects any mark above X because that would floor the reciprocal below 1.
- Example:
- Every branch is reviewable separately.
- Primary path, fallback path, wrapper path, and emergency path each preserve the same semantic domain and supported range, or they fail closed.
- Impossible states are encoded, not narrated.
- If the protocol believes
inverse == 0orcbETH ~= $1is impossible under the supported configuration, it should reject that state directly.
- If the protocol believes
- Tests cross both seams.
- One family checks dimensional correctness; another checks reciprocal nonzero safety.
Useful positive design shapes
1. Domain sheets in market-listing and migration reviews
- Every new market or migration should ship with one short domain sheet:
- raw sources and their units
- final normalized output and its scale
- downstream consumer formula
- reciprocal transform, if any
- supported min/max range
- explicit impossible states
- This is the cheapest habit that prevents a large share of
misconfigurationincidents from hiding as implementation trivia.
2. Dual-side guards
- The oracle side should reject semantically invalid outputs.
- The lending side should reject arithmetic states it cannot safely consume.
- Healthy systems overlap the defenses instead of assuming one side’s correctness makes the other side’s checks unnecessary.
3. Branch-local invariants
- Mixed-source or fallback-heavy oracles should state the domain for each branch independently.
- The right question is not only
does getPrice() return an integer?butdoes every branch return the same economic object in the same scale, and does every downstream transform still stay inside its safe range?
4. Collateral quarantine for fresh or donation-sensitive wrappers
- When a wrapper can print extreme prices cheaply, reciprocal-range review and collateral-admission review should travel together.
- If the wrapper’s supported domain is still mostly theoretical, the protocol should narrow borrow-side authority long before reciprocal collapse becomes reachable.
Negative exemplar cluster: what no explicit domain sheet looks like
- bad-debt liquidations (2026-02-15) — the protocol published
cbETH / ETHas if it were alreadycbETH / USD, so the semantic domain was wrong before any later lending math ran. - whitehat (2023-03-07) and USDC market oracle decimal misconfiguration (2024-10-13) — the protocol published the wrong scale, so the arithmetic domain was already broken at the final price output.
- zero-exchange-rate exploit (2025-06-26) — the upstream wrapper price was economically reachable, but the borrow engine had no explicit reciprocal-range discipline and accepted
1e36 / price = 0as if it were valid solvency state. - The preserved common lesson is not merely
one path had bad unitsand anotherpath had bad reciprocal math. It is that the protocols never forced themselves to publish one supported end-to-end domain sheet before those paths controlled real money.
Red flags that usually mean the seam is underdesigned
The feed address is correct, so the output must be correctThe price looks normalized enoughThe reciprocal is just a harmless internal transformZero can only happen if the price gets absurdly highwithout any enforced bound proving that claimThe primary path is finewhen no one can state the branch-local units and range for fallbacks or wrapper branches- comments that reason in reals while the implementation floors integers to zero
Design questions worth asking first
- What exact economic object does this path publish:
asset / quote, wrapper ratio, LP NAV, or something else? - What exact scale does it publish in?
- Which branch, adapter, or migration step is responsible for the final normalization into the solvency domain?
- Does downstream code consume the raw mark directly or invert it first?
- If it inverts the mark, what is the largest supported upstream value before the reciprocal becomes unsafe or zero?
- Which states are explicitly impossible and how does the system fail when they appear?
- Can operators, auditors, and governance reviewers recover all of that from one short artifact without reconstructing it from several contracts and comments?
Failure-prevention checklist
- Require one domain sheet for every solvency-critical price path that names the raw inputs, branch-local transforms, final output units, scale, downstream consumer formula, reciprocal transform if any, and explicit impossible states.
- Make the three promotions explicit in review artifacts and monitoring:
branch emitted a number,protocol accepted that number as final solvency truth, anddownstream code may now spend against itshould be separately visible rather than implied. - Keep semantic-domain review and arithmetic-range review in the same approval step so a path cannot launch just because the feed address is correct or the decimals look familiar.
- For every branch — primary, fallback, migration, emergency, or wrapper-specific — prove it returns the same economic object in the same scale, or fail closed instead of silently widening the accepted domain.
- Write down the maximum supported direct mark and minimum supported reciprocal before launch; if nobody can state them, the protocol is still depending on folklore rather than an owned invariant.
- Reject impossible states on both sides of the seam: semantically invalid final prices upstream and arithmetically invalid downstream states like
inverse == 0or out-of-domain scale jumps. - Re-run the same domain-sheet review on every oracle migration, collateral migration, wrapper replacement, decimal rewiring, and new listing. Those are balance-sheet changes, not bookkeeping chores.
- Fuzz and invariant-test both classes of boundary crossing: wrong units / wrong scale and truthful-but-extreme direct marks that break reciprocal safety.
- Keep collateral caps, borrow-side quarantine, and fast pause controls under the price path so one domain-sheet miss cannot immediately socialize loss across the whole market.
Audit prompts
- What exact economic object should this path publish at the final consumer boundary, and can reviewers write it down as dimensional algebra without guessing?
- Which branch actually performs the last normalization step into solvency truth, and do all sibling branches preserve that same semantic object?
- What exact scale and quote asset does each branch output, and where would a wrong-unit or wrong-decimal branch first be caught?
- Does downstream code use the direct mark or a reciprocal, and what exact bounds make that arithmetic safe in deployed integer math?
- Are impossible states explicitly encoded, or are they only implied by comments such as
this should never happen? - Which launch, migration, or fallback paths can bypass the reviewed domain sheet in practice?
- Can a fresh wrapper, thin market, or attacker-shaped local mark push the path out of its supported arithmetic domain even if the semantic units remain locally correct?
- If the published price left its supported domain today, which guard would fire first: upstream publication rejection, downstream revert, collateral de-recognition, market pause, or nothing at all?
Lessons that should already be standard
- A correct feed address is not the same thing as a correct solvency object.
A branch returned a number,the protocol accepted that number as final price truth, anddownstream code may spend against itare three different claims. Good reviews keep those promotions separate.- Unit correctness and reciprocal safety are not separate nice-to-haves; they are one joined balance-sheet boundary.
- Domain sheets are security artifacts, not documentation garnish. If a market cannot explain its final price object in one short page, it is not ready to control borrowing.
- Fallback branches and migrations are where semantic drift hides.
Primary path is correctdoes not help if a secondary path publishes a different economic object under the same interface. This value should never reach zerois not a control until the code proves what stops it.- Fresh or manipulable wrappers can keep semantic units locally correct while still pushing arithmetic outside the supported reciprocal range.
- Reviewers need both plain-language meaning and machine-range bounds. A number can be dimensionally correct and still economically unusable downstream.
- When semantic domain, scale, and reciprocal-safe range are reviewed separately by different people, nobody really owns the solvency object.
How this note complements the exploit corpus
- Start with unit-normalization failure when the key question is
did the protocol publish the wrong unit domain or decimal scale as final price truth? - Start with inverse-price floor-to-zero when the key question is
did a large but locally reachable mark become zero-risk collateral after reciprocal floor rounding? - Use this note when the sharper design question becomes
what exact domain sheet should have been written down so reviewers could prove both semantic correctness and reciprocal safety before launch? - Pair with reciprocal-price-normalization-and-nonzero-invariant-discipline when the reciprocal side is the main focus.
- Pair with oracle-migration-quarantine-and-canary-design when the same domain object is changing during a live rollout.
- Pair with collateral-admission-lag-and-borrow-side-quarantine when a fresh wrapper or migrated collateral path should not yet have had full borrow-side authority even if the domain sheet looked locally coherent.
Internal linkages
- Dimensional failure family: unit-normalization failure.
- Reciprocal failure family: inverse-price floor-to-zero.
- Reciprocal-side positive-design companion: reciprocal-price-normalization-and-nonzero-invariant-discipline.
- Rollout companion: oracle-migration-quarantine-and-canary-design.
- Borrow-side rollout companion: collateral-admission-lag-and-borrow-side-quarantine.
- Negative exemplars: moonwell-cbeth-usd-oracle-misconfiguration-bad-debt-liquidations-2026-02-15, tender-fi-tgmx-gmxpriceoracle-decimal-misconfiguration-borrow-drain-whitehat-2023-03-07, morpho-paxg-usdc-market-oracle-decimal-misconfiguration-2024-10-13, resupplyfi-cvcrvusd-donation-zero-exchange-rate-exploit-2025-06-26.
Control surface
-
The decisive control surface is not only
which feed is live. -
It is also who defines the final unit domain, who owns the normalization step, who inverts the result, what numeric range that inversion can safely support, and where impossible states are rejected.
-
Protocols get materially safer when
what does this price mean?andwhat arithmetic range can downstream code survive?are reviewed as one object instead of two loosely connected implementation details. -
Sources:
- unit-normalization failure
- inverse-price floor-to-zero
- reciprocal-price-normalization-and-nonzero-invariant-discipline
- oracle-migration-quarantine-and-canary-design
- moonwell-cbeth-usd-oracle-misconfiguration-bad-debt-liquidations-2026-02-15
- tender-fi-tgmx-gmxpriceoracle-decimal-misconfiguration-borrow-drain-whitehat-2023-03-07
- morpho-paxg-usdc-market-oracle-decimal-misconfiguration-2024-10-13
- resupplyfi-cvcrvusd-donation-zero-exchange-rate-exploit-2025-06-26
-
Last reviewed: 2026-07-28 UTC