Add VIRTUS Protocol DEX adapters for basic AMM and CL pools on Base#6248
Add VIRTUS Protocol DEX adapters for basic AMM and CL pools on Base#6248cto-virtus wants to merge 1 commit intoDefiLlama:masterfrom
Conversation
📝 WalkthroughWalkthroughAdds two new Virtus Protocol adapter modules for Base that enumerate pools, fetch pool metadata (tokens, fees), scan Swap events, and compute per-day volumes and fee-based revenues. Changes
Sequence DiagramsequenceDiagram
participant Adapter as Adapter
participant Factory as Factory / Pool Contracts
participant Multicall as Multicall
participant Logs as Event Indexer
Adapter->>Factory: Query pool list (factory logs or allPools)
Factory-->>Adapter: Pool addresses
Adapter->>Multicall: Batch fetch token0, token1, fee/getFee per pool
Multicall-->>Adapter: Pool metadata (tokens, fee or null)
Adapter->>Logs: Query Swap events for each pool
Logs-->>Adapter: Swap events (amount0, amount1)
Adapter->>Adapter: Aggregate dailyVolume (amounts)
Adapter->>Adapter: Calculate dailyFees (amount * fee)
Adapter-->>Adapter: Return {dailyVolume, dailyFees, dailyRevenue, dailyHoldersRevenue}
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ 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 virtus-protocol-cl adapter exports: |
|
The virtus-protocol adapter exports: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
dexs/virtus-protocol/index.ts (1)
34-46: Consider logging or filtering pools with failed fee lookups.When
permitFailure: truecauses a fee lookup to returnnull/undefined, the code silently falls back to 30 basis points. While this maintains resilience, it may produce inaccurate fee calculations for pools with non-standard fees.For comparison, the Aerodrome adapter (referenced in context snippet 1) doesn't use
permitFailureon thegetFeecall, ensuring fee data is always accurate or the call fails explicitly.💡 Optional: Filter out pools with failed fee lookups instead of using fallback
pools.forEach((pool, index) => { const p = pool.toLowerCase() + const rawFee = fees[index] + if (rawFee === null || rawFee === undefined) return; // Skip pools with failed fee lookup poolTokens[p] = [token0s[index], token1s[index]] - poolFees[p] = (fees[index] ?? 30) / 1e4 + poolFees[p] = rawFee / 1e4 }) + + const targets = Object.keys(poolTokens) + if (!targets.length) return { dailyVolume, dailyFees }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@dexs/virtus-protocol/index.ts` around lines 34 - 46, The multiCall to api.multiCall with abi factoryAbis.getFee and permitFailure: true can return null/undefined fees which are silently converted to a 30 bps fallback; update the handling after receiving fees to detect failed lookups (check fees[index] === null || fees[index] === undefined) and either (a) log a warning including the pool address from pools[index] and index so operators can investigate, or (b) filter those pools out entirely by skipping adding entries to poolTokens and poolFees (or remove them from pools/token arrays) instead of unconditionally using 30/1e4; apply this change in the loop that sets poolTokens and poolFees to ensure inaccurate default fees are not silently used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@dexs/virtus-protocol/index.ts`:
- Around line 34-46: The multiCall to api.multiCall with abi factoryAbis.getFee
and permitFailure: true can return null/undefined fees which are silently
converted to a 30 bps fallback; update the handling after receiving fees to
detect failed lookups (check fees[index] === null || fees[index] === undefined)
and either (a) log a warning including the pool address from pools[index] and
index so operators can investigate, or (b) filter those pools out entirely by
skipping adding entries to poolTokens and poolFees (or remove them from
pools/token arrays) instead of unconditionally using 30/1e4; apply this change
in the loop that sets poolTokens and poolFees to ensure inaccurate default fees
are not silently used.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 43bf0bf8-df12-402a-9393-cce615110075
📒 Files selected for processing (2)
dexs/virtus-protocol-cl/index.tsdexs/virtus-protocol/index.ts
|
@cto-virtus thanks for the PR. |
- dexs/virtus-protocol: basic AMM pools via PoolFactory - dexs/virtus-protocol-cl: concentrated liquidity pools via CLFactory
cdf4158 to
ffa90c2
Compare
|
The virtus-protocol-cl adapter exports: |
Thanks! Updated the description with links. Website: https://virtus-protocol.com TVL adapter PR raised here: DefiLlama/DefiLlama-Adapters#18516 |
|
The virtus-protocol adapter exports: |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
dexs/virtus-protocol-cl/index.ts (1)
68-68: Unnecessary type cast.The
as anycast may hide type mismatches. If thefetchfunction's signature doesn't match expected types, consider adjusting the function signature rather than silencing the type checker.♻️ Suggested fix
[CHAIN.BASE]: { - fetch: fetch as any, + fetch, start: '2026-03-05', }If this causes type errors, ensure
fetchreturns the correctFetchResulttype.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@dexs/virtus-protocol-cl/index.ts` at line 68, Remove the unnecessary "as any" cast on the fetch assignment and fix the fetch function's signature/return type so it matches the expected FetchResult type instead of silencing the type checker; locate the fetch implementation referenced by the fetch property (symbol: fetch) and adjust its parameter/return typings (or convert its return value) to conform to the expected FetchResult interface used by the surrounding code so the cast is no longer needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@dexs/virtus-protocol-cl/index.ts`:
- Line 61: The return object currently sets both dailyRevenue and
dailyHoldersRevenue to dailyFees, double-counting revenue; update the return to
set dailyRevenue: 0 and dailyHoldersRevenue: dailyFees so protocol revenue is
zero and holders get 100% of fees (adjust the same pattern wherever you find the
same return with dailyVolume, dailyFees, dailyRevenue, dailyHoldersRevenue).
---
Nitpick comments:
In `@dexs/virtus-protocol-cl/index.ts`:
- Line 68: Remove the unnecessary "as any" cast on the fetch assignment and fix
the fetch function's signature/return type so it matches the expected
FetchResult type instead of silencing the type checker; locate the fetch
implementation referenced by the fetch property (symbol: fetch) and adjust its
parameter/return typings (or convert its return value) to conform to the
expected FetchResult interface used by the surrounding code so the cast is no
longer needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4197266c-9037-49df-bfad-1ead0572d2d9
📒 Files selected for processing (2)
dexs/virtus-protocol-cl/index.tsdexs/virtus-protocol/index.ts
✅ Files skipped from review due to trivial changes (1)
- dexs/virtus-protocol/index.ts
| }) | ||
| }) | ||
|
|
||
| return { dailyVolume, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how fees are distributed in similar Aerodrome-fork adapters
rg -n -A5 "dailyRevenue.*dailyFees|dailyHoldersRevenue.*dailyFees" --type=ts dexs/ -g '!node_modules' | head -60Repository: DefiLlama/dimension-adapters
Length of output: 3189
🌐 Web query:
What is the fee distribution mechanism for Aerodrome concentrated liquidity pools between LPs, veNFT holders, and protocol?
💡 Result:
The fee distribution mechanism for Aerodrome concentrated liquidity pools (Slipstream) follows the same model as standard pools, with a split between Liquidity Providers (LPs), veNFT (veAERO) holders, and protocol (minimal or none). Trading fees from swaps are generated based on pool fee tiers (e.g., 1bps to 0.3%) plus dynamic adjustments. - LPs earn fees directly proportional to their liquidity contribution if they do not stake their position NFT in the gauge. Staked LPs forgo swap fees to earn AERO emissions instead. - A portion of fees accrues to staked liquidity (gauged positions). These fees, along with an "unstaked liquidity fee" (default 10%, max 50%) skimmed from unstaked LP fees, are collected by the gauge via collectProtocol at the end of each epoch. These fees are then distributed to veAERO holders who voted for the pool in the previous epoch, proportional to their voting power. - Protocol receives no direct cut; 100% of collected fees flow to veAERO voters. No explicit protocol treasury retention is mentioned. This creates incentives: LPs choose fees (unstaked) or emissions (staked); voters earn fees by directing emissions to high-fee pools; emissions are separate AERO rewards to staked LPs.
Citations:
- 1: https://aerodrome.finance/docs
- 2: https://aerodrome.limo/about.html
- 3: https://tokenomics.com/articles/aerodrome-tokenomics-how-aero-captures-100-of-protocol-fees
- 4: https://github.com/aerodrome-finance/slipstream/blob/main/SPECIFICATION.md
- 5: https://github.com/aerodrome-finance/contracts/blob/main/SPECIFICATION.md
Fix double-counted revenue fields for Aerodrome-style fee distribution.
Setting both dailyRevenue and dailyHoldersRevenue to the full dailyFees value misrepresents the fee distribution. In Aerodrome concentrated liquidity (and VIRTUS if following the same model):
- Protocol receives 0% of fees
- veAERO holders receive 100% of collected fees
This same issue appears in dexs/velodrome-slipstream/index.ts:119 and dexs/virtus-protocol/index.ts:65.
Change to: dailyRevenue: 0, dailyHoldersRevenue: dailyFees (or verify if VIRTUS deviates from Aerodrome's model with an explicit protocol treasury cut).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dexs/virtus-protocol-cl/index.ts` at line 61, The return object currently
sets both dailyRevenue and dailyHoldersRevenue to dailyFees, double-counting
revenue; update the return to set dailyRevenue: 0 and dailyHoldersRevenue:
dailyFees so protocol revenue is zero and holders get 100% of fees (adjust the
same pattern wherever you find the same return with dailyVolume, dailyFees,
dailyRevenue, dailyHoldersRevenue).
|
added here #6273 |
Adds on-chain DEX volume/fees adapters for VIRTUS Protocol (Aerodrome fork) on Base mainnet.
Website: https://virtus-protocol.com
Twitter: https://x.com/VirtusCEO
dexs/virtus-protocol/— Basic AMM pools (PoolFactory: 0x7F03ae4452192b0E280fB0d4f9c225DDa88C7623)dexs/virtus-protocol-cl/— Concentrated Liquidity pools (CLFactory: 0x0e5Ab24beBdA7e5Bb3961f7E9b3532a83aE86B48)Both read swap events directly from on-chain contracts. No backend API dependency.
Tested with
ts-node cli/testAdapter.ts dexs virtus-protocolandvirtus-protocol-cl.Summary by CodeRabbit