Aggregating on-chain lending: making fragmented credit comparable
Why DeFi lending data isn't comparable across protocols - and how the 1delta API turns 3,000+ disjoint markets into a single, queryable surface.

If you've ever tried to answer a question as simple as "what's the best USDC supply rate right now?" across DeFi lending protocols, you already know the punchline: the question has no clean answer. Not because the rates aren't on-chain - they are - but because every protocol exposes them differently. Different ABIs. Different math. Different units. Different definitions of risk. Different opinions of what a "market" even is.
A single chain (Ethereum) lists 533 lending markets in our index today, spread across Aave V3, Spark, Compound V3, Morpho Blue, Euler V2, Fluid, Silo V2, and a long tail of smaller deployments. Each one is its own integration. None of them speak the same language.
This article is about why that fragmentation exists, why "just compare the APYs" doesn't work, and how the 1delta API turns those 3,000+ disjoint markets into a single, queryable surface.
Without an aggregator
Every lender on-chain ships its own schema. The fields are named differently, defined differently, and unit-encoded differently. There's no middle layer, so your application either supports one protocol or builds the normalization itself.
The chaos has three flavours, all of which the chart hints at:
1. Fragmentation
"DeFi lending" is no longer a single product category with a few implementations. It's six or seven different products that happen to share the words deposit, borrow, collateral. Aave V3 is a multi-asset cross-margin pool. Morpho Blue is a registry of isolated (collateral, debt) markets. Spark is a CDP attached to a savings rate. Euler V2 is a vault factory. Fluid splits collateral and debt into separate ledgers. Integrating one is roughly the cost of integrating any other - and the long tail keeps growing.
2. Non-unified data: cross-margin vs. isolated markets
The deepest fork is between cross-margin and isolated market designs.
In a cross-margin protocol (Aave V3, Compound V2/V3, Spark, Fluid), every asset you deposit contributes to one shared collateral pot, and every asset you borrow draws from it. There's a single health factor and a single liquidation event. The market is the protocol.
In an isolated protocol (Morpho Blue, Euler V2 vaults, Silo V2), each (collateral, debt) pair is its own market with its own oracle, its own interest-rate model, its own LLTV, its own liquidation. The market is the pair. On Ethereum we currently index dozens of distinct Morpho Blue markets - Morpho wstETH-USDT, Morpho cbBTC-USDC, Morpho WBTC-USDC, each $200M–$700M TVL on its own.
These two designs aren't returning the same data because they aren't modelling the same thing. A "supply rate for USDC on Morpho" isn't well-defined - there are dozens of Morpho USDC markets, each with a different counter-asset and risk profile. Aave's "supply rate for USDC" is one number per network.
3. Comparability: same word, different math
Even where the protocols do model the same concept, they don't agree on how to name or compute it.
| Concept | Aave | Compound | Morpho Blue |
|---|---|---|---|
| Max borrow against a unit of collateral | LTV | Collateral Factor | LLTV |
| Level at which liquidation can fire | Liquidation Threshold (separate from LTV) | same as Collateral Factor | same as LLTV |
| Penalty paid by the borrower at liquidation | Liquidation Bonus (paid to liquidator) | Liquidation Incentive | Liquidation Incentive Factor (different formula) |
| Per-asset cap on supply / borrow | supplyCap / borrowCap (token units) | supplyCap only | per-market, implicit in IRM |
| Interest accrual unit | percent APY per second | per-block rate | per-second WAD rate |
| What "net" yield means after rewards & costs | net APR including incentives | base + tracking APR | base only (rewards via curators) |
An integrator who normalizes only the names (e.g. relabels Aave's liquidationThreshold as collateralFactor) ships a footgun: Aave's LTV and Liquidation Threshold are different numbers, and pretending they're the same as Compound's collateral factor will mis-estimate how close a position is to liquidation by hundreds of basis points.
This is what we mean by non-unified data. The fields don't just have different names; they have different definitions.
With the 1delta API
We wrote one response shape - LendingMarket - and an opinionated mapping from every supported protocol into it. Every numeric field is in the same unit, computed the same way, regardless of where the market came from.
Three things this gives you that the raw protocols don't:
- A universal handle. Every market is keyed by
(chainId, lenderKey, underlying). An Aave V3 cross-margin entry and a Morpho Blue isolated market live in the same address space, even though one is a 12-asset shared pool and the other is a single isolated pair. - Unit-normalized numbers. APR is always in percent. Utilization is always in
[0, 1]. USD values are priced through one shared oracle, so two pools aren't being compared at two different USDC prices. Per-block rates, RAY, WAD, per-second WAD - converted once, on the server. - A unified risk surface. Aave's split
(LTV, Liquidation Threshold), Compound's(Collateral Factor, Liquidation Factor), and Morpho's singleLLTVcollapse into the same(config.collateralFactor, config.liquidationThreshold, config.liquidationIncentive)triple, with the protocol-specific quirks normalized out. A health factor is therefore comparable across protocols.
What this looks like in practice
The lending data surface lives under /v1/data/lending/. Three endpoints carry most of it:
A lender enumeration endpoint returns every (chainId, lenderKey) pair we index on the chains you ask for, sorted by TVL. Ethereum returns 533 entries today - Aave V3 at the top with $11.2B, Spark at $3.0B, then a long tail of Morpho Blue isolated markets, Compound V3 deployments, Euler V2 vaults, and so on.
A latest-data endpoint takes a page of those lender keys and returns one flat array of unified market items. A WETH market in Aave V3 and a WETH market in Compound V3 come back as two entries with the same field names, the same units, and the same risk-score scale - even though under the hood one is IPool.getReserveData and the other is Comet.getAssetInfo.
A pools endpoint pre-filters and pre-sorts across all of them in one call. "USDC supply opportunities above $1M TVL, paying more than 4% APR, with risk score 3 or better" is one request - not seven SDKs and a normalization layer you write yourself.
Why this matters beyond data
Unified data unlocks unified actions. Once a position on Aave and a position on Morpho Blue look the same to your code, you can do things that previously required custom integration per pair:
- Optimize across protocols. Find the cheapest borrow and best supply for a target leverage across every lender we index - not just within one.
- Migrate atomically. A withdraw from Aave → deposit into Compound → borrow on Compound → repay Aave sequence becomes a single signed transaction through the Composer.
- Compare apples to apples in your UI. Health factors, liquidation prices, and net APRs are computed off the same fields, so a "Position" row in your front-end doesn't lie about how risky a Morpho position is relative to an Aave one.
The fragmentation isn't going away - every new credit primitive in DeFi makes the surface area bigger, not smaller. But it doesn't have to be your integration team's problem.
Where to go next
- API reference - endpoints, response shapes, and
x-api-keysetup. - Docs site - narrative guides, supported protocols, network coverage.
- The rest of this series digs into looping, atomic migrations, and the Composer contract that makes the cross-protocol actions atomic.