fix(aerodrome-slipstream): use onchain calls for newer pools#2824
Conversation
📝 WalkthroughWalkthroughChangesAerodrome fee snapshot supplementation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant main
participant Subgraph
participant getGaugeApy
participant fetchFeesAtBlock
participant fetchPoolFeesTargeted
participant Multicall
main->>Subgraph: retrieve pool coverage
main->>getGaugeApy: pass coverage and historical-fee options
getGaugeApy->>fetchFeesAtBlock: request historical fee snapshots
fetchFeesAtBlock->>fetchPoolFeesTargeted: request fees for uncovered pools
fetchPoolFeesTargeted->>Multicall: query gauge fees, liquidity, and staked liquidity
Multicall-->>fetchPoolFeesTargeted: return per-pool results
fetchPoolFeesTargeted-->>getGaugeApy: return targeted fee data
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install timed out. The project may have too many dependencies for the sandbox. 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 aerodrome-slipstream adapter exports pools: Test Suites: 1 passed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/adaptors/aerodrome-slipstream/index.js (1)
567-577: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winSkip 24h APY calculation for subgraph-covered pools when targeted fetching is active.
Because
fees24hAgois now populated with targeted snapshots (instead of beingnullwhen historical fees are skipped), theif (fees24hAgo)condition evaluates to true for all pools.For pools that were intentionally skipped (i.e., they are in
subgraphCoveredPools),priorwill beundefined, causingpriorFeeUsdto default to0. Consequently,feeDeltais calculated ascurrentFeeUsd(the pool's lifetime gauge fees), resulting in a massively inflated 24h APY for these covered pools.Although
main()attempts to overwrite this with the subgraph'sv.apyBase, it will fall back to this inflated outlier if the subgraph returnsnullorundefinedfor a pool's APY.Add a check to ensure covered pools bypass this calculation when historical fees are intentionally skipped.
🐛 Proposed fix
- if (fees24hAgo) { + const isSkipped = skipHistoricalFees && subgraphCoveredPools?.has(lpKey); + if (fees24hAgo && !isSkipped) { const currentFeeUsd = calcFeeUsd(p); const prior = fees24hAgo[lpKey]; const priorFeeUsd = prior ? calcFeeUsd(prior) : 0;🤖 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/aerodrome-slipstream/index.js` around lines 567 - 577, Update the 24h APY calculation guarded by fees24hAgo to skip pools present in subgraphCoveredPools when targeted historical fetching is active. Ensure covered pools do not derive feeDelta, apyBase, or volumeUsd1d from a missing prior snapshot, while preserving the existing calculation for pools with historical fee data.
🤖 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/aerodrome-slipstream/index.js`:
- Around line 40-42: Update the stakedLiquidity multiCall in the Slipstream
adaptor to query the gauge-side contract/helper rather than the pool ABI, while
keeping the existing liquidity and gaugeFees calls unchanged so pools with
staked liquidity are not skipped by the fallback path.
---
Outside diff comments:
In `@src/adaptors/aerodrome-slipstream/index.js`:
- Around line 567-577: Update the 24h APY calculation guarded by fees24hAgo to
skip pools present in subgraphCoveredPools when targeted historical fetching is
active. Ensure covered pools do not derive feeDelta, apyBase, or volumeUsd1d
from a missing prior snapshot, while preserving the existing calculation for
pools with historical fee data.
🪄 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: 3cd09077-bd66-45f4-abb3-9cb4a7e7d72c
📒 Files selected for processing (1)
src/adaptors/aerodrome-slipstream/index.js
| sdk.api.abi.multiCall({ abi: gaugeFeesAbi, ...opts }), | ||
| sdk.api.abi.multiCall({ abi: 'uint128:liquidity', ...opts }), | ||
| sdk.api.abi.multiCall({ abi: 'uint128:stakedLiquidity', ...opts }), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
"stakedLiquidity" "Aerodrome" slipstream pool
💡 Result:
Slipstream is Aerodrome Finance's concentrated liquidity implementation on the Base network, designed to function similarly to Uniswap V3 [1][2][3]. In Slipstream pools, liquidity providers (LPs) choose specific price ranges for their deposits, which concentrates capital and improves fee efficiency within those ranges [2][4][5]. Staking liquidity in Slipstream pools is a mandatory step to maximize rewards [5]. Because Slipstream positions are represented as non-fungible tokens (NFTs) rather than fungible LP tokens, LPs must stake their NFT position into the corresponding pool gauge [2][4]. Key aspects of staking for Slipstream pools include: Mandatory Staking: Unstaked positions do not receive AERO emissions and result in the protocol withholding a portion (approximately 10%) of earned swap fees, which are then distributed to veAERO voters [4][5]. Mechanism: After depositing liquidity and receiving an NFT representing that position, users must stake the NFT via the Aerodrome interface [2][4][5]. Rewards: Staked positions are eligible for a "triple income stream": Trading fees accrued while the position remains within the active price range [2][4][5]. AERO emissions distributed through the gauge [4][5]. Additional rewards (bribes) from veAERO voters [5]. Management: Because Slipstream pools concentrate liquidity, positions require active monitoring [2]. If the market price exits the selected range, the position stops earning swap fees until the price returns to that range or the LP adjusts it [2][4][5]. For more technical details, including integration interfaces and contract addresses, the official Aerodrome Finance GitHub repository maintains the specification and core contracts for Slipstream [1][6][7].
Citations:
- 1: https://github.com/aerodrome-finance/slipstream
- 2: https://cryptoadventure.com/aerodrome-slipstream-review-2026-concentrated-liquidity-on-base-and-how-lp-positions-work/
- 3: https://dappdefi.com/protocols/aerodrome-slipstream/
- 4: https://www.dextools.io/tutorials/what-is-aerodrome-base-dex-velodrome-fork-guide-2026
- 5: https://bytwork.com/en/defi/aerodrome
- 6: https://github.com/aerodrome-finance/slipstream/blob/main/SPECIFICATION.md
- 7: https://github.com/velodrome-finance/docs/blob/main/content/sdk.mdx
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant file and any nearby references to stakedLiquidity / liquidity fields.
git ls-files src/adaptors/aerodrome-slipstream index.js src/adaptors/aerodrome-slipstream
printf '\n--- index.js outline ---\n'
ast-grep outline src/adaptors/aerodrome-slipstream/index.js --view expanded || true
printf '\n--- occurrences ---\n'
rg -n "stakedLiquidity|liquidity|gaugeFeesAbi|multiCall" src/adaptors/aerodrome-slipstream src/adaptors -g '!**/node_modules/**' || true
printf '\n--- file excerpt ---\n'
cat -n src/adaptors/aerodrome-slipstream/index.js | sed -n '1,160p'Repository: DefiLlama/yield-server
Length of output: 50379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=src/adaptors/aerodrome-slipstream/index.js
printf '%s\n' "--- ${file} (1-180) ---"
cat -n "$file" | sed -n '1,180p'
printf '\n--- direct matches in %s ---\n' "$file"
rg -n "stakedLiquidity|liquidity|gaugeFeesAbi|pool|gauge" "$file" || true
printf '\n--- nearby adaptor files mentioning aerodrome-slipstream ---\n'
rg -n "aerodrome-slipstream|stakedLiquidity" src/adaptors -g '!**/node_modules/**' | sed -n '1,120p' || trueRepository: DefiLlama/yield-server
Length of output: 12564
🌐 Web query:
"Aerodrome Slipstream" stakedLiquidity function pool ABI
💡 Result:
In Aerodrome Slipstream, there is no single function named stakedLiquidity defined in the core pool contract ABI [1][2]. Aerodrome Slipstream is a concentrated liquidity AMM (based on the Uniswap V3 architecture) where liquidity is managed via non-fungible position tokens (ERC-721 NFTs) [1][2][3]. The concept of "staked liquidity" refers to these NFT positions being deposited into a Gauge contract to earn AERO emissions [2]. To retrieve information related to staked liquidity, you must interact with the relevant Gauge contract and the NonfungiblePositionManager, rather than a single pool function [2]: 1. To check if a position is staked: You typically interact with the Gauge contract, which handles the staking of position NFTs [2]. 2. To calculate or view liquidity amounts: You query the NonfungiblePositionManager's positions(uint256 tokenId) function to get the position details, including the liquidity amount [4][5]. 3. For APR/Reward calculations: These are often derived by aggregating total staked liquidity within the gauge, which is documented at the pool/gauge level [6][7]. Because Slipstream follows the Concentrated Liquidity standard, the ABI for the pool itself exposes standard functions such as mint, burn, collect, and position management [1], while staking logic is externalized to the Gauge system [2]. If you are looking for specific data (like total staked liquidity), you should query the Gauge contract's view functions or use a protocol-specific subgraph/indexer that tracks gauge deposits [2][7].
Citations:
- 1: https://github.com/cyotee/aerodrome-V2-slipstream-skill
- 2: https://wayfinder-1.gitbook.io/wayfinder/protocols-and-adapters/aerodrome-slipstream.md
- 3: https://blog.web3wagmi.com/aerodrome-guide
- 4: https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/fuses/aerodrome_slipstream/AreodromeSlipstreamModifyPositionFuse.sol
- 5: https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/fuses/aerodrome_slipstream/AreodromeSlipstreamBalanceFuse.sol
- 6: https://github.com/aerodrome-finance/docs/blob/main/content/liquidity.mdx
- 7: https://docs.bitquery.io/docs/blockchain/Base/aerodrome-gauge-vaults-api/
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=src/adaptors/aerodrome-slipstream/index.js
printf '%s\n' '--- pool/gauge target wiring around targeted fees ---'
sed -n '300,460p' "$file" | cat -n
printf '\n%s\n' '--- where fetchPoolFeesTargeted is called ---'
rg -n "fetchPoolFeesTargeted|fetchPoolFeesAtBlock|gaugeFees|stakedLiquidity" "$file" src/adaptors/aerodrome-slipstream -g '!**/node_modules/**'
printf '\n%s\n' '--- any ABI references for stakedLiquidity in repo ---'
rg -n '"stakedLiquidity"|stakedLiquidity\(' src/adaptors -g '!**/node_modules/**' | sed -n '1,120p' || trueRepository: DefiLlama/yield-server
Length of output: 8217
Use the gauge for stakedLiquidity
stakedLiquidity() isn’t part of the Slipstream pool ABI; query the gauge-side contract/helper here instead, or the fallback path will skip these 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/aerodrome-slipstream/index.js` around lines 40 - 42, Update the
stakedLiquidity multiCall in the Slipstream adaptor to query the gauge-side
contract/helper rather than the pool ABI, while keeping the existing liquidity
and gaugeFees calls unchanged so pools with staked liquidity are not skipped by
the fallback path.
Summary by CodeRabbit
New Features
Bug Fixes