Morpho Blue's price() returns a rate between token base units, scaled by 10^36. In the core health check, multiply raw collateral by that price, divide by 10^36 and round down to loan-token base units. For a human quote, divide price() by ten raised to the exponent (36 + loan-token decimals − collateral-token decimals). An 18-decimal collateral and six-decimal loan token therefore use a 24-decimal quote scale.
A very large oracle integer can be correctly scaled. The useful check is whether it reproduces the value of a known collateral quantity in the market's loan token. A screen that divides every Blue oracle answer by 10^36 can pass its contract read while showing the wrong exchange rate.
Identify the collateral and loan units first
This article follows the variable-rate Blue core at v1.0.0, commit 55d2d99304fb. Morpho's current Blue contract reference identifies each market through five parameters: loan token, collateral token, oracle, interest-rate model and liquidation loan-to-value limit (LLTV). Vault V1/V2 accounting and Midnight fixed-rate contracts require their own implementation analysis. The pin here does not identify a particular live deployment.
Call the collateral token C and the loan token L. A base unit is one unit of the raw token integer. If C has 18 decimals, one C contains 10^18 base units. If L has six decimals, one L contains 10^6 base units. The ERC-20 amount guide explains the token metadata behind those display scales.
| Quantity | Unit or purpose |
|---|---|
| Raw collateral amount | C base units |
| Oracle output P | L base units per C base unit, multiplied by 10^36 |
| Oracle normalization constant | 10^36 |
| Collateral value after normalization | L base units |
| Human collateral value | Whole L, after applying L's decimals |
The pinned IOracle interface specifies this pair-dependent interpretation. The core's ConstantsLib separately fixes ORACLE_PRICE_SCALE at 10^36. Different token decimals change how P represents a human quote; they do not change that core constant.
Derive the human quote from the raw-unit rate
Let q mean whole L per whole C. Let dC and dL be the collateral and loan decimal counts. One C base unit is 10 raised to negative dC whole C. Its value is therefore q multiplied by that quantity, expressed in whole L. Converting those L into base units adds a factor of 10^dL.
Consequently, the base-unit exchange rate is q multiplied by 10 raised to dL minus dC. P stores that rate multiplied by another 10^36. To recover q, divide P by ten raised to the combined exponent:
Human-quote exponent = 36 + dL − dC.
Morpho's oracle contract documentation gives the same precision relationship. For ordinary pairs in the following table, the divisor is a positive integer power of ten.
| C decimals | L decimals | Divide P by this for whole L per whole C |
|---|---|---|
| 18 | 6 | 10^24 |
| 8 | 6 | 10^34 |
| 6 | 6 | 10^36 |
| 6 | 18 | 10^48 |
The first row needs twelve fewer human-quote places because the collateral's 18-place scale exceeds the loan token's six-place scale by twelve. That adjustment is already represented in P. Applying another collateral-to-loan decimal correction during raw collateral valuation would repeat the adjustment.
For unusual decimal combinations, treat the exponent algebraically and check the selected oracle's construction and integer range. Do not turn this table into an assumption that every ERC-20 decimal configuration is supported by every adapter.
Reconstruct an 18-to-6 valuation exactly
The following example is entirely hypothetical. C and L are fictional ordinary tokens, and none of the inputs is a live Morpho quote. Assume C has 18 decimals, L has six, and the selected oracle correctly represents a rate of 3,125.75 L per C.
For this pair, P equals 3,125.75 multiplied by 10^24. Its exact integer is 3125750000000000000000000000. This preserves both the human rate and the difference between the token units.
Assume a position has 1234567890123456789 C base units, representing exactly 1.234567890123456789 C. Reconstruct its collateral valuation in this order:
- Multiply that raw collateral integer by P, keeping the product exact.
- Divide the product by 10^36, rounding down for the health-check valuation.
- Format the resulting L base units with L's six decimals.
| Result | Exact value |
|---|---|
| Collateral quantity | 1.234567890123456789 C |
| Human exchange rate | 3,125.75 L/C |
| Value before raw-unit rounding | 3,858.95058255339505821675 L |
| Value rounded down to L base units | 3,858,950,582 |
| Human value of that integer | 3,858.950582 L |
The division discards 0.55339505821675 of one L base unit, equivalent to 0.00000055339505821675 L. This is a numerical rounding difference. The collateral quantity remains unchanged, and no token sale has occurred.
The unit cancellation is the reason the procedure works: C base units multiplied by a scaled L-base-unit-per-C-base-unit rate leave scaled L base units. Dividing by 10^36 removes that rate scale. Only the final display conversion uses L's six decimals.
Use exact integer arithmetic for this reconstruction. The pinned MathLib multiplies before dividing in mulDivDown. Its Solidity multiplication also needs to fit uint256; an off-chain arbitrary-precision result alone does not establish that every proposed input fits the contract's arithmetic.
Locate a scale error before adjusting the answer
Dividing this P by 10^36 yields 0.00000000312575. That number describes L base units per C base unit. Labeling it “L per C” makes the human quote one trillion times too small.
Multiplying the human collateral quantity by that mislabeled rate produces 0.00000000385895058255339505821675 L. The correct unrounded value is 3,858.95058255339505821675 L. The factor between them is exactly 10^12, matching the twelve-place difference between the token decimals.
Other shortcuts fail differently. Integer-dividing P by 10^36 before multiplication gives zero for this fixture. Integer-dividing the collateral amount by 10^18 first leaves only one C and loses the fractional holding. Display formatting should happen after the exact valuation path has preserved those fractions.
Check the price and quantity independently. For one whole C, the raw valuation must produce 3,125,750,000 L base units, displayed as 3,125.75 L. For one C base unit, the exact value is only 0.00000000000000312575 L; downward conversion to L base units produces zero. That zero is expected dust rounding, while zero for the full position identifies a broken calculation.
An Aave scaled aToken balance involves a separate income-index conversion. Blue's P is a collateral-to-loan rate. Importing Aave's 10^27 ray scale would introduce a different quantity into this worksheet.
Apply LLTV and debt conversion after valuation
The pinned Blue health check first rounds collateral valuation down, then multiplies that integer by LLTV and rounds down again using WAD, or 10^18. It compares the resulting maximum debt with upward-rounded debt assets. Equality passes this comparison.
Add an illustrative LLTV of 80%, encoded as 800000000000000000. Multiplying the example's 3,858,950,582 L base units by 0.8 gives 3,087,160,465.6. The second downward rounding leaves 3,087,160,465 L base units, or 3,087.160465 L. Keep this separate from the collateral value above.
Carrying the unrounded collateral value into the LLTV multiplication and rounding only once would instead yield 3,087,160,466 L base units. That is one base unit more. Reproduce the core's two divisions separately when checking a boundary; combining them changes this fixture's result.
Debt needs its own conversion. In SharesMathLib, VIRTUAL_ASSETS is 1 and VIRTUAL_SHARES is 10^6. For borrow shares B, multiply B by totalBorrowAssets plus 1, divide by totalBorrowShares plus 10^6, and round up. The virtual-share constant is independent of L's decimal count.
For example, stipulate totalBorrowAssets of 5,000,000,000 L base units, totalBorrowShares of 5,000,000,000,000,000 internal shares and B of 3,000,000,000,000,001 internal shares. That conversion gives debt of 3,000,000,001 L base units, displayed as 3,000.000001 L. This is below the illustrative maximum debt. All totals must represent the appropriate accrued state; Morpho's market mechanics reference distinguishes stored asset totals from shares.
The broader LTV versus liquidation-threshold guide uses an Aave-style model with separate borrowing parameters. For this Blue calculation, use the actual market's LLTV and integer comparison. The Blue LLTV and liquidation-incentive guide follows what the liquidation parameters mean after valuation. A healthy comparison also does not establish available cash; Blue withdrawal liquidity versus supply examines that separate market constraint.
Validate the oracle boundary and preserve the snapshot
A component feed can have its own decimals. An adapter may combine several feeds or a wrapper exchange rate before returning P. The Chainlink feed-versus-token-decimals guide covers those upstream units. Once reading the market oracle's final price(), interpret its output under IOracle's convention. Do not divide that output by a component feed's precision again.
Morpho is oracle agnostic. The shared interface defines the returned unit but does not certify the underlying price. IOracle exposes no timestamp or round identifier, so checking freshness requires examining the selected implementation and its dependencies. The official oracle inspection guide shows how feed paths, administrators and fixed 1:1 assumptions can matter. A correct decimal calculation can still reproduce an economically unsuitable oracle result.
Retain a record that another reader can reconstruct:
| Snapshot field | Validation |
|---|---|
| Chain, Blue contract and market ID | Recover all five market parameters |
| Collateral and loan contracts | Establish both token identities and decimal counts |
| Oracle address and implementation | Confirm the selected price path and assumptions |
| Block reference and P | Bind the raw output to the position observation |
| Raw collateral and valuation | Reproduce multiplication, division and remainder |
| LLTV and accrued debt inputs | Preserve both rounding stages and virtual constants |
Exercise the record with one whole collateral token, one base unit and the full position. Require the first to reconstruct the human quote, explain dust rounding in the second, and reproduce the loan-base-unit integer in the third. Save those exact results before rounding anything for a screen.
