Webacy continuously scores thousands DeFi vaults across Ethereum, Arbitrum, Base, Optimism, Polygon, and BSC (with more coverage coming soon). Every vault gets a composite risk score, a listing verdict, real-time withdrawal signals, and a 90-day history.
Risk Tiers
Letter Grades
Each vault receives a letter grade (A–F) derived from its composite risk score. Grades are the inverse of risk — A is safest, F is most dangerous. The expected capital-at-risk ranges are calibrated against historical DeFi exploit loss data.
Letter grades align with risk tiers: A maps to Low, B spans Low/Medium, C spans Medium/High, D maps to High, and F maps to Critical. Thevault_grade field is available on all vault records alongside the numeric vault_score (0–100).
Listing Verdict
Every vault receives a listing_verdict — a clear signal for teams deciding whether to integrate, list, or accept a vault as collateral. It’s computed from the composite risk score plus hard blocking conditions, updated with every data refresh.
Available via GET /api/vaults → listing_verdict field on each vault item.
Withdrawal Risk
The withdrawal_risk field tells you how freely users can exit a vault right now. For Morpho vaults, utilization is fetched live every ~5 minutes, so this signal reflects actual on-chain liquidity — not yesterday’s data.
Real-Time Data Signals
Several signals are fetched live at request time and overlaid on top of nightly pipeline data. This means the dashboard reflects current on-chain conditions, not just yesterday’s snapshot.
| Signal | Source | Freshness | Coverage |
|---|
| Share price | DeFiLlama coins API | ~5 min | ~18% of vaults (those with DEX liquidity) |
| Morpho utilization rate | Morpho Blue GraphQL | ~5 min | All Morpho vaults |
| Vault score (utilization) | Recomputed from live utilization | ~5 min | All Morpho vaults |
| Withdrawal risk level | Live utilization + stored flags | ~5 min | All vaults |
Price indicator: A green dot (●) next to a share price means DeFiLlama provided a live quote. A grey dot means the price is from the last nightly pipeline run. Prices above $500 or equal to zero are treated as bad data and shown as —.
Score History & Trends
Every vault detail page includes a 90-day score sparkline so you can see whether a vault is improving, degrading, or stable over time. The delta badge shows the score change vs 30 days ago.
Each daily snapshot records:
• Risk score (0–100)
• Tier (low / medium / high / critical)
• Active risk flags
• Share price
• Looping exposure %
History endpoint: GET /api/vaults/[chain:address]/history — returns up to 90 snapshots.
Share Price & Depeg Signals
last_share_price is the vault token price in USD. For yield-bearing vaults — sDAI, sUSDe, Yearn, Fluid — the share price legitimately drifts above $1 as yield accumulates. This is expected behaviour, not a risk signal. Depeg flags only fire when the price falls meaningfully below par.
Monitoring Status
Each vault is assigned a monitoring_status derived from TVL and trend data. Legacy and deprecated vaults are hidden by default in the dashboard (toggle with ‘Show legacy (N)’).
| Status | Condition | What it means |
|---|
active | TVL ≥ $500K and no severe trend decline | Fully monitored and shown by default |
watch | TVL $100K–$500K OR TVL dropped >50% in 90d | At-risk; shown by default but flagged |
legacy | TVL < $100K | Effectively dead capital; hidden by default |
deprecated | Protocol officially shut down | Hidden by default |
Actionability Class
Every vault output includes an actionability_class that identifies the dominant risk driver and returns a targeted one-line action recommendation. The class with the highest weighted average sub-score wins.
| Class | Key sub-scores | Example action |
|---|
smart_contract | Protocol risk (40%), Code (20%), Audit recency (10%), Oracle (10%), Asset (10%), Webacy code (10%) | “Reduce position: elevated code or protocol risk warrants caution.” |
liquidity_lock | Closed liquidity (50%), Utilization (30%), Utilisation risk (10%), Exit liquidity (10%) | “Exit now: liquidity is critically constrained.” |
governance | Centralization (40%), Upgrade (30%), Strategy (15%), Governance behavior (15%) | “Reduce position: centralization or upgrade risk is elevated.” |
market_conditions | Depeg (35%), Looping (25%), TVL outflow (20%), Size (10%), Maturity (10%) | “Reduce exposure: market or collateral conditions are deteriorating.” |
Action verb (monitor / review / plan / watch / reduce / exit) is selected by combining class × tier. The actionability_class, actionability_action, actionability_detail, and actionability_class_scores fields are all available in the API output.
Exchange Rate Velocity
ERC-4626 vaults accumulate yield slowly — a 15% APY vault moves ~0.04% per day. A sudden large movement in the exchange rate is a direct indicator of an attack in progress or structural failure.
| Signal | Threshold | Scoring Impact | Pattern |
|---|
exchange_rate_spike | > +2% since last checkpoint | Hard floor at 70 (critical boundary) | Donation attack — assets transferred directly into vault inflate convertToAssets() without minting shares. Venus wUSDM: 65% jump → $902K bad debt (Feb 2024). |
exchange_rate_crash | > −1% since last checkpoint | Hard floor at 65 (high tier) | Exploit in progress, collateral collapse, or bad-debt crystallisation. Yield vaults should never go down for stablecoins. |
Previous price is persisted across pipeline runs. No external API required — uses the share price already fetched by the Trading Strategy enrichment.
ERC-4626 Donation Attack Risk
When an ERC-4626 vault is used as collateral in a lending protocol and that protocol prices it via convertToAssets(), the vault becomes vulnerable to a donation attack: an attacker transfers assets directly into the vault contract (without calling deposit()), inflating the exchange rate without minting new shares. The lending protocol’s oracle reads the inflated rate and allows overborrowing against the manipulated collateral.
Venus wUSDM (Feb 27, 2024):Attacker donated USDM directly into the wUSDM contract, inflating the exchange rate from 1.0694 → 1.764. Venus used convertToAssets() as its price oracle with no TWAP or manipulation protection. ~$902K bad debt generated from a $350 initial deposit.
DetectionVault is ERC-4626 AND its address appears as collateralAsset in ≥ 1 active Morpho market. Queried via Morpho Blue GraphQL at scoring time.
Scoring Impacterc4626_donation_risk = true → +15 additive penalty + erc4626_donation_risk flag. This is a latent (pre-exploit) structural risk; pair with exchange rate velocity for real-time detection.
Large Redemption Alerts
Every 6 hours, Webacy scans 24 hours of on-chain Withdraw events across 600+ vaults (TVL ≥ $500K) to detect concentrated exits before they appear in price data. A vault is flagged when a single wallet redeems more than $500K or more than 1% of vault TVL within the lookback window.
| Chain | Lookback window | Data source |
|---|
| Ethereum | 24h | Alchemy (primary) → Etherscan V2 (fallback) |
| Arbitrum | 2h (high-frequency chain) | Etherscan V2 → Moralis (fallback) |
| Base | 24h | Etherscan V2 → Moralis (fallback) |
| Optimism | 24h | Etherscan V2 → Moralis (fallback) |
| Polygon | 24h | Etherscan V2 → Moralis (fallback) |
| BSC | 6h | Etherscan V2 → Moralis (fallback) |
Flagged vaults receive a large_redemption_alert risk flag and expose four fields: large_redemption_count_24h, large_redemption_usd_24h, large_redemption_max_pct_tvl, and large_redemption_wallets. Each alert run is archived to S3 at vaults/redemption-alerts/{date}/{timestamp}.json.
Risk Summary (Natural Language)
Every vault includes a risk_summary field — a one-sentence plain-English explanation of why the vault scored the way it did. Generated deterministically from the top weighted sub-score contributors and highest-priority active flags. No LLM required.
Example“Score 74 (HIGH). Primary drivers: restricted withdrawals, centralized governance, unverified/unaudited code. Active signals: yield trap, thin collateral market.”
Available as risk_summary on every vault record. Useful for surfacing in alerts, reports, and API consumers without additional processing.
Output Fields Reference
Additional fields returned on every vault record. These fields feed into the scoring pipeline and are exposed in the API response for consumers that need to inspect data freshness, vault architecture, or audit provenance directly.
| Field | Type | Description |
|---|
data_as_of | ISO 8601 timestamp | When this vault was last scored and enriched by the pipeline. Used in the UI as a staleness indicator — an amber ⚠ badge appears when the timestamp is more than 48 hours old. Useful for API consumers to detect stale records before acting on them. |
ts_feature_tags | string[] | Trading Strategy feature tags for the vault architecture (e.g. euler_earn_like, pendle_pt, yearn_v3_like). Used internally to apply architecture-specific scoring rules — for example, utilization zero-out for EulerEarn and Pendle vaults, and depeg suppression for Pendle PT vaults. See Architecture-specific scoring rules above for how each tag affects scoring. |
last_audit_date | ISO date string | Date of the most recent security audit on record (sourced via DeFiLlama protocols API and manual curation). Drives the graduated audit recency sub-score: Fresh (<6 months) → 5, Moderate (6–18 months) → 10–30, Aging (18–36 months) → 30–60, Stale (>3 years) → 70. null when no audit date is available. |
audit_firms | string[] | Names of the audit firms that have reviewed this protocol (e.g. Trail of Bits, OpenZeppelin, Spearbit, Pashov). Reputable firms with audits within the last 12 months apply up to a −20 reduction to the audit recency sub-score. An empty array means no audit firms are on record — equivalent to no_audits for scoring purposes. |
days_since_harvest | integer (nullable) | Days since the vault’s last harvest() keeper call. Populated from last_harvest_at in Trading Strategy data. Used to apply graduated harvest inactivity penalties for strategy/keeper vaults (Yearn V2/V3, Harvest, etc.): < 30 days → no penalty; 30–60 days → +10, harvest_slow; 60–90 days → +25, harvest_stale; ≥ 90 days → full inactivity penalty, harvest_dormant. null when unavailable — harvest penalty is suppressed when data is absent. |