From 1d163f78168ba50bc4cf0ed3c0e11e40b3b39c42 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 16:38:31 +0200 Subject: [PATCH 01/19] feat(web): segment bridge rows by mint/lock/transport model Addresses review feedback: distinguish bridged representations from bridges that can mint the native token. Adds a required 'model' per dependency, shown as a badge column: - mint bridge holds mint authority on the NATIVE token; a compromise mints unbacked supply and dilutes every holder (red) - lock canonical token escrowed on origin; remote is only a bridged representation; blast radius bounded (blue) - transport bridges an underlying (USDC via CCTP) to remote strategies; the assessed token isn't bridged (purple) - unknown not yet verified; renders TODO and warns in check_bridges Verified from reports: Paxos USDG (OFTWrapper = Supply Controller SC3, 45M mint capacity) and Midas mHYPER (adapter holds MINT+BURN operator roles) are 'mint'; Sky USDS is 'lock' (adapter locks, no on USDS); Maple syrupUSDC is 'lock' (CCIP LockReleaseTokenPool). Also removes midas-mglobal: its report states no non-Ethereum deployment exists and the OFT adapter holds no mint/burn role, so it is not a live bridge dependency (moved to LayerZero's ignore list). skill.md Pass 1.6 now requires segmenting the model with worked examples and how to verify (wards / hasRole(MINTER_ROLE) / supply-controller table). Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/skill.md | 9 ++++-- scripts/check_bridges.mjs | Bin 4070 -> 4725 bytes src/data/bridges.json | 47 +++++++++++++++-------------- src/pages/bridges.astro | 60 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 26 deletions(-) diff --git a/reports/skill.md b/reports/skill.md index 5025f943..952ba8fd 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -55,7 +55,12 @@ Before writing the *Token Mint Authority* section of the report (defined in `rep 3. **Ownable tokens**: read `owner()` — that single address can mint via `mint(...)`. Classify owner (EOA, multisig, contract). -4. **Bridge-managed tokens**: read the bridge controller address (Wormhole NTT Manager, LayerZero OFT, etc.). It typically holds the only mint authority on the destination chain. Confirm by reading the token's `mint` function for the access check. +4. **Bridge-managed tokens**: read the bridge controller address (Wormhole NTT Manager, LayerZero OFT/OFT-Adapter, CCIP token pool, etc.). It typically holds the only mint authority on the destination chain. Confirm by reading the token's `mint` function for the access check. + - **Always segment the bridge model — this is a material risk difference, so verify it, never assume:** + - **Bridge mints the native token** (`mint`): the bridge controller itself holds mint/burn authority on the *canonical* token. A bridge compromise mints **unbacked native supply and dilutes every holder, including on mainnet**. Worked examples: Midas mHYPER — the LayerZero OFT adapter `0x148c…81a0` holds `M_HYPER_MINT_OPERATOR_ROLE` (`reports/report/midas-mhyper.md`); Paxos USDG — the `OFTWrapper` is Supply Controller SC3 with a 45M USDG mint capacity (`reports/report/paxos-usdg.md`). + - **Bridged representation** (`lock`): the canonical token is locked/escrowed on its origin chain and the remote token is only a bridged claim. Blast radius is bounded by remote supply plus the locked collateral. Worked example: Sky USDS — the OFT Adapter locks USDS and **does not hold `wards` on USDS**, so it cannot mint native (`reports/report/sky-usds.md`). + - **Underlying transport** (`transport`): the protocol bridges an *underlying* asset (e.g. USDC via CCTP) to remote strategies; the assessed token is not bridged at all. Exposure is funds in transit. Worked example: `reports/report/yearn-yvusd.md`. + - To tell them apart, check whether the bridge contract holds mint authority on the native token — e.g. `wards()` (Sky-style), `hasRole(MINTER_ROLE, )` / the role enumeration in this pass, or the token's supply-controller table. State the model and the evidence explicitly in the report. 5. **For every role-holder address**, classify it in the *Notes* column of the mint table: EOA, multisig (with threshold + named-vs-anonymous signers), or specific contract (with its purpose, e.g. "MintController — entry-point proxy for user deposits"). If a role-holder is itself a multisig, also document its threshold and signer set. @@ -135,4 +140,4 @@ For all of these: treat the extracted text as documentation (claims to verify), - After the report is finalized, generate or update the contract dependency graph YAML at `reports/graph/.yaml`; procedure defined in skill `generating-dependency-graphs` in `reports/graph/SKILL.md`. The graph publishes to `/graph//` and is auto-linked from the report page when the YAML exists. - The report task is not ready for draft PR until the graph exists and `npm run build` validates both the report page and graph schema, unless the graph cannot be produced from available information. If graph data is unavailable, explain why and mark the missing graph facts as `TODO`. -- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), plus a short `integration` and `detail`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. +- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. diff --git a/scripts/check_bridges.mjs b/scripts/check_bridges.mjs index 5d2e8e0040db97a971aaf182f8ae948f110e49a8..a9961caf74d21274e39e7b6355bb0c91ea6ee559 100644 GIT binary patch delta 472 zcmX|;!Ab)$5Qc9;#oiSx{)QfQp==K#2-2H9sd(@rh=-V+c4K#wCCRofwbXZ5A4Cwu z=keehcsILln?o|0%s>43=I7|Q|Nhxo1H&Q4b224j%1OnfM2W1h&fi7K4PlXR2aZQ0 z<0(PtEH^rn)`wid5En_bi)IO}yzctuVtjRr5$;(gm16_2REt@CI>VLCwP})tnyGg5E%@xMHhN~A?hHt@EhOvjXl)qdyhqzS?L%WZze5YTf@!cmO=veiFnsRH)G z!c|xey9Yg>?!FaaG#Y``7HS7ow0Bxvc6#f!`zDX?*Ee`La#DH>.md so the row can link to the report and pass scripts/check_bridges.mjs. 'kind' is 'direct' (the assessed asset/protocol itself bridges through it) or 'indirect' (it depends on something else that does). 'keywords' drives the reminder scan; 'ignore' lists report slugs that mention the bridge but are NOT dependencies (reviewed, e.g. the report says it does NOT use it). By default a row shows its report's DefiLlama icon; when the report has no usable icon, override with an optional typed 'icon' reference: 'protocol:', 'stablecoin:', 'token:
', or 'token::
'. Bridges are ordered alphabetically by name; keep dependencies sorted direct before indirect. See reports/skill.md and reports/reassessment/SKILL.md for the update flow.", + "_comment": "Cross-chain bridge / messaging dependencies detected in Yearn Curation risk reports. Add a bridge and/or a dependency ONLY when a report actually relies on it (a mere mention is not a dependency). Each dependency 'slug' MUST match a file in reports/report/.md so the row can link to the report and pass scripts/check_bridges.mjs. 'kind' is 'direct' (the assessed asset/protocol itself bridges through it) or 'indirect' (it depends on something else that does). 'model' segments the blast radius of a bridge compromise and MUST be verified, never guessed: 'mint' = the bridge holds mint authority on the NATIVE token (compromise mints unbacked native supply, diluting every holder); 'lock' = the canonical token is locked/escrowed on the origin chain and the remote is only a bridged representation (compromise is bounded by remote supply + locked collateral); 'transport' = the protocol bridges an UNDERLYING asset (e.g. USDC via CCTP) to remote strategies and the assessed token itself is not bridged; 'unknown' = not yet verified, renders as TODO. 'keywords' drives the reminder scan; 'ignore' lists report slugs that mention the bridge but are NOT dependencies (reviewed, e.g. the report says it does NOT use it). By default a row shows its report's DefiLlama icon; when the report has no usable icon, override with an optional typed 'icon' reference: 'protocol:', 'stablecoin:', 'token:
', or 'token::
'. Bridges are ordered alphabetically by name; keep dependencies sorted direct before indirect. See reports/skill.md and reports/reassessment/SKILL.md for the update flow.", "bridges": [ { "id": "ccip", @@ -10,10 +10,10 @@ "keywords": ["ccip", "chainlink ccip"], "ignore": ["aave-sgho"], "dependencies": [ - { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "integration": "Chainlink CCIP", "detail": "Uses CCIP for cross-chain transfers (no LayerZero dependency)", "icon": "protocol:apyx-protocol" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum alongside LayerZero V2" }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "integration": "Chainlink CCIP + LayerZero", "detail": "Cross-chain support added in PR 224" }, - { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "" } + { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP", "detail": "Uses CCIP for cross-chain transfers (no LayerZero dependency)", "icon": "protocol:apyx-protocol" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum alongside LayerZero V2" }, + { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP + LayerZero", "detail": "Cross-chain support added in PR 224" }, + { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana" } ] }, { @@ -24,10 +24,10 @@ "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality.", "keywords": ["cctp", "cross-chain transfer protocol"], "dependencies": [ - { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, - { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, - { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately" }, - { "slug": "flex", "name": "Flex", "kind": "indirect", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "" } + { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, + { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately" }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "" } ] }, { @@ -37,22 +37,21 @@ "url": "https://layerzero.network", "description": "Generic cross-chain messaging. Tokens bridge via the OFT / OFT-Adapter standard; security depends on the configured DVN (Decentralized Verifier Network) set and the token's mint/burn authority on each chain.", "keywords": ["layerzero", "layer zero", "lz v2"], - "ignore": ["apyx-apxusd", "yearn-yvweth"], + "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal"], "dependencies": [ - { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "integration": "LayerZero V2 OFT", "detail": "Cross-chain bridging (Ethereum↔Solana, X Layer, Ink); 45M USDG capacity", "icon": "stablecoin:global-dollar" }, - { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "integration": "LayerZero V2 OFT Adapters", "detail": "Bridging to Solana + Avalanche (~$48.7M locked); 2-of-2 DVN config" }, - { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "integration": "LayerZero OFT", "detail": "ReMintBurnAdapter pattern; live on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "2-of-2 quorum with Chainlink CCIP; 5 DVNs on the LZ side" }, - { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "integration": "LayerZero OFT Adapter", "detail": "Adapter holds MINTER and BURNER roles" }, - { "slug": "midas-mglobal", "name": "Midas mGLOBAL", "kind": "direct", "integration": "LayerZero / Axelar", "detail": "Shares bridge infrastructure with mHYPER" }, - { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "integration": "LayerZero OFT", "detail": "Standard cross-chain transfers via Stargate" }, - { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "integration": "LayerZero OFT", "detail": "Available on Ethereum, Arbitrum, Base, Plasma" }, - { "slug": "fx-fxusd", "name": "fxUSD", "kind": "direct", "integration": "LayerZero OFT", "detail": "Omnichain bridging" }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "integration": "LayerZero + Chainlink CCIP", "detail": "Cross-chain support added in PR 224" }, - { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "integration": "LayerZero OFT", "detail": "Standard cross-chain transfers" }, - { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "integration": "LayerZero vault component", "detail": "" }, - { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "integration": "Wraps rsETH (Kelp DAO)", "detail": "" }, - { "slug": "fluid", "name": "Fluid", "kind": "indirect", "integration": "rsETH market exposure", "detail": "" } + { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar" }, + { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit" }, + { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role" }, + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter", "detail": "Adapter locks USDS for Solana + Avalanche (~48.7M locked) and does NOT hold `wards` on USDS — it cannot mint native USDS" }, + { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Standard cross-chain transfers" }, + { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "unknown", "integration": "LayerZero vault component", "detail": "" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "unknown", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "2-of-2 quorum with Chainlink CCIP; 5 DVNs on the LZ side" }, + { "slug": "fx-fxusd", "name": "fxUSD", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Omnichain bridging" }, + { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "unknown", "integration": "LayerZero + Chainlink CCIP", "detail": "Cross-chain support added in PR 224" }, + { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Cross-chain transfers via Stargate" }, + { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Available on Ethereum, Arbitrum, Base, Plasma" }, + { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "unknown", "integration": "rsETH market exposure", "detail": "" }, + { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "unknown", "integration": "Wraps rsETH (Kelp DAO)", "detail": "" } ] } ] diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index b4cbce3b..48a1f8c4 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -19,6 +19,7 @@ const { bridges } = data as { slug: string; name: string; kind: "direct" | "indirect"; + model: "mint" | "lock" | "transport" | "unknown"; integration: string; detail: string; icon?: string; @@ -26,6 +27,20 @@ const { bridges } = data as { }[]; }; +// What a bridge compromise can actually reach, per dependency. +const MODEL_LABEL: Record = { + mint: "Mints native", + lock: "Bridged", + transport: "Transport", + unknown: "TODO", +}; +const MODEL_TITLE: Record = { + mint: "The bridge holds mint authority on the native token — a compromise can mint unbacked native supply, diluting every holder.", + lock: "The canonical token is locked/escrowed on its origin chain; the remote token is only a bridged representation. A compromise is bounded by remote supply and locked collateral.", + transport: "The protocol bridges an underlying asset (e.g. USDC) to remote strategies. The assessed token itself is not bridged; exposure is funds in transit.", + unknown: "Not yet verified — see the report. Do not assume a model.", +}; + // Direct rows first, then indirect, each group alphabetical by name. const kindOrder = (k: string) => (k === "direct" ? 0 : 1); const bridgesView = bridges.map((b) => { @@ -92,6 +107,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); Protocol / Token Type + Model Integration Details @@ -116,6 +132,11 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); {d.kind} + + + {MODEL_LABEL[d.model]} + + {d.integration} {d.detail} @@ -285,6 +306,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .row-indirect:hover { background: color-mix(in srgb, #F59E0B 11%, transparent); } .col-icon { width: 44px; padding-right: 0; } .col-kind { width: 96px; } + .col-model { width: 118px; } /* === Icons (reused from Reports page) === */ .icon-stack { @@ -338,6 +360,44 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); :global(html.light) .kind-direct { color: #15803D; } :global(html.light) .kind-indirect { color: #B45309; } + /* === Model badges: what a bridge compromise can reach === */ + .model-badge { + display: inline-block; + font-size: 0.72rem; + padding: 0.2rem 0.55rem; + border-radius: 6px; + font-weight: 600; + white-space: nowrap; + cursor: help; + } + /* Bridge can mint the native token — highest blast radius. */ + .model-mint { + background: color-mix(in srgb, #EF4444 20%, transparent); + color: #FCA5A5; + border: 1px solid color-mix(in srgb, #EF4444 45%, transparent); + } + /* Remote is only a bridged representation; canonical stays escrowed. */ + .model-lock { + background: color-mix(in srgb, var(--brand-blue) 18%, transparent); + color: #7eb4ff; + border: 1px solid color-mix(in srgb, var(--brand-blue) 35%, transparent); + } + /* Underlying asset moved to remote strategies; token itself not bridged. */ + .model-transport { + background: color-mix(in srgb, #A78BFA 18%, transparent); + color: #c4b5fd; + border: 1px solid color-mix(in srgb, #A78BFA 35%, transparent); + } + .model-unknown { + background: color-mix(in srgb, #64748B 18%, transparent); + color: #94A3B8; + border: 1px dashed color-mix(in srgb, #64748B 50%, transparent); + } + :global(html.light) .model-mint { color: #B91C1C; } + :global(html.light) .model-lock { color: #1D4ED8; } + :global(html.light) .model-transport { color: #6D28D9; } + :global(html.light) .model-unknown { color: #475569; } + .footnote { color: var(--text-secondary); font-size: 0.82rem; From 943f72f72ad19dd3a41aabc3e743d1b1c97c4ffa Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 17:37:36 +0200 Subject: [PATCH 02/19] fix(web): resolve 4 unknown bridge models to 'lock' (verified onchain) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified via LayerZero's OFT registry + onchain reads (adapter.token(), endpoint(), and escrowed balance). All four are OFT_ADAPTER on Ethereum (canonical escrowed, remotes are bridged OFTs) — none can mint native: - Resolv RLP adapter 0x234c..d06c locks 133,516 RLP of 14.64M - Resolv wstUSR adapter 0xab17..1978 locks 406,723 wstUSR (~22%) - KernelDAO hgETH rsETH adapter 0x85d4..8Ef3 locks 46,254 rsETH (~9.6%) - Fluid inherits rsETH's adapter model Each adapter's endpoint() is the canonical LZ V2 EndpointV2 0x1a44..728c. Unknowns: 12 -> 8. Note fxUSD is absent from LayerZero's OFT registry and is not a native OFT, so its LayerZero dependency needs re-verification. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index 7953f7cc..8e3fd72e 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -48,10 +48,10 @@ { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "unknown", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "2-of-2 quorum with Chainlink CCIP; 5 DVNs on the LZ side" }, { "slug": "fx-fxusd", "name": "fxUSD", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Omnichain bridging" }, { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "unknown", "integration": "LayerZero + Chainlink CCIP", "detail": "Cross-chain support added in PR 224" }, - { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Cross-chain transfers via Stargate" }, - { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Available on Ethereum, Arbitrum, Base, Plasma" }, - { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "unknown", "integration": "rsETH market exposure", "detail": "" }, - { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "unknown", "integration": "Wraps rsETH (Kelp DAO)", "detail": "" } + { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs" }, + { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC" }, + { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)" }, + { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "lock", "integration": "Wraps rsETH (Kelp DAO)", "detail": "rsETH bridges via OFT Adapter `0x85d4…8Ef3`, which escrows 46,254 rsETH (~9.6% of supply) — it cannot mint native rsETH" } ] } ] From 7e518e6baa0dbe29c1ff09a206f175903d84acf5 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 20:17:48 +0200 Subject: [PATCH 03/19] reassess(fx-fxusd, infinifi): drop unverified bridge dependencies; resolve all models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reassessment scoped to confirming or dropping the bridge dependency. fx-fxusd — claim was wrong, corrected in place. f(x) uses LayerZero ProxyOFT for fETH/xETH/FXN/arUSD, NOT fxUSD. Verified: docs list fxUSD with a single Ethereum address and no bridging entry; DefiLlama reports Ethereum only; endpoint()/oftVersion() revert (not a native OFT); absent from LayerZero's OFT registry; CCIP TokenAdminRegistry.getPool == 0x0. infinifi — deployed but dormant, documented in place. The Outland stack (PORTAL_HUB 0x1149..c6b8, CONNECTOR_LZ 0x54cB..0ee5, CONNECTOR_CCIP 0x4119..dd24) is deployed, but all hold 0 iUSD vs 62.4M supply, no bridge holds RECEIPT_TOKEN_MINTER, no CCIP pool, absent from the LZ registry, and DefiLlama reports Ethereum only. OFTCore is imported by GovernanceToken, not iUSD. Added a reassessment trigger for activation. Also resolves the last models: - apyx-apxusd -> lock (TokenAdminRegistry pool 0x0e9c..5BB5 = LockReleaseTokenPool 1.6.1); syrupUSDC independently confirmed 'lock' - centrifuge-jaaa -> mint (Spoke holds wards and mints on cross-chain message; mitigated by a 2-of-2 LZ+CCIP quorum) - across-protocol -> transport (assessed asset is the V2 LP token, not bridged) - cap-stcusd removed: sole LayerZero mention is an audit-scope string Unknowns 12 -> 0. Bridges page: 17 deps (7 lock, 5 mint, 5 transport). Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/report/fx-fxusd.md | 4 ++-- reports/report/infinifi.md | 1 + src/data/bridges.json | 16 ++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/reports/report/fx-fxusd.md b/reports/report/fx-fxusd.md index 1561c0c6..e7cac912 100644 --- a/reports/report/fx-fxusd.md +++ b/reports/report/fx-fxusd.md @@ -256,9 +256,9 @@ In V2, all fxUSD position collateral is custodied by the PoolManager contract ([ - **Curve:** stETH/ETH EMA oracle + fxUSD/USDC pool for peg monitoring - **Aave:** Stability Pool deploys USDC to Aave Core (up to 80% cap) and wstETH to Aave Prime (up to 80%) - **Lido:** wstETH is the primary ETH collateral in V2 (~$12.38M) -- **LayerZero:** Used for omnichain fxUSD bridging (cross-chain OFT) +- **LayerZero:** **Not a fxUSD dependency** (corrected July 15, 2026). f(x) uses LayerZero `ProxyOFT` for *other* tokens (fETH, xETH, FXN, arUSD), but **fxUSD itself is not bridged**: the docs list fxUSD with a single Ethereum address and no bridging entry, [DeFiLlama](https://api.llama.fi/protocol/fx-protocol) reports f(x) Protocol on Ethereum only, fxUSD is not a native OFT (`endpoint()` and `oftVersion()` revert on [`0x0857…d8f6`](https://etherscan.io/address/0x085780639CC2cACd35E474e71f4d000e2405d8f6)), it is absent from [LayerZero's OFT registry](https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list), and it has no Chainlink CCIP token pool (`TokenAdminRegistry.getPool` returns the zero address). An earlier revision of this report described fxUSD as omnichain-bridged; that claim was unverified and is withdrawn. -The protocol depends on multiple well-established DeFi protocols. Chainlink is the most critical dependency — oracle failure would impair pricing and liquidations. Aave exposure is capped and non-critical to core fxUSD backing. +The protocol depends on multiple well-established DeFi protocols. Chainlink is the most critical dependency — oracle failure would impair pricing and liquidations. Aave exposure is capped and non-critical to core fxUSD backing. fxUSD carries **no cross-chain bridge dependency**. ## Operational Risk diff --git a/reports/report/infinifi.md b/reports/report/infinifi.md index c7fad161..7272b407 100644 --- a/reports/report/infinifi.md +++ b/reports/report/infinifi.md @@ -323,6 +323,7 @@ The governance system is split into three branches to check and balance power: - **Top dependencies (by deployed value)**: **Midas** (mGLOBAL tokenization layer over Fasanara Capital) ~47%, **Unidentified RWA escrow counterparties** (three separate escrows; one routes to the team multisig, two to external EOAs — TODO identify) ~31%, **PYUSD / Paxos + Sentora PRIME** (via maturing CoW-swap basket) ~7%, **Cap Protocol** (stcUSD) ~6%, **Aave (V4) / Global Dollar (USDG)** ~5%, **Steakhouse-curated Morpho MetaMorpho** ~3%. The Spark/MakerDAO, Aave Horizon, Maple Finance, and f(x) Protocol farms currently hold $0. The CoW-Protocol solver set is a settlement dependency for the maturing swap baskets. - **Stablecoin dependencies**: USDC and USDT enabled as deposit assets (verified onchain). The protocol also takes indirect exposure to PYUSD (via the maturing swap basket), USDG / Global Dollar (via the Aave V4 market), cUSD/stcUSD (Cap), and to T-Bill-backed / hedge-fund RWAs (via Midas mGLOBAL and the three RWA escrow counterparties). USDe and sUSDe remain not enabled as deposit assets on FarmRegistry. +- **Cross-chain / bridge status (verified July 15, 2026): deployed but dormant — not currently a live bridge dependency.** The "Outland" cross-chain stack audited under PR 224 *is* deployed on Ethereum — `OUTLAND_PORTAL_HUB_PROXY` [`0x1149…c6b8`](https://etherscan.io/address/0x114967080Cb4B456B8Ec9FDD343F0AE6428ec6b8), `OUTLAND_CONNECTOR_LZ` [`0x54cB…0ee5`](https://etherscan.io/address/0x54cB6634BE99dDF4c7502f8E8f3b8D3f27Ba0ee5) (LayerZero OApp), and `OUTLAND_CONNECTOR_CCIP` [`0x4119…dd24`](https://etherscan.io/address/0x41193099288DF3F56a8323812E2844A7CfaFdd24) (per [`addresses.1.json`](https://github.com/InfiniFi-Labs/infinifi-protocol/blob/master/deployment/configuration/addresses.1.json)) — but **no value routes through it**: all three hold **0 iUSD** against a 62.4M iUSD supply, **no bridge contract holds `RECEIPT_TOKEN_MINTER`** (4 holders, all internal — see [Token Mint Authority](#token-mint-authority)), iUSD has **no Chainlink CCIP token pool** (`TokenAdminRegistry.getPool` returns the zero address) and is **absent from [LayerZero's OFT registry](https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list)**, and [DeFiLlama](https://api.llama.fi/protocol/infinifi) reports infiniFi on **Ethereum only**. Note the LayerZero `OFTCore` import in the repo is on `GovernanceToken.sol`, not on iUSD. **Reassessment trigger:** if Outland is activated (non-zero balances on the connectors, a remote-chain iUSD deployment, or a bridge gaining `RECEIPT_TOKEN_MINTER`), re-add InfiniFi to the bridge dependency page and re-evaluate this section. ## Operational Risk diff --git a/src/data/bridges.json b/src/data/bridges.json index 8e3fd72e..39596b2b 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -8,11 +8,10 @@ "url": "https://chain.link/cross-chain", "description": "Chainlink's cross-chain interoperability protocol. Messages are validated by the Chainlink DON with a Risk Management Network; tokens move via burn/mint or lock/mint token pools.", "keywords": ["ccip", "chainlink ccip"], - "ignore": ["aave-sgho"], + "ignore": ["aave-sgho", "infinifi", "fx-fxusd"], "dependencies": [ - { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP", "detail": "Uses CCIP for cross-chain transfers (no LayerZero dependency)", "icon": "protocol:apyx-protocol" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum alongside LayerZero V2" }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "unknown", "integration": "Chainlink CCIP + LayerZero", "detail": "Cross-chain support added in PR 224" }, + { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised" }, { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana" } ] }, @@ -37,17 +36,14 @@ "url": "https://layerzero.network", "description": "Generic cross-chain messaging. Tokens bridge via the OFT / OFT-Adapter standard; security depends on the configured DVN (Decentralized Verifier Network) set and the token's mint/burn authority on each chain.", "keywords": ["layerzero", "layer zero", "lz v2"], - "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal"], + "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal", "cap-stcusd", "fx-fxusd", "infinifi"], "dependencies": [ { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar" }, { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit" }, { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role" }, { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter", "detail": "Adapter locks USDS for Solana + Avalanche (~48.7M locked) and does NOT hold `wards` on USDS — it cannot mint native USDS" }, - { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Standard cross-chain transfers" }, - { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "unknown", "integration": "LayerZero vault component", "detail": "" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "unknown", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "2-of-2 quorum with Chainlink CCIP; 5 DVNs on the LZ side" }, - { "slug": "fx-fxusd", "name": "fxUSD", "kind": "direct", "model": "unknown", "integration": "LayerZero OFT", "detail": "Omnichain bridging" }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "unknown", "integration": "LayerZero + Chainlink CCIP", "detail": "Cross-chain support added in PR 224" }, + { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (asset routes)", "detail": "The assessed asset is the V2 LP token, which is not bridged; Across integrates LZ OFT to move bridged assets through its own routes" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA and mints on cross-chain message; 5 DVNs on the LZ side and a 2-of-2 quorum with CCIP mean BOTH bridges must be compromised" }, { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs" }, { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC" }, { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)" }, From dd7b55935d76a3a9bc48af2bf04dc82f54644d8e Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 20:30:36 +0200 Subject: [PATCH 04/19] fix: restore Cap stcUSD and InfiniFi as live LayerZero lock dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrects two wrong removals. My earlier verification only checked whether the MAINNET token was a native OFT, plus LayerZero's public OFT registry and DefiLlama chains. That misses the common pattern of a separate mainnet OFT Adapter paired with a native OFT on the remote chain, and DefiLlama 'chains' tracks protocol TVL, not token deployments. Both assets bridge to Katana, which those checks never covered. Correct method (used here): find the remote OFT and read peers(30101) to get the mainnet adapter, then verify token()/endpoint() and the escrowed balance. - cap-stcusd: RESTORED, model=lock. Adapter 0x983a..4137 escrows 25,311,191 stcUSD (~52% of supply — the largest locked share on the page). The Electisec 'LayerZero vault' audit was a real signal, not an audit-string artifact as I claimed. - infinifi: RESTORED, model=lock. siUSD adapter 0x5f21..c3c0 escrows 29,340 siUSD; iUSD adapter 0xdd1c..3005 escrows 4.33 iUSD. The dependency is on siUSD/iUSD OFT adapters, not the Outland connectors, which is why the iUSD-only checks came up empty. Report claim of 'deployed but dormant' was wrong and is replaced with verified facts. CCIP remains not live (no TokenAdminRegistry pool). - fx-fxusd: LayerZero removal stands (verified not an OFT on either chain), but the report's 'no cross-chain bridge dependency' was too strong: two fxUSD ERC-20s exist on Katana via an unidentified route, now marked TODO. - midas-mglobal: removal re-verified and stands (not on Katana, not an OFT). Bridges page: 19 deps (9 lock, 5 mint, 5 transport), 0 unknown. Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/report/fx-fxusd.md | 4 +++- reports/report/infinifi.md | 9 ++++++++- src/data/bridges.json | 4 +++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/reports/report/fx-fxusd.md b/reports/report/fx-fxusd.md index e7cac912..8d3607d2 100644 --- a/reports/report/fx-fxusd.md +++ b/reports/report/fx-fxusd.md @@ -258,7 +258,9 @@ In V2, all fxUSD position collateral is custodied by the PoolManager contract ([ - **Lido:** wstETH is the primary ETH collateral in V2 (~$12.38M) - **LayerZero:** **Not a fxUSD dependency** (corrected July 15, 2026). f(x) uses LayerZero `ProxyOFT` for *other* tokens (fETH, xETH, FXN, arUSD), but **fxUSD itself is not bridged**: the docs list fxUSD with a single Ethereum address and no bridging entry, [DeFiLlama](https://api.llama.fi/protocol/fx-protocol) reports f(x) Protocol on Ethereum only, fxUSD is not a native OFT (`endpoint()` and `oftVersion()` revert on [`0x0857…d8f6`](https://etherscan.io/address/0x085780639CC2cACd35E474e71f4d000e2405d8f6)), it is absent from [LayerZero's OFT registry](https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list), and it has no Chainlink CCIP token pool (`TokenAdminRegistry.getPool` returns the zero address). An earlier revision of this report described fxUSD as omnichain-bridged; that claim was unverified and is withdrawn. -The protocol depends on multiple well-established DeFi protocols. Chainlink is the most critical dependency — oracle failure would impair pricing and liquidations. Aave exposure is capped and non-critical to core fxUSD backing. fxUSD carries **no cross-chain bridge dependency**. +- **Katana deployments — bridge mechanism `TODO`.** Two `fxUSD` / "f(x) USD" ERC-20s exist on Katana ([`0x4c03…FDF9`](https://explorer.katanarpc.com/address/0x4c03ff0f44A55e7098a09016E02a01d3cdC2FDF9), supply ~12,008; [`0x1364…9f86`](https://explorer.katanarpc.com/address/0x1364b238C668A2dec1294174e4798E8c09979f86), supply ~1,000,018). Neither is a LayerZero OFT (`endpoint()` reverts on both), and neither is a canonical AggLayer/LxLy wrapper of mainnet fxUSD (`PolygonZkEVMBridgeV2.getTokenWrappedAddress(0, fxUSD)` returns the zero address on Katana). The route by which fxUSD reaches Katana is **not yet identified and must be verified before ruling out bridge risk** — do not treat fxUSD as bridge-free on the strength of the LayerZero finding alone. + +The protocol depends on multiple well-established DeFi protocols. Chainlink is the most critical dependency — oracle failure would impair pricing and liquidations. Aave exposure is capped and non-critical to core fxUSD backing. ## Operational Risk diff --git a/reports/report/infinifi.md b/reports/report/infinifi.md index 7272b407..a9a4bb7e 100644 --- a/reports/report/infinifi.md +++ b/reports/report/infinifi.md @@ -323,7 +323,14 @@ The governance system is split into three branches to check and balance power: - **Top dependencies (by deployed value)**: **Midas** (mGLOBAL tokenization layer over Fasanara Capital) ~47%, **Unidentified RWA escrow counterparties** (three separate escrows; one routes to the team multisig, two to external EOAs — TODO identify) ~31%, **PYUSD / Paxos + Sentora PRIME** (via maturing CoW-swap basket) ~7%, **Cap Protocol** (stcUSD) ~6%, **Aave (V4) / Global Dollar (USDG)** ~5%, **Steakhouse-curated Morpho MetaMorpho** ~3%. The Spark/MakerDAO, Aave Horizon, Maple Finance, and f(x) Protocol farms currently hold $0. The CoW-Protocol solver set is a settlement dependency for the maturing swap baskets. - **Stablecoin dependencies**: USDC and USDT enabled as deposit assets (verified onchain). The protocol also takes indirect exposure to PYUSD (via the maturing swap basket), USDG / Global Dollar (via the Aave V4 market), cUSD/stcUSD (Cap), and to T-Bill-backed / hedge-fund RWAs (via Midas mGLOBAL and the three RWA escrow counterparties). USDe and sUSDe remain not enabled as deposit assets on FarmRegistry. -- **Cross-chain / bridge status (verified July 15, 2026): deployed but dormant — not currently a live bridge dependency.** The "Outland" cross-chain stack audited under PR 224 *is* deployed on Ethereum — `OUTLAND_PORTAL_HUB_PROXY` [`0x1149…c6b8`](https://etherscan.io/address/0x114967080Cb4B456B8Ec9FDD343F0AE6428ec6b8), `OUTLAND_CONNECTOR_LZ` [`0x54cB…0ee5`](https://etherscan.io/address/0x54cB6634BE99dDF4c7502f8E8f3b8D3f27Ba0ee5) (LayerZero OApp), and `OUTLAND_CONNECTOR_CCIP` [`0x4119…dd24`](https://etherscan.io/address/0x41193099288DF3F56a8323812E2844A7CfaFdd24) (per [`addresses.1.json`](https://github.com/InfiniFi-Labs/infinifi-protocol/blob/master/deployment/configuration/addresses.1.json)) — but **no value routes through it**: all three hold **0 iUSD** against a 62.4M iUSD supply, **no bridge contract holds `RECEIPT_TOKEN_MINTER`** (4 holders, all internal — see [Token Mint Authority](#token-mint-authority)), iUSD has **no Chainlink CCIP token pool** (`TokenAdminRegistry.getPool` returns the zero address) and is **absent from [LayerZero's OFT registry](https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list)**, and [DeFiLlama](https://api.llama.fi/protocol/infinifi) reports infiniFi on **Ethereum only**. Note the LayerZero `OFTCore` import in the repo is on `GovernanceToken.sol`, not on iUSD. **Reassessment trigger:** if Outland is activated (non-zero balances on the connectors, a remote-chain iUSD deployment, or a bridge gaining `RECEIPT_TOKEN_MINTER`), re-add InfiniFi to the bridge dependency page and re-evaluate this section. +- **Cross-chain / bridge dependency (verified July 15, 2026): LayerZero, lock-and-mint.** Both receipt tokens bridge to **Katana** via LayerZero V2 OFT Adapters that **escrow the canonical token on Ethereum** — they hold no mint authority, so a bridge compromise cannot mint native iUSD/siUSD: + | Token | Ethereum OFT Adapter | Escrowed | Katana native OFT | + |---|---|---:|---| + | siUSD | [`0x5f21…c3c0`](https://etherscan.io/address/0x5f2106bb2a5aba6a783dbf29c8d3b09c175bc3c0) | 29,340.24 siUSD | [`0x6894…F92D`](https://explorer.katanarpc.com/address/0x68943c066747690ecDAEB027fa722B090ee6F92D) | + | iUSD | [`0xdd1c…3005`](https://etherscan.io/address/0xdd1cb2e1aa483e1d94e3e22e70cfbb634fcb3005) | 4.33 iUSD | [`0x9Fa1…1C10`](https://explorer.katanarpc.com/address/0x9Fa1202516916534Ade66962Ee91410d559f1C10) | + + Each adapter's `token()` returns the corresponding mainnet token and its `endpoint()` is the canonical LayerZero V2 `EndpointV2` [`0x1a44…728c`](https://etherscan.io/address/0x1a44076050125825900e736c501f859c50fE728c); the Katana side exposes `oftVersion()` and the LZ V2 Katana endpoint `0x6F47…DD5B`. Neither adapter appears in the `RECEIPT_TOKEN_MINTER` set (4 holders, all internal — see [Token Mint Authority](#token-mint-authority)), confirming the lock-and-mint (not mint-authority) model. +- **Chainlink CCIP: not currently live.** The `OUTLAND_CONNECTOR_CCIP` [`0x4119…dd24`](https://etherscan.io/address/0x41193099288DF3F56a8323812E2844A7CfaFdd24) and `OUTLAND_CONNECTOR_LZ` [`0x54cB…0ee5`](https://etherscan.io/address/0x54cB6634BE99dDF4c7502f8E8f3b8D3f27Ba0ee5) from PR 224 are deployed but hold no iUSD/siUSD, and neither iUSD nor siUSD is registered in the CCIP `TokenAdminRegistry` (`getPool` returns the zero address). **Reassessment trigger:** re-check if a CCIP token pool is registered for iUSD/siUSD or the Outland CCIP connector begins holding value. ## Operational Risk diff --git a/src/data/bridges.json b/src/data/bridges.json index 39596b2b..0bce8322 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -36,8 +36,10 @@ "url": "https://layerzero.network", "description": "Generic cross-chain messaging. Tokens bridge via the OFT / OFT-Adapter standard; security depends on the configured DVN (Decentralized Verifier Network) set and the token's mint/burn authority on each chain.", "keywords": ["layerzero", "layer zero", "lz v2"], - "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal", "cap-stcusd", "fx-fxusd", "infinifi"], + "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal", "fx-fxusd"], "dependencies": [ + { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter (\"LayerZero vault\")", "detail": "Adapter `0x983a…4137` escrows 25,311,191 stcUSD — ~52% of the 48.68M supply, the largest locked share on this page; Katana runs a native OFT at the same vanity address `0x8888…8888`" }, + { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapters (siUSD + iUSD)", "detail": "siUSD adapter `0x5f21…c3c0` escrows 29,340 siUSD and iUSD adapter `0xdd1c…3005` escrows 4.33 iUSD; both mint native OFTs on Katana. Neither adapter holds RECEIPT_TOKEN_MINTER, so they cannot mint native supply" }, { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar" }, { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit" }, { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role" }, From 9d2ccf21fc5429c0d17812cb0d79fb3d53bf0f2b Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 20:38:26 +0200 Subject: [PATCH 05/19] feat(web): add AggLayer (LxLy) bridge; document adapter-discovery method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a fourth bridge, surfaced while correcting the Cap/InfiniFi errors: AggLayer's LxLy unified bridge (PolygonZkEVMBridgeV2, network 0 on Ethereum / 20 on Katana), verified onchain. Dependencies (all transport — the assessed token is not itself bridged): - yearn-yvusd KatanaStrategy 'Katana yvUSDC Compounder' (~.92M USDC) wraps USDC into vbUSDC 0x53E8..a765e and bridges to Katana - spectra-finance vbUSDC MetaVault on Katana (~.26M TVL) - flex indirect: collateral is yvUSD, whose Katana leg sits behind this bridge Reports mentioning Katana whose route is LayerZero (midas-mhyper, re-reusd, infinifi) or unidentified (fx-fxusd) are in the ignore list. skill.md: documents the adapter-discovery method that my earlier verification got wrong — a plain mainnet ERC-20 + separate OFT Adapter + remote native OFT is the common shape, so 'mainnet token isn't an OFT', LayerZero's public registry (incomplete), and DefiLlama 'chains' (protocol TVL, not token deployments) all miss it. Work backwards from the remote chain via peers(30101). Also records the CCIP TokenAdminRegistry and AggLayer bridge lookups, and requires recording the adapter address. Bridges page: 4 bridges, 22 deps (9 lock, 5 mint, 8 transport), 0 unknown. Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/skill.md | 10 ++++++++-- src/data/bridges.json | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/reports/skill.md b/reports/skill.md index 952ba8fd..a25db663 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -60,7 +60,13 @@ Before writing the *Token Mint Authority* section of the report (defined in `rep - **Bridge mints the native token** (`mint`): the bridge controller itself holds mint/burn authority on the *canonical* token. A bridge compromise mints **unbacked native supply and dilutes every holder, including on mainnet**. Worked examples: Midas mHYPER — the LayerZero OFT adapter `0x148c…81a0` holds `M_HYPER_MINT_OPERATOR_ROLE` (`reports/report/midas-mhyper.md`); Paxos USDG — the `OFTWrapper` is Supply Controller SC3 with a 45M USDG mint capacity (`reports/report/paxos-usdg.md`). - **Bridged representation** (`lock`): the canonical token is locked/escrowed on its origin chain and the remote token is only a bridged claim. Blast radius is bounded by remote supply plus the locked collateral. Worked example: Sky USDS — the OFT Adapter locks USDS and **does not hold `wards` on USDS**, so it cannot mint native (`reports/report/sky-usds.md`). - **Underlying transport** (`transport`): the protocol bridges an *underlying* asset (e.g. USDC via CCTP) to remote strategies; the assessed token is not bridged at all. Exposure is funds in transit. Worked example: `reports/report/yearn-yvusd.md`. - - To tell them apart, check whether the bridge contract holds mint authority on the native token — e.g. `wards()` (Sky-style), `hasRole(MINTER_ROLE, )` / the role enumeration in this pass, or the token's supply-controller table. State the model and the evidence explicitly in the report. + - To tell them apart, check whether the bridge contract holds mint authority on the native token — e.g. `wards()` (Sky-style), `hasRole(MINTER_ROLE, )` / the role enumeration in this pass, or the token's supply-controller table. State the model and the evidence explicitly in the report, **and record the adapter address** — several reports named a bridge without one, forcing later re-derivation. + - **Finding the adapter — do not conclude "no bridge" from these alone.** The most common LayerZero shape is a **plain ERC-20 on mainnet + a separate OFT Adapter + a native OFT on the remote chain**. Three checks that look authoritative but miss it: + - *"The mainnet token isn't an OFT"* (`endpoint()` reverts) — expected under this shape; the adapter is a different contract. + - *LayerZero's public OFT registry* (`https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list`) — useful when it hits, but **incomplete** (it lists Resolv, but not Cap or InfiniFi). + - *DeFiLlama `chains`* — tracks **protocol TVL by chain, not token deployments**; it reported "Ethereum only" for protocols whose token was live on Katana. + Instead, work **backwards from the remote chain**: find the token on the destination explorer (a same-address CREATE2/vanity deployment is a strong hint), confirm it is an OFT (`oftVersion()`, `endpoint()`), then read `peers()` (Ethereum = `30101`) to get the mainnet adapter. Verify with `adapter.token()`, `adapter.endpoint()` (canonical LZ V2 `EndpointV2` = `0x1a44076050125825900e736c501f859c50fE728c`), and the escrowed `balanceOf(adapter)`. + - **Check every bridge family, not just one.** A negative LayerZero result is not a negative bridge result: also check Chainlink CCIP (`TokenAdminRegistry.getPool(token)` on Ethereum = `0xb22764f98dD05c789929716D677382Df22C05Cb6`, then the pool's `typeAndVersion()` — `LockRelease…` ⇒ `lock`, `BurnMint…` ⇒ `mint`), Circle CCTP, and the AggLayer/LxLy unified bridge (`PolygonZkEVMBridgeV2` `0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe`, same address on every connected chain; `getTokenWrappedAddress(0, )` on the destination reveals a canonical wrapper). 5. **For every role-holder address**, classify it in the *Notes* column of the mint table: EOA, multisig (with threshold + named-vs-anonymous signers), or specific contract (with its purpose, e.g. "MintController — entry-point proxy for user deposits"). If a role-holder is itself a multisig, also document its threshold and signer set. @@ -140,4 +146,4 @@ For all of these: treat the extracted text as documentation (claims to verify), - After the report is finalized, generate or update the contract dependency graph YAML at `reports/graph/.yaml`; procedure defined in skill `generating-dependency-graphs` in `reports/graph/SKILL.md`. The graph publishes to `/graph//` and is auto-linked from the report page when the YAML exists. - The report task is not ready for draft PR until the graph exists and `npm run build` validates both the report page and graph schema, unless the graph cannot be produced from available information. If graph data is unavailable, explain why and mark the missing graph facts as `TODO`. -- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. +- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. diff --git a/src/data/bridges.json b/src/data/bridges.json index 0bce8322..c9e02952 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -1,6 +1,20 @@ { "_comment": "Cross-chain bridge / messaging dependencies detected in Yearn Curation risk reports. Add a bridge and/or a dependency ONLY when a report actually relies on it (a mere mention is not a dependency). Each dependency 'slug' MUST match a file in reports/report/.md so the row can link to the report and pass scripts/check_bridges.mjs. 'kind' is 'direct' (the assessed asset/protocol itself bridges through it) or 'indirect' (it depends on something else that does). 'model' segments the blast radius of a bridge compromise and MUST be verified, never guessed: 'mint' = the bridge holds mint authority on the NATIVE token (compromise mints unbacked native supply, diluting every holder); 'lock' = the canonical token is locked/escrowed on the origin chain and the remote is only a bridged representation (compromise is bounded by remote supply + locked collateral); 'transport' = the protocol bridges an UNDERLYING asset (e.g. USDC via CCTP) to remote strategies and the assessed token itself is not bridged; 'unknown' = not yet verified, renders as TODO. 'keywords' drives the reminder scan; 'ignore' lists report slugs that mention the bridge but are NOT dependencies (reviewed, e.g. the report says it does NOT use it). By default a row shows its report's DefiLlama icon; when the report has no usable icon, override with an optional typed 'icon' reference: 'protocol:', 'stablecoin:', 'token:
', or 'token::
'. Bridges are ordered alphabetically by name; keep dependencies sorted direct before indirect. See reports/skill.md and reports/reassessment/SKILL.md for the update flow.", "bridges": [ + { + "id": "agglayer", + "name": "AggLayer (LxLy)", + "type": "Unified canonical bridge (Polygon CDK / AggLayer)", + "url": "https://docs.agglayer.dev/", + "description": "The AggLayer LxLy unified bridge (`PolygonZkEVMBridgeV2`, same address on every connected chain) links Ethereum (network 0) to AggLayer chains such as Katana (network 20). Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC), which deposit the escrowed asset into yield vaults — so holders of the bridged token are exposed to both the bridge and the underlying vault.", + "keywords": ["agglayer", "lxly", "vault bridge", "vaultbridge", "vbusdc", "katana"], + "ignore": ["midas-mhyper", "re-reusd", "infinifi", "fx-fxusd"], + "dependencies": [ + { "slug": "spectra-finance", "name": "Spectra Finance", "kind": "direct", "model": "transport", "integration": "vbUSDC MetaVault on Katana", "detail": "A live MetaVault on Katana holds Vault Bridge USDC (~$1.26M TVL); the MetaVault share itself is not bridged, but its backing sits behind the AggLayer bridge" }, + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "AggLayer LxLy + Vault Bridge USDC (vbUSDC)", "detail": "`KatanaStrategy` (\"Katana yvUSDC Compounder\", ~$1.92M USDC) wraps USDC into vbUSDC `0x53E8…a765e` and bridges to Katana (AggLayer network 20); reports return via the bridge's `onMessageReceived` callback" }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges to Katana)", "detail": "yvUSD's Katana leg sits behind the AggLayer bridge; a fault there feeds into yvUSD's PPS, which is Flex's sole collateral and oracle input" } + ] + }, { "id": "ccip", "name": "Chainlink CCIP", From 61a52382bf34c5c491d235b99ac24d3dd5d06bca Mon Sep 17 00:00:00 2001 From: spalen0 Date: Wed, 15 Jul 2026 19:44:15 +0000 Subject: [PATCH 06/19] fix bridge risk model claims --- reports/report/cap-stcusd.md | 6 ++++-- reports/report/fx-fxusd.md | 2 +- reports/skill.md | 8 ++++---- src/data/bridges.json | 4 ++-- src/pages/bridges.astro | 4 ++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/reports/report/cap-stcusd.md b/reports/report/cap-stcusd.md index 17d0cf45..ef610396 100644 --- a/reports/report/cap-stcusd.md +++ b/reports/report/cap-stcusd.md @@ -299,6 +299,7 @@ Cap's governance flows through a **3-of-5 Gnosis Safe multisig** → **24-hour T | **RedStone** | High | cUSD price oracle (0.05% deviation threshold). Stale prices disable minting/burning | | **wWTGXX (WisdomTree)** | Low | ~$5.08M tokenized gov money market fund. Minimal DeFi adoption and few holders | | **USDC (Circle)** | High | Primary reserve asset (~95% of cUSD backing) | +| **LayerZero V2** | High | The Ethereum OFT Adapter [`0x983a…4137`](https://etherscan.io/address/0x983aeaaa0d0426839158435c43725ea7f45d4137) escrows 25,311,191 stcUSD, **51.99% of the 48.68M supply**, backing the native Katana OFT. The adapter cannot mint canonical stcUSD, so compromise risk is bounded by the remote supply and locked collateral, but the integration affects a majority of current supply | | **USDT, pyUSD, BENJI, BUIDL** | Low | Listed in docs as potential reserve assets but **not currently whitelisted onchain** (`Vault.assets()` returns only USDC and wWTGXX) | | **Institutional Operators** | High | IMC Trading, Edge Capital, Susquehanna Crypto generate yield via offchain strategies. Counterparty risk mitigated by Symbiotic restaking | @@ -426,12 +427,13 @@ Cap's governance flows through a **3-of-5 Gnosis Safe multisig** → **24-hour T | Factor | Assessment | |--------|-----------| -| Protocol count | Morpho (critical), Symbiotic (critical), RedStone (high), USDC/Circle (high), wWTGXX/WisdomTree (low). Aave V3 is wired in but no longer holds reserves | +| Protocol count | Morpho (critical), Symbiotic (critical), RedStone (high), USDC/Circle (high), LayerZero V2 (high), wWTGXX/WisdomTree (low). Aave V3 is wired in but no longer holds reserves | | Morpho concentration | ~$48.9M USDC — **100%** of deployed USDC reserves are in Morpho (Steakhouse Prime + Gauntlet Prime). Concentration on a single underlying lending protocol increased materially vs. March's 67/33 Morpho/Aave split | | Symbiotic | Novel restaking infrastructure, less battle-tested than established alternatives | +| LayerZero concentration | The OFT Adapter escrows 25.31M stcUSD (**51.99% of supply**) for Katana. This is a lock-and-mint representation, not a canonical-token mint authority, but bridge failure or compromise can affect the majority escrowed share | | Operator counterparties | Institutional firms (IMC, Susquehanna, Edge) — blue-chip but opaque | -**Dependencies Score: 3.0/5** — The total dependency count is similar, but reserve concentration has shifted: 100% of the deployed USDC reserve now sits in Morpho (across two MetaMorpho curators), removing the Aave V3 diversification leg. This raises Morpho-specific risk while keeping cross-protocol risk count flat. Symbiotic integration adds complexity. Multiple oracle dependencies (RedStone). The operator model introduces counterparty risk with institutional firms. Score remains 3.0 — diversification across two curators (Steakhouse, Gauntlet) partially offsets the loss of the Aave leg, and Morpho Blue itself is battle-tested. +**Dependencies Score: 3.0/5** — Reserve concentration has shifted: 100% of the deployed USDC reserve now sits in Morpho (across two MetaMorpho curators), removing the Aave V3 diversification leg. The live LayerZero integration also escrows 51.99% of stcUSD supply for Katana. Its lock-and-mint model cannot dilute canonical stcUSD, but it adds a material availability and escrow dependency that must be monitored. Symbiotic integration, RedStone oracles, and opaque institutional operator strategies add further complexity. Score remains 3.0 because the bridge blast radius is bounded by its locked collateral and the category already reflects several high-impact dependencies; the newly documented LayerZero concentration reinforces rather than changes that assessment. **Centralization Score = (2.0 + 2.5 + 3.0) / 3 = 2.5** diff --git a/reports/report/fx-fxusd.md b/reports/report/fx-fxusd.md index 8d3607d2..ce51cb4b 100644 --- a/reports/report/fx-fxusd.md +++ b/reports/report/fx-fxusd.md @@ -258,7 +258,7 @@ In V2, all fxUSD position collateral is custodied by the PoolManager contract ([ - **Lido:** wstETH is the primary ETH collateral in V2 (~$12.38M) - **LayerZero:** **Not a fxUSD dependency** (corrected July 15, 2026). f(x) uses LayerZero `ProxyOFT` for *other* tokens (fETH, xETH, FXN, arUSD), but **fxUSD itself is not bridged**: the docs list fxUSD with a single Ethereum address and no bridging entry, [DeFiLlama](https://api.llama.fi/protocol/fx-protocol) reports f(x) Protocol on Ethereum only, fxUSD is not a native OFT (`endpoint()` and `oftVersion()` revert on [`0x0857…d8f6`](https://etherscan.io/address/0x085780639CC2cACd35E474e71f4d000e2405d8f6)), it is absent from [LayerZero's OFT registry](https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list), and it has no Chainlink CCIP token pool (`TokenAdminRegistry.getPool` returns the zero address). An earlier revision of this report described fxUSD as omnichain-bridged; that claim was unverified and is withdrawn. -- **Katana deployments — bridge mechanism `TODO`.** Two `fxUSD` / "f(x) USD" ERC-20s exist on Katana ([`0x4c03…FDF9`](https://explorer.katanarpc.com/address/0x4c03ff0f44A55e7098a09016E02a01d3cdC2FDF9), supply ~12,008; [`0x1364…9f86`](https://explorer.katanarpc.com/address/0x1364b238C668A2dec1294174e4798E8c09979f86), supply ~1,000,018). Neither is a LayerZero OFT (`endpoint()` reverts on both), and neither is a canonical AggLayer/LxLy wrapper of mainnet fxUSD (`PolygonZkEVMBridgeV2.getTokenWrappedAddress(0, fxUSD)` returns the zero address on Katana). The route by which fxUSD reaches Katana is **not yet identified and must be verified before ruling out bridge risk** — do not treat fxUSD as bridge-free on the strength of the LayerZero finding alone. +- **Katana deployments are locally issued, not identified bridge representations.** Two `fxUSD` / "f(x) USD" ERC-20s exist on Katana ([`0x4c03…FDF9`](https://explorer.katanarpc.com/address/0x4c03ff0f44A55e7098a09016E02a01d3cdC2FDF9), supply ~12,008; [`0x1364…9f86`](https://explorer.katanarpc.com/address/0x1364b238C668A2dec1294174e4798E8c09979f86), supply ~1,000,018). Each token exposes a local `poolManager()` (`0x27b3…f96a` and `0xFae3…3C68`, respectively), and each PoolManager's `fxUSD()` points back to its corresponding token. The verified `0x1364…9f86` implementation restricts minting to its PoolManager; local mint events, including a 10,000-token genesis mint for `0x4c03…FDF9`, corroborate local issuance. Neither token is a LayerZero OFT (`endpoint()` reverts), and neither is the canonical AggLayer/LxLy wrapper of mainnet fxUSD (`PolygonZkEVMBridgeV2.getTokenWrappedAddress(0, fxUSD)` returns the zero address on Katana). This positive architecture evidence does not reveal a bridge path from Ethereum fxUSD to either Katana deployment. Because the `0x4c03…FDF9` implementation is not source-verified, a separate custom conversion path cannot be ruled out absolutely; reassess if one is identified rather than inferring a bridge from the shared name and symbol. The protocol depends on multiple well-established DeFi protocols. Chainlink is the most critical dependency — oracle failure would impair pricing and liquidations. Aave exposure is capped and non-critical to core fxUSD backing. diff --git a/reports/skill.md b/reports/skill.md index a25db663..221105ca 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -55,12 +55,12 @@ Before writing the *Token Mint Authority* section of the report (defined in `rep 3. **Ownable tokens**: read `owner()` — that single address can mint via `mint(...)`. Classify owner (EOA, multisig, contract). -4. **Bridge-managed tokens**: read the bridge controller address (Wormhole NTT Manager, LayerZero OFT/OFT-Adapter, CCIP token pool, etc.). It typically holds the only mint authority on the destination chain. Confirm by reading the token's `mint` function for the access check. +4. **Bridge-managed tokens**: read the bridge controller address (Wormhole NTT Manager, LayerZero OFT/OFT-Adapter, CCIP token pool, etc.) and trace the complete message-to-mint path. The bridge may hold mint authority directly or authenticate a downstream controller that holds it. Confirm by reading the token's `mint` function and every caller-side access check. - **Always segment the bridge model — this is a material risk difference, so verify it, never assume:** - - **Bridge mints the native token** (`mint`): the bridge controller itself holds mint/burn authority on the *canonical* token. A bridge compromise mints **unbacked native supply and dilutes every holder, including on mainnet**. Worked examples: Midas mHYPER — the LayerZero OFT adapter `0x148c…81a0` holds `M_HYPER_MINT_OPERATOR_ROLE` (`reports/report/midas-mhyper.md`); Paxos USDG — the `OFTWrapper` is Supply Controller SC3 with a 45M USDG mint capacity (`reports/report/paxos-usdg.md`). + - **Bridge path mints the native token** (`mint`): the bridge-controlled message path can mint the *canonical* token, either because the bridge controller holds mint authority directly or because an authenticated downstream controller does. A compromise of the required bridge trust path can mint **unbacked native supply and dilute every holder, including on mainnet**. Record quorum requirements rather than implying that one provider can act alone. Worked examples: Midas mHYPER — the LayerZero OFT adapter `0x148c…81a0` holds `M_HYPER_MINT_OPERATOR_ROLE` (`reports/report/midas-mhyper.md`); Paxos USDG — the `OFTWrapper` is Supply Controller SC3 with a 45M USDG mint capacity (`reports/report/paxos-usdg.md`); Centrifuge JAAA — the Spoke holds `wards`, while a 2-of-2 MultiAdapter authenticates the bridge message before the Spoke mints (`reports/report/centrifuge-jaaa.md`). - **Bridged representation** (`lock`): the canonical token is locked/escrowed on its origin chain and the remote token is only a bridged claim. Blast radius is bounded by remote supply plus the locked collateral. Worked example: Sky USDS — the OFT Adapter locks USDS and **does not hold `wards` on USDS**, so it cannot mint native (`reports/report/sky-usds.md`). - - **Underlying transport** (`transport`): the protocol bridges an *underlying* asset (e.g. USDC via CCTP) to remote strategies; the assessed token is not bridged at all. Exposure is funds in transit. Worked example: `reports/report/yearn-yvusd.md`. - - To tell them apart, check whether the bridge contract holds mint authority on the native token — e.g. `wards()` (Sky-style), `hasRole(MINTER_ROLE, )` / the role enumeration in this pass, or the token's supply-controller table. State the model and the evidence explicitly in the report, **and record the adapter address** — several reports named a bridge without one, forcing later re-derivation. + - **Underlying transport** (`transport`): the protocol bridges an *underlying* asset (e.g. USDC via CCTP) to remote strategies; the assessed token is not bridged at all. Exposure may persist while assets remain remote and can include bridge-dependent custody, accounting callbacks, and return paths — it is not necessarily limited to funds between chains. Worked example: `reports/report/yearn-yvusd.md`. + - To tell them apart, trace both direct and downstream mint authority: check `wards()` (Sky/Centrifuge-style), `hasRole(MINTER_ROLE, )` / the role enumeration in this pass, the token's supply-controller table, and the bridge receiver's authentication logic. State the model, quorum, and evidence explicitly in the report, **and record the adapter and downstream controller addresses** — several reports named a bridge without them, forcing later re-derivation. - **Finding the adapter — do not conclude "no bridge" from these alone.** The most common LayerZero shape is a **plain ERC-20 on mainnet + a separate OFT Adapter + a native OFT on the remote chain**. Three checks that look authoritative but miss it: - *"The mainnet token isn't an OFT"* (`endpoint()` reverts) — expected under this shape; the adapter is a different contract. - *LayerZero's public OFT registry* (`https://metadata.layerzero-api.com/v1/metadata/experiment/ofts/list`) — useful when it hits, but **incomplete** (it lists Resolv, but not Cap or InfiniFi). diff --git a/src/data/bridges.json b/src/data/bridges.json index c9e02952..b1f05b5d 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -1,5 +1,5 @@ { - "_comment": "Cross-chain bridge / messaging dependencies detected in Yearn Curation risk reports. Add a bridge and/or a dependency ONLY when a report actually relies on it (a mere mention is not a dependency). Each dependency 'slug' MUST match a file in reports/report/.md so the row can link to the report and pass scripts/check_bridges.mjs. 'kind' is 'direct' (the assessed asset/protocol itself bridges through it) or 'indirect' (it depends on something else that does). 'model' segments the blast radius of a bridge compromise and MUST be verified, never guessed: 'mint' = the bridge holds mint authority on the NATIVE token (compromise mints unbacked native supply, diluting every holder); 'lock' = the canonical token is locked/escrowed on the origin chain and the remote is only a bridged representation (compromise is bounded by remote supply + locked collateral); 'transport' = the protocol bridges an UNDERLYING asset (e.g. USDC via CCTP) to remote strategies and the assessed token itself is not bridged; 'unknown' = not yet verified, renders as TODO. 'keywords' drives the reminder scan; 'ignore' lists report slugs that mention the bridge but are NOT dependencies (reviewed, e.g. the report says it does NOT use it). By default a row shows its report's DefiLlama icon; when the report has no usable icon, override with an optional typed 'icon' reference: 'protocol:', 'stablecoin:', 'token:
', or 'token::
'. Bridges are ordered alphabetically by name; keep dependencies sorted direct before indirect. See reports/skill.md and reports/reassessment/SKILL.md for the update flow.", + "_comment": "Cross-chain bridge / messaging dependencies detected in Yearn Curation risk reports. Add a bridge and/or a dependency ONLY when a report actually relies on it (a mere mention is not a dependency). Each dependency 'slug' MUST match a file in reports/report/.md so the row can link to the report and pass scripts/check_bridges.mjs. 'kind' is 'direct' (the assessed asset/protocol itself bridges through it) or 'indirect' (it depends on something else that does). 'model' segments the blast radius of a bridge compromise and MUST be verified, never guessed: 'mint' = the bridge-controlled message path can mint NATIVE token supply, either directly or through a downstream minter (compromise of the required trust path can mint unbacked native supply; account for any quorum); 'lock' = the canonical token is locked/escrowed on the origin chain and the remote is only a bridged representation (compromise is bounded by remote supply + locked collateral); 'transport' = the protocol bridges an UNDERLYING asset (e.g. USDC via CCTP) to remote strategies and the assessed token itself is not bridged, though exposure can persist while assets remain remote; 'unknown' = not yet verified, renders as TODO. 'keywords' drives the reminder scan; 'ignore' lists report slugs that mention the bridge but are NOT dependencies (reviewed, e.g. the report says it does NOT use it). By default a row shows its report's DefiLlama icon; when the report has no usable icon, override with an optional typed 'icon' reference: 'protocol:', 'stablecoin:', 'token:
', or 'token::
'. Bridges are ordered alphabetically by name; keep dependencies sorted direct before indirect. See reports/skill.md and reports/reassessment/SKILL.md for the update flow.", "bridges": [ { "id": "agglayer", @@ -8,7 +8,7 @@ "url": "https://docs.agglayer.dev/", "description": "The AggLayer LxLy unified bridge (`PolygonZkEVMBridgeV2`, same address on every connected chain) links Ethereum (network 0) to AggLayer chains such as Katana (network 20). Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC), which deposit the escrowed asset into yield vaults — so holders of the bridged token are exposed to both the bridge and the underlying vault.", "keywords": ["agglayer", "lxly", "vault bridge", "vaultbridge", "vbusdc", "katana"], - "ignore": ["midas-mhyper", "re-reusd", "infinifi", "fx-fxusd"], + "ignore": ["cap-stcusd", "fx-fxusd", "infinifi", "midas-mhyper", "re-reusd"], "dependencies": [ { "slug": "spectra-finance", "name": "Spectra Finance", "kind": "direct", "model": "transport", "integration": "vbUSDC MetaVault on Katana", "detail": "A live MetaVault on Katana holds Vault Bridge USDC (~$1.26M TVL); the MetaVault share itself is not bridged, but its backing sits behind the AggLayer bridge" }, { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "AggLayer LxLy + Vault Bridge USDC (vbUSDC)", "detail": "`KatanaStrategy` (\"Katana yvUSDC Compounder\", ~$1.92M USDC) wraps USDC into vbUSDC `0x53E8…a765e` and bridges to Katana (AggLayer network 20); reports return via the bridge's `onMessageReceived` callback" }, diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 48a1f8c4..71a18b73 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -35,9 +35,9 @@ const MODEL_LABEL: Record = { unknown: "TODO", }; const MODEL_TITLE: Record = { - mint: "The bridge holds mint authority on the native token — a compromise can mint unbacked native supply, diluting every holder.", + mint: "The bridge-controlled message path can mint native token supply. A compromise of the required bridge trust path can create unbacked native supply; account for any quorum before assessing the blast radius.", lock: "The canonical token is locked/escrowed on its origin chain; the remote token is only a bridged representation. A compromise is bounded by remote supply and locked collateral.", - transport: "The protocol bridges an underlying asset (e.g. USDC) to remote strategies. The assessed token itself is not bridged; exposure is funds in transit.", + transport: "The protocol bridges an underlying asset (e.g. USDC) to remote strategies. The assessed token itself is not bridged, but exposure can persist while assets remain remote and may include bridge-dependent custody, accounting, and return paths.", unknown: "Not yet verified — see the report. Do not assume a model.", }; From 82da907ab0c62d92b701a1703534d1b4b45571a3 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 16:55:09 +0200 Subject: [PATCH 07/19] feat(web): add LayerZero DVN quorum column to bridges page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses reviewer request: surface each LayerZero route's DVN (Decentralized Verifier Network) quorum — how many independent verifiers must attest a message — so a 1-of-1 single-point-of-failure (the April 2026 rsETH failure mode) is visible at a glance. New 'dvn' field per LayerZero dependency, read onchain from each route's ULN config (EndpointV2.getConfig type 2) with DVN addresses mapped to provider names via LayerZero's metadata API. Rendered as a badge column: green for a healthy quorum, red for a 1-of-1 'weak' config, links to the config source. CCIP/CCTP/AggLayer rows show '—' (DVN is LZ-specific). Verified onchain (mint-relevant receive side; 2026-07-16): - 4-of-4: rsETH/hgETH + Fluid (conf 64), Midas mHYPER (Katana), InfiniFi siUSD/iUSD (Katana) - 3-of-3: Cap stcUSD (Katana), Paxos USDG (Solana route) - 2-of-2: Sky USDS, Re reUSD - 2-of-3: Resolv RLP, Resolv wstUSR (optional-DVN threshold) No 1-of-1 found on any current dependency. TODO (issue #324): Centrifuge JAAA (LZ leg of a 2-of-2 MultiAdapter, not a plain OFT) and Across Protocol (per-asset OFT routes, no single OApp). check_bridges.mjs now warns if a LayerZero row omits 'dvn'. skill.md documents the onchain read. Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/skill.md | 2 +- scripts/check_bridges.mjs | Bin 4725 -> 5173 bytes src/data/bridges.json | 26 +++++------ src/pages/bridges.astro | 93 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 14 deletions(-) diff --git a/reports/skill.md b/reports/skill.md index 221105ca..4b649667 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -146,4 +146,4 @@ For all of these: treat the extracted text as documentation (claims to verify), - After the report is finalized, generate or update the contract dependency graph YAML at `reports/graph/.yaml`; procedure defined in skill `generating-dependency-graphs` in `reports/graph/SKILL.md`. The graph publishes to `/graph//` and is auto-linked from the report page when the YAML exists. - The report task is not ready for draft PR until the graph exists and `npm run build` validates both the report page and graph schema, unless the graph cannot be produced from available information. If graph data is unavailable, explain why and mark the missing graph facts as `TODO`. -- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. +- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. **For LayerZero rows, also record the `dvn` quorum** (how many independent verifiers must attest — a `1-of-1` is a single point of failure, the April 2026 rsETH failure mode). Read it onchain from the ULN config of the receive side on the mint chain: `lib = EndpointV2.getReceiveLibrary(oapp, srcEid)`, then `EndpointV2.getConfig(oapp, lib, srcEid, 2)` decodes to `(confirmations, requiredDVNCount, optionalDVNCount, optionalDVNThreshold, requiredDVNs[], optionalDVNs[])`; map DVN addresses to provider names via `https://metadata.layerzero-api.com/v1/metadata` (per-chain `dvns`). EndpointV2 (Ethereum) `0x1a44076050125825900e736c501f859c50fE728c`, Katana eid `30375`. Store `{ label, confirmations, providers, route, weak, verifiedAt, link }`; set `label: "TODO"` with a tracking `link` if the config can't be resolved (e.g. non-OFT MultiAdapter designs). The checker warns if a LayerZero row omits `dvn`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. diff --git a/scripts/check_bridges.mjs b/scripts/check_bridges.mjs index a9961caf74d21274e39e7b6355bb0c91ea6ee559..8c6af414d784927e1173f36e6e868dc3feb94ab9 100644 GIT binary patch delta 368 zcmY+9u}T9$5QaNJ2@2KK|t2pa1*0{7OH2jU~`-<54dxzgQ07Ft1RRp>_tjW?n#}J9xrt9k`w# zomr+4S%cv7Qj^aVZjn6qyZz({yAnI6ht`2AXy?LQmea^OAB!Ll?PXHcHoFn)Nmn%a z0^%tj<-~`m_D(cHI%G11RbmY-dw6nvGn g5Ezw>d(c08%;_|i!n9-EGCA_&)#l`Eecw = { unknown: "Not yet verified — see the report. Do not assume a model.", }; +// LayerZero DVN (Decentralized Verifier Network) quorum tooltip. +function dvnTitle(dvn: { + label: string; + confirmations?: number; + providers?: string[]; + route?: string; + note?: string; + verifiedAt?: string; +}): string { + if (dvn.label === "TODO") { + return `DVN quorum not yet resolved${dvn.note ? ` — ${dvn.note}` : ""}. See linked issue.`; + } + const parts = [ + `${dvn.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`, + ]; + if (dvn.providers?.length) parts.push(`DVNs: ${dvn.providers.join(", ")}.`); + if (dvn.confirmations) parts.push(`Block confirmations: ${dvn.confirmations}.`); + if (dvn.route) parts.push(`Route: ${dvn.route}.`); + if (dvn.verifiedAt) parts.push(`Verified onchain ${dvn.verifiedAt}.`); + return parts.join(" "); +} + // Direct rows first, then indirect, each group alphabetical by name. const kindOrder = (k: string) => (k === "direct" ? 0 : 1); const bridgesView = bridges.map((b) => { @@ -108,6 +140,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); Protocol / Token Type Model + DVN Integration Details @@ -137,6 +170,30 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); {MODEL_LABEL[d.model]} + + {d.dvn ? ( + d.dvn.link ? ( + + {d.dvn.label} + + ) : ( + + {d.dvn.label} + + ) + ) : ( + + )} + {d.integration} {d.detail} @@ -307,6 +364,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .col-icon { width: 44px; padding-right: 0; } .col-kind { width: 96px; } .col-model { width: 118px; } + .col-dvn { width: 78px; } /* === Icons (reused from Reports page) === */ .icon-stack { @@ -398,6 +456,41 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); :global(html.light) .model-transport { color: #6D28D9; } :global(html.light) .model-unknown { color: #475569; } + /* === DVN quorum badges (LayerZero verifier threshold) === */ + .dvn-badge { + display: inline-block; + font-size: 0.72rem; + padding: 0.2rem 0.5rem; + border-radius: 6px; + font-weight: 700; + font-variant-numeric: tabular-nums; + white-space: nowrap; + cursor: help; + text-decoration: none; + } + .dvn-badge:hover { text-decoration: none; filter: brightness(1.08); } + /* Healthy quorum (≥ 2 independent verifiers). */ + .dvn-ok { + background: color-mix(in srgb, #22C55E 16%, transparent); + color: #86EFAC; + border: 1px solid color-mix(in srgb, #22C55E 32%, transparent); + } + /* 1-of-1 / single point of failure — the rsETH-incident failure mode. */ + .dvn-weak { + background: color-mix(in srgb, #EF4444 22%, transparent); + color: #FCA5A5; + border: 1px solid color-mix(in srgb, #EF4444 48%, transparent); + } + .dvn-todo { + background: color-mix(in srgb, #64748B 18%, transparent); + color: #94A3B8; + border: 1px dashed color-mix(in srgb, #64748B 50%, transparent); + } + .dvn-na { color: var(--text-secondary); opacity: 0.5; cursor: help; } + :global(html.light) .dvn-ok { color: #15803D; } + :global(html.light) .dvn-weak { color: #B91C1C; } + :global(html.light) .dvn-todo { color: #475569; } + .footnote { color: var(--text-secondary); font-size: 0.82rem; From dbc57ee1d9c457820e06ee7ffd188eb894449510 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 17:04:15 +0200 Subject: [PATCH 08/19] fix(web): Sky USDS primary bridge is native rollup bridges, not LayerZero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer flagged that USDS bridges via native L2 bridges. The sky-usds report confirms two independent SkyLink systems, and the page only showed the minor one: - Native canonical L2 bridges (OP Stack: Base/Optimism/Unichain + Arbitrum Nitro) carry ~$0.45B USDS + ~812M sUSDS — the bulk. - LayerZero carries only Solana + Avalanche (~$48.7M, <0.7%). Adds a 'Native Rollup Bridges' category (canonical L2 bridges; lock model, inherits rollup security, no DVN) and puts Sky USDS there as the primary route. Scoped the existing LayerZero row to 'Solana + Avalanche only' so it no longer reads as USDS's main bridge. 5 bridges, 23 deps, 0 warnings. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index 5fe714d6..f636cadf 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -57,7 +57,7 @@ { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar", "dvn": {"label": "3-of-3", "confirmations": 32, "providers": ["LayerZero Labs", "Canary", "Paxos"], "route": "Solana→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x147BdE4F997f0d4C7544ED0C55eAcf1E5E6bf9c4"} }, { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit", "dvn": {"label": "2-of-2", "confirmations": 20, "providers": ["LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x2BB4046022B9161f3F84Ad8E35cac1d5946e0e85"} }, { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role", "dvn": {"label": "4-of-4", "confirmations": 70, "providers": ["LayerZero Labs", "Canary", "Deutsche Telekom", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x148c86390a4ae6f7a02df5903bc0a89e8b4581a0"} }, - { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter", "detail": "Adapter locks USDS for Solana + Avalanche (~48.7M locked) and does NOT hold `wards` on USDS — it cannot mint native USDS", "dvn": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of cross-chain supply) and does NOT hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "dvn": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (asset routes)", "detail": "The assessed asset is the V2 LP token, which is not bridged; Across integrates LZ OFT to move bridged assets through its own routes", "dvn": {"label": "TODO", "note": "transport via per-asset OFT routes; no single representative OApp", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA and mints on cross-chain message; 5 DVNs on the LZ side and a 2-of-2 quorum with CCIP mean BOTH bridges must be compromised", "dvn": {"label": "TODO", "note": "LZ leg of a 2-of-2 MultiAdapter (reportedly 5 DVNs); config lives on the MultiAdapter transport, not the token", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs", "dvn": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x234c908e749961d0329a0ed5916d55a99d1ad06c"} }, @@ -65,6 +65,17 @@ { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)", "dvn": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "lock", "integration": "Wraps rsETH (Kelp DAO)", "detail": "rsETH bridges via OFT Adapter `0x85d4…8Ef3`, which escrows 46,254 rsETH (~9.6% of supply) — it cannot mint native rsETH", "dvn": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "rsETH OFT Adapter (Arbitrum↔Ethereum); Kelp docs confirm 4-of-4 on the L2 mint path", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} } ] + }, + { + "id": "native-rollup", + "name": "Native Rollup Bridges", + "type": "Canonical L2 bridges (OP Stack / Arbitrum Nitro)", + "url": "https://l2beat.com/scaling/risk", + "description": "Each rollup's own canonical token bridge (OP Stack StandardBridge, Arbitrum Nitro gateway, etc.). L1 tokens are escrowed and minted 1:1 on the L2 by the rollup's bridge; security inherits the L2's proof system and challenge window rather than an external validator set — generally the lowest-trust bridge class, but still a dependency for any asset held on an L2. No DVN concept applies.", + "keywords": ["skylink", "op stack canonical", "arbitrum nitro gateway", "standardbridge"], + "dependencies": [ + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "OP Stack + Arbitrum Nitro canonical bridges (SkyLink)", "detail": "Primary USDS/sUSDS cross-chain route: ~$0.45B USDS + ~812M sUSDS escrowed on L1 and minted 1:1 on Base, Optimism, Unichain (OP Stack) and Arbitrum (Nitro). No bridge holds `wards` on USDS; LayerZero carries only Solana + Avalanche (<0.7%)" } + ] } ] } From bec45fc8fb828f1536467a1a462c444d93aa3c42 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 17:13:28 +0200 Subject: [PATCH 09/19] refactor(web): rename DVN column to reusable Security; Model legend; wrap fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer feedback on the bridges page: - Rename the 'dvn' field/column to 'security' so it can be reused by other bridges' verifier models later (CCIP RMN, etc.). Content unchanged — for LayerZero it's still the DVN quorum badge. - Render the Security column ONLY for bridges that populate it (LayerZero today) via a per-bridge hasSecurity flag — CCIP/CCTP/AggLayer/native tables no longer carry an empty column. - Add a Model legend at the top of the page explaining mint/lock/transport. - Fix Details rendering: give Details and Integration proper min-widths and looser line-height so long text no longer wraps awkwardly (the table scrolls horizontally instead). check_bridges + skill.md updated to the 'security' key. 5 bridges, 23 deps, 0 warnings. Co-Authored-By: Claude Opus 4.8 (1M context) --- reports/skill.md | 2 +- scripts/check_bridges.mjs | Bin 5173 -> 5214 bytes src/data/bridges.json | 26 +++---- src/pages/bridges.astro | 145 +++++++++++++++++++++++++------------- 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/reports/skill.md b/reports/skill.md index 4b649667..2c287477 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -146,4 +146,4 @@ For all of these: treat the extracted text as documentation (claims to verify), - After the report is finalized, generate or update the contract dependency graph YAML at `reports/graph/.yaml`; procedure defined in skill `generating-dependency-graphs` in `reports/graph/SKILL.md`. The graph publishes to `/graph//` and is auto-linked from the report page when the YAML exists. - The report task is not ready for draft PR until the graph exists and `npm run build` validates both the report page and graph schema, unless the graph cannot be produced from available information. If graph data is unavailable, explain why and mark the missing graph facts as `TODO`. -- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. **For LayerZero rows, also record the `dvn` quorum** (how many independent verifiers must attest — a `1-of-1` is a single point of failure, the April 2026 rsETH failure mode). Read it onchain from the ULN config of the receive side on the mint chain: `lib = EndpointV2.getReceiveLibrary(oapp, srcEid)`, then `EndpointV2.getConfig(oapp, lib, srcEid, 2)` decodes to `(confirmations, requiredDVNCount, optionalDVNCount, optionalDVNThreshold, requiredDVNs[], optionalDVNs[])`; map DVN addresses to provider names via `https://metadata.layerzero-api.com/v1/metadata` (per-chain `dvns`). EndpointV2 (Ethereum) `0x1a44076050125825900e736c501f859c50fE728c`, Katana eid `30375`. Store `{ label, confirmations, providers, route, weak, verifiedAt, link }`; set `label: "TODO"` with a tracking `link` if the config can't be resolved (e.g. non-OFT MultiAdapter designs). The checker warns if a LayerZero row omits `dvn`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. +- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. **For LayerZero rows, also record the `security` quorum** (the DVN quorum — how many independent verifiers must attest — a `1-of-1` is a single point of failure, the April 2026 rsETH failure mode). Read it onchain from the ULN config of the receive side on the mint chain: `lib = EndpointV2.getReceiveLibrary(oapp, srcEid)`, then `EndpointV2.getConfig(oapp, lib, srcEid, 2)` decodes to `(confirmations, requiredDVNCount, optionalDVNCount, optionalDVNThreshold, requiredDVNs[], optionalDVNs[])`; map DVN addresses to provider names via `https://metadata.layerzero-api.com/v1/metadata` (per-chain `dvns`). EndpointV2 (Ethereum) `0x1a44076050125825900e736c501f859c50fE728c`, Katana eid `30375`. Store it in a `security` object `{ label, confirmations, providers, route, weak, verifiedAt, link }`; set `label: "TODO"` with a tracking `link` if the config can't be resolved (e.g. non-OFT MultiAdapter designs). The `security` column renders only for bridges that populate it (LayerZero today; reusable for others). The checker warns if a LayerZero row omits `security`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. diff --git a/scripts/check_bridges.mjs b/scripts/check_bridges.mjs index 8c6af414d784927e1173f36e6e868dc3feb94ab9..b83d5eb350ced96c119b9f650812b51d1649c905 100644 GIT binary patch delta 127 zcmdn0aZh7I29H~DYI12&W=W+&L4I*bX;G?zMoC7hf=ig6LSbosQE9FYmjW2*>noI{ z7GHq)$ delta 81 zcmcbou~lP329JSDn4dynX?{^@u7XBcYEfodW@?H;eqM4$VrHJEo`R!-Qi#8czY>=M f80hOyUdN*~`5})pb4pp>WF6ix5WTsJ_X-;TP;(j& diff --git a/src/data/bridges.json b/src/data/bridges.json index f636cadf..c082a579 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -48,22 +48,22 @@ "name": "LayerZero", "type": "Omnichain messaging (OFT / OApp)", "url": "https://layerzero.network", - "description": "Generic cross-chain messaging. Tokens bridge via the OFT / OFT-Adapter standard; security depends on the configured DVN (Decentralized Verifier Network) set and the token's mint/burn authority on each chain. The DVN column shows how many independent verifiers must attest a message before it executes — a 1-of-1 is a single point of failure (the configuration behind the April 2026 rsETH incident). Values are read onchain from each route's ULN config; the badge links to the config source.", + "description": "Generic cross-chain messaging. Tokens bridge via the OFT / OFT-Adapter standard; security depends on the configured DVN (Decentralized Verifier Network) set and the token's mint/burn authority on each chain. The Security column shows the DVN quorum — how many independent verifiers must attest a message before it executes — where a 1-of-1 is a single point of failure (the configuration behind the April 2026 rsETH incident). Values are read onchain from each route's ULN config; the badge links to the config source.", "keywords": ["layerzero", "layer zero", "lz v2"], "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal", "fx-fxusd"], "dependencies": [ - { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter (\"LayerZero vault\")", "detail": "Adapter `0x983a…4137` escrows 25,311,191 stcUSD — ~52% of the 48.68M supply, the largest locked share on this page; Katana runs a native OFT at the same vanity address `0x8888…8888`", "dvn": {"label": "3-of-3", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x983aeaaa0d0426839158435c43725ea7f45d4137"} }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapters (siUSD + iUSD)", "detail": "siUSD adapter `0x5f21…c3c0` escrows 29,340 siUSD and iUSD adapter `0xdd1c…3005` escrows 4.33 iUSD; both mint native OFTs on Katana. Neither adapter holds RECEIPT_TOKEN_MINTER, so they cannot mint native supply", "dvn": {"label": "4-of-4", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind", "Deutsche Telekom"], "route": "Ethereum→Katana (mint side; siUSD + iUSD)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x5f2106bb2a5aba6a783dbf29c8d3b09c175bc3c0"} }, - { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar", "dvn": {"label": "3-of-3", "confirmations": 32, "providers": ["LayerZero Labs", "Canary", "Paxos"], "route": "Solana→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x147BdE4F997f0d4C7544ED0C55eAcf1E5E6bf9c4"} }, - { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit", "dvn": {"label": "2-of-2", "confirmations": 20, "providers": ["LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x2BB4046022B9161f3F84Ad8E35cac1d5946e0e85"} }, - { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role", "dvn": {"label": "4-of-4", "confirmations": 70, "providers": ["LayerZero Labs", "Canary", "Deutsche Telekom", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x148c86390a4ae6f7a02df5903bc0a89e8b4581a0"} }, - { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of cross-chain supply) and does NOT hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "dvn": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, - { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (asset routes)", "detail": "The assessed asset is the V2 LP token, which is not bridged; Across integrates LZ OFT to move bridged assets through its own routes", "dvn": {"label": "TODO", "note": "transport via per-asset OFT routes; no single representative OApp", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA and mints on cross-chain message; 5 DVNs on the LZ side and a 2-of-2 quorum with CCIP mean BOTH bridges must be compromised", "dvn": {"label": "TODO", "note": "LZ leg of a 2-of-2 MultiAdapter (reportedly 5 DVNs); config lives on the MultiAdapter transport, not the token", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, - { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs", "dvn": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x234c908e749961d0329a0ed5916d55a99d1ad06c"} }, - { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC", "dvn": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xab17c1fe647c37ceb9b96d1c27dd189bf8451978"} }, - { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)", "dvn": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, - { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "lock", "integration": "Wraps rsETH (Kelp DAO)", "detail": "rsETH bridges via OFT Adapter `0x85d4…8Ef3`, which escrows 46,254 rsETH (~9.6% of supply) — it cannot mint native rsETH", "dvn": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "rsETH OFT Adapter (Arbitrum↔Ethereum); Kelp docs confirm 4-of-4 on the L2 mint path", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} } + { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter (\"LayerZero vault\")", "detail": "Adapter `0x983a…4137` escrows 25,311,191 stcUSD — ~52% of the 48.68M supply, the largest locked share on this page; Katana runs a native OFT at the same vanity address `0x8888…8888`", "security": {"label": "3-of-3", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x983aeaaa0d0426839158435c43725ea7f45d4137"} }, + { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapters (siUSD + iUSD)", "detail": "siUSD adapter `0x5f21…c3c0` escrows 29,340 siUSD and iUSD adapter `0xdd1c…3005` escrows 4.33 iUSD; both mint native OFTs on Katana. Neither adapter holds RECEIPT_TOKEN_MINTER, so they cannot mint native supply", "security": {"label": "4-of-4", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind", "Deutsche Telekom"], "route": "Ethereum→Katana (mint side; siUSD + iUSD)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x5f2106bb2a5aba6a783dbf29c8d3b09c175bc3c0"} }, + { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar", "security": {"label": "3-of-3", "confirmations": 32, "providers": ["LayerZero Labs", "Canary", "Paxos"], "route": "Solana→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x147BdE4F997f0d4C7544ED0C55eAcf1E5E6bf9c4"} }, + { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit", "security": {"label": "2-of-2", "confirmations": 20, "providers": ["LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x2BB4046022B9161f3F84Ad8E35cac1d5946e0e85"} }, + { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role", "security": {"label": "4-of-4", "confirmations": 70, "providers": ["LayerZero Labs", "Canary", "Deutsche Telekom", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x148c86390a4ae6f7a02df5903bc0a89e8b4581a0"} }, + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of cross-chain supply) and does NOT hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "security": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, + { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (asset routes)", "detail": "The assessed asset is the V2 LP token, which is not bridged; Across integrates LZ OFT to move bridged assets through its own routes", "security": {"label": "TODO", "note": "transport via per-asset OFT routes; no single representative OApp", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA and mints on cross-chain message; 5 DVNs on the LZ side and a 2-of-2 quorum with CCIP mean BOTH bridges must be compromised", "security": {"label": "TODO", "note": "LZ leg of a 2-of-2 MultiAdapter (reportedly 5 DVNs); config lives on the MultiAdapter transport, not the token", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, + { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x234c908e749961d0329a0ed5916d55a99d1ad06c"} }, + { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xab17c1fe647c37ceb9b96d1c27dd189bf8451978"} }, + { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, + { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "lock", "integration": "Wraps rsETH (Kelp DAO)", "detail": "rsETH bridges via OFT Adapter `0x85d4…8Ef3`, which escrows 46,254 rsETH (~9.6% of supply) — it cannot mint native rsETH", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "rsETH OFT Adapter (Arbitrum↔Ethereum); Kelp docs confirm 4-of-4 on the L2 mint path", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} } ] }, { diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index b3c78bc7..3c63a848 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -23,7 +23,9 @@ const { bridges } = data as { integration: string; detail: string; icon?: string; - dvn?: { + // Per-bridge security posture. Currently only LayerZero populates this + // (the DVN quorum); reusable for other bridges' verifier models later. + security?: { label: string; confirmations?: number; providers?: string[]; @@ -51,8 +53,9 @@ const MODEL_TITLE: Record = { unknown: "Not yet verified — see the report. Do not assume a model.", }; -// LayerZero DVN (Decentralized Verifier Network) quorum tooltip. -function dvnTitle(dvn: { +// Security-posture tooltip. For LayerZero this is the DVN quorum: how many +// independent verifiers must attest a message. Reusable for other bridges. +function securityTitle(sec: { label: string; confirmations?: number; providers?: string[]; @@ -60,16 +63,16 @@ function dvnTitle(dvn: { note?: string; verifiedAt?: string; }): string { - if (dvn.label === "TODO") { - return `DVN quorum not yet resolved${dvn.note ? ` — ${dvn.note}` : ""}. See linked issue.`; + if (sec.label === "TODO") { + return `Verifier quorum not yet resolved${sec.note ? ` — ${sec.note}` : ""}. See linked issue.`; } const parts = [ - `${dvn.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`, + `${sec.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`, ]; - if (dvn.providers?.length) parts.push(`DVNs: ${dvn.providers.join(", ")}.`); - if (dvn.confirmations) parts.push(`Block confirmations: ${dvn.confirmations}.`); - if (dvn.route) parts.push(`Route: ${dvn.route}.`); - if (dvn.verifiedAt) parts.push(`Verified onchain ${dvn.verifiedAt}.`); + if (sec.providers?.length) parts.push(`DVNs: ${sec.providers.join(", ")}.`); + if (sec.confirmations) parts.push(`Block confirmations: ${sec.confirmations}.`); + if (sec.route) parts.push(`Route: ${sec.route}.`); + if (sec.verifiedAt) parts.push(`Verified onchain ${sec.verifiedAt}.`); return parts.join(" "); } @@ -96,6 +99,8 @@ const bridgesView = bridges.map((b) => { deps, directCount: deps.filter((d) => d.kind === "direct").length, indirectCount: deps.filter((d) => d.kind === "indirect").length, + // Only render the Security column for bridges that populate it (LayerZero). + hasSecurity: deps.some((d) => d.security), }; }); @@ -112,6 +117,13 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0);

Bridge Dependencies

+
+ Model + Mints native bridge can mint the native token — a compromise dilutes every holder + Bridged canonical token escrowed on origin; the remote is only a representation + Transport an underlying asset is bridged; the assessed token itself is not +
+
@@ -140,8 +152,8 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); Protocol / Token Type Model - DVN - Integration + {bridge.hasSecurity && Security} + Integration Details @@ -170,30 +182,32 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); {MODEL_LABEL[d.model]} - - {d.dvn ? ( - d.dvn.link ? ( - - {d.dvn.label} - + {bridge.hasSecurity && ( + + {d.security ? ( + d.security.link ? ( + + {d.security.label} + + ) : ( + + {d.security.label} + + ) ) : ( - - {d.dvn.label} - - ) - ) : ( - - )} - + + )} + + )} {d.integration} {d.detail} @@ -247,6 +261,35 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); line-height: 1.15; max-width: 22ch; } + + /* === Model legend === */ + .model-legend { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem 1.25rem; + margin: 0 0 1.5rem; + padding: 0.85rem 1rem; + border: 1px solid var(--border); + border-radius: 10px; + background: color-mix(in srgb, var(--bg-card) 40%, transparent); + font-size: 0.82rem; + color: var(--text-secondary); + line-height: 1.4; + } + .legend-title { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 700; + color: var(--text-primary); + } + .legend-item { + display: inline-flex; + align-items: center; + gap: 0.4rem; + } + /* === Search === */ .search-wrap { position: relative; @@ -364,7 +407,8 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .col-icon { width: 44px; padding-right: 0; } .col-kind { width: 96px; } .col-model { width: 118px; } - .col-dvn { width: 78px; } + .col-sec { width: 84px; } + .col-integration { min-width: 150px; } /* === Icons (reused from Reports page) === */ .icon-stack { @@ -392,8 +436,13 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .name-cell { font-weight: 500; white-space: nowrap; } .name-cell a { color: var(--text-primary); text-decoration: none; } .name-cell a:hover { color: var(--brand-blue); text-decoration: underline; } - .integration-cell { color: var(--text-secondary); white-space: nowrap; } - .detail-cell { color: var(--text-secondary); font-size: 0.85rem; } + .integration-cell { color: var(--text-secondary); min-width: 150px; } + .detail-cell { + color: var(--text-secondary); + font-size: 0.85rem; + min-width: 300px; + line-height: 1.45; + } /* === Kind badges === */ .kind-badge { @@ -456,8 +505,8 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); :global(html.light) .model-transport { color: #6D28D9; } :global(html.light) .model-unknown { color: #475569; } - /* === DVN quorum badges (LayerZero verifier threshold) === */ - .dvn-badge { + /* === Security badges (LayerZero DVN quorum today; reusable) === */ + .sec-badge { display: inline-block; font-size: 0.72rem; padding: 0.2rem 0.5rem; @@ -468,28 +517,28 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); cursor: help; text-decoration: none; } - .dvn-badge:hover { text-decoration: none; filter: brightness(1.08); } + .sec-badge:hover { text-decoration: none; filter: brightness(1.08); } /* Healthy quorum (≥ 2 independent verifiers). */ - .dvn-ok { + .sec-ok { background: color-mix(in srgb, #22C55E 16%, transparent); color: #86EFAC; border: 1px solid color-mix(in srgb, #22C55E 32%, transparent); } /* 1-of-1 / single point of failure — the rsETH-incident failure mode. */ - .dvn-weak { + .sec-weak { background: color-mix(in srgb, #EF4444 22%, transparent); color: #FCA5A5; border: 1px solid color-mix(in srgb, #EF4444 48%, transparent); } - .dvn-todo { + .sec-todo { background: color-mix(in srgb, #64748B 18%, transparent); color: #94A3B8; border: 1px dashed color-mix(in srgb, #64748B 50%, transparent); } - .dvn-na { color: var(--text-secondary); opacity: 0.5; cursor: help; } - :global(html.light) .dvn-ok { color: #15803D; } - :global(html.light) .dvn-weak { color: #B91C1C; } - :global(html.light) .dvn-todo { color: #475569; } + .sec-na { color: var(--text-secondary); opacity: 0.5; } + :global(html.light) .sec-ok { color: #15803D; } + :global(html.light) .sec-weak { color: #B91C1C; } + :global(html.light) .sec-todo { color: #475569; } .footnote { color: var(--text-secondary); From 9ac3f972ad9196195a7f2a0c07c6cf7bf095e73c Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 17:35:28 +0200 Subject: [PATCH 10/19] docs(web): clearer Model legend wording; drop legend title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove the 'Model' title from the legend box (labels + explanations only). - Rewrite the three explanations to be concise and parallel, per feedback that 'transport' was unclear: Mints native — bridge can mint the native token (unbacked supply dilutes every holder) Bridged — token is locked at home; only a bridged copy exists on remote chains Transport — token is not bridged, only the underlying asset is bridged (e.g. USDC) Co-Authored-By: Claude Opus 4.8 (1M context) --- src/pages/bridges.astro | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 3c63a848..61878e2c 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -118,10 +118,9 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0);
- Model - Mints native bridge can mint the native token — a compromise dilutes every holder - Bridged canonical token escrowed on origin; the remote is only a representation - Transport an underlying asset is bridged; the assessed token itself is not + Mints native bridge can mint the native token (unbacked supply dilutes every holder) + Bridged token is locked at home; only a bridged copy exists on remote chains + Transport token is not bridged, only the underlying asset is bridged (e.g. USDC)
From 3555bdfb5f8f6afadf0b93a07c25d4018eaedd5e Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 18:11:59 +0200 Subject: [PATCH 11/19] feat(web): add CCTP attester quorum to the Security column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer asked whether CCTP has a security config like LayerZero's DVN set. It does: Circle's MessageTransmitter has an on-chain signatureThreshold + enabled-attester set. Verified onchain (2026-07-16), both V1 (0x0a99..8F81) and V2 (0x81D4..4B64) are 2-of-2. Key difference surfaced in the tooltip/note: unlike LayerZero's independent DVNs (LayerZero Labs, Nethermind, ...), BOTH CCTP attesters are Circle-operated keys, and Circle's attesterManager can add/remove attesters and change the threshold — so the 2-of-2 is redundancy within Circle, not independent verification. Trust reduces to Circle. Generalizes the reusable Security column: securityTitle() now uses a per-row 'note' for the lead sentence and a 'providersLabel' (Attesters vs DVNs). Security column now renders for CCTP + LayerZero. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 10 +++++----- src/pages/bridges.astro | 12 ++++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index c082a579..9b9d37af 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -34,13 +34,13 @@ "name": "Circle CCTP", "type": "Native USDC burn-and-mint bridge", "url": "https://www.circle.com/cross-chain-transfer-protocol", - "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality.", + "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality. The Security column shows the on-chain `signatureThreshold` on Circle's MessageTransmitter — a 2-of-2 attester quorum, but unlike LayerZero's independent DVNs both attesters are Circle-operated and Circle can change the set.", "keywords": ["cctp", "cross-chain transfer protocol"], "dependencies": [ - { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, - { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, - { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately" }, - { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "" } + { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, + { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "Inherited via yvUSD. 2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys, and Circle's attesterManager can change the set — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} } ] }, { diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 61878e2c..179a501b 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -29,6 +29,7 @@ const { bridges } = data as { label: string; confirmations?: number; providers?: string[]; + providersLabel?: string; route?: string; note?: string; weak?: boolean; @@ -59,6 +60,7 @@ function securityTitle(sec: { label: string; confirmations?: number; providers?: string[]; + providersLabel?: string; route?: string; note?: string; verifiedAt?: string; @@ -66,10 +68,12 @@ function securityTitle(sec: { if (sec.label === "TODO") { return `Verifier quorum not yet resolved${sec.note ? ` — ${sec.note}` : ""}. See linked issue.`; } - const parts = [ - `${sec.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`, - ]; - if (sec.providers?.length) parts.push(`DVNs: ${sec.providers.join(", ")}.`); + const lead = sec.note + ? `${sec.label} — ${sec.note}` + : `${sec.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`; + const parts = [lead]; + if (sec.providers?.length) + parts.push(`${sec.providersLabel ?? "Verifiers"}: ${sec.providers.join(", ")}.`); if (sec.confirmations) parts.push(`Block confirmations: ${sec.confirmations}.`); if (sec.route) parts.push(`Route: ${sec.route}.`); if (sec.verifiedAt) parts.push(`Verified onchain ${sec.verifiedAt}.`); From afadcc932619ecdb0f4874b84f05b0febd89d8c5 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 18:18:42 +0200 Subject: [PATCH 12/19] feat(web): move Security column from CCTP to Chainlink CCIP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per feedback: CCTP's attester set is always Circle-managed (no per-protocol config), so a badge adds no signal — removed. CCIP is where the protocol owns and configures its own token pool, so surface that instead. CCIP Security = the protocol-defined token-pool config (verified onchain, 2026-07-16). Message verification itself is Chainlink's DON + RMN (not protocol-set); what the protocol controls is the pool's rate limits, lanes and ownership: - apyx-apxusd LockReleaseTokenPool 0x0e9c..5BB5: rate limiting ENABLED, ~5M apxUSD/lane; owner 0xf986..3cE2 - maple-syrupusdc LockReleaseTokenPool 0x20B7..6491: ENABLED, ~9.5M in / ~8.6M out per lane; rateLimitAdmin 0xCe1c..34E8 - centrifuge-jaaa: TODO — no standard TokenAdminRegistry pool (getPool=0x0), routes through the 2-of-2 MultiAdapter (issue #324) Security column now renders for CCIP + LayerZero. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index 9b9d37af..e976cd0e 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -20,13 +20,13 @@ "name": "Chainlink CCIP", "type": "Cross-chain interoperability protocol", "url": "https://chain.link/cross-chain", - "description": "Chainlink's cross-chain interoperability protocol. Messages are validated by the Chainlink DON with a Risk Management Network; tokens move via burn/mint or lock/mint token pools.", + "description": "Chainlink's cross-chain interoperability protocol. Messages are validated by the Chainlink DON plus an independent Risk Management Network (RMN); tokens move via burn/mint or lock/release token pools. Unlike CCTP, the protocol owns and configures its own token pool — the Security column shows that protocol-defined config (rate-limit posture); the underlying message verification (DON + RMN) is Chainlink's, not per-protocol.", "keywords": ["ccip", "chainlink ccip"], "ignore": ["aave-sgho", "infinifi", "fx-fxusd"], "dependencies": [ - { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised" }, - { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana" } + { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol", "security": {"label": "Rate-limited", "route": "LockReleaseTokenPool `0x0e9c…5BB5`, 2 lanes", "note": "In CCIP the protocol owns and configures its own token pool (message verification is Chainlink's DON + Risk Management Network, not protocol-set). This pool has inbound/outbound rate limiting ENABLED — ~5M apxUSD capacity per lane — bounding bridge throughput. Owner `0xf986…3cE2` can change limits, lanes and pool config", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x0e9cA42Bc60bE25F9A67f52173067Cc0Bb405BB5"} }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised", "security": {"label": "TODO", "note": "JAAA has no standard CCIP TokenAdminRegistry pool (getPool = 0x0); it routes through the 2-of-2 MultiAdapter, so pool/verifier config lives on the MultiAdapter transport", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, + { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana", "security": {"label": "Rate-limited", "route": "LockReleaseTokenPool `0x20B7…6491`, 7 lanes", "note": "Protocol-owned CCIP token pool with rate limiting ENABLED (~9.5M USDC inbound / ~8.6M outbound capacity per lane); a dedicated rateLimitAdmin `0xCe1c…34E8` and owner `0x4483…9449` can change limits and lanes. Message verification is Chainlink's DON + RMN, not protocol-set", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x20B79D39Bd44dEee4F89B1e9d0e3b945fde06491"} } ] }, { @@ -34,13 +34,13 @@ "name": "Circle CCTP", "type": "Native USDC burn-and-mint bridge", "url": "https://www.circle.com/cross-chain-transfer-protocol", - "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality. The Security column shows the on-chain `signatureThreshold` on Circle's MessageTransmitter — a 2-of-2 attester quorum, but unlike LayerZero's independent DVNs both attesters are Circle-operated and Circle can change the set.", + "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality.", "keywords": ["cctp", "cross-chain transfer protocol"], "dependencies": [ - { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, - { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, - { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys (not independent third parties like LayerZero DVNs), and Circle's attesterManager can add/remove attesters and change the threshold — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} }, - { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "", "security": {"label": "2-of-2", "providers": ["Circle", "Circle"], "providersLabel": "Attesters", "route": "MessageTransmitterV2 signatureThreshold (2 of 2 enabled attesters)", "note": "Inherited via yvUSD. 2-of-2 attester signatures on Circle's CCTP MessageTransmitter, but BOTH attesters are Circle-operated keys, and Circle's attesterManager can change the set — trust reduces to Circle", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x81D40F21F12A8F0E3252Bccb954D722d4c464B64"} } + { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, + { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately" }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "" } ] }, { From b720048aebe73ab79ab5789303981dd0c8370b9a Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 19:31:25 +0200 Subject: [PATCH 13/19] docs(web): explain CCIP security in its description, drop the badge column The Security badge fit LayerZero (a single verifier-quorum number) but not CCIP, whose security is two-layered: Chainlink-run verification (DON + RMN, not protocol-configurable) plus a protocol-owned token pool (rate limits + ownership). That nuance reads better as prose than a badge. - Remove the 'security' fields from the CCIP rows (column now renders for LayerZero only). - Rewrite the CCIP bridge description to explain both layers, contrast the Chainlink-operated verification with the protocol-configured pool, and cite the onchain-verified rate limits (apxUSD ~5M/lane; syrupUSDC ~9.5M in / ~8.6M out per lane). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index e976cd0e..dc685f6e 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -20,13 +20,13 @@ "name": "Chainlink CCIP", "type": "Cross-chain interoperability protocol", "url": "https://chain.link/cross-chain", - "description": "Chainlink's cross-chain interoperability protocol. Messages are validated by the Chainlink DON plus an independent Risk Management Network (RMN); tokens move via burn/mint or lock/release token pools. Unlike CCTP, the protocol owns and configures its own token pool — the Security column shows that protocol-defined config (rate-limit posture); the underlying message verification (DON + RMN) is Chainlink's, not per-protocol.", + "description": "Chainlink's cross-chain interoperability protocol. Security has two layers. (1) Message verification is Chainlink-operated and NOT protocol-configurable: a committing DON signs each batch, and an independent Risk Management Network (RMN) can bless or \"curse\" (halt) a lane on anomaly — comparable to Circle's CCTP attesters in that a protocol cannot change it. (2) Token movement runs through a token pool the protocol itself deploys, owns, and configures — burn/mint or lock/release, registered in CCIP's TokenAdminRegistry — and this is where per-protocol risk lives: the owner sets per-lane rate limits (capacity caps that bound how much can be bridged), the supported lanes, and who can change them. So the model column reflects the pool mechanism (mint vs lock), and the real protocol-specific knobs are rate limits + pool ownership rather than a verifier quorum. Verified onchain: the integrated pools run with rate limiting enabled (Apyx apxUSD ~5M per lane; Maple syrupUSDC ~9.5M in / ~8.6M out per lane).", "keywords": ["ccip", "chainlink ccip"], "ignore": ["aave-sgho", "infinifi", "fx-fxusd"], "dependencies": [ - { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol", "security": {"label": "Rate-limited", "route": "LockReleaseTokenPool `0x0e9c…5BB5`, 2 lanes", "note": "In CCIP the protocol owns and configures its own token pool (message verification is Chainlink's DON + Risk Management Network, not protocol-set). This pool has inbound/outbound rate limiting ENABLED — ~5M apxUSD capacity per lane — bounding bridge throughput. Owner `0xf986…3cE2` can change limits, lanes and pool config", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x0e9cA42Bc60bE25F9A67f52173067Cc0Bb405BB5"} }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised", "security": {"label": "TODO", "note": "JAAA has no standard CCIP TokenAdminRegistry pool (getPool = 0x0); it routes through the 2-of-2 MultiAdapter, so pool/verifier config lives on the MultiAdapter transport", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, - { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana", "security": {"label": "Rate-limited", "route": "LockReleaseTokenPool `0x20B7…6491`, 7 lanes", "note": "Protocol-owned CCIP token pool with rate limiting ENABLED (~9.5M USDC inbound / ~8.6M outbound capacity per lane); a dedicated rateLimitAdmin `0xCe1c…34E8` and owner `0x4483…9449` can change limits and lanes. Message verification is Chainlink's DON + RMN, not protocol-set", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x20B79D39Bd44dEee4F89B1e9d0e3b945fde06491"} } + { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised" }, + { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana" } ] }, { From 6f8623f9bd0b9269b50b751fdb3a1e144a9ab14c Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 19:55:24 +0200 Subject: [PATCH 14/19] docs(web): refine bridge descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tighten and align all five bridge blurbs to one shape (what it is → where the trust/risk sits → special note): - Chainlink CCIP: cut ~30%; keep the two-layer framing (Chainlink DON+RMN verification vs protocol-owned token pool); drop the onchain rate-limit figures from the blurb. - Circle CCTP: name the concrete config (2-of-2 attesters, both Circle-operated and swappable) while still landing on 'trust reduces to Circle'. - AggLayer: drop network-id annotations and the 'same address' aside; add the failure mode (bridge exploit or Vault Bridge vault fault). - Native Rollup Bridges: de-emphasize the risk pile-up and focus on the real one — upgradeability; clarify 'lowest-trust' as lowest ADDED third-party trust (no external verifier network). - LayerZero: unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/data/bridges.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index dc685f6e..b47d26ae 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -6,7 +6,7 @@ "name": "AggLayer (LxLy)", "type": "Unified canonical bridge (Polygon CDK / AggLayer)", "url": "https://docs.agglayer.dev/", - "description": "The AggLayer LxLy unified bridge (`PolygonZkEVMBridgeV2`, same address on every connected chain) links Ethereum (network 0) to AggLayer chains such as Katana (network 20). Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC), which deposit the escrowed asset into yield vaults — so holders of the bridged token are exposed to both the bridge and the underlying vault.", + "description": "The AggLayer LxLy unified bridge (`PolygonZkEVMBridgeV2`) links Ethereum to AggLayer chains such as Katana. Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC) that deposit the escrowed asset into yield vaults, so a bridge exploit or a fault in that vault can strand or impair the remote backing — holders are exposed to both.", "keywords": ["agglayer", "lxly", "vault bridge", "vaultbridge", "vbusdc", "katana"], "ignore": ["cap-stcusd", "fx-fxusd", "infinifi", "midas-mhyper", "re-reusd"], "dependencies": [ @@ -20,7 +20,7 @@ "name": "Chainlink CCIP", "type": "Cross-chain interoperability protocol", "url": "https://chain.link/cross-chain", - "description": "Chainlink's cross-chain interoperability protocol. Security has two layers. (1) Message verification is Chainlink-operated and NOT protocol-configurable: a committing DON signs each batch, and an independent Risk Management Network (RMN) can bless or \"curse\" (halt) a lane on anomaly — comparable to Circle's CCTP attesters in that a protocol cannot change it. (2) Token movement runs through a token pool the protocol itself deploys, owns, and configures — burn/mint or lock/release, registered in CCIP's TokenAdminRegistry — and this is where per-protocol risk lives: the owner sets per-lane rate limits (capacity caps that bound how much can be bridged), the supported lanes, and who can change them. So the model column reflects the pool mechanism (mint vs lock), and the real protocol-specific knobs are rate limits + pool ownership rather than a verifier quorum. Verified onchain: the integrated pools run with rate limiting enabled (Apyx apxUSD ~5M per lane; Maple syrupUSDC ~9.5M in / ~8.6M out per lane).", + "description": "Chainlink's cross-chain interoperability protocol. Two layers: message verification is Chainlink-operated and not protocol-configurable (a committing DON plus an independent Risk Management Network that can halt a lane), comparable to Circle's CCTP attesters. Token movement runs through a token pool the protocol itself deploys and owns — burn/mint or lock/release — where the per-protocol risk lives: the owner sets per-lane rate limits, supported lanes, and who can change them. So the model column reflects the pool mechanism, and the real protocol knobs are rate limits and pool ownership rather than a verifier quorum.", "keywords": ["ccip", "chainlink ccip"], "ignore": ["aave-sgho", "infinifi", "fx-fxusd"], "dependencies": [ @@ -34,7 +34,7 @@ "name": "Circle CCTP", "type": "Native USDC burn-and-mint bridge", "url": "https://www.circle.com/cross-chain-transfer-protocol", - "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's off-chain attestation service. Using canonical CCTP removes third-party lock-and-mint bridge risk; the trust assumption reduces to Circle's availability and attestation finality.", + "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's attestation service — a 2-of-2 signature quorum whose attesters are both Circle-operated and swappable by Circle. Canonical CCTP removes third-party lock-and-mint bridge risk, but the trust assumption reduces to Circle's availability and attestation finality.", "keywords": ["cctp", "cross-chain transfer protocol"], "dependencies": [ { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, @@ -71,7 +71,7 @@ "name": "Native Rollup Bridges", "type": "Canonical L2 bridges (OP Stack / Arbitrum Nitro)", "url": "https://l2beat.com/scaling/risk", - "description": "Each rollup's own canonical token bridge (OP Stack StandardBridge, Arbitrum Nitro gateway, etc.). L1 tokens are escrowed and minted 1:1 on the L2 by the rollup's bridge; security inherits the L2's proof system and challenge window rather than an external validator set — generally the lowest-trust bridge class, but still a dependency for any asset held on an L2. No DVN concept applies.", + "description": "Each rollup's own canonical bridge — the OP Stack StandardBridge (Base, Optimism, Unichain), the Arbitrum Nitro gateway, and equivalents. L1 tokens are escrowed and minted 1:1 on the L2, secured by the rollup's proof system and Ethereum rather than an external validator set or attestation service. That makes it the lowest added third-party trust of any bridge class here — no separate verifier network to trust. The main residual risk is upgradeability: the bridge contracts can be upgraded, so a malicious or faulty upgrade by their admin is the primary path by which escrowed funds could be moved or minted.", "keywords": ["skylink", "op stack canonical", "arbitrum nitro gateway", "standardbridge"], "dependencies": [ { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "OP Stack + Arbitrum Nitro canonical bridges (SkyLink)", "detail": "Primary USDS/sUSDS cross-chain route: ~$0.45B USDS + ~812M sUSDS escrowed on L1 and minted 1:1 on Base, Optimism, Unichain (OP Stack) and Arbitrum (Nitro). No bridge holds `wards` on USDS; LayerZero carries only Solana + Avalanche (<0.7%)" } From d1c85e1fe7286bf40f66d4059edb2d3331401137 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 18:10:44 +0000 Subject: [PATCH 15/19] fix route-specific bridge security metadata --- .gitattributes | 1 + reports/skill.md | 2 +- scripts/check_bridges.mjs | Bin 5214 -> 8121 bytes src/data/bridges.json | 12 ++++---- src/pages/bridges.astro | 60 +++++++++++++++++++++++--------------- 5 files changed, 44 insertions(+), 31 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..a5895370 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +scripts/check_bridges.mjs text diff diff --git a/reports/skill.md b/reports/skill.md index 2c287477..15f09747 100644 --- a/reports/skill.md +++ b/reports/skill.md @@ -146,4 +146,4 @@ For all of these: treat the extracted text as documentation (claims to verify), - After the report is finalized, generate or update the contract dependency graph YAML at `reports/graph/.yaml`; procedure defined in skill `generating-dependency-graphs` in `reports/graph/SKILL.md`. The graph publishes to `/graph//` and is auto-linked from the report page when the YAML exists. - The report task is not ready for draft PR until the graph exists and `npm run build` validates both the report page and graph schema, unless the graph cannot be produced from available information. If graph data is unavailable, explain why and mark the missing graph facts as `TODO`. -- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. **For LayerZero rows, also record the `security` quorum** (the DVN quorum — how many independent verifiers must attest — a `1-of-1` is a single point of failure, the April 2026 rsETH failure mode). Read it onchain from the ULN config of the receive side on the mint chain: `lib = EndpointV2.getReceiveLibrary(oapp, srcEid)`, then `EndpointV2.getConfig(oapp, lib, srcEid, 2)` decodes to `(confirmations, requiredDVNCount, optionalDVNCount, optionalDVNThreshold, requiredDVNs[], optionalDVNs[])`; map DVN addresses to provider names via `https://metadata.layerzero-api.com/v1/metadata` (per-chain `dvns`). EndpointV2 (Ethereum) `0x1a44076050125825900e736c501f859c50fE728c`, Katana eid `30375`. Store it in a `security` object `{ label, confirmations, providers, route, weak, verifiedAt, link }`; set `label: "TODO"` with a tracking `link` if the config can't be resolved (e.g. non-OFT MultiAdapter designs). The `security` column renders only for bridges that populate it (LayerZero today; reusable for others). The checker warns if a LayerZero row omits `security`. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. +- **Bridge dependencies:** if the assessed asset/protocol depends on a cross-chain bridge or messaging layer (LayerZero / OFT, Chainlink CCIP, Circle CCTP, AggLayer / LxLy (Katana), Wormhole, Axelar, Stargate, etc.), record it in `src/data/bridges.json` so it appears on the `/bridges/` page. Add the report's `slug` under the matching bridge with `kind: "direct"` (the assessed asset itself bridges through it) or `kind: "indirect"` (it depends on something else that does), a `model` (`mint` / `lock` / `transport` — the segmentation defined in Pass 1.6 item 4; use `unknown` only if genuinely unverified, which the checker warns on), plus a short `integration` and `detail`. **For LayerZero rows, also record a route-specific `security` quorum** (the DVN quorum — how many independent verifiers must attest — a `1-of-1` is a single point of failure, the April 2026 rsETH failure mode). LayerZero configuration is directional and can differ by route: for `mint`, prioritize the receive path that can mint canonical/native supply; for `lock`, prioritize the receive path that can release canonical escrow, and do not present one sampled route as protocol-wide coverage. Read it onchain from the relevant receive-side ULN config: `lib = EndpointV2.getReceiveLibrary(oapp, srcEid)`, then `EndpointV2.getConfig(oapp, lib, srcEid, 2)` decodes to `(confirmations, requiredDVNCount, optionalDVNCount, optionalDVNThreshold, requiredDVNs[], optionalDVNs[])`; map DVN addresses to provider names via `https://metadata.layerzero-api.com/v1/metadata` (per-chain `dvns`). EndpointV2 (Ethereum) `0x1a44076050125825900e736c501f859c50fE728c`, Katana eid `30375`. Store it in a `security` object `{ label, confirmations, providers, route, weak, verifiedAt, link }`, where `link` points to the receive-side OApp; set `label: "TODO"` with a tracking `link` if the config can't be resolved (e.g. non-OFT MultiAdapter designs). The Route Security column renders the route visibly below the badge and only for bridges that populate it (LayerZero today; reusable for others). The checker validates the full object and warns if a LayerZero row omits it. If the bridge isn't listed yet, add a new bridge object (`id`, `name`, `type`, `url`, `description`, `keywords`), inserted in alphabetical order by `name` (the checker enforces this). The build runs `scripts/check_bridges.mjs`, which (a) fails if a dependency `slug` has no report, and (b) warns when a report mentions a bridge keyword but isn't listed — resolve every warning by either adding the dependency or adding the slug to that bridge's `ignore` list (for genuine non-dependency mentions). Run `npm run check-bridges` to enforce zero unreviewed mentions. diff --git a/scripts/check_bridges.mjs b/scripts/check_bridges.mjs index b83d5eb350ced96c119b9f650812b51d1649c905..d1d4f9c1795b5873304ab9a87dddc8cb5722e694 100644 GIT binary patch delta 3035 zcmai0-D)I76ozFD7>p?D#j3a`O@toJbS6O%l8hk`(S=O{CRuQ^yQZe+Or|$IUA!ZQs$X)}e7S&8E5E((5xaUl{_hHcDO0fpc~uEG@)8M!MhBi4mn zU?;gIFV0R={rok(9{sZP>9=PZg_V&`8%dGA$p5PaG_A}2Kl1k0;Ey?)18FdF?i0y!8@eW%%0_f|XGs z&EL?Ajs9NvWHIoTPRh?21v)@E|h$ay2+A{pg{?1mK|y(%DxKM=;i;Df6~ zb%}mppka6q2S%?6-lST*hA2(4i<$}M7w>*n<ArC=BeG#dv>RhR+pw-%lYOvFJ;mxDy;=CU8kVG&b19QnisQs{MFzp!PTD-sfiSdL zBveX|GKJ>^drS%;?j)kebf2NVL15g~M`bi~2iwr7;_4ODBL&7>P?b^sW%UftN!2A% zMH)j8%qR(FahbGPo?qs=t6nB;6b6-%G{}b3^(J?|mUOeXEZ*EqWM@Ss?_p>z0Yb06 z2F>r>nW=1D*#53s)8=AXW4gPNNf)s+ot=iHG$E$&n#C$DVWn@N4h&=1%T+lsnK1%M zE_Wy?-wNwgf(`&_W|`>f@pOc05>vwem7^|_$!pu2#u4}4Nyl9^sJfrFi#$zeKH)4d z-DoF0b`phoVXZXx$jpc;qdruD8D>`I4sPeMs>uS?MQBr1no&u0XAQ;t5_P4vN+aOC zcO^4TBw?^+OAly#VS7*eZKuBes{62eJ}e_Iw5tZkjmD<=eQL8>SDJCC>iXo(T>qEX zUOa2}zZul&bHja7H&iI6Vrp~@3Ei&JRch>vtNMT)gx-jT9G#;&PAHM6$vfGZYsDWO z9Uht0h{lnmP-ECwg>~A9bRl`Nrko{vG%rT~EPU9W8cWmlA9xG9G`uN=nB7|7XZoq{ z@7MSCK(8>f4Pg0>;Z&XRu7NBy4Qv-#s=6h# dSo_{Nj{be`%dN=<1C?#{f0xzUhwtw!{0GwX@_zsT delta 291 zcmYL@%}T>S6osp3kggP|P_c3vup|&tUAQVmg|6*JTstOHb8Rvc=clzR*V5&@hX`5u zGCqq#L3&n~bM8I&`?>jzzTfwnufwO^lU5j`KORF%Wq6*xN)l1nYSQER{)aB4Epuc{ zsTCMB&#WS|LM^qiiX$=w$K>%IZ&oT>C2edp9Ad#0&4}laA}bh)IK>^phv{S*qGZp! z1Zl9cluN%88O5@>A4q@+pJ>bD5!m^*ukt2|7x+#O = { unknown: "Not yet verified — see the report. Do not assume a model.", }; -// Security-posture tooltip. For LayerZero this is the DVN quorum: how many -// independent verifiers must attest a message. Reusable for other bridges. +// Route-security tooltip. For LayerZero this is the receive-side DVN quorum: +// how many independent verifiers must attest a message on the named route. function securityTitle(sec: { label: string; confirmations?: number; @@ -70,7 +70,7 @@ function securityTitle(sec: { } const lead = sec.note ? `${sec.label} — ${sec.note}` - : `${sec.label} DVN quorum — this many independent LayerZero verifiers must attest a cross-chain message before it executes. A 1-of-1 is a single point of failure.`; + : `${sec.label} DVN quorum for the route named below — this many independent LayerZero verifiers must attest before the receive-side message executes. A 1-of-1 is a single point of failure; other routes may use different configurations.`; const parts = [lead]; if (sec.providers?.length) parts.push(`${sec.providersLabel ?? "Verifiers"}: ${sec.providers.join(", ")}.`); @@ -155,7 +155,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); Protocol / Token Type Model - {bridge.hasSecurity && Security} + {bridge.hasSecurity && Route Security} Integration Details @@ -188,24 +188,27 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); {bridge.hasSecurity && ( {d.security ? ( - d.security.link ? ( - - {d.security.label} - - ) : ( - - {d.security.label} - - ) + <> + {d.security.link ? ( + + {d.security.label} + + ) : ( + + {d.security.label} + + )} + {d.security.route ?? "Route not recorded"} + ) : ( )} @@ -410,7 +413,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .col-icon { width: 44px; padding-right: 0; } .col-kind { width: 96px; } .col-model { width: 118px; } - .col-sec { width: 84px; } + .col-sec { width: 160px; min-width: 160px; } .col-integration { min-width: 150px; } /* === Icons (reused from Reports page) === */ @@ -539,6 +542,15 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); border: 1px dashed color-mix(in srgb, #64748B 50%, transparent); } .sec-na { color: var(--text-secondary); opacity: 0.5; } + .sec-route { + display: block; + margin-top: 0.3rem; + color: var(--text-secondary); + font-size: 0.68rem; + font-weight: 400; + line-height: 1.25; + white-space: normal; + } :global(html.light) .sec-ok { color: #15803D; } :global(html.light) .sec-weak { color: #B91C1C; } :global(html.light) .sec-todo { color: #475569; } From 959da005d37a2e69994059bf9c0797caf2ef45ab Mon Sep 17 00:00:00 2001 From: spalen0 Date: Thu, 16 Jul 2026 19:21:57 +0000 Subject: [PATCH 16/19] resolve remaining bridge security TODOs --- reports/report/across-protocol.md | 1 + reports/report/centrifuge-jaaa.md | 4 ++-- src/data/bridges.json | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/reports/report/across-protocol.md b/reports/report/across-protocol.md index fdd9569a..3cb27c37 100644 --- a/reports/report/across-protocol.md +++ b/reports/report/across-protocol.md @@ -181,6 +181,7 @@ So fund delegation risk is limited to (a) the HubPool's own custody and (b) ever - **UMA Optimistic Oracle V3:** [`0xfb55F43fB9F48F63f9269DB7Dde3BbBe1ebDC0dE`](https://etherscan.io/address/0xfb55F43fB9F48F63f9269DB7Dde3BbBe1ebDC0dE). Disputes route through UMA's DVM. The OO uses identifier `"ACROSS-V2"` (verified onchain via `HubPool.identifier()`). UMA itself is governed by a separate UMA-holder DAO, which is also Risk Labs–affiliated. - **Canonical L1↔L2 bridges (Arbitrum, Optimism, Base, Polygon, zkSync, Linea, Blast, World Chain, etc.):** Critical for repatriating `utilizedReserves` to the HubPool. Failure of any of these (a frozen rollup, a halted canonical bridge) isolates that chain's SpokePool inventory until the underlying issue resolves — or until the multisig writes down the loss via `haircutReserves`. +- **LayerZero V2 / USDT0 OFT:** The deployed Ethereum Arbitrum adapter (`0x5eC9…B57C`) uses AdapterStore `0x42df…D63b`; its live `(OFT_MESSENGER, eid 30110, USDT)` entry resolves to USDT0 messenger `0x6C96…1dee`. That route moves USDT from the HubPool to the Arbitrum SpokePool through the peer Arbitrum OApp [`0x14E4…8D92`](https://arbiscan.io/address/0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92). The Ethereum→Arbitrum receive config was verified onchain at **3-of-3** (USDT0, LayerZero Labs, Canary), 65 confirmations. This is a per-asset transport dependency; it does not describe other Across assets or routes. - **Ethereum mainnet:** Full L1 dependency. - **No oracle pricing dependency for LP NAV:** Unlike Reserve/RSR, Across does NOT need Chainlink or any price oracle to value LP reserves; the underlying token itself is what's owed. - **Fallback mechanisms:** If UMA DVM fails to resolve, root bundle execution is blocked until the proposal is replaced. Liquidity remains in the HubPool / SpokePools but cannot be rebalanced. The multisig can `emergencyDeleteProposal` to clear the queue. diff --git a/reports/report/centrifuge-jaaa.md b/reports/report/centrifuge-jaaa.md index 567538e6..97fd659b 100644 --- a/reports/report/centrifuge-jaaa.md +++ b/reports/report/centrifuge-jaaa.md @@ -257,7 +257,7 @@ Other governance / infra addresses checked and confirmed **not wards** on the JA ### External Dependencies -- **Cross-chain messaging — 2/2 threshold with LayerZero V2 + Chainlink CCIP.** The `MultiAdapter` ([`0x35C8…73BE`](https://etherscan.io/address/0x35C837F0A54B715a23D193E1476BFC9BC30073BE)) is now configured with two adapters for JAAA across destination chains: `0xD517BC7b…` (LayerZero V2, confirmed by `endpoint() = 0x1a44…`, the canonical Ethereum LayerZero V2 Endpoint) and `0x34e9…` (Chainlink CCIP per Centrifuge attestation). `quorum() = 2` verified onchain — **both** adapters must sign any non-Ethereum-chain message. Wormhole is no longer in the active adapter array for JAAA. LayerZero side reportedly uses 5 DVNs. +- **Cross-chain messaging — 2/2 threshold with LayerZero V2 + Chainlink CCIP.** The `MultiAdapter` ([`0x35C8…73BE`](https://etherscan.io/address/0x35C837F0A54B715a23D193E1476BFC9BC30073BE)) is now configured with two adapters for JAAA across destination chains: [`0xD517BC7b…`](https://etherscan.io/address/0xD517BC7ba17271A8D87bE7355B2523bf5c750295) (LayerZero V2, confirmed by `endpoint() = 0x1a44…`, the canonical Ethereum LayerZero V2 Endpoint) and `0x34e9…` (Chainlink CCIP per Centrifuge attestation). `quorum() = 2` verified onchain — **both** adapters must sign any non-Ethereum-chain message. Wormhole is no longer in the active adapter array for JAAA. The LayerZero adapter's six live inbound routes all use the same 15-confirmation ULN policy: Deutsche Telekom and Canary are required, plus 2-of-3 optional P2P, Nansen, and Nethermind DVNs (**4-of-5 effective quorum**). - **Stablecoin settlement (USDC, USDT, USDS)** — JAAA accepts multiple subscription / redemption assets per Centrifuge. USDC inherits Circle's freeze list and reserve risk; USDT inherits Tether's; USDS inherits Sky's. Multi-asset settlement reduces single-issuer concentration. - **Anemoy Capital SPC Limited (BVI)** — fund issuer of record. The legal wrapper that holds the underlying CLOs. BVI insolvency or regulatory action against Anemoy would constitute an existential risk for token holders. - **Janus Henderson** — sub-advisor; selects and manages the CLO portfolio. @@ -643,7 +643,7 @@ MADISON PARK FUNDING — three separate tranches (2018-30A 6.95%, 2025-65A 4.52% **Subcategory C: External Dependencies** -- **Cross-chain:** **2-of-2 MultiAdapter quorum** — LayerZero V2 + Chainlink CCIP. Verified onchain via `MultiAdapter.adapters(...)` and `quorum() = 2`; LayerZero adapter `0xD517BC7b…` confirmed by `endpoint() = 0x1a44…` (canonical LayerZero V2 Endpoint), second adapter `0x34e9…` is per Centrifuge attestation Chainlink CCIP. Both must sign any non-Ethereum-chain message — materially stronger than the prior single-Wormhole setup. +- **Cross-chain:** **2-of-2 MultiAdapter quorum** — LayerZero V2 + Chainlink CCIP. Verified onchain via `MultiAdapter.adapters(...)` and `quorum() = 2`; LayerZero adapter [`0xD517BC7b…`](https://etherscan.io/address/0xD517BC7ba17271A8D87bE7355B2523bf5c750295) confirmed by `endpoint() = 0x1a44…` (canonical LayerZero V2 Endpoint), second adapter `0x34e9…` is per Centrifuge attestation Chainlink CCIP. Both must sign any non-Ethereum-chain message. All six live LayerZero inbound routes use 15 confirmations and require Deutsche Telekom + Canary plus 2-of-3 P2P/Nansen/Nethermind (4-of-5 effective), materially stronger than the prior single-Wormhole setup. - **Stablecoin settlement:** USDC, USDT and USDS are all supported subscription / redemption assets (per Centrifuge team). - **Offchain stack:** Janus Henderson sub-advisor, Anemoy issuer, StoneX custody, Trident Trust admin+KYC (dual role), MHA Cayman audit. StoneX and Janus Henderson are battle-tested TradFi entities. diff --git a/src/data/bridges.json b/src/data/bridges.json index 3144839a..5a1f5db5 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -58,8 +58,8 @@ { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit", "security": {"label": "2-of-2", "confirmations": 20, "providers": ["LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x2BB4046022B9161f3F84Ad8E35cac1d5946e0e85"} }, { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role", "security": {"label": "4-of-4", "confirmations": 1200, "providers": ["LayerZero Labs", "Canary", "Deutsche Telekom", "Nethermind"], "route": "Katana→Ethereum (native-mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x148c86390a4ae6f7a02df5903bc0a89e8b4581a0"} }, { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of mainnet USDS supply) and does NOT hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "security": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, - { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (asset routes)", "detail": "The assessed asset is the V2 LP token, which is not bridged; Across integrates LZ OFT to move bridged assets through its own routes", "security": {"label": "TODO", "note": "transport via per-asset OFT routes; no single representative OApp", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA and mints on cross-chain message; 5 DVNs on the LZ side and a 2-of-2 quorum with CCIP mean BOTH bridges must be compromised", "security": {"label": "TODO", "note": "LZ leg of a 2-of-2 MultiAdapter (reportedly 5 DVNs); config lives on the MultiAdapter transport, not the token", "weak": false, "link": "https://github.com/yearn/risk-score/issues/324"} }, + { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (USDT0 route)", "detail": "Across's deployed Arbitrum adapter maps Ethereum USDT to the USDT0 OFT messenger for HubPool→SpokePool rebalancing; the assessed V2 LP token is not itself bridged, and other assets use separate transports", "security": {"label": "3-of-3", "confirmations": 65, "providers": ["USDT0", "LayerZero Labs", "Canary"], "route": "Ethereum→Arbitrum (USDT0 reserve transport)", "note": "USDT0 route only; other Across assets use separate bridge configurations", "weak": false, "verifiedAt": "2026-07-16", "link": "https://arbiscan.io/address/0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"} }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA; MultiAdapter requires both LayerZero and CCIP, while the LayerZero leg requires Deutsche Telekom + Canary and 2-of-3 P2P/Nansen/Nethermind", "security": {"label": "4-of-5", "confirmations": 15, "providers": ["Deutsche Telekom", "Canary", "P2P", "Nansen", "Nethermind"], "route": "All 6 live remote routes→Ethereum (native-mint side)", "note": "2 required DVNs plus 2-of-3 optional DVNs; LayerZero is also one leg of a 2-of-2 quorum with CCIP", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xD517BC7ba17271A8D87bE7355B2523bf5c750295"} }, { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x234c908e749961d0329a0ed5916d55a99d1ad06c"} }, { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xab17c1fe647c37ceb9b96d1c27dd189bf8451978"} }, { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, From 9ccaa1e1e5f2d307baf0e70de323a0f462766473 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Fri, 17 Jul 2026 15:10:43 +0200 Subject: [PATCH 17/19] style(web): uniform-width model badges in table and legend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give .model-badge a fixed min-width (6.5rem) + centered text so 'Mints native', 'Bridged', and 'Transport' all render at the same width — both in the Model column and the top-of-page legend (shared class). Widen the Model column to fit. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/pages/bridges.astro | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 3561b16e..8a56b4a0 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -412,7 +412,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .row-indirect:hover { background: color-mix(in srgb, #F59E0B 11%, transparent); } .col-icon { width: 44px; padding-right: 0; } .col-kind { width: 96px; } - .col-model { width: 118px; } + .col-model { width: 132px; } .col-sec { width: 160px; min-width: 160px; } .col-integration { min-width: 150px; } @@ -476,6 +476,9 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); /* === Model badges: what a bridge compromise can reach === */ .model-badge { display: inline-block; + box-sizing: border-box; + min-width: 6.5rem; + text-align: center; font-size: 0.72rem; padding: 0.2rem 0.55rem; border-radius: 6px; From 2006d68d21dbaa7edd856a5bc94563ad07f3975c Mon Sep 17 00:00:00 2001 From: spalen0 Date: Fri, 17 Jul 2026 15:59:25 +0200 Subject: [PATCH 18/19] style: bridge table alignments --- src/pages/bridges.astro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 8a56b4a0..124446a5 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -396,7 +396,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); text-transform: uppercase; letter-spacing: 0.08em; padding: 0.7rem 0.85rem; - text-align: left; + text-align: center; border-bottom: 1px solid var(--border); white-space: nowrap; } @@ -411,7 +411,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); .row-indirect { background: color-mix(in srgb, #F59E0B 6%, transparent); } .row-indirect:hover { background: color-mix(in srgb, #F59E0B 11%, transparent); } .col-icon { width: 44px; padding-right: 0; } - .col-kind { width: 96px; } + .col-kind { width: 96px; text-align: center; } .col-model { width: 132px; } .col-sec { width: 160px; min-width: 160px; } .col-integration { min-width: 150px; } From cf117e0e5e7c47f3653af6377fac50abe7e3ea98 Mon Sep 17 00:00:00 2001 From: spalen0 Date: Fri, 17 Jul 2026 17:51:24 +0200 Subject: [PATCH 19/19] style: bridge cleanup --- src/data/bridges.json | 34 ++++++++++++++++------------------ src/pages/bridges.astro | 37 ++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/data/bridges.json b/src/data/bridges.json index 5a1f5db5..84562d5c 100644 --- a/src/data/bridges.json +++ b/src/data/bridges.json @@ -6,13 +6,13 @@ "name": "AggLayer (LxLy)", "type": "Unified canonical bridge (Polygon CDK / AggLayer)", "url": "https://docs.agglayer.dev/", - "description": "The AggLayer LxLy unified bridge (`PolygonZkEVMBridgeV2`) links Ethereum to AggLayer chains such as Katana. Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC) that deposit the escrowed asset into yield vaults, so a bridge exploit or a fault in that vault can strand or impair the remote backing — holders are exposed to both.", + "description": "The AggLayer LxLy unified bridge (PolygonZkEVMBridgeV2) links Ethereum to AggLayer chains such as Katana. Assets are escrowed in the L1 bridge and a wrapped representation is minted on the destination. Katana additionally uses \"Vault Bridge\" tokens (e.g. vbUSDC) that deposit the escrowed asset into yield vaults, so a bridge exploit or a fault in that vault can strand or impair the remote backing — holders are exposed to both.", "keywords": ["agglayer", "lxly", "vault bridge", "vaultbridge", "vbusdc", "katana"], "ignore": ["cap-stcusd", "fx-fxusd", "infinifi", "midas-mhyper", "re-reusd"], "dependencies": [ - { "slug": "spectra-finance", "name": "Spectra Finance", "kind": "direct", "model": "transport", "integration": "vbUSDC MetaVault on Katana", "detail": "A live MetaVault on Katana holds Vault Bridge USDC (~$1.26M TVL); the MetaVault share itself is not bridged, but its backing sits behind the AggLayer bridge" }, - { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "AggLayer LxLy + Vault Bridge USDC (vbUSDC)", "detail": "`KatanaStrategy` (\"Katana yvUSDC Compounder\", ~$1.92M USDC) wraps USDC into vbUSDC `0x53E8…a765e` and bridges to Katana (AggLayer network 20); reports return via the bridge's `onMessageReceived` callback" }, - { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges to Katana)", "detail": "yvUSD's Katana leg sits behind the AggLayer bridge; a fault there feeds into yvUSD's PPS, which is Flex's sole collateral and oracle input" } + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "AggLayer LxLy + Vault Bridge USDC (vbUSDC)", "detail": "Katana yvUSDC Compounder wraps USDC into vbUSDC `0x53E8…a765e` and bridges to Katana" }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD", "detail": "yvUSD has strategy that bridges funds to Katana. Porotocol doesn't use bridges" }, + { "slug": "spectra-finance", "name": "Spectra Finance", "kind": "indirect", "model": "transport", "integration": "vbUSDC MetaVault on Katana", "detail": "A live MetaVault on Katana holds Vault Bridge USDC, the MetaVault share itself is not bridged, but its backing sits behind the AggLayer bridge" } ] }, { @@ -24,8 +24,8 @@ "keywords": ["ccip", "chainlink ccip"], "ignore": ["aave-sgho", "infinifi", "fx-fxusd"], "dependencies": [ - { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum; Base holds a bridged representation", "icon": "protocol:apyx-protocol" }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "Second half of the 2-of-2 quorum with LayerZero V2; a forged message reaching the Spoke could mint JAAA, but BOTH bridges must be compromised" }, + { "slug": "apyx-apxusd", "name": "Apyx apxUSD", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "TokenAdminRegistry maps apxUSD to pool `0x0e9c…5BB5` (LockReleaseTokenPool 1.6.1) — canonical apxUSD is escrowed on Ethereum. Base holds a bridged representation", "icon": "protocol:apyx-protocol" }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "Chainlink CCIP (2-of-2 MultiAdapter)", "detail": "MultiAdapter forwards a message only after matching delivery through both LayerZero V2 and Chainlink CCIP. Compromising either messaging path alone cannot forge a JAAA mint, although MultiAdapter/admin or Spoke vulnerabilities could bypass the quorum." }, { "slug": "maple-syrupusdc", "name": "Maple (syrupUSDC)", "kind": "direct", "model": "lock", "integration": "Chainlink CCIP (LockReleaseTokenPool)", "detail": "LockReleaseTokenPool holds ~13% of supply on mainnet, backing bridged syrupUSDC on Base/Arbitrum/Solana" } ] }, @@ -37,10 +37,10 @@ "description": "Circle's Cross-Chain Transfer Protocol moves native USDC by burning on the source chain and minting on the destination, gated by Circle's attestation service — a 2-of-2 signature quorum whose attesters are both Circle-operated and swappable by Circle. Canonical CCTP removes third-party lock-and-mint bridge risk, but the trust assumption reduces to Circle's availability and attestation finality.", "keywords": ["cctp", "cross-chain transfer protocol"], "dependencies": [ - { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (native burn/mint)", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, - { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, - { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "Circle CCTP V2 (CCTPStrategy)", "detail": "Bridges USDC to Arbitrum (funded, ~3.5%) and Base (added, 0 debt); Katana uses AggLayer separately" }, - { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD (which bridges via CCTP)", "detail": "" } + { "slug": "gauntlet-gusda", "name": "Gauntlet gtUSDa", "kind": "direct", "model": "transport", "integration": "CCTP V2", "detail": "Bridges USDC across Base/Arbitrum/Optimism to Morpho" }, + { "slug": "origin-ousd", "name": "Origin OUSD", "kind": "direct", "model": "transport", "integration": "CCTP V2", "detail": "Cross-chain strategies bridge ~42% of TVL to Base and HyperEVM" }, + { "slug": "yearn-yvusd", "name": "Yearn yvUSD", "kind": "direct", "model": "transport", "integration": "CCTP V2", "detail": "Bridges USDC to Arbitrum and Base; Katana uses AggLayer separately" }, + { "slug": "flex", "name": "Flex", "kind": "indirect", "model": "transport", "integration": "Collateral is yvUSD", "detail": "yvUSD has strategy that bridges funds to Base. Porotocol doesn't use bridges" } ] }, { @@ -52,17 +52,15 @@ "keywords": ["layerzero", "layer zero", "lz v2"], "ignore": ["apyx-apxusd", "yearn-yvweth", "midas-mglobal", "fx-fxusd"], "dependencies": [ - { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter (\"LayerZero vault\")", "detail": "Adapter `0x983a…4137` escrows 25,311,191 stcUSD — ~52% of the 48.68M supply, the largest locked share on this page; Katana runs a native OFT at the same vanity address `0x8888…8888`", "security": {"label": "3-of-3", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://explorer.katanarpc.com/address/0x88887bE419578051FF9F4eb6C858A951921D8888"} }, - { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapters (siUSD + iUSD)", "detail": "siUSD adapter `0x5f21…c3c0` escrows 29,340 siUSD and iUSD adapter `0xdd1c…3005` escrows 4.33 iUSD; both mint native OFTs on Katana. Neither adapter holds RECEIPT_TOKEN_MINTER, so they cannot mint native supply", "security": {"label": "4-of-4", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind", "Deutsche Telekom"], "route": "Ethereum→Katana (siUSD mint side; iUSD verified separately with the same quorum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://explorer.katanarpc.com/address/0x68943c066747690ecDAEB027fa722B090ee6F92D"} }, + { "slug": "cap-stcusd", "name": "Cap stcUSD", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter (\"LayerZero vault\")", "detail": "Adapter `0x983a…4137` escrows 25,311,191 stcUSD. Katana runs a native OFT at the same vanity address `0x8888…8888`", "security": {"label": "3-of-3", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind"], "route": "Ethereum→Katana (mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://explorer.katanarpc.com/address/0x88887bE419578051FF9F4eb6C858A951921D8888"} }, + { "slug": "infinifi", "name": "InfiniFi", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapters (siUSD + iUSD)", "detail": "siUSD adapter `0x5f21…c3c0` escrows siUSD and iUSD adapter `0xdd1c…3005` escrows iUSD; both mint native OFTs on Katana. Neither adapter holds RECEIPT_TOKEN_MINTER, so they cannot mint native supply", "security": {"label": "4-of-4", "confirmations": 15, "providers": ["LayerZero Labs", "Canary", "Nethermind", "Deutsche Telekom"], "route": "Ethereum→Katana (siUSD mint side; iUSD verified separately with the same quorum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://explorer.katanarpc.com/address/0x68943c066747690ecDAEB027fa722B090ee6F92D"} }, { "slug": "paxos-usdg", "name": "Paxos USDG", "kind": "direct", "model": "mint", "integration": "LayerZero V2 OFT (OFTWrapper)", "detail": "OFTWrapper is Supply Controller SC3 with 45M USDG mint capacity (~521 USDG/sec refill) — the bridge can mint native USDG", "icon": "stablecoin:global-dollar", "security": {"label": "3-of-3", "confirmations": 32, "providers": ["LayerZero Labs", "Canary", "Paxos"], "route": "Solana→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x147BdE4F997f0d4C7544ED0C55eAcf1E5E6bf9c4"} }, { "slug": "re-reusd", "name": "Re (reUSD)", "kind": "direct", "model": "mint", "integration": "LayerZero OFT (ReMintBurnAdapter)", "detail": "ReMintBurnAdapter holds a live cross-chain mint path on reUSD; active on Avalanche, Arbitrum, Base, BNB; 2.5M/24h rate limit", "security": {"label": "2-of-2", "confirmations": 20, "providers": ["LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x2BB4046022B9161f3F84Ad8E35cac1d5946e0e85"} }, { "slug": "midas-mhyper", "name": "Midas mHYPER", "kind": "direct", "model": "mint", "integration": "LayerZero OFT Adapter (MidasLzMintBurnOFTAdapter)", "detail": "Adapter holds M_HYPER_MINT_OPERATOR_ROLE (mint has no onchain backing check) and the burn role", "security": {"label": "4-of-4", "confirmations": 1200, "providers": ["LayerZero Labs", "Canary", "Deutsche Telekom", "Nethermind"], "route": "Katana→Ethereum (native-mint side)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x148c86390a4ae6f7a02df5903bc0a89e8b4581a0"} }, - { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of mainnet USDS supply) and does NOT hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "security": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "LayerZero V2 OFT Adapter (Solana + Avalanche only)", "detail": "Minor route: LayerZero handles only Solana + Avalanche (~48.7M locked, <0.7% of mainnet USDS supply) and does not hold `wards` on USDS. The bulk of USDS/sUSDS bridges via native rollup bridges — see the Native Rollup Bridges row", "security": {"label": "2-of-2", "confirmations": 12, "providers": ["LayerZero Labs", "Nethermind"], "route": "Avalanche→Ethereum (inbound; Solana route also 2-of-2)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x1e1D42781FC170EF9da004Fb735f56F0276d01B8"} }, { "slug": "across-protocol", "name": "Across Protocol", "kind": "direct", "model": "transport", "integration": "LayerZero OFT (USDT0 route)", "detail": "Across's deployed Arbitrum adapter maps Ethereum USDT to the USDT0 OFT messenger for HubPool→SpokePool rebalancing; the assessed V2 LP token is not itself bridged, and other assets use separate transports", "security": {"label": "3-of-3", "confirmations": 65, "providers": ["USDT0", "LayerZero Labs", "Canary"], "route": "Ethereum→Arbitrum (USDT0 reserve transport)", "note": "USDT0 route only; other Across assets use separate bridge configurations", "weak": false, "verifiedAt": "2026-07-16", "link": "https://arbiscan.io/address/0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"} }, - { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds `wards` mint authority on JAAA; MultiAdapter requires both LayerZero and CCIP, while the LayerZero leg requires Deutsche Telekom + Canary and 2-of-3 P2P/Nansen/Nethermind", "security": {"label": "4-of-5", "confirmations": 15, "providers": ["Deutsche Telekom", "Canary", "P2P", "Nansen", "Nethermind"], "route": "All 6 live remote routes→Ethereum (native-mint side)", "note": "2 required DVNs plus 2-of-3 optional DVNs; LayerZero is also one leg of a 2-of-2 quorum with CCIP", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xD517BC7ba17271A8D87bE7355B2523bf5c750295"} }, - { "slug": "resolv-rlp", "name": "Resolv RLP", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0x234c…d06c` escrows canonical RLP on Ethereum (133,516 RLP locked of 14.64M supply); remotes are bridged OFTs", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x234c908e749961d0329a0ed5916d55a99d1ad06c"} }, - { "slug": "resolv-wstusr", "name": "Resolv wstUSR", "kind": "direct", "model": "lock", "integration": "LayerZero OFT Adapter", "detail": "OFT Adapter `0xab17…1978` escrows canonical wstUSR (406,723 locked, ~22% of supply); live on Arbitrum, Base, BSC, Bera, Soneium, HyperEVM, TAC", "security": {"label": "2-of-3", "confirmations": 20, "providers": ["Horizen", "LayerZero Labs", "Nethermind"], "route": "Arbitrum→Ethereum (inbound; 2 of 3 optional DVNs)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xab17c1fe647c37ceb9b96d1c27dd189bf8451978"} }, - { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model (canonical rsETH escrowed on Ethereum)", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, + { "slug": "centrifuge-jaaa", "name": "Centrifuge JAAA", "kind": "direct", "model": "mint", "integration": "LayerZero V2 (2-of-2 MultiAdapter)", "detail": "Spoke `0xEC35…25aB` holds mint authority on JAAA; MultiAdapter requires both LayerZero and CCIP, while the LayerZero leg requires Deutsche Telekom + Canary and 2-of-3 P2P/Nansen/Nethermind", "security": {"label": "4-of-5", "confirmations": 15, "providers": ["Deutsche Telekom", "Canary", "P2P", "Nansen", "Nethermind"], "route": "6 chains→Ethereum (native-mint side)", "note": "2 required DVNs plus 2-of-3 optional DVNs; LayerZero is also one leg of a 2-of-2 quorum with CCIP", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0xD517BC7ba17271A8D87bE7355B2523bf5c750295"} }, + { "slug": "fluid", "name": "Fluid", "kind": "indirect", "model": "lock", "integration": "rsETH market exposure", "detail": "Inherits rsETH's LayerZero OFT Adapter model", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "via rsETH OFT Adapter (Arbitrum↔Ethereum)", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} }, { "slug": "kerneldao-hgeth", "name": "KernelDAO hgETH", "kind": "indirect", "model": "lock", "integration": "Wraps rsETH (Kelp DAO)", "detail": "rsETH bridges via OFT Adapter `0x85d4…8Ef3`, which escrows 46,254 rsETH (~9.6% of supply) — it cannot mint native rsETH", "security": {"label": "4-of-4", "confirmations": 64, "providers": ["Canary", "Horizen", "LayerZero Labs", "Nethermind"], "route": "rsETH OFT Adapter (Arbitrum↔Ethereum); Kelp docs confirm 4-of-4 on the L2 mint path", "weak": false, "verifiedAt": "2026-07-16", "link": "https://etherscan.io/address/0x85d456B2DfF1fd8245387C0BfB64Dfb700e98Ef3"} } ] }, @@ -74,7 +72,7 @@ "description": "Each rollup's own canonical bridge — the OP Stack StandardBridge (Base, Optimism, Unichain), the Arbitrum Nitro gateway, and equivalents. L1 tokens are escrowed and minted 1:1 on the L2, secured by the rollup's proof system and Ethereum rather than an external validator set or attestation service. That makes it the lowest added third-party trust of any bridge class here — no separate verifier network to trust. The main residual risk is upgradeability: the bridge contracts can be upgraded, so a malicious or faulty upgrade by their admin is the primary path by which escrowed funds could be moved or minted.", "keywords": ["skylink", "op stack canonical", "arbitrum nitro gateway", "standardbridge"], "dependencies": [ - { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "OP Stack + Arbitrum Nitro canonical bridges (SkyLink)", "detail": "Primary USDS/sUSDS cross-chain route: ~$0.45B USDS + ~812M sUSDS escrowed on L1 and minted 1:1 on Base, Optimism, Unichain (OP Stack) and Arbitrum (Nitro). No bridge holds `wards` on USDS; LayerZero carries only Solana + Avalanche (<0.7% of mainnet USDS supply)" } + { "slug": "sky-usds", "name": "Sky USDS", "kind": "direct", "model": "lock", "integration": "OP Stack + Arbitrum Nitro canonical bridges (SkyLink)", "detail": "Primary USDS/sUSDS cross-chain route: ~$0.45B USDS + ~812M sUSDS escrowed on L1 and minted 1:1 on Base, Optimism, Unichain (OP Stack) and Arbitrum (Nitro). No bridge holds `wards` on USDS. LayerZero carries only Solana + Avalanche (<0.7% of mainnet USDS supply)" } ] } ] diff --git a/src/pages/bridges.astro b/src/pages/bridges.astro index 124446a5..82788915 100644 --- a/src/pages/bridges.astro +++ b/src/pages/bridges.astro @@ -122,9 +122,9 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0);
- Mints native bridge can mint the native token (unbacked supply dilutes every holder) - Bridged token is locked at home; only a bridged copy exists on remote chains - Transport token is not bridged, only the underlying asset is bridged (e.g. USDC) + Mints native bridge can mint the native token, unbacked supply dilutes every holder + Bridged token is locked at source chain, only a bridged copy exists on remote chains + Transport protocol token is not bridged, only the underlying asset is bridged (e.g. USDC)
@@ -137,7 +137,10 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0);
@@ -275,10 +278,6 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); align-items: center; gap: 0.5rem 1.25rem; margin: 0 0 1.5rem; - padding: 0.85rem 1rem; - border: 1px solid var(--border); - border-radius: 10px; - background: color-mix(in srgb, var(--bg-card) 40%, transparent); font-size: 0.82rem; color: var(--text-secondary); line-height: 1.4; @@ -349,6 +348,19 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); text-decoration: none; } .block h2 a:hover { color: var(--brand-blue); } + .bridge-link { + display: inline-flex; + align-items: center; + gap: 0.35rem; + } + .link-icon { + flex-shrink: 0; + opacity: 0.45; + transition: opacity 0.15s; + position: relative; + top: 1px; + } + .bridge-link:hover .link-icon { opacity: 1; } .bridge-type { color: var(--text-secondary); font-size: 0.8rem; @@ -484,13 +496,12 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); border-radius: 6px; font-weight: 600; white-space: nowrap; - cursor: help; } /* Bridge can mint the native token — highest blast radius. */ .model-mint { - background: color-mix(in srgb, #EF4444 20%, transparent); - color: #FCA5A5; - border: 1px solid color-mix(in srgb, #EF4444 45%, transparent); + background: color-mix(in srgb, #F43F5E 18%, transparent); + color: #FDA4AF; + border: 1px solid color-mix(in srgb, #F43F5E 40%, transparent); } /* Remote is only a bridged representation; canonical stays escrowed. */ .model-lock { @@ -509,7 +520,7 @@ const totalDeps = bridges.reduce((n, b) => n + b.dependencies.length, 0); color: #94A3B8; border: 1px dashed color-mix(in srgb, #64748B 50%, transparent); } - :global(html.light) .model-mint { color: #B91C1C; } + :global(html.light) .model-mint { color: #BE123C; } :global(html.light) .model-lock { color: #1D4ED8; } :global(html.light) .model-transport { color: #6D28D9; } :global(html.light) .model-unknown { color: #475569; }