Risk Scoring Guide
EarnForge computes a composite 0-10 risk score for every vault. Higher score means safer. The score is deterministic, purely data-driven, and based on 7 dimensions with fixed weights.
Score Labels
Section titled “Score Labels”| Score Range | Label | Color |
|---|---|---|
| >= 8.0 | low risk | Green |
| 6.0 - 7.9 | medium risk | Yellow |
| < 6.0 | high risk | Red |
These cuts are calibrated against the live fleet, whose scores span 4.1 to 9.7 with a median of 7.9. The original thresholds (low >= 7, high < 4) put roughly 80% of vaults in “low” and made “high” unreachable, so the label carried no information.
The 8.0 cut is deliberate. A verification-flagged vault scores at most 7.96 even with a perfect showing on every other dimension, so no flagged vault can ever be labelled low risk. That upper bound is real rather than theoretical: no protocol scores above 9, and no asset type scores above 9, so the remaining 0.78 of weight cannot reach 8.0 on its own.
The 7 Dimensions
Section titled “The 7 Dimensions”1. TVL Magnitude (18% weight)
Section titled “1. TVL Magnitude (18% weight)”Measures how much capital is locked in the vault. Higher TVL generally indicates more trust and lower risk of rug pulls or liquidity crises.
| TVL (USD) | Score |
|---|---|
| >= $100M | 10 |
| >= $50M | 9 |
| >= $10M | 8 |
| >= $5M | 7 |
| >= $1M | 5 |
| >= $100K | 3 |
| < $100K | 1 |
2. APY Stability (14% weight)
Section titled “2. APY Stability (14% weight)”Measures how much the current APY diverges from the 30-day (or 1-day) historical APY. Large divergence suggests volatile or unsustainable yield.
| Divergence | Score |
|---|---|
| < 5% | 10 |
| < 10% | 8 |
| < 20% | 6 |
| < 50% | 4 |
| >= 50% | 2 |
The divergence formula is:
divergence = |apy.total - ref| / max(apy.total, ref)Where ref is apy30d (preferred) or apy1d (fallback). If both are null, or either
side is zero, the score defaults to 5 (moderate).
3. Protocol Maturity (18% weight)
Section titled “3. Protocol Maturity (18% weight)”Known protocols receive a fixed tier score based on track record, audit history, and scale. All 27 live protocols carry a tier; the table below is keyed by LI.FI’s unversioned protocol id.
| Tier | Protocols | Score |
|---|---|---|
| Blue chip: multi-year record, deep audits, systemic scale | aave, morpho |
9 |
yearn |
8 | |
| Established: long record or very large, well audited | spark-v2 |
8 |
euler, fluid, pendle, etherfi-staking |
7 | |
ethena, maple |
6 | |
| Mid: real adoption, but young, thin, or unaudited | ipor, midas, kinetiq, hyperlend, upshift |
5 |
| Small or young: audited, but short record and limited scale | avant, cap, neverland, yo, usdai, nest, concrete, infinifi, auto-finance, ember |
4 |
| Examined and still unknown | apyx, hypurrfi |
3 |
| Unknown protocol (fallback) | anything unlisted | 3 |
| Examined, findings adverse | ample |
2 |
Two entries are worth calling out, because they are where size and safety come apart:
kinetiqscores 5 despite $785M TVL: listed 2025-07 with zero audits. Scale is not a substitute for review.amplescores 2, below the unknown-protocol fallback: listed 2026-03, zero audits, and lottery-style payout mechanics. Being examined can be worse than being unexamined.
4. Redeemability (10% weight)
Section titled “4. Redeemability (10% weight)”Whether the vault supports withdrawals. Non-redeemable vaults carry additional liquidity risk since you may not be able to exit your position.
| Redeemable | Score |
|---|---|
Yes (isRedeemable: true) |
10 |
No (isRedeemable: false) |
3 |
5. Asset Type (10% weight)
Section titled “5. Asset Type (10% weight)”Whether the vault holds stablecoins, less any impermanent-loss exposure LI.FI tags.
| Asset Type | Score |
|---|---|
Has stablecoin tag |
9 |
No stablecoin tag |
5 |
| minus impermanent-loss exposure | −3 (floored at 1) |
6. Verification (22% weight)
Section titled “6. Verification (22% weight)”LI.FI publishes verificationStatus on every vault and flags ~10% of the fleet
(74 of 703). The field appears in no spec, changelog, or quickstart, and LI.FI’s own
hosted MCP server does not expose it, but it is LI.FI’s own vault-quality signal, so it
carries the single largest weight here.
| Verification | Score |
|---|---|
| Not flagged | 10 |
Flagged, reason includes apy_outlier |
1 |
| Flagged, any other reason | 2 |
7. Reward Dependency (8% weight)
Section titled “7. Reward Dependency (8% weight)”What share of the yield is paid in token incentives rather than earned. Incentives stop; lending fees generally do not.
| Reward share of total APY | Score |
|---|---|
| 0%. No rewards reported | 10 |
| < 20% | 9 |
| < 40% | 7 |
| < 60% | 5 |
| < 80% | 3 |
| >= 80% | 2 |
Not reported (null) |
7 |
Weighted Formula
Section titled “Weighted Formula”The final score is a weighted average:
score = (tvl * 0.18) + (apyStability * 0.14) + (protocol * 0.18) + (redeemability * 0.10) + (assetType * 0.10) + (verification * 0.22) + (rewardDependency * 0.08)Weight rationale:
| Dimension | Weight | Rationale |
|---|---|---|
| Verification | 22% | LI.FI’s own quality signal. The only dimension sourced from the vendor’s judgment rather than inferred |
| TVL Magnitude | 18% | Strong signal of trust and liquidity |
| Protocol Maturity | 18% | Audit history and track record are the strongest safety indicators |
| APY Stability | 14% | Volatile APY suggests high risk or unsustainable incentives |
| Redeemability | 10% | Ability to exit is important but secondary |
| Asset Type | 10% | Price risk matters but is user-preference dependent |
| Reward Dependency | 8% | Sustainability signal, but a high reward share is a reason to look closer rather than to avoid |
Example Calculations
Section titled “Example Calculations”Both examples are real vaults, scored against the live API.
A clean vault: STEAKUSDC (Morpho, Base)
Section titled “A clean vault: STEAKUSDC (Morpho, Base)”| Dimension | Raw Score | Weight | Weighted |
|---|---|---|---|
| TVL ($579.9M >= $100M) | 10 | 0.18 | 1.80 |
| APY Stability (divergence < 5%) | 10 | 0.14 | 1.40 |
| Protocol (morpho) | 9 | 0.18 | 1.62 |
| Redeemability (true) | 10 | 0.10 | 1.00 |
| Asset Type (stablecoin) | 9 | 0.10 | 0.90 |
| Verification (not flagged) | 10 | 0.22 | 2.20 |
| Reward Dependency (0% rewards) | 10 | 0.08 | 0.80 |
| Total | 9.7 |
Label: low risk. This is the highest score in the fleet.
The highest APY in the fleet: USP (Pendle, Ethereum)
Section titled “The highest APY in the fleet: USP (Pendle, Ethereum)”Advertised at 106.16% total APY. 92.40 points of that are rewards.
| Dimension | Raw Score | Weight | Weighted |
|---|---|---|---|
| TVL ($216K >= $100K) | 3 | 0.18 | 0.54 |
| APY Stability | 10 | 0.14 | 1.40 |
| Protocol (pendle) | 7 | 0.18 | 1.26 |
| Redeemability (true) | 10 | 0.10 | 1.00 |
| Asset Type (stablecoin) | 9 | 0.10 | 0.90 |
Verification (flagged apy_outlier) |
1 | 0.22 | 0.22 |
| Reward Dependency (87% of APY) | 2 | 0.08 | 0.16 |
| Total | 5.5 |
Label: high risk: despite the best headline number on the platform.
import { createEarnForge } from '@earnforge/sdk';
const forge = createEarnForge({ apiKey: process.env.LIFI_API_KEY });const vault = await forge.vaults.get('morpho:8453:_:0xbeef...');const risk = forge.riskScore(vault);
console.log(risk.score); // 9.7console.log(risk.label); // "low"console.log(risk.flags); // [], populated with plain-language reasons when risk is presentconsole.log(risk.breakdown);// { tvl: 10, apyStability: 10, protocol: 9, redeemability: 10,// assetType: 9, verification: 10, rewardDependency: 10 }earnforge risk morpho:8453:_:0xbeef0e0834849acc03f0089f01f4f1eeb06873c9Prints all seven dimensions plus a Flags section naming why a vault carries risk.
Requires @earnforge/cli 1.0.1 or later: 1.0.0 printed five dimensions and no flags.
import { useRiskScore } from '@earnforge/react';
function RiskDisplay({ vault }) { const { data: risk } = useRiskScore(vault); // risk.score, risk.label, risk.breakdown, risk.flags}Prompt: “What’s the risk score for vault morpho:8453:_:0xbeef…?”
The get-vault-risk MCP tool returns the full breakdown as validated structured output.
Filtering by Risk
Section titled “Filtering by Risk”Use the risk-adjusted strategy preset to filter for low-risk vaults only:
const top = await forge.vaults.top({ asset: 'USDC', strategy: 'risk-adjusted', // score >= 7, flagged vaults excluded});Note that the preset’s cutoff of 7 predates the label recalibration, so it admits the
top of the medium band rather than low-risk vaults only. Filter on
riskScore(vault).label === 'low' if you want the stricter reading.
Or use the suggest() engine, which weights allocations by risk score:
const allocation = await forge.suggest({ amount: 10_000, asset: 'USDC',});// Higher-scoring (safer) vaults get larger allocationssuggest() excludes verification-flagged vaults unconditionally. Pass
includeFlagged: true to opt back in.