feat: integrate Citrea (4114) as second-class EVM chain#12368
Draft
swdiscordia wants to merge 3 commits into
Draft
feat: integrate Citrea (4114) as second-class EVM chain#12368swdiscordia wants to merge 3 commits into
swdiscordia wants to merge 3 commits into
Conversation
Adds Citrea Bitcoin L2 mainnet (chainId 4114) as a second-class EVM chain behind the VITE_FEATURE_CITREA flag. Native gas token cBTC (18 decimals, BTC-pegged via Clementine BitVM bridge). Standard contract Phase 1-2 items implemented (CAIP, KnownChainIds, ChainAdapter, EvmBaseAdapter, Plugin, FeatureFlag, 10x HDWallet, viem/ethers, baseAsset, utils, CSP, asset generation, coingecko adapter, migration 335). cBTC pricing falls back to WBTC mainnet via manualRelatedAssetIndex (cBTC has no direct CoinGecko price as of mainnet launch). Incidental fix: market-service-manager treats price=0 as not-found in findByAssetId, so providers returning partial data with zero price don't block the related-asset fallback. Symmetric with the existing findPriceHistoryByAssetId behavior. Discovered during cBTC smoke testing.
…nd-class pattern Returning `process.env.VITE_CITREA_NODE_URL` directly diverged from the second-class chain convention (Mantle, Berachain, Sonic, etc. all return `PUBLIC_RPC_URLS.<chain>[0]`). Switched to `PUBLIC_RPC_URLS.citrea[0]` to align with the existing pattern at `ethersProviderSingleton.ts:30-84`. The citrea entry was already present at `publicRpcUrls.ts:98`. Refs shapeshift#12367 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two corrections to manualRelatedAssetIndex in both generateRelatedAssetIndex.ts and generateChainRelatedAssetIndex.ts: 1. WBTC.e (Citrea Bridged WBTC at `0xdf240dc...`) was mis-mapped by Zerion's algo to ETH USDT — a ~$77k vs ~$1 pricing divergence in the UI. Added a manual override `'eip155:1/erc20:0x2260...': ['eip155:4114/erc20:0xdf240dc...']` so WBTC.e correctly resolves to the Ethereum Wrapped Bitcoin canonical. 2. Removed the prior `[citreaAssetId]: ['eip155:1/erc20:0x2260...']` entry that grouped cBTC under ETH WBTC. Per Citrea team input (cBTC is the main token of Citrea — analogous to SOL for Solana), cBTC is its own primary asset rather than a wrapped variant. This aligns with the convention already followed for BTC/AVAX/MNT/BERA natives (`relatedAssetKey: null`, no group). Adding `[citreaAssetId]: [btcAssetId]` was considered but would mutate BTC native's `relatedAssetKey` to cBTC at the line 422-427 group- update step, breaking BTC's primary status — unsafe. Regenerated `public/generated/*` artifacts via `pnpm run generate:chain eip155:4114`. Final state verified: - cBTC.relatedAssetKey = null (primary, standalone) - WBTC.e.relatedAssetKey = ETH WBTC (in ETH WBTC group, +1 member) - BTC native.relatedAssetKey = null (untouched, still primary) - ETH WBTC.relatedAssetKey = self (canonical, unchanged) Refs shapeshift#12367 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Integrate Citrea — the first Bitcoin L2 ZK-rollup (EVM-equivalent Type-2) — as a second-class EVM chain in ShapeShift. After this PR, users can hold and view their
cBTCand Citrea-bridged tokens (USDC.e, USDT.e, WBTC.e, etc.) directly in the wallet behind theVITE_FEATURE_CITREAfeature flag.Chain facts
4114(CAIPeip155:4114) — verified live viaeth_chainId→0x1012cBTC(18 decimals, BTC-pegged via Clementine BitVM, slip44:60)cBTC(WcBTC ERC-20):0x3100000000000000000000000000000000000006(system contract, deployed — verified viaeth_getCode)Scope
All Phase 1 / Phase 2 / Phase 3.5 / Phase 4 / Phase 4.5 points of
.claude/contracts/second-class-evm-chain.mdare covered:KnownChainIds, chain adapter (CitreaChainAdapterextendsSecondClassEvmAdapter), discriminated unionssrc/plugins/citrea/index.tsx), feature flag,.env/.env.developmentsupportsCitrea()+_supportsCitrea(13 files touched in total: 9 wallet packages +hdwallet-metamask-multichain's 2 sub-impls +hdwallet-core's 2 shared abstraction files)defineChain— viem 2.43.5 shipscitreaTestnetonly, no mainnet definition), ethers provider returningPUBLIC_RPC_URLS.citrea[0](second-class pattern), public RPC URLeip155_4114/adapter.json), Citrea asset-data script335: clearAssets), vite env type declarationsSECOND_CLASS_CHAINS, plugin provider, markets row, popular assets, asset service, opportunities mappingsSecondClassEvmAdapter.WRAPPED_NATIVE_CONTRACT_BY_CHAIN_IDasset-manifest.json,generatedAssetData.json,relatedAssetIndex.json(+.br/.gz)Related-asset mapping
cBTCis treated as its own primary asset (relatedAssetKey: null, no group) — matches BTC/AVAX/MNT/BERA convention. Aligns with Citrea team guidance ("cBTC is the main token of Citrea — like SOL for Solana").WBTC.e(0xdf240dc...) had to be manually overridden inmanualRelatedAssetIndexbecause Zerion's algo was mis-mapping it to ETH USDT ($1) instead of ETH WBTC ($77k) — material pricing bug if left uncorrected.Phase 3 swapper / data-provider research (verified 2026-05-21):
0xE413743B51f3cC8b3ac24addf50D18fa138cB0Bbare pre-integrated in Garden's/v2/chains(evm:4114, nativecitrea:cbtc,is_active: true,min_amount: 0.0001 cBTC,max_amount: 5 cBTC), but noorder_pairis activated server-side. Verified via/v2/quoteon 8 representative pairs (bitcoin:btc↔citrea:cbtc,citrea:cbtc↔arbitrum:wbtc,starknet:strkbtc→citrea:cbtc,base:cbbtc→citrea:cbtc,ethereum:wbtc↔citrea:cbtc) — all returnNo order pair found. Routes can activate at any time via Garden backend config without requiring a code change in shapeshift/web. Note: the ShapeShift GardenSwapper integration is tracked in feat(swapper): integrate Garden Finance for BTC and wrapped BTC swaps #12355 (open, not yet merged)./chainsreturns 73 chains; chainId 4114 is not in the list. ❌ Not currently supported./v2/networksdoes not list Citrea. ❌ Not currently supported./api/available-routesendpoint returned a parse error; inconclusive without further investigation. 🔍 Follow-up./v1/chainsrequires API auth for full enumeration; inconclusive from public endpoint. 🔍 Follow-up.No swap routes are usable today.
Out of scope (tracked separately)
Issue (if applicable)
closes #12367
Risk
HIGH-RISK — new chain integration touches:
_supportsCitreaboolean +supportsCitrea()predicate)335: clearAssets)SecondClassEvmAdapterregistered for chainId 4114)cBTC— relevant if/when a swapper enables Citrea)Affected paths: HDWallet, CAIP, chain-adapters, contracts, asset-service, portfolio, plugin layer, persistor migrations.
Unaffected: existing swappers (no Citrea routes wired), existing chains' adapters, existing HDWallet derivations for other chains.
Please apply the
high risklabel (external contributor cannot add it directly — 403 on REST).Testing
Engineering
Setup
pnpm installVITE_FEATURE_CITREA=truein.env.development(default) andVITE_CITREA_NODE_URL=https://rpc.mainnet.citrea.xyzpnpm run devVerification checklist
cBTCand any held Citrea tokens with correct icons (no perma-loading spinner)cBTC→ "Actifs connexes" section is empty / absent (cBTC standalone)WBTC.e) → "Actifs connexes" shows Wrapped Bitcoin on Ethereum (NOT USDT)cBTCto self → tx history shows confirmed (uses genericSecondClassEvmAdapter.getTransactionStatus)pnpm run type-check && pnpm run lintpnpm run generate:chain eip155:4114(withZERION_API_KEYset) re-generates without diff ingeneratedAssetData.json/relatedAssetIndex.json(idempotent)Math walkthrough — Zerion override correctness
Before fix:
WBTC.e.relatedAssetKey = ETH USDT→ UI used USDT price ($1) for a Bitcoin-pegged asset ($77k) →77000× pricing error in portfolio display.$77k). Verified by inspectingAfter fix:
WBTC.e.relatedAssetKey = ETH WBTC→ UI uses WBTC price (public/generated/generatedAssetData.jsonafter regen.Operations
The chain is gated behind
VITE_FEATURE_CITREA(defaultfalsein.env, defaulttruein.env.development). Production rollout would be a separate config flip with QA on a preview environment.Screenshots (if applicable)
N/A for this draft. UI is identical to other second-class chains (Mantle, Berachain, etc.) — the chain selector adds Citrea at the bottom; asset detail pages render the standard layout. Screenshots will be added before marking ready-for-review.