Update surf-liquid TVL adapter with V2/V3 vault support and staking#18401
Update surf-liquid TVL adapter with V2/V3 vault support and staking#18401rohansingh4 wants to merge 4 commits intoDefiLlama:mainfrom
Conversation
- Enumerate V2 vaults via factory getTotalVaults/getVaultInfo - Discover V3 vaults via VaultDeployed event logs - Count Morpho ERC-4626 vault share positions as TVL - Add staking: SURF staked + CreatorBid subscriptions
📝 WalkthroughWalkthroughReplaces single-target TVL with Changes
Sequence Diagram(s)sequenceDiagram
participant Client as API Handler
participant V2F as V2 Factory
participant V3Logs as V3 Event Logs
participant Vault as Vault Contract
participant Sum as api.sumTokens
Client->>V2F: call getTotalVaults / getVaultInfo
V2F-->>Client: return V2 vault addresses & currentVault data
Client->>V3Logs: query VaultDeployed logs from V3 factory
V3Logs-->>Client: return V3 vault addresses (asset → vault)
Client->>Vault: read token() and owner() for each discovered vault
Vault-->>Client: token/owner pairs
Client->>Sum: submit tokensAndOwners list
Sum-->>Client: aggregated TVL per token
sequenceDiagram
participant Client as API Handler
participant STK as SURF_STAKING Contract
participant SURF as SURF_TOKEN Contract
participant Acc as Aggregator
Client->>STK: call totalStaked()
STK-->>Client: staked SURF amount
Client->>SURF: call balanceOf(SURF_TOKEN) for subscriptions
SURF-->>Client: subscription SURF amount
Client->>Acc: add SURF balances to tokensAndOwners
Acc-->>Client: SURF included in final TVL
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
The adapter at projects/surf-liquid exports TVL: |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@projects/surf-liquid/index.js`:
- Around line 71-76: The exported adapter object (module.exports) currently
exposes base: { tvl, staking } where base.tvl reports Morpho ERC‑4626 share
balances held by Surf vaults; mark this as a wrapped/downstream TVL by adding
doublecounted: true and misrepresentedTokens: true to the exported object (next
to methodology and base) so consumers know it’s vault‑in‑vault/wrapped-share
TVL; alternatively, if you prefer to represent underlying assets instead, modify
the tvl implementation referenced by the tvl symbol to unwrap ERC‑4626 shares to
their underlying before summing, but the quick fix is to add the two flags to
module.exports alongside base and methodology.
- Around line 25-27: The V2 loop pushes [v2MorphoVaults[i], v2Owners[i]] even
when one of those values is falsy; mirror the V3 guard by checking both the
vault address and owner are truthy and not ZERO_ADDR before pushing to
tokensAndOwners. Update the loop that iterates v2Owners / v2MorphoVaults to skip
iterations where v2MorphoVaults[i] is ZERO_ADDR or where v2MorphoVaults[i] or
v2Owners[i] are falsy (e.g., result of getVaultInfo()/currentVault()), so
sumTokens only receives valid [token, owner] pairs. Ensure you reference the
same variables (v2MorphoVaults, v2Owners, ZERO_ADDR, tokensAndOwners, sumTokens)
when making the check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b9bb8de9-d9d4-4001-8461-aff70cf9d3e1
📒 Files selected for processing (1)
projects/surf-liquid/index.js
|
Revenue is 70,000 Surf tokens, you can convert them to USD. Please refer- https://dune.com/surfliquid/stats, tvl, volume, surf buyback (is our revenue) here should't divert much from dune numbers. Dune also tracks historical prices, so I am aware there will be slight variation though most of the volume/tvl is in usdc. |
Include SURF staking and CreatorBid subscriptions directly in the tvl function instead of a separate staking category.
|
The adapter at projects/surf-liquid exports TVL: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
projects/surf-liquid/index.js (1)
56-67: Consider separating staking into its own export.SURF staking and CreatorBid subscriptions are currently merged into the
tvlfunction. DefiLlama convention typically separates protocol token staking into a dedicatedstakingexport. This provides clearer metrics and matches the test output showing distinctbase($239k) andbase-staking($31k) values.♻️ Suggested refactor to separate staking
async function tvl(api) { const tokensAndOwners = []; // ... V2 and V3 vault logic ... await api.sumTokens({ tokensAndOwners }); - - // SURF staking contract - const totalStaked = await api.call({ abi: "uint256:totalStaked", target: SURF_STAKING }); - api.add(SURF_TOKEN, totalStaked); - - // CreatorBid SURF subscriptions (SURF locked in the token contract) - const subscribed = await api.call({ - abi: "function balanceOf(address) view returns (uint256)", - target: SURF_TOKEN, - params: [SURF_TOKEN], - }); - api.add(SURF_TOKEN, subscribed); } +async function staking(api) { + // SURF staking contract + const totalStaked = await api.call({ abi: "uint256:totalStaked", target: SURF_STAKING }); + api.add(SURF_TOKEN, totalStaked); + + // CreatorBid SURF subscriptions (SURF locked in the token contract) + const subscribed = await api.call({ + abi: "function balanceOf(address) view returns (uint256)", + target: SURF_TOKEN, + params: [SURF_TOKEN], + }); + api.add(SURF_TOKEN, subscribed); +} module.exports = { // ... base: { tvl, + staking, }, };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@projects/surf-liquid/index.js` around lines 56 - 67, Split the SURF staking logic out of the tvl function into a dedicated staking export: move the call that reads totalStaked (the api.call with abi "uint256:totalStaked" targeting SURF_STAKING) and the corresponding api.add(SURF_TOKEN, totalStaked) into a new exported async function named staking (or export const staking = { tvl: ... } per repo convention) that returns the staking balances; keep the existing CreatorBid subscription code (the balanceOf call using SURF_TOKEN as target and params [SURF_TOKEN] and its api.add) inside tvl. Ensure the new staking export uses the same api instance pattern and is exported alongside tvl so tests/reporting show separate base and base-staking values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@projects/surf-liquid/index.js`:
- Around line 56-67: Split the SURF staking logic out of the tvl function into a
dedicated staking export: move the call that reads totalStaked (the api.call
with abi "uint256:totalStaked" targeting SURF_STAKING) and the corresponding
api.add(SURF_TOKEN, totalStaked) into a new exported async function named
staking (or export const staking = { tvl: ... } per repo convention) that
returns the staking balances; keep the existing CreatorBid subscription code
(the balanceOf call using SURF_TOKEN as target and params [SURF_TOKEN] and its
api.add) inside tvl. Ensure the new staking export uses the same api instance
pattern and is exported alongside tvl so tests/reporting show separate base and
base-staking values.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 84b8abd6-d866-4fd3-a80c-e0bf4684b494
📒 Files selected for processing (1)
projects/surf-liquid/index.js
projects/surf-liquid/index.js
Outdated
|
|
||
| module.exports = { | ||
| methodology: "Counts the morpho deposits of each Surf Liquid vault.", | ||
| methodology: "TVL counts Morpho vault deposits across V2 and V3 Surf Liquid vaults, SURF staked, and CreatorBid SURF subscriptions.", |
There was a problem hiding this comment.
can you add a hallmarks entry for the v3 factory deployment date so the spike in tvl is explained
| target: SURF_TOKEN, | ||
| params: [SURF_TOKEN], | ||
| }); | ||
| api.add(SURF_TOKEN, subscribed); |
There was a problem hiding this comment.
please move the SURF token tracking back under the staking export
There was a problem hiding this comment.
Done, also when will numbers be updated and depreciation tag removed?
Per reviewer feedback: - Move SURF staking + CreatorBid subscriptions back under staking export - Add hallmarks entry for V3 factory launch (2025-11-30) to explain TVL spike
|
The adapter at projects/surf-liquid exports TVL: |
There was a problem hiding this comment.
♻️ Duplicate comments (2)
projects/surf-liquid/index.js (2)
71-77:⚠️ Potential issue | 🟠 MajorMark wrapped/downstream TVL explicitly in adapter metadata.
base.tvlsums Morpho ERC-4626 share balances held by Surf vaults, which is wrapped/downstream exposure and can overlap with underlying protocol TVL. Adddoublecounted: trueandmisrepresentedTokens: true(or unwrap to underlying instead).🏷️ Proposed metadata update
module.exports = { methodology: "TVL counts Morpho vault deposits across V2 and V3 Surf Liquid vaults. Staking includes SURF staked and SURF subscriptions.", + doublecounted: true, + misrepresentedTokens: true, hallmarks: [["2025-11-30", "V3 factory launched"]], base: { tvl, staking, }, };Based on learnings, the Royco v2 adapter marks vault-in-vault accounting as
doublecounted: true, and AFI marks raw vault-share reporting asmisrepresentedTokens: true.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@projects/surf-liquid/index.js` around lines 71 - 77, The adapter metadata currently exports module.exports with base: { tvl, staking } but does not mark that base.tvl reports wrapped/downstream Morpho ERC-4626 share balances; update the exported metadata to explicitly flag this by adding doublecounted: true and misrepresentedTokens: true (or alternatively unwrap the vault shares to underlying assets) so consumers know the TVL may overlap with underlying protocols; locate the module.exports block (symbols: module.exports, base, tvl, staking) and add those two boolean flags to the metadata object.
25-27:⚠️ Potential issue | 🟡 MinorHarden V2 pair validation before
sumTokens.At Line 26, the guard still only checks
v2MorphoVaults[i] !== ZERO_ADDR. Ifv2Owners[i]orv2MorphoVaults[i]is falsy, an invalid[token, owner]pair can still be pushed.🛡️ Proposed fix
for (let i = 0; i < v2Owners.length; i++) { - if (v2MorphoVaults[i] !== ZERO_ADDR) { + if (v2Owners[i] && v2Owners[i] !== ZERO_ADDR && v2MorphoVaults[i] && v2MorphoVaults[i] !== ZERO_ADDR) { tokensAndOwners.push([v2MorphoVaults[i], v2Owners[i]]); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@projects/surf-liquid/index.js` around lines 25 - 27, The loop that builds tokensAndOwners currently only checks v2MorphoVaults[i] !== ZERO_ADDR and can push invalid pairs when v2Owners[i] or v2MorphoVaults[i] is falsy; update the guard in the loop that iterates over v2Owners to ensure both v2MorphoVaults[i] is truthy and not ZERO_ADDR and v2Owners[i] is truthy before pushing into tokensAndOwners so sumTokens receives only valid [token, owner] tuples (refer to v2Owners, v2MorphoVaults, ZERO_ADDR, tokensAndOwners and the code path that calls sumTokens).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@projects/surf-liquid/index.js`:
- Around line 71-77: The adapter metadata currently exports module.exports with
base: { tvl, staking } but does not mark that base.tvl reports
wrapped/downstream Morpho ERC-4626 share balances; update the exported metadata
to explicitly flag this by adding doublecounted: true and misrepresentedTokens:
true (or alternatively unwrap the vault shares to underlying assets) so
consumers know the TVL may overlap with underlying protocols; locate the
module.exports block (symbols: module.exports, base, tvl, staking) and add those
two boolean flags to the metadata object.
- Around line 25-27: The loop that builds tokensAndOwners currently only checks
v2MorphoVaults[i] !== ZERO_ADDR and can push invalid pairs when v2Owners[i] or
v2MorphoVaults[i] is falsy; update the guard in the loop that iterates over
v2Owners to ensure both v2MorphoVaults[i] is truthy and not ZERO_ADDR and
v2Owners[i] is truthy before pushing into tokensAndOwners so sumTokens receives
only valid [token, owner] tuples (refer to v2Owners, v2MorphoVaults, ZERO_ADDR,
tokensAndOwners and the code path that calls sumTokens).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 736dc5ba-3ccc-4d6a-91fd-fbfec4ee2caa
📒 Files selected for processing (1)
projects/surf-liquid/index.js
- Mark adapter as doublecounted and misrepresentedTokens since TVL counts Morpho ERC-4626 vault shares (vault-in-vault) - Harden V2 loop to check both owner and vault are truthy before pushing
|
The adapter at projects/surf-liquid exports TVL: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
projects/surf-liquid/index.js (1)
37-37: Consider documenting the hardcodedfromBlock.The magic number
38856207should have a brief inline comment explaining it's the V3 factory deployment block, improving maintainability for future developers.- fromBlock: 38856207, + fromBlock: 38856207, // V3 factory deployment block🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@projects/surf-liquid/index.js` at line 37, The literal 38856207 assigned to fromBlock is a magic number; add a brief inline comment next to the fromBlock assignment (the "fromBlock" property containing 38856207) stating that this is the V3 factory deployment block (include network and approximate date if known) so future maintainers understand why it is hardcoded and can update it safely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@projects/surf-liquid/index.js`:
- Line 37: The literal 38856207 assigned to fromBlock is a magic number; add a
brief inline comment next to the fromBlock assignment (the "fromBlock" property
containing 38856207) stating that this is the V3 factory deployment block
(include network and approximate date if known) so future maintainers understand
why it is hardcoded and can update it safely.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7cd87ec0-142d-4205-a8cd-adaf1c88b72a
📒 Files selected for processing (1)
projects/surf-liquid/index.js
Summary
getTotalVaults/getVaultInfo) and V3 vaults viaVaultDeployedevent logsTest results
Contracts
0x1D283b668F947E03E8ac8ce8DA5505020434ea0E(Base)0xf1d64dee9f8e109362309a4bfbb523c8e54fa1aa(Base)0xB0fDFc081310A5914c2d2c97e7582F4De12FA9d6(Base)0xcdca2eaae4a8a6b83d7a3589946c2301040dafbf(Base)Summary by CodeRabbit
New Features
Documentation