Skip to content

feat: integrate Mantle (chainId 5000) as second-class EVM chain#11905

Merged
gomesalexandre merged 15 commits intodevelopfrom
feat/integrate-mantle-relay
Feb 20, 2026
Merged

feat: integrate Mantle (chainId 5000) as second-class EVM chain#11905
gomesalexandre merged 15 commits intodevelopfrom
feat/integrate-mantle-relay

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Feb 17, 2026

Description

Add support for Mantle (EVM chain, chainId 5000) as a second-class citizen. Mantle is an Optimistic Rollup L2 with MNT as the native gas token.

Implements: CAIP constants, chain adapter, plugin, feature flag, Relay swapper mapping, HDWallet support flags, CSP headers, asset generation script, and all required shared-file entries.

This is PR 1 of 17 in a sequential chain integration series. These PRs must be reviewed and merged in order, as each builds on the previous one (stacked branches).

PR merge order:

  1. Mantle (feat: integrate Mantle (chainId 5000) as second-class EVM chain #11905) ✅ merged
  2. Cronos (feat: integrate Cronos (chainId 25) as second-class EVM chain #11910)
  3. Sonic (feat: integrate Sonic (eip155:146) as second-class EVM chain #11923)
  4. Unichain (feat: integrate Unichain (eip155:130) as second-class citizen via Relay #11924)
  5. BOB (feat: integrate BOB (eip155:60808) as second-class citizen #11925)
  6. Mode (feat: integrate Mode (eip155:34443) as second-class citizen #11926)
  7. Soneium (feat: integrate Soneium (chainId: 1868) via Relay #11930)
  8. Hemi (feat: integrate Hemi (chainId: 43111) via Relay #11931)
  9. World Chain (feat: integrate World Chain (480) as second-class Relay chain #11932)
  10. Blast (feat: integrate Blast (81457) as second-class Relay chain #11933)
  11. zkSync Era (feat: integrate zkSync Era (324) as second-class Relay chain #11934)
  12. Story (feat: integrate Story (1514) as second-class Relay chain #11936)
  13. Plume (feat: integrate Plume (98866) as second-class Relay chain #11937)
  14. Flow EVM (feat: integrate Flow EVM (747) as second-class Relay chain #11938)
  15. Celo (feat: integrate Celo (42220) as second-class Relay chain #11939)
  16. Ethereal (feat: integrate Ethereal (5064014) as second-class Relay chain #11940)

Note: Linea (#11922) is already in develop.

Issue (if applicable)

Part of #11902

Risk

Low - All changes are behind the Mantle feature flag (VITE_FEATURE_MANTLE), disabled by default in production.

No new on-chain transactions or contract interactions. Standard EVM chain support using existing SecondClassEvmAdapter pattern.

Testing

Engineering

  1. Set VITE_FEATURE_MANTLE=true in .env.development
  2. Run yarn dev
  3. Verify Mantle appears in chain selector
  4. Verify native MNT balance loads on Mantle
  5. Verify Relay swap routes include Mantle
  6. Verify cross-chain swap TO MNT shows execution price (wrapped native detection fix)

Operations

  • 🏁 My feature is behind a flag and doesn't require operations testing (yet)

Summary by CodeRabbit

  • New Features

    • Mantle (MNT) added: chain support, wallet compatibility, RPC connectivity, and asset visibility across the app.
  • Assets

    • Mantle tokens included in asset listings, CoinGecko mappings, and popular-assets discovery.
  • Configuration

    • New Mantle node URL and feature flag to enable runtime support; CSP and plugin integration updated.
  • Chores

    • Project planning and tracking entries added for Mantle integration and asset-generation workflows.

…Relay bridge support

Add support for Mantle (MNT native gas) including CAIP constants, chain adapter,
plugin, feature flag, Relay swapper mapping, HDWallet support flags, CSP headers,
asset generation script, and all required shared-file entries.

Part of #11902
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Adds Mantle (eip155:5000) as a second-class EVM chain across the codebase: env/config, CAIP constants, viem/ethers clients, chain adapters, asset data and generators, swapper mappings, HDWallet capability flags/guards, plugins, transaction-status utilities, CSP, feature-flag gating, and project metadata.

Changes

Cohort / File(s) Summary
Env & CSP / Config
\.env, \.env.development, src/config.ts, src/vite-env.d.ts, headers/csps/chains/mantle.ts, headers/csps/index.ts
Adds VITE_MANTLE_NODE_URL and VITE_FEATURE_MANTLE, validators, ImportMetaEnv entries, and a Mantle CSP connect-src entry.
CAIP & Types
packages/types/src/base.ts, packages/types/src/zerion.ts, packages/caip/src/constants.ts
Introduces MantleMainnet (eip155:5000), mantleChainId/mantleAssetId, updates CHAIN_REFERENCE/ASSET_REFERENCE/ZERION mappings and valid chain lists.
Chain Adapters & Types
packages/chain-adapters/src/evm/..., packages/chain-adapters/src/types.ts
Adds MantleChainAdapter, barrel exports, includes Mantle in evmChainIds, wallet-switch mapping, display-name/type mappings, and wrapped-native-per-chain mapping used by SecondClassEvmAdapter.
RPC / Clients
packages/contracts/src/viemClient.ts, packages/contracts/src/ethersProviderSingleton.ts
Adds viemMantleClient, maps Mantle network/client, and resolves Mantle RPC URL from VITE_MANTLE_NODE_URL.
HDWallet capabilities & guards
packages/hdwallet-core/src/*, packages/hdwallet-*/src/* (multiple)
Adds _supportsMantle flags across HDWallet implementations and ETHWallet interface; adds supportsMantle type guard.
Swapper / Relay mapping
packages/swapper/src/swappers/RelaySwapper/constant.ts, packages/swapper/.../relayTokenToAssetId.ts
Maps mantleChainId ↔ Relay chain id and adds Mantle native-token resolution branch.
Base assets & asset utilities
packages/utils/src/assetData/baseAssets.ts, packages/utils/src/assetData/getBaseAsset.ts, packages/utils/src/chainIdToFeeAssetId.ts, packages/utils/src/getAssetNamespaceFromChainId.ts, packages/utils/src/getChainShortName.ts, packages/utils/src/getNativeFeeAssetReference.ts
Adds Mantle base asset (MNT) and wires chain→asset/namespace/fee/short-name mappings.
Asset generation & Coingecko
scripts/generateAssetData/*, packages/caip/src/adapters/coingecko/*, packages/caip/src/adapters/coingecko/utils.test.ts
Adds Mantle asset generator module, integrates Mantle into aggregation, extends Coingecko platform enum/mappings and tests, and updates blacklist.
App utilities, hooks & tx status
src/lib/utils/mantle.ts, src/hooks/*, src/lib/account/evm.ts, src/lib/coingecko/utils.ts, src/lib/asset-service/service/AssetService.ts, src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx
Adds Mantle JSON-RPC tx-status helper and adapter guard, feature-flag gating for assets/popular lists, wallet-support checks, and asset-service filtering.
Plugins & UI gating
src/plugins/mantle/index.tsx, src/plugins/activePlugins.ts, src/pages/Markets/components/MarketsRow.tsx, src/constants/chains.ts
Registers Mantle plugin/adapter with dynamic known-token discovery and gates SECOND_CLASS_CHAINS and Markets UI via Mantle feature flag.
State & mocks
src/state/slices/preferencesSlice/preferencesSlice.ts, src/state/slices/portfolioSlice/utils/index.ts, src/state/slices/opportunitiesSlice/mappings.ts, src/test/mocks/store.ts
Adds Mantle feature flag to state and mocks; updates account labeling and isAssetSupportedByWallet checks; adds empty DeFi opportunities mapping.
Asset-data pipeline tweaks
scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts, scripts/generateAssetData/mantle/index.ts, scripts/generateAssetData/generateAssetData.ts, scripts/generateAssetData/coingecko.ts, scripts/generateAssetData/blacklist.json
Adds Mantle asset source, merges mantle assets into generation, updates blacklist, and adds manual related-asset index helper for overrides.
Project metadata & docs
.beads/ss-dx5.3.json, .claude/worktrees/ai-release-summary, .beads/pr-context.jsonl, .claude/contracts/second-class-evm-chain.md
Adds planning bead for Mantle integration, updates submodule pointer and pr-context entries, and documents wrapped-native detection, blacklist, append-only convention, and runtime-test guidance.

Sequence Diagram(s)

sequenceDiagram
  participant Subscriber as ActionCenterSubscriber
  participant MantleUtil as MantleUtil
  participant Node as MantleNode (VITE_MANTLE_NODE_URL)
  participant Store as AppStore

  Subscriber->>MantleUtil: getMantleTransactionStatus(txHash)
  MantleUtil->>Node: JSON-RPC eth_getTransactionReceipt (txHash)
  Node-->>MantleUtil: HTTP 200 + receipt / HTTP error
  MantleUtil-->>Subscriber: TxStatus (Confirmed|Failed|Pending|Unknown)
  Subscriber->>Store: dispatch status update
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • 0xApotheosis

"🐰 I hopped through configs, flags, and code,
Mantle cards stacked in my tiny load,
Nodes and assets, adapters aligned,
A careful hop — one chain defined! 🥕"

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: integrating Mantle as a second-class EVM chain with specific chainId 5000, which is the core objective of this large multi-file changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/integrate-mantle-relay

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.

NeOMakinG and others added 8 commits February 17, 2026 15:38
Add src/lib/utils/mantle.ts with getMantleTransactionStatus using
eth_getTransactionReceipt via the Mantle RPC.

Add KnownChainIds.MantleMainnet case to useSendActionSubscriber.tsx
so Mantle transactions resolve in the action center.
Address PR review feedback:
- Add mantleChainId to getCoingeckoSupportedChainIds (feature-flagged)
- Add mantle to ZERION_CHAINS array and ZERION_CHAINS_MAP
- Across does not support Mantle, skipped
…tle-relay

# Conflicts:
#	.env
#	.env.development
#	packages/caip/src/adapters/coingecko/generated/index.ts
#	packages/caip/src/adapters/coingecko/index.ts
#	packages/caip/src/adapters/coingecko/utils.test.ts
#	packages/caip/src/adapters/coingecko/utils.ts
#	packages/caip/src/constants.ts
#	packages/chain-adapters/src/evm/EvmBaseAdapter.ts
#	packages/chain-adapters/src/types.ts
#	packages/contracts/src/ethersProviderSingleton.ts
#	packages/contracts/src/viemClient.ts
#	packages/hdwallet-coinbase/src/coinbase.ts
#	packages/hdwallet-core/src/ethereum.ts
#	packages/hdwallet-core/src/wallet.ts
#	packages/hdwallet-gridplus/src/gridplus.ts
#	packages/hdwallet-keepkey/src/keepkey.ts
#	packages/hdwallet-ledger/src/ledger.ts
#	packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts
#	packages/hdwallet-native/src/ethereum.ts
#	packages/hdwallet-phantom/src/phantom.ts
#	packages/hdwallet-trezor/src/trezor.ts
#	packages/hdwallet-vultisig/src/vultisig.ts
#	packages/hdwallet-walletconnectv2/src/walletconnectV2.ts
#	packages/swapper/src/swappers/RelaySwapper/constant.ts
#	packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts
#	packages/types/src/base.ts
#	packages/types/src/zerion.ts
#	packages/utils/src/assetData/baseAssets.ts
#	packages/utils/src/assetData/getBaseAsset.ts
#	packages/utils/src/chainIdToFeeAssetId.ts
#	packages/utils/src/getAssetNamespaceFromChainId.ts
#	packages/utils/src/getChainShortName.ts
#	packages/utils/src/getNativeFeeAssetReference.ts
#	scripts/generateAssetData/coingecko.ts
#	scripts/generateAssetData/generateAssetData.ts
#	src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx
#	src/config.ts
#	src/constants/chains.ts
#	src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
#	src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts
#	src/lib/account/evm.ts
#	src/lib/asset-service/service/AssetService.ts
#	src/lib/coingecko/utils.ts
#	src/pages/Markets/components/MarketsRow.tsx
#	src/state/slices/portfolioSlice/utils/index.ts
#	src/state/slices/preferencesSlice/preferencesSlice.ts
#	src/test/mocks/store.ts
#	src/vite-env.d.ts
Missing closing braces in 7 files where auto-resolve stripped
them at mantle/next-entry boundaries.

Also made generateChainRelatedAssetIndex self-contained (no
import from generateRelatedAssetIndex to avoid module-scope
ZERION_API_KEY check).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
77 Mantle assets added with relatedAssetKey cross-chain linking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Swaps from/to MNT/tokens happy
  • Popular assets gucci
  • Same like Berachain previously, cross-chain swaps to MNT don't have an execution price nor MNT entry - probably the same lack of trace debugging in RPCs and parseTx() kind of fix re:un/wrapping

https://jam.dev/c/7f3d3fa9-100e-469d-8c85-417b255ae6de

Prompts for AI agents:

Look into the Berachain commit. Notice how we circumvented the lack of trace debugging to be able to upsert second-class Txs for BERA by manually detecting un/wrapping without a need for trace debug.
The fix is most likely similar here, look at the Txx below, figure out the ABI/patterns
Initiating Relay Tx on Ethereum: https://etherscan.io/tx/0xee22f39981ca5199eb76b57507b23458d0278b3df4259c2876801778dd3d658a
Receive Tx on Mantle: https://mantlescan.xyz/tx/0x90d278e7c30e6d15902e50b6940c780bf27dc2251fef8d0a1dcd04771ce4fffe

Notice WMNT which is a similar pattern to WBERA
Make no mistakes you degen, commit, let user fix, push after they confirmed worky or iterate with them

@gomesalexandre gomesalexandre marked this pull request as ready for review February 20, 2026 14:27
@gomesalexandre gomesalexandre requested a review from a team as a code owner February 20, 2026 14:27
Copy link
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: 3

🧹 Nitpick comments (3)
.beads/ss-dx5.3.json (1)

20-36: Consider trimming the inlined parent epic notes in child task dependencies.

The dependency entry for ss-dx5 embeds the entire epic's procedural documentation (~3KB) verbatim. If multiple child task beads reference this same epic, this content is duplicated in each .beads/*.json file and must be kept in sync manually. Consider keeping only the reference fields (id, title, dependency_type) here and relying on ss-dx5's own bead file as the single source of truth for its notes/description.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.beads/ss-dx5.3.json around lines 20 - 36, The dependency entry for "ss-dx5"
currently in the child bead embeds the full epic notes; replace the verbose
fields with a minimal reference: keep "id": "ss-dx5", "title": "Add support for
missing Relay.link EVM chains", and "dependency_type": "parent-child"
(optionally include "status" or "external_ref" if needed), and remove/trim
"description", "notes", and large freeform fields so the epic's full
documentation remains only in the ss-dx5 bead file; update any other child beads
that reference this epic to follow the same minimal pattern so the parent bead
is the single source of truth.
.env.development (1)

65-65: Fix key ordering reported by dotenv-linter

Two UnorderedKey warnings from the static analysis tool:

  • VITE_MANTLE_NODE_URL (line 65) should be placed before VITE_MONAD_NODE_URL (alphabetical ordering within the nodes block).
  • VITE_FEATURE_MANTLE (line 102) should be placed before VITE_FEATURE_WC_DIRECT_CONNECTION (alphabetical ordering within the feature flags block).
🔧 Proposed ordering fix
-VITE_MONAD_NODE_URL=https://rpc.monad.xyz
-VITE_PLASMA_NODE_URL=https://rpc.plasma.to
-VITE_KATANA_NODE_URL=https://rpc.katana.network
-VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
-VITE_MANTLE_NODE_URL=https://rpc.mantle.xyz
+VITE_MANTLE_NODE_URL=https://rpc.mantle.xyz
+VITE_MONAD_NODE_URL=https://rpc.monad.xyz
+VITE_PLASMA_NODE_URL=https://rpc.plasma.to
+VITE_KATANA_NODE_URL=https://rpc.katana.network
+VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
-VITE_FEATURE_WC_DIRECT_CONNECTION=true
-VITE_FEATURE_CETUS_SWAP=true
-VITE_FEATURE_MANTLE=true
+VITE_FEATURE_MANTLE=true
+VITE_FEATURE_WC_DIRECT_CONNECTION=true
+VITE_FEATURE_CETUS_SWAP=true

Also applies to: 102-102

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.development at line 65, Reorder environment keys to satisfy
dotenv-linter alphabetical rules: move VITE_MANTLE_NODE_URL so it appears
alphabetically before VITE_MONAD_NODE_URL within the node URLs block, and move
VITE_FEATURE_MANTLE so it appears alphabetically before
VITE_FEATURE_WC_DIRECT_CONNECTION within the feature flags block; ensure no
other keys or comments are changed and run dotenv-linter to confirm UnorderedKey
warnings are resolved.
src/plugins/mantle/index.tsx (1)

22-36: Minor: fromAssetId is called twice per matching asset.

The filter at line 26 and map at line 31 each call fromAssetId on the same asset.assetId. Consider consolidating into a single pass (e.g., flatMap or reduce) to avoid the redundant parse. That said, this matches other plugin files so it's fine to defer.

♻️ Optional: single-pass approach
-                const getKnownTokens = () => {
-                  const assetService = getAssetService()
-                  return assetService.assets
-                    .filter(asset => {
-                      const { chainId, assetNamespace } = fromAssetId(asset.assetId)
-                      return chainId === mantleChainId && assetNamespace === 'erc20'
-                    })
-                    .map(asset => ({
-                      assetId: asset.assetId,
-                      contractAddress: fromAssetId(asset.assetId).assetReference,
-                      symbol: asset.symbol,
-                      name: asset.name,
-                      precision: asset.precision,
-                    }))
-                }
+                const getKnownTokens = () => {
+                  const assetService = getAssetService()
+                  return assetService.assets.reduce<
+                    {
+                      assetId: string
+                      contractAddress: string
+                      symbol: string
+                      name: string
+                      precision: number
+                    }[]
+                  >((acc, asset) => {
+                    const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId)
+                    if (chainId === mantleChainId && assetNamespace === 'erc20') {
+                      acc.push({
+                        assetId: asset.assetId,
+                        contractAddress: assetReference,
+                        symbol: asset.symbol,
+                        name: asset.name,
+                        precision: asset.precision,
+                      })
+                    }
+                    return acc
+                  }, [])
+                }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/mantle/index.tsx` around lines 22 - 36, getKnownTokens currently
calls fromAssetId twice per asset (once in the filter and again in the map),
causing redundant parsing; fix by parsing each assetId once (e.g., transform the
asset list into [{ asset, parsed }] via map or use reduce/flatMap) so you can
check parsed.chainId and parsed.assetNamespace against mantleChainId in a single
pass and then build the returned object using parsed.assetReference for
contractAddress — change getKnownTokens to use a single parse call to
fromAssetId per asset obtained from getAssetService().assets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts`:
- Around line 18-20: The isMantleChainAdapter type guard must defensively handle
null/undefined and objects missing getType; update isMantleChainAdapter to first
ensure adapter is non-null and that (adapter as any).getType is a function
before calling it, then compare the returned type to KnownChainIds.MantleMainnet
(i.e., add checks like adapter != null && typeof (adapter as any).getType ===
'function' prior to (adapter as ChainAdapter).getType()).

In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts`:
- Around line 65-68: Add an inline Gitleaks suppression for the Solana mint
literal on the array value for [starknetAssetId]; locate the array entry in
generateChainRelatedAssetIndex where [starknetAssetId] maps to the two CAIP-19
strings (the Ethereum ERC-20
'eip155:1/erc20:0xca14007eff0db1f8135f4c25b34de49ab0d42766' and the Solana token
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:HsRpHQn6VbyMs5b5j5SV6xQ2VvpvvCCzu19GjytVSCoz')
and add a single-line suppression comment (// gitleaks:allow) adjacent to the
Solana token literal to prevent Gitleaks from flagging the known CAIP-19 mint as
a secret.

In `@src/lib/utils/mantle.ts`:
- Around line 7-14: There are two conflicting isMantleChainAdapter definitions
(one typing as EvmChainAdapter using getChainId, and another typing as
ChainAdapter using getType) — remove the duplicate and consolidate to a single
exported utility: keep the defensive utility version named isMantleChainAdapter
(the one that narrows to EvmChainAdapter and calls getChainId), delete the
duplicate definition in the adapter file, and update exports/imports so only the
single consolidated isMantleChainAdapter is exported/used across the codebase;
if you prefer the adapter-file implementation, instead replace the utility
implementation with the adapter one and ensure its signature and usage (getType
vs getChainId) are consistent everywhere.

---

Nitpick comments:
In @.beads/ss-dx5.3.json:
- Around line 20-36: The dependency entry for "ss-dx5" currently in the child
bead embeds the full epic notes; replace the verbose fields with a minimal
reference: keep "id": "ss-dx5", "title": "Add support for missing Relay.link EVM
chains", and "dependency_type": "parent-child" (optionally include "status" or
"external_ref" if needed), and remove/trim "description", "notes", and large
freeform fields so the epic's full documentation remains only in the ss-dx5 bead
file; update any other child beads that reference this epic to follow the same
minimal pattern so the parent bead is the single source of truth.

In @.env.development:
- Line 65: Reorder environment keys to satisfy dotenv-linter alphabetical rules:
move VITE_MANTLE_NODE_URL so it appears alphabetically before
VITE_MONAD_NODE_URL within the node URLs block, and move VITE_FEATURE_MANTLE so
it appears alphabetically before VITE_FEATURE_WC_DIRECT_CONNECTION within the
feature flags block; ensure no other keys or comments are changed and run
dotenv-linter to confirm UnorderedKey warnings are resolved.

In `@src/plugins/mantle/index.tsx`:
- Around line 22-36: getKnownTokens currently calls fromAssetId twice per asset
(once in the filter and again in the map), causing redundant parsing; fix by
parsing each assetId once (e.g., transform the asset list into [{ asset, parsed
}] via map or use reduce/flatMap) so you can check parsed.chainId and
parsed.assetNamespace against mantleChainId in a single pass and then build the
returned object using parsed.assetReference for contractAddress — change
getKnownTokens to use a single parse call to fromAssetId per asset obtained from
getAssetService().assets.

@gomes-bot
Copy link
Contributor

re: gitleaks false positive on the Solana SPL token mint - ser you're drunk @coderabbitai, that's a CAIP-19 asset ID not an API key. No suppression comment needed, we don't run gitleaks in strict mode.

gomesalexandre and others added 3 commits February 20, 2026 15:40
…ract

- Replace Berachain-only WBERA burn detection with generalized
  WRAPPED_NATIVE_CONTRACT_BY_CHAIN_ID mapping in SecondClassEvmAdapter
- Add WMNT address for Mantle cross-chain swap native receives
- Fix Linea networkIcon URL (CoinGecko 403 -> relay.link CDN)
- Update second-class-evm-chain contract with wrapped native,
  icon validation, and append-only convention sections

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (1)

420-438: ⚠️ Potential issue | 🟡 Minor

Synthesized internal tx unconditionally sets to: pubkey — may produce a spurious Receive in one edge case.

When internalTxs.length === 0 and a WMNT → zeroAddress Transfer event is found, the synthesized entry hardcodes to: getAddress(pubkey). The downstream parse() method then checks isAddressEqual(address, internalTo), where internalTo will always equal address (they are both derived from pubkey), so the user always sees a Receive for that value.

The intended scenario — user receives native MNT via a Relay cross-chain swap — is handled correctly. However, if the user is the sender of a transaction that incidentally triggers a WMNT burn for a different final recipient (e.g., a contract they called that unwraps WMNT and sends MNT to a third party), parseTx would generate a spurious Receive entry for the user.

This is the same limitation already accepted for Berachain, and the feature is gated behind VITE_FEATURE_MANTLE. Worth keeping in mind for future hardening (e.g., cross-checking log.args.from against the transaction participants).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts` around lines 420 -
438, The synthesized internalTx currently hardcodes to: getAddress(pubkey) for
any WMNT -> zeroAddress burn, causing spurious Receive entries; change the logic
in SecondClassEvmAdapter where wrappedNativeBurnLogs are processed (use symbols
WRAPPED_NATIVE_CONTRACT_BY_CHAIN_ID, wrappedNativeBurnLogs, internalTxs,
parseEventLogs, erc20Abi, getAddress, pubkey, log.args.from) so you only push a
synthesized internalTx with to: getAddress(pubkey) when the burn's
sender/participant matches the transaction participant (e.g., require
isAddressEqual(getAddress(log.args.from), getAddress(pubkey)) or the
tx.from/other transaction participants include that address); otherwise skip
adding the synthesized internalTx (or populate a more accurate recipient if
available) so parse() won't produce a false Receive for the user.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts`:
- Around line 420-438: The synthesized internalTx currently hardcodes to:
getAddress(pubkey) for any WMNT -> zeroAddress burn, causing spurious Receive
entries; change the logic in SecondClassEvmAdapter where wrappedNativeBurnLogs
are processed (use symbols WRAPPED_NATIVE_CONTRACT_BY_CHAIN_ID,
wrappedNativeBurnLogs, internalTxs, parseEventLogs, erc20Abi, getAddress,
pubkey, log.args.from) so you only push a synthesized internalTx with to:
getAddress(pubkey) when the burn's sender/participant matches the transaction
participant (e.g., require isAddressEqual(getAddress(log.args.from),
getAddress(pubkey)) or the tx.from/other transaction participants include that
address); otherwise skip adding the synthesized internalTx (or populate a more
accurate recipient if available) so parse() won't produce a false Receive for
the user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/contracts/second-class-evm-chain.md:
- Around line 171-188: The numbered checklist in
.claude/contracts/second-class-evm-chain.md is out of order (items labeled 42,
then 44, then 43); update the item numbers so they increment sequentially in
document order—specifically, rename the "44. **Blacklist native ERC20 wrapper**"
entry to "43." and rename the subsequent "43." entry (Phase 4.5) to "44."
(ensure any internal references or cross-links to
WRAPPED_NATIVE_CONTRACT_BY_CHAIN_ID, the blacklist.json guidance, or Phase
numbers are updated accordingly).

gomesalexandre and others added 2 commits February 20, 2026 19:51
- fix early-return bug in processRelatedAssetIds: assets with
  relatedAssetKey set but not in the group array now get added
- fix existing group merge: when CoinGecko/Zerion fail but
  relatedAssetKey points to an existing group, merge the asset
  into that group instead of setting null
- add manual stablecoin mappings for Linea + Mantle native
  USDC/USDT/DAI to manualRelatedAssetIndex
- update second-class-evm-chain contract with stablecoin
  mapping step
- regen Linea + Mantle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Canonical defensive version lives in src/lib/utils/mantle.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both linea and mantle are happy campers now UwU

https://jam.dev/c/92059af1-d1ef-4a2b-bb0d-d89a9329050f

@gomesalexandre gomesalexandre enabled auto-merge (squash) February 20, 2026 18:55
Copy link
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts`:
- Around line 260-274: The code silently returns when existingRelatedAssetKey is
set but relatedAssetIndex[existingRelatedAssetKey] is undefined, leaving an
orphaned key; change the logic inside the existingRelatedAssetKey branch in
generateChainRelatedAssetIndex.ts so that if group is falsy you create and
assign a new group containing assetId (e.g.,
relatedAssetIndex[existingRelatedAssetKey] = [assetId]) and optionally log the
recovery, while keeping the existing checks that avoid duplicate inserts when
the asset is already present.

---

Duplicate comments:
In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts`:
- Around line 65-68: The suppressing Gitleaks comment is unnecessary for the
Solana CAIP-19 mint entry inside the mapping keyed by starknetAssetId in
generateChainRelatedAssetIndex.ts; remove any gitleaks suppression
annotation/comment around the Solana asset string (the array value for
[starknetAssetId]) so the file contains only the CAIP-19 IDs without a
suppression note.

@gomesalexandre gomesalexandre merged commit eb671f4 into develop Feb 20, 2026
6 checks passed
@gomesalexandre gomesalexandre deleted the feat/integrate-mantle-relay branch February 20, 2026 19:06
gomesalexandre added a commit that referenced this pull request Feb 20, 2026
Emulates squash merge of #11905 into develop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

3 participants