Skip to content

Add Unblock Equity yield adapter — 24 vaults on Base#2659

Open
vladimirzoyan wants to merge 1 commit into
DefiLlama:masterfrom
vladimirzoyan:unblock-equity-yields
Open

Add Unblock Equity yield adapter — 24 vaults on Base#2659
vladimirzoyan wants to merge 1 commit into
DefiLlama:masterfrom
vladimirzoyan:unblock-equity-yields

Conversation

@vladimirzoyan
Copy link
Copy Markdown

@vladimirzoyan vladimirzoyan commented May 7, 2026

Adds yield adapter for Unblock Equity — a tokenized junior-lien home-equity lending protocol on Base. Depositors fund 24 segmented MetaMorpho vaults; homeowners borrow USDC against tokenized property liens (ERC-1155).

The TVL adapter was merged earlier this week in DefiLlama-Adapters#19102. This PR adds the matching yield-server entry so APYs surface on the yields page.

What this adapter publishes

  • 24 USDC pools on Base, one per {Verification × Recovery × BR} combo
  • TVL: live from each vault's totalAssets() (ERC4626)
  • APY: modeled equilibrium yield from each vault's published risk model (PD × LGD → net yield). Range: 7.50% – 9.26%
  • All required fields present: pool, chain, project, symbol, tvlUsd, apyBase, underlyingTokens, url, poolMeta

Why not live IRM rates?

Considered using borrowRateView() from Morpho's IRM, but Morpho's adaptive-curve IRM drifts toward zero on idle high-utilization markets — at the moment of this PR our genesis market shows 0.34% on-chain APY despite 86% utilization, simply because no one has interacted with it for 6 days. The drift is normal IRM behavior but it would misrepresent the long-run yield depositors actually earn.

The modeled net yield = expected yield given PD × LGD per the published risk model. It's exactly what's displayed in the protocol's earn page (https://app.unblockequity.com/earn) and what's documented in the risk whitepaper.

Live verification

```
Pools: 24 TVL: $11,876.62
Standard Lien BR12 TVL=$11,876.39 APY=8.03% ← genesis vault (active)

  • 23 other vaults seeded at $0.01 each, modeled APY 7.50%–9.26%
    ```

Links

Summary by CodeRabbit

  • New Features
    • Added support for unblock-equity vaults on the Base network. Users can now monitor yield rates from 24 vault contracts with real-time asset data updates, enabling them to discover and track earning strategies. The new integration provides comprehensive support across the protocol's complete vault ecosystem.

UnblockEquity is a tokenized junior-lien home-equity lending protocol on Base.
Depositors fund 24 segmented MetaMorpho vaults (verification × recovery × escrow tier);
borrowers (homeowners) collateralize tokenized property liens (ERC-1155).

TVL adapter for the protocol was merged in DefiLlama-Adapters#19102.
This PR adds the matching yield-server adapter so APYs surface on /yields.

- TVL: live from each vault's totalAssets() (ERC4626)
- APY: modeled equilibrium yield from each vault's published risk model
       (PD × LGD → net yield). Matches the displayed APY in the protocol's
       earn page and the published risk whitepaper. Live IRM rates are
       intentionally NOT used because Morpho's adaptive-curve IRM drifts
       toward zero on idle high-utilization markets, which would
       misrepresent the long-run yield depositors actually earn.
- Verified: 24/24 vaults addressable, total TVL $11.8K (matches on-chain).
- APY range across 24 pools: 7.50%–9.26%

Adapter URL: https://app.unblockequity.com/earn
DefiLlama protocol page: https://defillama.com/protocol/unblock-equity
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Added a new Unblock Equity yield adapter module for Base chain. The adapter defines 24 vault contracts with hardcoded net yields, fetches live TVL for each vault via ERC-4626 totalAssets() calls, converts assets to USDC-denominated USD, processes vaults in batches, and returns a pool array with fallback error handling.

Changes

Unblock Equity Yield Adapter

