Morpho Blue tracks a borrower's debt in borrow shares. Borrowing an exact asset amount rounds newly issued shares up; repaying an exact asset amount rounds burned shares down. To close the debt, pass the position's exact remaining borrow shares with assets set to zero. The core contract then calculates the loan-token payment with upward rounding after accruing interest.
That difference matters at the last payment. A token amount truncated for display can leave debt shares behind. Rounding the token amount up can instead request more shares than the borrower owns and make the transaction revert. A worked integer ledger shows why neither is a reliable substitute for selecting the shares to retire.
Identify the debt and the contract first
This article covers Morpho Blue's variable-rate isolated markets. It examines the core implementation at commit 8e26ca6a8dbc, checked on 28 October 2026. It does not cover Morpho Vault V1/V2 shares or fixed-rate Midnight. A repository pin defines the code examined; verify the actual deployment before applying it.
The Blue contract reference identifies a market through its loan token, collateral token, oracle, interest-rate model and liquidation loan-to-value parameter. A repayment must address that market and the correct borrower. Two markets using the same loan token can have different debt totals and share conversions.
Keep three quantities separate:
- Loan assets are amounts of the borrowed token, represented as raw token base units.
- Borrow shares are internal units recording the borrower's part of the market's debt.
- Collateral is the separate asset backing that borrowing position.
Borrow shares are not an ERC-20 balance in the borrower's wallet. The market-mechanics documentation describes them as internal, non-transferable accounting units. Our Aave scaled-balance comparison illustrates a different accounting system; its ray index must not be substituted for Blue's market conversion.
Include the virtual units before rounding
Let A be totalBorrowAssets, S be totalBorrowShares, and B be the borrower's borrowShares. All three are raw integers. Use borrow totals throughout; the supply side has its own totals.
The pinned SharesMathLib adds one virtual asset and 1,000,000 virtual shares to conversions. One virtual asset means one loan-token base unit, not one whole token. These offsets establish the empty-market conversion and mitigate share-price manipulation; they do not make the exchange rate permanently one million shares per asset unit.
For an asset amount x, calculate shares from:
x × (S + 1,000,000) / (A + 1).
For a share amount q, calculate assets from:
q × (A + 1) / (S + 1,000,000).
Apply the rounding direction selected by the operation. The pinned borrow and repay branches use these four combinations after interest accrual:
| Requested operation | Fixed input | Calculated output |
|---|---|---|
| Borrow exact assets | Token amount | Shares issued, rounded up |
| Borrow exact shares | Shares issued | Tokens received, rounded down |
| Repay exact assets | Tokens paid | Shares burned, rounded down |
| Repay exact shares | Shares burned | Tokens paid, rounded up |
“Down” means the greatest integer no larger than the quotient; “up” means the smallest integer no smaller than it. The MathLib implementation performs integer multiplication and division. Floating-point approximations can select a different integer at the boundary.
The supply-shares versus assets article follows the lender's separate ledger. Choosing the right rounding direction while accidentally using supply totals still produces the wrong repayment.
Follow a hypothetical borrow and partial repayment
The following is a constructed example using fictional loan token U with six decimals. One raw asset unit is 0.000001 U. These are invented accounting states, not a live market, quote or rate forecast. Assume adequate collateral and liquidity, ordinary exact-amount token transfers, empty repayment callback data, and no liquidation or other borrower changes. After the stipulated interest update, hold accrual fixed for the partial payment and closing alternatives.
For the initial borrow, take the following totals after that call's interest accrual and before the new debt is added. Market debt A is 1,234,567,890 raw units, and total borrow shares S are 1,000,000,000,000,000. Our borrower starts with no debt shares and borrows exactly 100 U, or 100,000,000 raw units.
Multiply the requested assets by 1,000,000,001,000,000, divide by 1,234,567,891, and round up. The borrower is assigned 81,000,000,752,491 borrow shares. Following the borrow, A is 1,334,567,890 and S is 1,081,000,000,752,491.
Converting the new borrower shares back with upward rounding gives 100,000,001 raw asset units, or 100.000001 U. The one-base-unit difference from the 100 U received is a conversion outcome in this fixture.
Next, stipulate an interest update adding 12,345,678 raw units to the market's total debt. This is interest across the market, not an amount charged entirely to this borrower. A becomes 1,346,913,568; S and the borrower's shares stay unchanged. The borrower's upward-rounded debt is now 100,925,070 raw units, or 100.925070 U.
The borrower then repays exactly 40 U. Convert 40,000,000 raw assets using the current market totals and round the share result down. That burns 32,103,025,068,046 shares. The resulting state is:
| Field after the partial repayment | Raw integer |
|---|---|
| Market borrow assets, A | 1,306,913,568 |
| Market borrow shares, S | 1,048,896,975,684,445 |
| Borrower's remaining shares, B | 48,896,975,684,445 |
| B converted to assets, rounded down | 60,925,069 |
| B converted to assets, rounded up | 60,925,070 |
The difference between those last two rows is just 0.000001 U. It is enough to produce three different outcomes when supplied to the core repayment function in different ways.
Compare three attempts to close the same debt
Each alternative starts from the post-partial-repayment state above. They are not consecutive payments.
Truncating the asset amount leaves shares behind
Suppose the caller submits 60,925,069 raw assets, displayed as 60.925069 U, with the shares input zero. Asset-mode repayment rounds the shares burned down to 48,896,975,434,487.
Subtract that from B. The borrower still owes 249,958 shares. Market assets become 1,245,988,499, and market borrow shares become 1,000,000,000,249,958. Use these updated totals to value the remainder: upward rounding produces one raw asset unit, or 0.000001 U.
The payment succeeded and the debt remains open. A screen showing only four decimal places could conceal it.
Rounding the asset amount up can revert
Now submit 60,925,070 raw assets instead, again with shares set to zero. The asset-to-share conversion calculates 48,896,976,237,062 shares to burn. That exceeds B by 552,617 shares.
The borrower does not own those extra shares, so the subtraction underflows and the transaction reverts. The core interface documentation explicitly warns that repaying more shares than borrowed reverts. The larger token input is not automatically capped to the borrower's debt.
This also explains why a debt estimate rounded up for funding cannot simply be reused as an exact asset-mode repayment instruction. The two conversions answer different questions.
Selecting the exact shares closes the debt
Set assets to zero and shares to the borrower's actual 48,896,975,684,445. The share-to-asset conversion rounds the required payment up to 60,925,070 raw units, or 60.925070 U.
The transaction burns exactly B. Market assets become 1,245,988,498, market borrow shares return to 1,000,000,000,000,000, and this borrower's shares become zero.
| Closing input | Token payment | Borrower result |
|---|---|---|
| 60,925,069 raw assets | 60.925069 U | 249,958 shares remain |
| 60,925,070 raw assets | Reverted | Debt unchanged |
| Exact remaining shares | 60.925070 U | Zero borrow shares |
Including the earlier 40 U payment, the successful share-close route pays 100.925070 U overall. Alternatively, after the truncated payment, an exact-share repayment of the 249,958-share remainder would cost one raw asset unit at the stipulated unchanged state. Both routes then reach the same final market totals. An extra transaction can still have separate gas costs, which this ledger does not model.
Interest changes the payment, while other actions can change the shares
The interest-rate documentation explains why stored market assets can lag pending accrual. Use the market's actual interest-rate model when calculating the debt expected at a later timestamp; this example assumes no particular rate curve or elapsed period.
The pinned MorphoBalancesLib provides internal helpers for integrators to calculate expected market balances. Its expected borrower asset balance uses upward rounding. It does not expose a callable conversion getter on the core contract, and an expected value is not a guaranteed later payment.
Interest accrual alone leaves B unchanged, so a share-sized close can retire the same debt shares while requiring more tokens. The payer still needs enough loan tokens and allowance. Another repayment, new borrow or liquidation can change B itself. In particular, the Blue reference warns that someone else's small repayment can make a previously prepared share-sized close revert. Refreshing an old token estimate does not resolve an outdated share selection.
Distinguish the core call from a repay-all adapter
For the examined core contract, supply exactly one positive sizing input: assets or shares. The Blue repayment reference says to pass the borrower's share balance for a full repayment.
The current assets-flow tutorial instead demonstrates an SDK 7.0.0 route using repayShares: maxUint256 through BlueBundlesV1. That is a separate integration path. The pinned raw core repayment code has no max-value sentinel that replaces the input with the borrower's current shares. Confirm the actual adapter and version before using a tutorial's sentinel.
The distinction also matters across protocols. The Aave repayment article examines an underlying-payment path with its own cap and self-repayment sentinel. Those behaviors do not define Blue's direct call.
Validate the completed close
Before submitting, record the chain, core address, market parameters, borrower, payer and observation block. Read B and both borrow totals at the same state. If B is already zero, skip the repayment; setting both sizing inputs to zero is invalid. Otherwise, recompute with integer arithmetic, including virtual units and pending interest. For a share-sized close, estimate the token requirement separately from the shares being retired and simulate the exact route.
After confirmation, reconcile these records:
| Record | Required check |
|---|---|
| Transaction receipt | The intended repayment succeeded |
| Repay event | Assets and shares match the executed operation |
| Loan-token movement | The actual payer funded that payment |
| Borrower position | Remaining borrow shares equal zero |
| Collateral position | Any intended withdrawal completed separately |
Repayment itself does not withdraw collateral. The collateral versus interest-bearing supply guide explains those separate balances. If debt remains, assessing its liquidation boundary requires the market's own rules; the broader LTV versus liquidation-threshold guide shows why borrowing capacity and liquidation tests need distinct inputs.
For this example, a reproducible closure record states: 48,896,975,684,445 shares retired, 60,925,070 raw loan-token units paid, and zero borrower shares remaining after confirmation. Keep the exact share result even when the interface displays the token balance as zero.
