Documentation Index Fetch the complete documentation index at: https://docs.generalmarket.io/llms.txt
Use this file to discover all available pages before exploring further.
Morpho Endpoints
Lending is borrowing against the future. These endpoints show you the terms, the position, and how close you are to losing it.
+------------------------------------------------------------------+
| MORPHO API OVERVIEW |
+------------------------------------------------------------------+
| |
| /morpho-position?user=0x... Position + market state |
| /morpho-history?address=0x... Transaction history |
| /user-state?address=0x... Balances + allowances |
| |
| SSE Streams (real-time push): |
| user-positions ............. collateral, borrow_shares |
| oracle-prices .............. NAV price, borrow_rate |
| |
+------------------------------------------------------------------+
Architecture
Two channels: REST for snapshots, SSE for real-time updates. Both read from the same on-chain Morpho Blue state on L3.
+------------------+
| Frontend |
| (React hooks) |
+--------+---------+
|
+------------+------------+
| |
+--------v--------+ +---------v---------+
| REST API | | SSE Streams |
| /morpho-* | | user-positions |
| /user-state | | oracle-prices |
+--------+---------+ +---------+---------+
| |
+------------+------------+
|
+--------v---------+
| Data Node |
| (Rust, Axum) |
+--------+---------+
|
+------------+------------+
| |
+--------v--------+ +---------v---------+
| Morpho Blue | | ITPNAVOracle |
| (L3 Orbit) | | (L3 Orbit) |
+------------------+ +-------------------+
Get Lending Position
Position and market state in one call. Collateral, debt, oracle price, and the computed limits that tell you how much room you have left.
User wallet address (e.g., 0x...). Pass 0x0000...0000 to get market state only.
curl "https://generalmarket.io/api/morpho-position?user=0xYourWalletAddress"
{
"collateral" : "10000000000000000000000" ,
"borrow_shares" : "4850000000000000000000" ,
"debt_amount" : "5012340000000000000000" ,
"oracle_price" : "1045000000000000000000000000000000000000" ,
"max_borrow" : "8046500000000000000000" ,
"max_withdraw" : "4200000000000000000000" ,
"market" : {
"total_supply_assets" : "50000000000000000000000" ,
"total_supply_shares" : "49800000000000000000000" ,
"total_borrow_assets" : "35000000000000000000000" ,
"total_borrow_shares" : "34750000000000000000000"
}
}
Position Fields
Field Type Description collateralstring DTF shares deposited as collateral (18 decimals) borrow_sharesstring Morpho borrow shares (not USDC amount — see debt_amount) debt_amountstring Actual USDC debt including accrued interest (18 decimals on L3) oracle_pricestring DTF NAV price from ITPNAVOracle (36 decimals, Morpho format) max_borrowstring Maximum additional USDC borrowable (18 decimals) max_withdrawstring Maximum collateral withdrawable without liquidation (18 decimals)
Market Fields
Field Type Description market.total_supply_assetsstring Total USDC supplied to the market (18 decimals) market.total_supply_sharesstring Total supply shares minted market.total_borrow_assetsstring Total USDC borrowed from the market (18 decimals) market.total_borrow_sharesstring Total borrow shares minted
A health factor below 1.0 means the position is eligible for liquidation. Compute the health factor client-side using:
healthFactor = (collateral * oraclePrice / 1e36 * LLTV / 1e18) / debtAmount
Get User State
Balances and allowances. What you have, and what you have authorized Morpho to touch.
curl "https://generalmarket.io/api/user-state?address=0xYourWalletAddress"
{
"usdc_balance" : "25000000000000000000000" ,
"usdc_allowance_custody" : "0" ,
"usdc_allowance_morpho" : "115792089237316195423570985008687907853269984665640564039457584007913129639935" ,
"bridged_itp_address" : "0xabc123..." ,
"bridged_itp_balance" : "15000000000000000000000" ,
"bridged_itp_allowance_custody" : "0" ,
"bridged_itp_allowance_morpho" : "115792089237316195423570985008687907853269984665640564039457584007913129639935" ,
"bridged_itp_name" : "Top 100 Crypto Index" ,
"bridged_itp_symbol" : "T100" ,
"bridged_itp_total_supply" : "500000000000000000000000"
}
Field Type Description usdc_balancestring L3 USDC balance (18 decimals) usdc_allowance_morphostring USDC approval for Morpho contract bridged_itp_addressstring Collateral token (DTF) address on L3 bridged_itp_balancestring DTF token balance (18 decimals) bridged_itp_allowance_morphostring DTF approval for Morpho contract bridged_itp_namestring DTF token name bridged_itp_symbolstring DTF token symbol bridged_itp_total_supplystring Total DTF supply (18 decimals)
All values on L3 use 18 decimal USDC (not 6 decimals like on Ethereum mainnet or Arbitrum). See the USDC Decimals section.
Get Lending History
Every deposit, withdrawal, borrow, and repayment. Indexed from on-chain logs. The chain remembers what you did.
curl "https://generalmarket.io/api/morpho-history?address=0xYourWalletAddress"
[
{
"event_type" : "deposit" ,
"amount" : "10000.0" ,
"token" : "T100" ,
"tx_hash" : "0xaaa111..." ,
"block_number" : 54200 ,
"timestamp" : 1708518400
},
{
"event_type" : "borrow" ,
"amount" : "5000.0" ,
"token" : "USDC" ,
"tx_hash" : "0xbbb222..." ,
"block_number" : 54210 ,
"timestamp" : 1708518500
},
{
"event_type" : "repay" ,
"amount" : "2000.0" ,
"token" : "USDC" ,
"tx_hash" : "0xccc333..." ,
"block_number" : 54680 ,
"timestamp" : 1708604800
},
{
"event_type" : "withdraw" ,
"amount" : "2000.0" ,
"token" : "T100" ,
"tx_hash" : "0xddd444..." ,
"block_number" : 55120 ,
"timestamp" : 1708691200
}
]
Field Type Description event_typestring One of deposit, withdraw, borrow, repay amountstring Human-readable amount tokenstring Token symbol (T100, USDC, etc.) tx_hashstring On-chain transaction hash block_numbernumber L3 block number timestampnumber Unix timestamp (0 if unavailable)
Vault Deposit and Withdraw Flow
Deposit USDC. Receive vault shares. The vault lends your capital across Morpho markets. You earn yield. You bear risk. The two are inseparable.
DEPOSIT FLOW
============
+----------+ approve() +----------+ deposit() +-----------------+
| | -----------------> | USDC | ---------------> | MetaMorpho |
| Lender | | (L3) | | Vault (ERC4626)|
| Wallet | <----------------- +----------+ | |
| | vault shares | totalAssets++ |
+----------+ +--------+--------+
|
reallocate() |
+---------------------------------------+
| | |
+-------v------+ +-------v------+ +--------v-----+
| Morpho Market| | Morpho Market| | Morpho Market|
| ITP-A / USDC| | ITP-B / USDC| | ITP-C / USDC|
+--------------+ +--------------+ +--------------+
WITHDRAW FLOW
=============
+----------+ redeem() +-----------------+ withdraw from +--------------+
| | -----------------> | MetaMorpho | ------------------> | Morpho Market|
| Lender | | Vault (ERC4626)| | (available |
| Wallet | <----------------- | | | liquidity) |
| | USDC returned | totalAssets-- | +--------------+
+----------+ +-----------------+
Vault Contract Calls
Standard ERC4626. The interface is familiar. The risk is your own.
Function Description deposit(assets, receiver)Deposit USDC, receive vault shares redeem(shares, receiver, owner)Burn vault shares, receive USDC totalAssets()Total USDC managed by vault totalSupply()Total vault shares outstanding balanceOf(address)User’s vault share balance convertToAssets(shares)Preview USDC value of shares
The vault’s totalAssets includes USDC currently lent out to borrowers. If utilization is very high, a full withdrawal may not be possible until borrowers repay or positions are liquidated.
Curator Allocation Bot
The bot that moves capital where it is needed. It monitors utilization, respects concentration caps, and rebalances without asking permission.
+---------------------+
| Curator Bot |
| (Rust daemon) |
+----------+----------+
|
+------------+------------+
| |
+--------v--------+ +--------v--------+
| Read Metrics | | Set Rates |
| | | |
| morpho.market() | | CuratorRateIRM |
| morpho.position()| | .setRates() |
| vault.totalAssets| | |
+--------+---------+ +---------+--------+
| |
v v
+------------------+ +------------------+
| Allocation | | SERM Algorithm |
| Decisions | | (rate pricing) |
| | | |
| Supply to high- | | Kink curve + |
| utilization mkts | | stress + conc. |
| Withdraw from | | + liquidity + |
| low-util. mkts | | tier premium |
+--------+---------+ +------------------+
|
v
+------------------+
| vault.reallocate |
| (MarketAlloc[]) |
+------------------+
REBALANCING LOGIC
=================
For each market:
utilization = totalBorrowed / totalSupplied * 100
TARGET BAND
0% 50% 70% |===========| 85% 90% 100%
|-----+------+--+-----------+--+------+------|
| | | |
critical target target critical
low min max high
| |
v v
Withdraw Supply
candidate candidate
Risk Tier Concentration Limits
Each DTF market is assigned a risk tier that caps the maximum percentage of vault assets the curator can allocate to it:
Tier Description Max Concentration A Blue-chip, diversified DTFs 30% B Medium risk DTFs 20% C Higher risk, narrower DTFs 10% D Watch list, new DTFs 5%
Example: Vault with $100,000 USDC
==================================
+------------------+------+-------+-----------+
| Market | Tier | Cap | Max Alloc |
+------------------+------+-------+-----------+
| Top 100 Crypto | A | 30% | $30,000 |
| DeFi Blue Chips | B | 20% | $20,000 |
| AI Tokens | C | 10% | $10,000 |
| Meme Index | D | 5% | $5,000 |
+------------------+------+-------+-----------+
Interest Rate Model (CuratorRateIRM)
Most DeFi rate models compute on-chain. This one delegates to an off-chain curator that runs the SERM algorithm — because the inputs (volatility, stress, liquidity) are too complex for a pure on-chain computation. The curator pushes. The contract stores. Morpho reads.
HOW CURATORRATEIRM WORKS
========================
+------------------+ +---------------------+
| Curator Bot | setRates() | CuratorRateIRM |
| (off-chain) | -----------------> | (on-chain) |
| | market_id + rate | |
| Runs SERM algo | | rates[id] = rate |
| every ~5 min | | lastUpdate[id]=now |
+------------------+ +----------+----------+
|
borrowRate()| Called by Morpho
| on every interaction
v
+----------+----------+
| Morpho Blue |
| (interest accrual)|
+---------------------+
SERM RATE FORMULA
=================
rate = kink(global_util) * (1 + stress*0.5) * (1 + concentration) * liquidity_mult + tier_premium
Where:
- kink(global_util): Piecewise linear curve
0%-80% util -> 2%-5% APR (gentle slope)
80%-100% util -> 5%-100% APR (steep slope)
- stress: Weighted avg of 24h price moves across ITP assets
Capped at 5x
- concentration: Penalty for single-asset dominance in an ITP
- liquidity_mult: Illiquid assets pay higher rates
- tier_premium: Extra cost for riskier tiers (C, D)
KINK CURVE (base rate)
======================
APR
100% | *
| *
| *
| *
| *
5% |..............................*
| * |
| * |
| * |
2% |*.................* |
+----+----+----+---+---------+---->
0% 20% 40% 60% 80% 100% Utilization
(kink)
Safety Mechanisms
Mechanism Value Description Minimum rate 0.5% APR Prevents zero-rate exploit Maximum rate 200% APR Prevents absurd rates Staleness timeout 48 hours If curator doesn’t update within 48h, a punitive 100% APR rate kicks in to protect lenders Only Morpho caller — borrowRate() can only be called by the Morpho Blue contractOnly curator setter — setRate() / setRates() can only be called by the curator address
If the curator bot goes offline for more than 48 hours, the punitive rate (100% APR) automatically applies. This protects lenders from stale rates but makes borrowing very expensive. The curator bot is monitored 24/7.
Liquidation Mechanics
When the health factor drops to 1.0, the position is exposed. Anyone can liquidate it. No warning, no grace period. The math is the only judge.
LIQUIDATION FLOW
================
Health factor drops below 1.0
|
v
+----------------+ liquidate() +------------------+
| Liquidator | ------------------> | Morpho Blue |
| | repays portion | |
| Repays X USDC | of borrower debt | Validates HF<1 |
| | | Transfers ITP |
| Receives ITP | <------------------ | collateral at |
| at discount | ITP + bonus | discount |
+----------------+ +------------------+
|
v
+------------------+
| Borrower's |
| Position |
| |
| collateral -= X |
| debt -= Y |
| HF improves |
+------------------+
PARTIAL LIQUIDATION EXAMPLE
===========================
Before liquidation:
+-------------------------------------------+
| Collateral: 10,000 ITP (worth $10,000) |
| Debt: $8,000 USDC |
| LLTV: 77% |
| HF: 0.96 (below 1.0!) |
+-------------------------------------------+
Liquidator repays $2,000 of debt:
+-------------------------------------------+
| Liquidator pays: $2,000 USDC |
| Liquidator gets: 2,100 ITP ($2,100) |
| (5% liquidation bonus) |
+-------------------------------------------+
After liquidation:
+-------------------------------------------+
| Collateral: 7,900 ITP (worth $7,900) |
| Debt: $6,000 USDC |
| HF: 1.01 (back above 1.0) |
+-------------------------------------------+
Key Liquidation Rules
Partial, not full : Only enough collateral is seized to bring the health factor back above 1.0. The borrower keeps the rest.
Anyone can liquidate : Liquidation is permissionless — any address can call liquidate() on Morpho Blue.
Liquidation bonus : The liquidator receives collateral at a discount (bonus percentage set per market).
No grace period : Once HF < 1.0, liquidation is immediate.
Oracle-dependent : The health factor is computed using the ITPNAVOracle price. If the oracle price is stale (> 365 days), the price() call reverts and liquidation is blocked.
DTF Collateral and NAV Oracle
DTF shares are collateral. The oracle that prices them is BLS-verified and oracle-signed. If the oracle lies, liquidations break. So it does not lie.
NAV ORACLE PIPELINE
====================
+------------------+ +------------------+ +------------------+
| Oracle Network | | BLS Aggregation | | ITPNAVOracle |
| (3 oracles) | --> | (2/3 threshold) | --> | (on-chain) |
| | | | | |
| Each computes | | Aggregated BLS | | updatePrice() |
| NAV from prices | | signature | | - verify BLS |
+------------------+ +------------------+ | - check dev <10%|
| - store price |
+--------+---------+
|
price() | Called by Morpho
| on every interaction
v
+--------+---------+
| Morpho Blue |
| Uses price for: |
| - Health factor |
| - Max borrow |
| - Liquidation |
+------------------+
NAV COMPUTATION
===============
ITP = basket of N assets with fixed per-share quantities
NAV = SUM( qty[i] * price[i] ) / 1e18
Example: "Top 10 Crypto" ITP
+--------+----------+----------+-----------+
| Asset | Qty/Share| Price | Value |
+--------+----------+----------+-----------+
| BTC | 0.00015 | $67,000 | $10.05 |
| ETH | 0.0028 | $3,400 | $9.52 |
| SOL | 0.053 | $180 | $9.54 |
| ... | ... | ... | ... |
+--------+----------+----------+-----------+
| NAV per share | $1.0450 |
+--------+----------+----------+-----------+
The ITPNAVOracle uses Morpho’s 36-decimal price convention:
Morpho formula: collateral_raw * price / 1e36 = loan_raw
For ITP(18 dec) / USDC(18 dec on L3):
price = NAV_in_USD * 1e36
Example: ITP worth $1.045
oracle price = 1.045 * 1e36
= 1045000000000000000000000000000000000000
Oracle Safety
Check Value Description BLS verification 2/3 threshold Same multi-pairing BLS as all other protocol operations Price deviation cap 10% per update Rejects jumps > 10% from last price Staleness 365 days (testnet) Oracle price() reverts if too stale Monotonic cycles — Cycle number must strictly increase Replay protection chainId + address Message hash includes chain ID and oracle address
Health Factor Monitoring
The health factor is one number. Above 1.0, you are solvent. Below 1.0, you are exposed. Everything else is commentary on that single ratio.
HEALTH FACTOR FORMULA
=====================
HF = (collateral * oraclePrice / 1e36 * LLTV / 1e18) / debt
Where:
- collateral: ITP amount (18 decimals)
- oraclePrice: from ITPNAVOracle (36 decimals)
- LLTV: Liquidation Loan-To-Value (e.g., 0.77e18 = 77%)
- debt: USDC owed including interest (18 decimals on L3)
HEALTH FACTOR ZONES
====================
HF 0.0 0.5 1.0 1.5 2.0 2.5 3.0+
| | | | | | |
+------+-----+-----+-----+-----+-----+---->
|XXXXX LIQUIDATABLE | | |
|XXXXXXXXXXXXX| | | |
| | | |
| CAUTION | |
| | | |
| MODERATE |
| | |
| SAFE |
| |
VERY SAFE
LIQUIDATION PRICE
=================
The ITP NAV price at which HF = 1.0:
liq_price = debt * 1e36 * 1e18 / (collateral * LLTV)
Example:
collateral = 10,000 ITP
debt = $5,000 USDC
LLTV = 77%
liq_price = 5000 / (10000 * 0.77) = $0.6494 per ITP
If ITP NAV drops to $0.6494, the position is liquidatable.
Monitoring Recommendations
Strategy Description Poll SSE stream Subscribe to oracle-prices for real-time NAV updates and recompute HF client-side REST fallback Poll /morpho-position every 30s for computed fields (debt_amount, max_borrow) Alert threshold Trigger alerts when HF drops below 1.5 Auto-repay Bots can monitor HF and automatically repay debt or add collateral before liquidation
Client-Side Health Factor Computation
// Using values from /morpho-position response
const collateral = BigInt ( position . collateral );
const oraclePrice = BigInt ( position . oracle_price );
const debt = BigInt ( position . debt_amount );
const lltv = BigInt ( "770000000000000000" ); // 77% in WAD
const E36 = BigInt ( "1" + "0" . repeat ( 36 ));
const WAD = BigInt ( "1" + "0" . repeat ( 18 ));
// collateralValue in loan-token units
const collateralValue = ( collateral * oraclePrice ) / E36 ;
// maxBorrow = collateralValue * LLTV / WAD
const maxBorrow = ( collateralValue * lltv ) / WAD ;
// healthFactor = maxBorrow / debt
const healthFactor = Number ( maxBorrow ) / Number ( debt );
SSE Real-Time Streams
Polling is asking the same question repeatedly. SSE is being told the answer when it changes.
user-positions Stream
Pushes raw position data whenever the user’s Morpho position changes on-chain.
{
"collateral" : "10000000000000000000000" ,
"borrow_shares" : "4850000000000000000000"
}
oracle-prices Stream
Pushes the latest NAV oracle price and borrow rate whenever they update.
{
"price" : "1045000000000000000000000000000000000000" ,
"borrow_rate_ray" : "158548960"
}
borrow_rate_ray is the per-second borrow rate in WAD (1e18) format, as set by the CuratorRateIRM. To convert to APR: APR = borrow_rate_ray / 1e18 * 31,536,000 * 100.
Data Priority
Three sources, in order of preference. The fastest wins. The slowest is the fallback of last resort.
+-------------------+ +-------------------+ +-------------------+
| SSE Stream | --> | REST Endpoint | --> | On-Chain Read |
| (instant push) | | (30s poll) | | (wagmi fallback) |
| | | | | |
| collateral | | debt_amount | | vault totalAssets|
| borrow_shares | | max_borrow | | vault balanceOf |
| oracle_price | | max_withdraw | | IRM rates() |
| borrow_rate | | market state | | |
+-------------------+ +-------------------+ +-------------------+
Priority: SSE > REST > on-chain reads
SSE provides instant updates for position + oracle data.
REST fills in computed fields (debt_amount requires market state).
On-chain reads are the fallback for vault-level data not yet in SSE/REST.