Add Wormhole bridge auto-tracker#791
Conversation
- add shared `BridgeAttribution` type for per-bridge per-source attributions - alias `LayerZeroConfig` and `HyperlaneConfig` to `BridgeAttribution` - rename `enrollBridge` to `enrollAttribution` - add `enrollSingleSource` guard wrapper
- add `WormholeConfig` (`BridgeAttribution[]`) and `BridgeConfigs.wormhole` - declare `BridgeConfigs` single-source members with literal `BridgeAttribution` shape - add `enrollMultiSource` enroller wired in `collectContributionsByDestination` - add `wormholeConfig` knobs to `BridgeConfig` and dispatch branch in `importAdapter`
- add `@wormhole-foundation/sdk-base` exact-pin `devDependencies` entry - add `generate-wormhole-config` npm script - add generator script with registry loader, cli parsing, asset orchestration, and stub `generateForAsset`
- implement `generateForAsset`: match by symbol on wormhole-wrapped tokens, filter on self-reference, evm-address shape, decimals bounds, llamakey resolution, exclude lists, and address dedup - apply bilateral `chainMap` with warn-once on unknown-target remappings; flag decimals diverging from the per-asset modal - group hits by source chain, sort outer and inner alphabetical, and emit `WormholeConfig` files (or stdout when `--dry`) with auto-doc header - extend `main` with end-of-run aggregate summary; add `Hit`, `AssetResult` types and `EVM_ADDRESS_RE` constant
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR extends the pegged assets bridge configuration system to support Wormhole, a cross-chain messaging protocol. It introduces a unified type schema, a code-generating script that reads the Wormhole registry and outputs per-asset configuration files, and runtime integration to load and apply those configurations alongside existing LayerZero and Hyperlane bridges. ChangesWormhole Bridge Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/peggedData/types.ts (1)
82-87: 💤 Low valueConsider documenting the chainMap key naming difference.
The
chainMapkey type differs across bridge configs:
lzConfig.chainMapandhyperlaneConfig.chainMapuse[llamaKey: string]wormholeConfig.chainMapuses[whLowerName: string]This inconsistency likely reflects different input formats (Wormhole registry names vs DefiLlama keys), but adding a brief comment explaining why the key type differs would help future maintainers understand the design choice.
🤖 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/peggedData/types.ts` around lines 82 - 87, Update the type comment for wormholeConfig.chainMap to explain the naming difference: note that wormholeConfig.chainMap keys are the Wormhole registry names (normalized/lowercased, hence whLowerName) while lzConfig.chainMap and hyperlaneConfig.chainMap expect DefiLlama chain keys (llamaKey), and clarify that the mapping is applied bilaterally to source and destination; place this explanatory comment next to the wormholeConfig.chainMap declaration in types.ts so future maintainers can see why the key naming differs.
🤖 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/adapters/peggedAssets/helper/scripts/generateWormholeConfig.ts`:
- Around line 131-139: The CLI currently allows `--asset` without a value
because the generic parser treats missing next tokens as flags; modify the
parser so that when `key === "asset"` and `next` is undefined or
`next.startsWith("--")` you do NOT set `args.asset = true` but instead surface
an error (throw or call process.exit(1) with a clear message like "Missing value
for --asset") so the run fails rather than defaulting to processing all assets;
also keep the downstream logic that computes `const asset = typeof args.asset
=== "string" ? args.asset : undefined` so it receives only a real string or the
program exits.
- Around line 376-380: The current validation for token.decimals uses typeof and
range checks which let NaN through; update the guard in the loop that handles
token/peggedAsset to explicitly reject non-finite values by using
Number.isFinite(token.decimals) combined with the existing range checks (e.g.,
ensure Number.isFinite(token.decimals) && token.decimals >= 0 && token.decimals
<= 77) so that NaN and Infinite values are rejected and the existing stderr
warning/continue behavior is preserved for invalid decimals.
---
Nitpick comments:
In `@src/peggedData/types.ts`:
- Around line 82-87: Update the type comment for wormholeConfig.chainMap to
explain the naming difference: note that wormholeConfig.chainMap keys are the
Wormhole registry names (normalized/lowercased, hence whLowerName) while
lzConfig.chainMap and hyperlaneConfig.chainMap expect DefiLlama chain keys
(llamaKey), and clarify that the mapping is applied bilaterally to source and
destination; place this explanatory comment next to the wormholeConfig.chainMap
declaration in types.ts so future maintainers can see why the key naming
differs.
🪄 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: 89bb4697-50eb-4ad2-86e1-eebd2f2dd8cb
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (10)
package.jsonsrc/adapters/peggedAssets/dai/wormholeConfig.tssrc/adapters/peggedAssets/eurc/wormholeConfig.tssrc/adapters/peggedAssets/helper/bridgeConfig.tssrc/adapters/peggedAssets/helper/scripts/generateWormholeConfig.tssrc/adapters/peggedAssets/tether/wormholeConfig.tssrc/adapters/peggedAssets/usd-coin/wormholeConfig.tssrc/peggedAssets/utils/importAdapter.tssrc/peggedData/peggedData.tssrc/peggedData/types.ts
- throw when `--asset` has no value - reject `NaN` and `±Infinity` in the decimals guard via `Number.isFinite`
This PR adds an auto-tracker for Wormhole Portal Token Bridge wrapped assets covering USDC, USDT, DAI, and EURC.
Reason
peggedassets-server already auto-tracks LayerZero (#762) and Hyperlane (#790) bridged supply via per-asset config files generated from each bridge's registry, both using single-source attribution. Wormhole's Portal Token Bridge uses permissionless attestation: an asset with multi-native deployment (USDC is minted natively by Circle on 8+ chains) gets multiple wormhole-wrapped variants per destination chain, one per source chain it was bridged from, each as a distinct ERC20 address. A single-source config can't capture this faithfully. This PR generalizes the bridge framework to admit multi-source attribution via
BridgeAttribution[]and adds a Wormhole generator + per-asset configs for the four assets. As Wormhole or future permissionless bridges add new attestations, re-running the generator picks them up without further code changes.Design notes
Wormhole's Portal Token Bridge uses permissionless attestation: an asset with multi-native deployment (USDC is minted natively by Circle on 8+ chains) gets multiple wormhole-wrapped variants per destination chain, one per source chain it was bridged from, each as a distinct ERC20 address. Faithful attribution requires modeling each
(source, destination)pair.To accommodate this, the bridge framework receives a small generalization: the shared attribution shape that LayerZero and Hyperlane already use (single source per asset) is extended so that a bridge can declare an array of attributions when its data is multi-source. The runtime groups contributions by
(destChain, sourceChain)pair, so #790's dedup and guard logic apply naturally per pair. To keep all bridge types coherent,LayerZeroConfigandHyperlaneConfigare now aliases of a sharedBridgeAttributionshape; topology is encoded at the consumer site (single-source bridges useBridgeAttribution, multi-source usesBridgeAttribution[]).Applied behavior on the 4 wired assets: 3 net-new tracked
(chain, source)slots emerge (USDT.base, DAI.base, DAI.celo). USDC's wormhole-wrapped variants collide withnative mintedstatus on each destination chain (Circle issues USDC natively across the major chains where wormhole-wrapped variants exist), so the runtime'slogNativeMintedSkipcorrectly suppresses them, accounting for preserved, no double-counting introduced. EURC is wired with an emptywormholeConfig: {}for forward compatibility; Wormhole currently has no EURC attestations, so regeneration picks up future ones without code changes.Changes
BridgeAttributionshared shape inbridgeConfig.ts; aliasLayerZeroConfigandHyperlaneConfigto it; renameenrollBridgetoenrollAttributionand addenrollSingleSourceguard wrapperWormholeConfig = BridgeAttribution[], extendBridgeConfigs.wormhole, addenrollMultiSourceenroller, addwormholeConfigknobs toBridgeConfig(symbols,excludeChains,excludeSources,chainMap), and add dispatch branch inimportAdapter.tsgenerateWormholeConfig.ts— a build-time generator that reads@wormhole-foundation/sdk-basevia its public token API, filters per asset symbol with EVM-only destinations, sane decimals, chain resolution, exclude lists, address dedup, and emits per-asset config files (~620 LOC)@wormhole-foundation/sdk-base4.20.0 (pinned exact, indevDependencies— generator is build-time only) andgenerate-wormhole-confignpm scriptwormholeConfig: {}on USDC, USDT, DAI, and EURC inpeggedData.ts[], forward-compat)Summary by CodeRabbit
New Features
Chores