Split Native monad credit pool into native-lend-monad#20002
Split Native monad credit pool into native-lend-monad#20002June-native wants to merge 2 commits into
Conversation
📝 WalkthroughWalkthroughAdds a Native Lend adapter for a Native-curated Monad vault, including TVL and borrowed calculations, and updates the existing Native Lend configuration to support X Layer, Morph, and Robinhood instead of Monad. ChangesNative Lend adapters
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant NativeLendMonadAdapter
participant MonadRPC
participant LPMarkets
participant UnderlyingTokens
participant Vault
NativeLendMonadAdapter->>MonadRPC: getLogs MarketListed(address)
MonadRPC-->>NativeLendMonadAdapter: listed LP tokens
NativeLendMonadAdapter->>LPMarkets: multicall underlying()
LPMarkets-->>NativeLendMonadAdapter: underlying token addresses
NativeLendMonadAdapter->>Vault: sumTokens2 cash balances
Vault-->>NativeLendMonadAdapter: TVL balances
NativeLendMonadAdapter->>LPMarkets: multicall totalUnderlying()
LPMarkets-->>NativeLendMonadAdapter: locked amounts
NativeLendMonadAdapter->>UnderlyingTokens: balanceOf(vault)
UnderlyingTokens-->>NativeLendMonadAdapter: cash balances
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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/native-lend exports TVL: |
|
The adapter at projects/native-lend-monad exports TVL: |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
projects/native-lend-monad/index.js (1)
24-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract shared LP discovery logic to avoid duplication.
The LP token discovery (
getLogsforMarketListed+multiCallforunderlying) is identical in bothtvlandborrowed. Any future change to event ABI, log fetching, or token resolution must be applied in two places, risking divergence.♻️ Proposed refactor
+async function getLpUnderlyingTokens(api, vault, vaultFromBlock) { + const lpListedLogs = await getLogs({ + api, + target: vault, + topic: "MarketListed(address)", + eventAbi: "event MarketListed(address lpToken)", + onlyArgs: true, + fromBlock: vaultFromBlock, + }); + const lps = lpListedLogs.map((i) => i.lpToken); + const tokens = await api.multiCall({ abi: 'address:underlying', calls: lps }); + return { lps, tokens }; +} + Object.keys(config).forEach((chain) => { // get vault and start block const { vault, vaultFromBlock } = config[chain]; module.exports[chain] = { tvl: async (api) => { - // get all lps - const lpListedLogs = await getLogs({ - api, - target: vault, - topic: "MarketListed(address)", - eventAbi: - "event MarketListed(address lpToken)", - onlyArgs: true, - fromBlock: vaultFromBlock, - }); - const lps = lpListedLogs.map((i) => i.lpToken); - - // get all underlying tokens - const tokens = await api.multiCall({ abi: 'address:underlying', calls: lps }); + const { tokens } = await getLpUnderlyingTokens(api, vault, vaultFromBlock); // use sumTokens2 to for cash balances in vault return sumTokens2({ api, owner: vault, tokens }); }, borrowed: async (api) => { - // get all lps - const lpListedLogs = await getLogs({ - api, - target: vault, - topic: "MarketListed(address)", - eventAbi: - "event MarketListed(address lpToken)", - onlyArgs: true, - fromBlock: vaultFromBlock, - }); - const lps = lpListedLogs.map((i) => i.lpToken); - - // get all underlying tokens - const tokens = await api.multiCall({ abi: 'address:underlying', calls: lps }); + const { lps, tokens } = await getLpUnderlyingTokens(api, vault, vaultFromBlock); // get total supplied let v2Locked = await api.multiCall({ abi: 'address:totalUnderlying', calls: lps });Also applies to: 47-60
🤖 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 `@projects/native-lend-monad/index.js` around lines 24 - 37, Extract the duplicated LP discovery sequence from both tvl and borrowed into a shared helper that fetches MarketListed logs via getLogs and resolves underlying tokens via api.multiCall. Replace both inline implementations with calls to this helper, preserving the existing vault, vaultFromBlock, and API inputs and returned LP/token 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 `@projects/native-lend-monad/index.js`:
- Line 63: Update the borrowed-balance calculations around v2Locked in both
native-lend-monad/index.js and native-lend/index.js to call totalUnderlying with
the uint256 ABI and perform subtraction using BigInt values instead of parseInt
or Number arithmetic. Preserve the existing locked-minus-cash behavior while
avoiding precision loss for large balances.
---
Nitpick comments:
In `@projects/native-lend-monad/index.js`:
- Around line 24-37: Extract the duplicated LP discovery sequence from both tvl
and borrowed into a shared helper that fetches MarketListed logs via getLogs and
resolves underlying tokens via api.multiCall. Replace both inline
implementations with calls to this helper, preserving the existing vault,
vaultFromBlock, and API inputs and returned LP/token 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: 2971f5e3-140a-4bfa-867b-ea2ab2a558a8
📒 Files selected for processing (2)
projects/native-lend-monad/index.jsprojects/native-lend/index.js
💤 Files with no reviewable changes (1)
- projects/native-lend/index.js
| const tokens = await api.multiCall({ abi: 'address:underlying', calls: lps }); | ||
|
|
||
| // get total supplied | ||
| let v2Locked = await api.multiCall({ abi: 'address:totalUnderlying', calls: lps }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify the totalUnderlying function return type on the vault's LP contracts.
# Check if the existing native-lend adapter uses the same ABI pattern.
rg -n "totalUnderlying" projects/native-lend/ --type=js
# Also search for other adapters using address:totalUnderlying to see if this is a common pattern.
rg -n "address:totalUnderlying" projects/ --type=js | head -20Repository: DefiLlama/DefiLlama-Adapters
Length of output: 541
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== native-lend-monad/index.js around the reported lines =="
sed -n '1,140p' projects/native-lend-monad/index.js | cat -n
echo
echo "== native-lend/index.js around the matching logic =="
sed -n '1,140p' projects/native-lend/index.js | cat -n
echo
echo "== search for parseInt usage in these adapters =="
rg -n "parseInt|BigInt|totalUnderlying|balanceOf" projects/native-lend-monad/index.js projects/native-lend/index.jsRepository: DefiLlama/DefiLlama-Adapters
Length of output: 8395
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== typed ABI examples in the repo =="
rg -n "abi: 'address:[^']+'|abi: \"address:[^\"]+\"|abi: 'uint256:[^']+'|abi: \"uint256:[^\"]+\"" projects helper | head -100
echo
echo "== any explicit totalUnderlying ABI definitions or contract source references =="
rg -n "totalUnderlying|MarketListed|underlying" . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' | head -200Repository: DefiLlama/DefiLlama-Adapters
Length of output: 11944
🌐 Web query:
Native Lend Monad totalUnderlying return type lp contract verified source
💡 Result:
The term Native Lend typically refers to a decentralized finance protocol or infrastructure layer, rather than a single specific standard contract that shares a uniform return type for a totalUnderlying function across all implementations. In various lending and liquidity pool protocols, the totalUnderlying function is commonly implemented to return a single uint256 value representing the total quantity of the underlying asset held by the contract or pool [1][2]. However, its exact signature and return type depend on the specific protocol's architecture: 1. Standard Lending/Pool Protocols: In many liquidity pool and lending contracts (such as various implementations found in DeFi protocol audits), totalUnderlying is defined to return a single uint256 [1][2]. This value aggregates the balance of the underlying asset held within the pool or vault [1][2]. 2. LP/Position Modules: In other specialized protocols like Arrakis Finance, which manage liquidity positions involving multiple assets (e.g., Uniswap V3 positions), the totalUnderlying function is designed to return a tuple of multiple values, specifically (uint256 amount0, uint256 amount1), representing the quantities of each underlying token in the position [3][4][5]. There is no singular verified source or universal standard for a Native Lend protocol's totalUnderlying return type on Monad. Because Monad is an EVM-compatible blockchain, developers often use varying architectural patterns (such as those from Fluid, Arrakis, or other lending frameworks) [6][7][3]. To verify the specific return type for a contract on Monad, you must examine the specific source code or the ABI for that particular deployment [8]. If the contract is verified on a blockchain explorer (like Etherscan-based explorers commonly used for Monad), you can inspect the Read Contract tab or the source code tab to confirm the specific function signature and return type.
Citations:
- 1: https://github.com/merofinance/protocol/blob/main/contracts/pool/LiquidityPool.sol
- 2: https://github.com/code-423n4/2022-04-backd/blob/c856714a50437cb33240a5964b63687c9876275b/backd/contracts/pool/LiquidityPool.sol
- 3: https://docs.arrakis.finance/autogenerated/interfaces/IArrakisLPModule.sol/interface.IArrakisLPModule.html
- 4: https://docs.arrakis.finance/text/arrakisModular/technicalReference/metaVaults/core/abstract.ArrakisMetaVault.html
- 5: https://docs.arrakis.finance/autogenerated/modules/BunkerModule.sol/contract.BunkerModule.html
- 6: https://docs.fluid.instadapp.io/autogenerated-docs/protocols/lending/fToken/nativeUnderlying/fTokenNativeUnderlying.sol/abstract.fTokenNativeUnderlyingOverrides.html
- 7: https://github.com/instadapp/fluid-contracts-public/blob/a9949b48ba1247d4f478cd0acb40896b5c8bf3f8/contracts/protocols/lending/fToken/nativeUnderlying/fTokenNativeUnderlying.sol
- 8: https://www.monad.xyz/infra
Use uint256:totalUnderlying and BigInt for the borrowed-balance math. parseInt(...) can lose precision once balances exceed Number.MAX_SAFE_INTEGER, so locked - cash can be wrong for large pools. The same change applies to the mirrored logic in projects/native-lend/index.js.
🤖 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 `@projects/native-lend-monad/index.js` at line 63, Update the borrowed-balance
calculations around v2Locked in both native-lend-monad/index.js and
native-lend/index.js to call totalUnderlying with the uint256 ABI and perform
subtraction using BigInt values instead of parseInt or Number arithmetic.
Preserve the existing locked-minus-cash behavior while avoiding precision loss
for large balances.
Source: Learnings
|
The adapter at projects/native-lend exports TVL: |
|
The adapter at projects/native-lend-monad exports TVL: |
There was a problem hiding this comment.
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 `@projects/native-lend/index.js`:
- Around line 25-35: Update the shared borrowed-balance calculation in the
native-lend configuration flow to avoid parseInt and preserve full uint256
precision using bigint or string arithmetic. Keep values precise through
intermediate calculations, converting only at the SDK boundary, including for
xlayer, morph, robinhood, and other chains using this path.
🪄 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: 30cfaaae-db54-4b68-abbb-c62e82f92937
📒 Files selected for processing (1)
projects/native-lend/index.js
| xlayer: { | ||
| vault: "0x4Df7557734B382EB542BEa6c74786D398DF4CC19", | ||
| vaultFromBlock: 59885325, | ||
| }, | ||
| morph: { | ||
| vault: "0x4Df7557734B382EB542BEa6c74786D398DF4CC19", | ||
| vaultFromBlock: 23245775, | ||
| }, | ||
| robinhood: { | ||
| vault: "0x57B8f68ef57Af2dB70BC9aAc891836661CA4cB51", | ||
| vaultFromBlock: 60423, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant file and locate the borrowed implementation.
git ls-files projects/native-lend/index.js
ast-grep outline projects/native-lend/index.js --view expanded || true
# Show the surrounding lines around the reported region and borrowed implementation.
nl -ba projects/native-lend/index.js | sed -n '1,220p'Repository: DefiLlama/DefiLlama-Adapters
Length of output: 280
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the file with line numbers, then jump to the borrowed implementation.
cat -n projects/native-lend/index.js | sed -n '1,220p'
printf '\n--- parseInt search ---\n'
rg -n "parseInt|borrowed|totalUnderlying|balanceOf" projects/native-lend/index.jsRepository: DefiLlama/DefiLlama-Adapters
Length of output: 4738
Preserve precision in the borrowed path. parseInt will lose precision for 18-decimal uint256 values above 2^53 - 1, so this shared calculation can underreport borrowed balances on any chain using it, including the newly added ones. Use bigint/string arithmetic here and convert only at the SDK boundary.
🤖 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 `@projects/native-lend/index.js` around lines 25 - 35, Update the shared
borrowed-balance calculation in the native-lend configuration flow to avoid
parseInt and preserve full uint256 precision using bigint or string arithmetic.
Keep values precise through intermediate calculations, converting only at the
SDK boundary, including for xlayer, morph, robinhood, and other chains using
this path.
Native Credit Pool: split monad into doublecounted adapter + add xlayer, morph, robinhood
1. New
native-lend-monadadapter (doublecounted)Moves the monad Credit Vault (
0xcD1D2D602C3e7394515DaAe96e4FFe16DE71e5B4) out ofnative-lendinto a newnative-lend-monadadapter flaggeddoublecounted: true.This vault is curated by Native but whitelabeled/owned by TownSquare, who track the same vault in a separate
townsquare-vaultsadapter. Splitting it out asdoublecountedlets both Native (curator) and TownSquare (protocol owner) attribute the TVL without inflating aggregate DeFi TVL.2. Added remaining Credit Vault chains to
native-lendAdded the remaining Credit Vaults per the Native docs:
0x4Df7557734B382EB542BEa6c74786D398DF4CC190x4Df7557734B382EB542BEa6c74786D398DF4CC190x57B8f68ef57Af2dB70BC9aAc891836661CA4cB51Changes
projects/native-lend/index.js: removed monad; added xlayer, morph, robinhood (existing eth/bsc/base/arbitrum unchanged).projects/native-lend-monad/index.js: new monad-only adapter reusing the existingMarketListed/underlying/totalUnderlyingtvl + borrowed logic, withdoublecounted: trueand updated methodology.Summary by CodeRabbit
New Features
Updates