Use when you need a conservative Morpho Vaults leaderboard across Ethereum/Base/Arbitrum with strict exposure-asset allowlists and liquidity/whitelist filters.
Conservative DeFi Vaults Ranking
Uses Morpho Vaults V2 GraphQL data to fetch vaults on Ethereum, Base, and Arbitrum, enforce strict exposure-asset address allowlists, apply conservative safety and liquidity filters, and rank by Net APY. Exposure enforcement relies on V2 adapter data: MetaMorphoAdapter (recursive vault exposure) and MorphoMarketV1Adapter (loan/collateral assets). No mock data is allowed.
Deposit Assets (Canonical):
vault.asset.address and mapped to symbols via the address allowlist.WETH -> ETH, WBTC/cbBTC -> BTC for deposit normalization.Exposure Assets (Enforced by Address):
Safety:
whitelisted must be truewarnings must be emptyThresholds:
totalAssetsUsd, fallback to totalAssets / 10^decimals for USDC/USDT)netApy > 0Target Chains:
Ethereum (1)
0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480xdac17f958d2ee523a2206206994597c13d831ec70xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20x2260fac5e5542a773aa44fbcfedf7c193bc2c5990xcbb7c0000ab88b473b1f5afd9ef808440eed33bf0xbe9895146f7af43049ca1c1ae358b0541ea497040x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca00xdc035d45d973e3ec169d2276ddab16f1e407384f0xa3931d71877c0e7a3148cb7eb4463524fec27fbdBase (8453)
0x833589fcd6edb6e08f4c7c32d4f71b54bda029130xfde4c96c8593536e31f229ea8f37b2ada2699bb20x42000000000000000000000000000000000000060x0555e30da8f98308edb960aa94c0db47230d2b9c0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf0x2ae3f1ec7f1f5012cfeab0185bfc7aa3cf0dec220xc1cba3fcea344f92d9239c08c0568f6f2f0ee4520x820c137fa70c8691f0e44dc420a5e53c168921dc0x5875eee11cf8398102fdad704c9e96607675467aArbitrum (42161)
0xaf88d065e77c8cc2239327c5edb3a432268e58310xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb90x82af49447d8a07e3bd95bd0d56f35241523fbab10x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf0x1debd73e752beaf79865fd6446b0c970eae7732f0x5979d7b546e38e414f7e9822514be443a4800529Note: USDS/sUSDS are listed for Ethereum and Base in Sky's official deployments tracker. They are omitted for Arbitrum to avoid guessing.
| Parameter | Type | Default | Description |
|---|---|---|---|
| CHAIN | string | all | Target chain: ethereum, base, arbitrum, or all (all merges results across chains) |
| LIMIT | number | 10 | Number of vaults to return (1-100) |
| FIRST | number | 500 | Vault list page size per chain; auto-downgrades on 5xx responses |
| SKIP | number | 0 | Starting offset for vault list pagination |
| POSITIONS_FIRST | number | 50 | Max positions per adapter; if returned count hits this limit, vault is excluded (conservative) |
| REQUEST_DELAY_MS | number | 100 | Delay between requests in milliseconds to reduce 5xx bursts |
1. Map chain param to chain IDs:
- ethereum -> [1]
- base -> [8453]
- arbitrum -> [42161]
- all -> [1, 8453, 42161]
2. Set result limit (default: 10, max: 100)
3. If chain == all, query each chain separately and merge results
4. Enable pagination with `skip` and `first` for vault lists (default: first=500)
5. Load address allowlists for each chain (see above)
6. Conservative safety gate: whitelisted == true AND warnings.length == 0
Source: Morpho GraphQL API
Endpoint: https://api.morpho.org/graphql
GraphQL query (V2 list):
query VaultV2s($chainIds: [Int!], $first: Int!, $skip: Int!) {
vaultV2s(
where: { chainId_in: $chainIds }
first: $first
skip: $skip
orderBy: TotalAssetsUsd
orderDirection: Desc
) {
items {
address
name
symbol
chain { id network }
asset { address symbol decimals }
totalAssets
totalAssetsUsd
netApy
whitelisted
warnings { type level }
}
pageInfo { countTotal count skip limit }
}
}
Example variables:
{ "chainIds": [1, 8453, 42161], "first": 500, "skip": 0 }
Normalization:
- depositAddress := vault.asset.address (lowercase)
- depositSymbol := map address -> symbol via allowlist
- depositCanonical :=
* WETH -> ETH
* WBTC/cbBTC -> BTC
* else -> same
- liquidityUsd := totalAssetsUsd
- if liquidityUsd is null AND depositCanonical in [USDC, USDT]:
liquidityUsd := totalAssets / (10 ^ asset.decimals)
Filtering:
- whitelisted == true
- warnings.length == 0
- liquidityUsd >= 10_000_000
- netApy > 0
- depositCanonical in [USDC, USDT, ETH, BTC]
Use adapter-specific fields to extract exposure assets. Any unknown adapter type or missing data => exclude vault.
GraphQL query (V2 exposure by address):
query VaultV2Exposure($address: String!, $chainId: Int!, $positionsFirst: Int!) {
vaultV2ByAddress(address: $address, chainId: $chainId) {
adapters {
items {
__typename
type
... on MetaMorphoAdapter {
metaMorpho {
address
asset { address symbol }
}
}
... on MorphoMarketV1Adapter {
positions(first: $positionsFirst) {
items {
market {
loanAsset { address symbol }
collateralAsset { address symbol }
}
}
}
}
}
}
}
}
Exposure rules:
MetaMorphoAdapter: recursively resolve exposures from the nested metaMorpho.address vault.metaMorpho.asset.address and log a warning.MorphoMarketV1Adapter: collect loanAsset.address and collateralAsset.address from all positions.positionsFirst, treat as possibly truncated => exclude vault (conservative).Sorting:
- Primary: netApy (descending)
- Secondary: liquidityUsd (descending)
Take:
- Top N = limit
link := https://app.morpho.org/{network}/vault/{address}
# network comes from chain.network; lowercase it for URL safety
# Recommended fast/stable defaults:
# CHAIN=all LIMIT=10 FIRST=500 POSITIONS_FIRST=50 REQUEST_DELAY_MS=100
python scripts/morpho_v2_conservative_leaderboard.py
# Morpho Protocol Leaderboard (Conservative)
> Top Vaults by Net APY
> Chains: Ethereum, Base, Arbitrum | Updated: 2026-02-05 14:00 UTC
> Filters: Liquidity >$10M USD | whitelisted only | no warnings
---
## Top Vaults
| Rank | Vault | Deposit Asset | Chain | Net APY | Liquidity | Exposure | Link |
|------|-------|---------------|-------|---------|-----------|----------|------|
| 1 | Example Vault A | USDC | Ethereum | 4.75% | $43.4M | USDT, sUSDS | https://app.morpho.org/ethereum/vault/0x... |
| 2 | Example Vault B | ETH | Base | 3.92% | $32.1M | WETH, wstETH | https://app.morpho.org/base/vault/0x... |
---
### Summary
- Total Vaults: 2
- Average APY: 4.33%
- Highest APY: 4.75% (Example Vault A)
---
*Generated by Morpho Protocol Leaderboard*
*Data Source: Morpho GraphQL API*
| Error | Action |
|---|---|
| GraphQL error | Return error payload and stop |
| API Timeout / 5xx | Retry once with backoff |
| Invalid Chain | Return valid options: ethereum, base, arbitrum, all |
| Vault list 5xx | Reduce page size and restart chain pagination |
| Unknown adapter type | Exclude vault (conservative) |
| No Vaults Found | Return table with a single row: No vaults matched filters |
MorphoMarketV1Adapter uses loan/collateral asset addresses, MetaMorphoAdapter is resolved recursively via nested vault adapters.REQUEST_DELAY_MS to throttle requests if 5xx persists.netApy is a decimal rate; multiply by 100 for percentage output.totalAssetsUsd; fallback to totalAssets / 10^decimals for USDC/USDT only.