Layer / File(s) Summary
Adapter Configuration & Vault Metadata
src/adaptors/unblock-equity/index.js
Defines Base RPC endpoint, USDC token address, ERC-4626 ABI fragment for totalAssets(), and hardcoded catalog of 24 vaults with contract addresses, modeled net yield rates, and display names.
APY Data Fetching
src/adaptors/unblock-equity/index.js
Implements apy() function that creates an ethers JSON-RPC provider, iterates through vaults in batches of 6 with inter-batch delay, calls totalAssets() on each vault contract, converts wei to USDC-denominated USD, constructs pool objects with standardized metadata, and returns zero TVL for any vault that errors.
Module Exports
src/adaptors/unblock-equity/index.js
Exports apy() async function, timetravel boolean set to false, and url string pointing to the canonical Unblock Equity earn page.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Hops through the vaults of Base so grand,
Fetching yields from every land,
Batches of six in swift parade,
USDC counts the pools we've made. 🌱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a yield adapter for Unblock Equity with 24 vaults on Base.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

The unblock-equity adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 148 passed, 148 total
Snapshots: 0 total
Time: 0.332 s
Ran all test suites.

Nb of pools: 24
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────┬────────┬──────────────────┬────────┬──────────────┬─────────┬──────────────────────────────────────────────────┬──────────────────────────────────────┬────────────────────────┐
│ (index) │ pool                                              │ chain  │ project          │ symbol │ tvlUsd       │ apyBase │ underlyingTokens                                 │ url                                  │ poolMeta               │
├─────────┼───────────────────────────────────────────────────┼────────┼──────────────────┼────────┼──────────────┼─────────┼──────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────┤
│ 0       │ '0x012f6f383f13bd437dfbfcbe94d1a8c5fc40e650-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 11876.391621 │ 8.03    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Standard Lien BR12'   │
│ 1       │ '0x287397fd29abcdb1f514179099121895a2f5beaf-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.76    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified Lien-Only'   │
│ 2       │ '0x376736a69b8f9c350f76e0b2802466eaee7e058f-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.58    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified Lien BR3'    │
│ 3       │ '0xd6313868b5cebad6fdc3ae48f80917b385c01c71-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.6     │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified Lien BR6'    │
│ 4       │ '0x2ffcbdea42311515e3db1f873a1cea0d463b5ced-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.58    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified Lien BR12'   │
│ 5       │ '0x0ed4c2cfff2ec06079e723f51aefc8cdf073ea68-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.66    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified Foreclosure' │
│ 6       │ '0x34ddd63fea2868eef439279d6feca7d5acfc4f53-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.61    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified FC BR3'      │
│ 7       │ '0xc24c630d27cbf1da6a78b09821212eb9c5e1be40-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.58    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified FC BR6'      │
│ 8       │ '0x8e246a89a7f8ffd4efd7d037bd585f7741c0c482-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.55    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Verified FC BR12'     │
│ 9       │ '0x13d2e770cefb62a8aa4e3393d59f88707abd4dd5-base' │ 'Base' │ 'unblock-equity' │ 'USDC' │ 0.01         │ 7.91    │ [ '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ] │ 'https://app.unblockequity.com/earn' │ 'Prime Lien-Only'      │
└─────────┴───────────────────────────────────────────────────┴────────┴──────────────────┴────────┴──────────────┴─────────┴──────────────────────────────────────────────────┴──────────────────────────────────────┴────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/adaptors/unblock-equity/index.js`:
- Around line 52-76: The code currently swallows all errors in the Promise.all
batch mapper (inside the catch after calling new ethers.Contract(v.vault,
ERC4626_ABI, provider).totalAssets()), turning failures into tvlUsd = 0; to
avoid returning many zero-TVL pools on an RPC-wide outage, add a top-level
failure counter (e.g., failedReads) in the function that increments inside that
catch, and after processing all VAULTS check if failedReads === VAULTS.length
and if so throw or return an error to abort publishing; update the catch to
still set tvlUsd = 0 for individual vaults but ensure you increment failedReads
there so the final guard can detect total RPC failure (refer to symbols:
Promise.all batch map, totalAssets, tvlUsd, VAULTS, pools).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c3d43070-841e-4bbe-8d6e-7474dcd1b99b

📥 Commits

Reviewing files that changed from the base of the PR and between 8abd2e4 and 41db981.

📒 Files selected for processing (1)
  • src/adaptors/unblock-equity/index.js

Comment on lines +52 to +76
const results = await Promise.all(batch.map(async (v) => {
let tvlUsd = 0;
try {
const totalAssets = await new ethers.Contract(v.vault, ERC4626_ABI, provider).totalAssets();
tvlUsd = parseFloat(ethers.utils.formatUnits(totalAssets, 6));
} catch {
// Vault unreachable — list with zero TVL, modeled APY still informative
}
return {
pool: `${v.vault.toLowerCase()}-base`,
chain: "Base",
project: "unblock-equity",
symbol: "USDC",
tvlUsd,
apyBase: v.netYield,
underlyingTokens: [USDC],
url: "https://app.unblockequity.com/earn",
poolMeta: v.name,
};
}));
pools.push(...results);
if (i + 6 < VAULTS.length) await new Promise((r) => setTimeout(r, 300));
}

return pools;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid silently publishing zero TVL during RPC-wide failures.

Right now every fetch error is swallowed and converted to tvlUsd = 0. If Base RPC is degraded, this can return 24 “valid-looking” pools with zero TVL, which is misleading data rather than a hard failure.

Suggested guardrail (fail when all vault reads fail)
   const pools = [];
+  let totalFailures = 0;
   for (let i = 0; i < VAULTS.length; i += 6) {
     const batch = VAULTS.slice(i, i + 6);
     const results = await Promise.all(batch.map(async (v) => {
       let tvlUsd = 0;
+      let failed = false;
       try {
         const totalAssets = await new ethers.Contract(v.vault, ERC4626_ABI, provider).totalAssets();
         tvlUsd = parseFloat(ethers.utils.formatUnits(totalAssets, 6));
       } catch {
+        failed = true;
         // Vault unreachable — list with zero TVL, modeled APY still informative
       }
       return {
         pool: `${v.vault.toLowerCase()}-base`,
         chain: "Base",
         project: "unblock-equity",
         symbol: "USDC",
         tvlUsd,
         apyBase: v.netYield,
         underlyingTokens: [USDC],
         url: "https://app.unblockequity.com/earn",
         poolMeta: v.name,
+        _failed: failed,
       };
     }));
-    pools.push(...results);
+    totalFailures += results.filter((r) => r._failed).length;
+    pools.push(...results.map(({ _failed, ...pool }) => pool));
     if (i + 6 < VAULTS.length) await new Promise((r) => setTimeout(r, 300));
   }
+
+  if (totalFailures === VAULTS.length) {
+    throw new Error("unblock-equity: failed to fetch totalAssets() for all vaults");
+  }
 
   return pools;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/unblock-equity/index.js` around lines 52 - 76, The code
currently swallows all errors in the Promise.all batch mapper (inside the catch
after calling new ethers.Contract(v.vault, ERC4626_ABI,
provider).totalAssets()), turning failures into tvlUsd = 0; to avoid returning
many zero-TVL pools on an RPC-wide outage, add a top-level failure counter
(e.g., failedReads) in the function that increments inside that catch, and after
processing all VAULTS check if failedReads === VAULTS.length and if so throw or
return an error to abort publishing; update the catch to still set tvlUsd = 0
for individual vaults but ensure you increment failedReads there so the final
guard can detect total RPC failure (refer to symbols: Promise.all batch map,
totalAssets, tvlUsd, VAULTS, pools).

@vladimirzoyan
Copy link
Copy Markdown
Author

Polite bump — this has been green for 8 days:

  • CodeRabbit review ✓
  • Automated test suite ✓ (148 passed, adapter exports pools cleanly)
  • Live TVL of ~$11.9K (matches the TVL adapter merged in DefiLlama-Adapters#19102)

Would appreciate a maintainer look when you have a moment. Happy to address any review feedback. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant