Skip to content

Add vesting APY as reward APY to selected IPOR Fusion vaults#2670

Open
rav-ipor wants to merge 2 commits into
DefiLlama:masterfrom
IPOR-Labs:master
Open

Add vesting APY as reward APY to selected IPOR Fusion vaults#2670
rav-ipor wants to merge 2 commits into
DefiLlama:masterfrom
IPOR-Labs:master

Conversation

@rav-ipor
Copy link
Copy Markdown
Contributor

@rav-ipor rav-ipor commented May 12, 2026

Summary by CodeRabbit

  • New Features
    • Added on-chain vesting reward APY calculations to the Fusion-by-IPOR adapter, significantly enhancing yield calculation accuracy. The adapter now computes and integrates vesting rewards into total APY for eligible vaults, while ensuring all underlying reward tokens are properly included in yield metrics. This provides users with more complete and transparent information about their vault returns.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

Warning

Rate limit exceeded

@rav-ipor has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 69a39ab0-e9cb-4e11-b4f4-656642bc4d85

📥 Commits

Reviewing files that changed from the base of the PR and between 3b477b8 and e833862.

📒 Files selected for processing (1)
  • src/adaptors/fusion-by-ipor/index.js
📝 Walkthrough

Walkthrough

This PR extends the Fusion-by-IPOR yield adapter with on-chain vesting reward APY computation. It adds a helper function to calculate annualized APY from vesting contract data, integrates vesting APY into the pool output for allowed vaults, and expands reward token metadata to include underlying tokens.

Changes

Vesting Reward APY Addition

Layer / File(s) Summary
Vesting APY helper and constants
src/adaptors/fusion-by-ipor/index.js
Adds @defillama/sdk dependency, defines vesting reward contract ABIs and vault allowlist constants (VESTING_APY_VAULTS), and implements getVestingRewardsApy() helper that fetches vesting parameters and total assets via ABI calls, then computes annualized APY using BigInt math with try/catch fallback to 0.
Pool APY reward field initialization
src/adaptors/fusion-by-ipor/index.js
Sets apyReward to 0 in buildPool() output, establishing the base APY value for downstream augmentation.
Vesting APY composition into main flow
src/adaptors/fusion-by-ipor/index.js
Integrates vesting APY into the main apy() function: applies Merkl rewards first, then conditionally calls getVestingRewardsApy() for pools matching VESTING_APY_VAULTS allowlist, increments apyReward with the computed vesting APY when positive, and unions rewardTokens with underlyingTokens.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A vesting reward awakens,
On-chain data calls and math,
BigInt arithmetic tokens
Flow through the IPOR path.
Merkl rewards now share the stage,
APY blooms on every page! 🌱

🚥 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 specifically describes the main change: adding vesting APY computation as reward APY to selected IPOR Fusion vaults, which aligns with the core modifications in the changeset.
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

The fusion-by-ipor adapter exports pools:

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

Nb of pools: 229
 

Sample pools:
┌─────────┬──────────────────────────────────────────────┬────────────┬──────────────────┬──────────┬────────────────────┬─────────────────────┬───────────────────┬──────────────────────────────────────────────────┬────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                         │ chain      │ project          │ symbol   │ tvlUsd             │ apyBase             │ apyReward         │ underlyingTokens                                 │ poolMeta                           │ url                                                                              │ rewardTokens                                     │
├─────────┼──────────────────────────────────────────────┼────────────┼──────────────────┼──────────┼────────────────────┼─────────────────────┼───────────────────┼──────────────────────────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0xb8a451107a9f87fde481d4d686247d6e43ed715e' │ 'ethereum' │ 'fusion-by-ipor' │ 'stETH'  │ 6196839.177901697  │ 7.7005436107460845  │ 0                 │ [ '0xae7ab96520de3a18e5e111b5eaab095312d7fe84' ] │ 'Fusion stETH looping Ethereum'    │ 'https://app.ipor.io/fusion/ethereum/0xb8a451107a9f87fde481d4d686247d6e43ed715e' │                                                  │
│ 1       │ '0x17d0f109ee895bad0b68aa104aa72bd0b003ad8e' │ 'base'     │ 'fusion-by-ipor' │ 'WETH'   │ 2036550.619389961  │ 1.1132384470150054  │ 5.337409502255673 │ [ '0x4200000000000000000000000000000000000006' ] │ 'Base ETH Lending Optimizer'       │ 'https://app.ipor.io/fusion/base/0x17d0f109ee895bad0b68aa104aa72bd0b003ad8e'     │ [ '0x4200000000000000000000000000000000000006' ] │
│ 2       │ '0xe9385eff3f937fcb0f0085da9a3f53d6c2b4fb5f' │ 'ethereum' │ 'fusion-by-ipor' │ 'rUSD'   │ 1771128.911768244  │ -41.096424405571994 │ 0                 │ [ '0x09d4214c03d01f49544c0448dbe3a27f768f2b34' ] │ 'Reservoir srUSD Looping Ethereum' │ 'https://app.ipor.io/fusion/ethereum/0xe9385eff3f937fcb0f0085da9a3f53d6c2b4fb5f' │                                                  │
│ 3       │ '0x7872893e528fe2c0829e405960db5b742112aa97' │ 'base'     │ 'fusion-by-ipor' │ 'WETH'   │ 1355358.9182623485 │ 3.4330300993836205  │ 0                 │ [ '0x4200000000000000000000000000000000000006' ] │ 'Harvest WETH vault Base'          │ 'https://app.ipor.io/fusion/base/0x7872893e528fe2c0829e405960db5b742112aa97'     │                                                  │
│ 4       │ '0xb0f56bb0bf13ee05fef8cd2d8df5ffdfcac7a74f' │ 'ethereum' │ 'fusion-by-ipor' │ 'USDC'   │ 1307084.2897874422 │ 3.4031225388147535  │ 0                 │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'TAU InfiniFi Pointsmax'           │ 'https://app.ipor.io/fusion/ethereum/0xb0f56bb0bf13ee05fef8cd2d8df5ffdfcac7a74f' │                                                  │
│ 5       │ '0xc4c00d8b323f37527eeda27c87412378be9f68ec' │ 'base'     │ 'fusion-by-ipor' │ 'WStETH' │ 1265499.1913724358 │ 7.9920602149433675  │ 0                 │ [ '0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452' ] │ 'IPOR WStETH Looping Base'         │ 'https://app.ipor.io/fusion/base/0xc4c00d8b323f37527eeda27c87412378be9f68ec'     │                                                  │
│ 6       │ '0x1166250d1d6b5a1dbb73526257f6bb2bbe235295' │ 'base'     │ 'fusion-by-ipor' │ 'USDC'   │ 978132.6024012131  │ 1.3664709901331518  │ 0                 │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'yoUSD Loooper'                    │ 'https://app.ipor.io/fusion/base/0x1166250d1d6b5a1dbb73526257f6bb2bbe235295'     │                                                  │
│ 7       │ '0xc2a119ea6de75e4b1451330321cb2474eb8d82d4' │ 'ethereum' │ 'fusion-by-ipor' │ 'USDC'   │ 836672.2095851743  │ 5.138054215507625   │ 0                 │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Tesseract USDC Lending Optimizer' │ 'https://app.ipor.io/fusion/ethereum/0xc2a119ea6de75e4b1451330321cb2474eb8d82d4' │                                                  │
│ 8       │ '0xf6cd9e8415162c8fb3c52676c7ca68812a34f76e' │ 'ethereum' │ 'fusion-by-ipor' │ 'WETH'   │ 809908.9277611567  │ 1.0238136082328237  │ 0                 │ [ '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' ] │ 'Reservoir ETH Yield'              │ 'https://app.ipor.io/fusion/ethereum/0xf6cd9e8415162c8fb3c52676c7ca68812a34f76e' │                                                  │
│ 9       │ '0x0d877dc7c8fa3ad980dfdb18b48ec9f8768359c4' │ 'base'     │ 'fusion-by-ipor' │ 'USDC'   │ 660992.2948138518  │ 5.463728879174214   │ 0                 │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'Harvest USDC vault Base'          │ 'https://app.ipor.io/fusion/base/0x0d877dc7c8fa3ad980dfdb18b48ec9f8768359c4'     │                                                  │
└─────────┴──────────────────────────────────────────────┴────────────┴──────────────────┴──────────┴────────────────────┴─────────────────────┴───────────────────┴──────────────────────────────────────────────────┴────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┘
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: 2

🤖 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/fusion-by-ipor/index.js`:
- Around line 64-67: The allowlist addresses in VESTING_APY_VAULTS contain
mixed-case Base addresses, but the matching code compares a lowercased pool
address (e.g., pool.address or poolAddressLower), so those entries never match;
fix by normalizing addresses to the same case—either convert all
VESTING_APY_VAULTS entries to lowercase during initialization or map the list
into a lowercased set before lookup, and ensure the matching logic (where
pool.address is lowercased on lines ~176-177) uses that lowercased set to
determine vesting APY.
- Around line 51-55: The APY calculation using apy_18 currently does
integer-divide SECONDS_IN_YEAR by vestingTime which can truncate to zero when
vestingTime > SECONDS_IN_YEAR—reorder the math to multiply first (e.g.,
(lastUpdateBalance * ONE_ETHER * SECONDS_IN_YEAR) / (totalAssets * vestingTime)
* 100n or equivalent) so you preserve precision before integer division;
additionally ensure address matching uses a consistent case by normalizing
VESTING_APY_VAULTS entries to lowercase (or stop lowercasing pool.pool) so the
allowlist lookup involving VESTING_APY_VAULTS and pool.pool matches correctly.
🪄 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: 13e8639d-2492-4c2d-a93c-f1efc4d9e662

📥 Commits

Reviewing files that changed from the base of the PR and between 4d12720 and 3b477b8.

📒 Files selected for processing (1)
  • src/adaptors/fusion-by-ipor/index.js

Comment thread src/adaptors/fusion-by-ipor/index.js Outdated
Comment thread src/adaptors/fusion-by-ipor/index.js Outdated
@github-actions
Copy link
Copy Markdown

The fusion-by-ipor adapter exports pools:

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

Nb of pools: 229
 

Sample pools:
┌─────────┬──────────────────────────────────────────────┬────────────┬──────────────────┬──────────┬────────────────────┬─────────────────────┬────────────────────┬──────────────────────────────────────────────────┬────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                         │ chain      │ project          │ symbol   │ tvlUsd             │ apyBase             │ apyReward          │ underlyingTokens                                 │ poolMeta                           │ url                                                                              │ rewardTokens                                     │
├─────────┼──────────────────────────────────────────────┼────────────┼──────────────────┼──────────┼────────────────────┼─────────────────────┼────────────────────┼──────────────────────────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0xb8a451107a9f87fde481d4d686247d6e43ed715e' │ 'ethereum' │ 'fusion-by-ipor' │ 'stETH'  │ 6196839.177901697  │ 7.7005436107460845  │ 0                  │ [ '0xae7ab96520de3a18e5e111b5eaab095312d7fe84' ] │ 'Fusion stETH looping Ethereum'    │ 'https://app.ipor.io/fusion/ethereum/0xb8a451107a9f87fde481d4d686247d6e43ed715e' │                                                  │
│ 1       │ '0x17d0f109ee895bad0b68aa104aa72bd0b003ad8e' │ 'base'     │ 'fusion-by-ipor' │ 'WETH'   │ 2036550.619389961  │ 1.1132384470150054  │ 5.3556209275646145 │ [ '0x4200000000000000000000000000000000000006' ] │ 'Base ETH Lending Optimizer'       │ 'https://app.ipor.io/fusion/base/0x17d0f109ee895bad0b68aa104aa72bd0b003ad8e'     │ [ '0x4200000000000000000000000000000000000006' ] │
│ 2       │ '0xe9385eff3f937fcb0f0085da9a3f53d6c2b4fb5f' │ 'ethereum' │ 'fusion-by-ipor' │ 'rUSD'   │ 1771128.911768244  │ -41.096424405571994 │ 0                  │ [ '0x09d4214c03d01f49544c0448dbe3a27f768f2b34' ] │ 'Reservoir srUSD Looping Ethereum' │ 'https://app.ipor.io/fusion/ethereum/0xe9385eff3f937fcb0f0085da9a3f53d6c2b4fb5f' │                                                  │
│ 3       │ '0x7872893e528fe2c0829e405960db5b742112aa97' │ 'base'     │ 'fusion-by-ipor' │ 'WETH'   │ 1355358.9182623485 │ 3.4330300993836205  │ 0                  │ [ '0x4200000000000000000000000000000000000006' ] │ 'Harvest WETH vault Base'          │ 'https://app.ipor.io/fusion/base/0x7872893e528fe2c0829e405960db5b742112aa97'     │                                                  │
│ 4       │ '0xb0f56bb0bf13ee05fef8cd2d8df5ffdfcac7a74f' │ 'ethereum' │ 'fusion-by-ipor' │ 'USDC'   │ 1307084.2897874422 │ 3.4031225388147535  │ 0                  │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'TAU InfiniFi Pointsmax'           │ 'https://app.ipor.io/fusion/ethereum/0xb0f56bb0bf13ee05fef8cd2d8df5ffdfcac7a74f' │                                                  │
│ 5       │ '0xc4c00d8b323f37527eeda27c87412378be9f68ec' │ 'base'     │ 'fusion-by-ipor' │ 'WStETH' │ 1265499.1913724358 │ 7.9920602149433675  │ 0                  │ [ '0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452' ] │ 'IPOR WStETH Looping Base'         │ 'https://app.ipor.io/fusion/base/0xc4c00d8b323f37527eeda27c87412378be9f68ec'     │                                                  │
│ 6       │ '0x1166250d1d6b5a1dbb73526257f6bb2bbe235295' │ 'base'     │ 'fusion-by-ipor' │ 'USDC'   │ 978132.6024012131  │ 1.3664709901331518  │ 0                  │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'yoUSD Loooper'                    │ 'https://app.ipor.io/fusion/base/0x1166250d1d6b5a1dbb73526257f6bb2bbe235295'     │                                                  │
│ 7       │ '0xc2a119ea6de75e4b1451330321cb2474eb8d82d4' │ 'ethereum' │ 'fusion-by-ipor' │ 'USDC'   │ 836672.2095851743  │ 5.138054215507625   │ 0                  │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Tesseract USDC Lending Optimizer' │ 'https://app.ipor.io/fusion/ethereum/0xc2a119ea6de75e4b1451330321cb2474eb8d82d4' │                                                  │
│ 8       │ '0xf6cd9e8415162c8fb3c52676c7ca68812a34f76e' │ 'ethereum' │ 'fusion-by-ipor' │ 'WETH'   │ 809908.9277611567  │ 1.0238136082328237  │ 0                  │ [ '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' ] │ 'Reservoir ETH Yield'              │ 'https://app.ipor.io/fusion/ethereum/0xf6cd9e8415162c8fb3c52676c7ca68812a34f76e' │                                                  │
│ 9       │ '0x0d877dc7c8fa3ad980dfdb18b48ec9f8768359c4' │ 'base'     │ 'fusion-by-ipor' │ 'USDC'   │ 660992.2948138518  │ 5.463728879174214   │ 0                  │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'Harvest USDC vault Base'          │ 'https://app.ipor.io/fusion/base/0x0d877dc7c8fa3ad980dfdb18b48ec9f8768359c4'     │                                                  │
└─────────┴──────────────────────────────────────────────┴────────────┴──────────────────┴──────────┴────────────────────┴─────────────────────┴────────────────────┴──────────────────────────────────────────────────┴────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

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