Skip to content

feat: BNB Smart Chain (56) support — AAVE V3 / Uniswap V3 / Chainlink / Superfluid / WBNB#3

Merged
chrisli30 merged 1 commit into
mainfrom
feat/bnb-mainnet
May 30, 2026
Merged

feat: BNB Smart Chain (56) support — AAVE V3 / Uniswap V3 / Chainlink / Superfluid / WBNB#3
chrisli30 merged 1 commit into
mainfrom
feat/bnb-mainnet

Conversation

@chrisli30
Copy link
Copy Markdown
Member

Summary

Adds Chains.BnbMainnet = 56 plus addresses for AAVE V3, Uniswap V3, Chainlink, Wrapped (WBNB), and Superfluid on BNB Smart Chain. Bumps to 0.2.0 (minor — new chain is additive).

Every address was verified live via eth_getCode against a BNB RPC before merge.

What's added

Protocol Contracts shipped on BNB
AAVE V3 Pool + Oracle. No WETH Gateway (native is BNB, not ETH).
Uniswap V3 SwapRouter02 + QuoterV2 + Factory + PositionManager + UniversalRouter + Permit2 (same address as everywhere) + tokens.WETH (= WBNB) + tokens.USDC (Binance-Peg)
Chainlink ETH/USD + BTC/USD feeds, plus a new bnbUsdFeed field for the chain's native-asset feed
Superfluid CFAv1Forwarder (same address as Ethereum / Base)
Wrapped weth[BnbMainnet]WBNB (0xbb4C…d95c)

Naming decision: wrapped.weth on chains without native ETH

Protocols.wrapped.weth[Chains.BnbMainnet] and Protocols.uniswapV3.tokens.WETH[Chains.BnbMainnet] both map to WBNB, not to Binance-Peg WETH (0x2170Ed0880ac9A755fd29B2688956BD959F933F8).

Rationale: the catalog's weth field is semantically "the canonical wrapper of the chain's native gas token." Keeping the field name stable means chain-agnostic consumers can write Protocols.wrapped.weth[chainId] without per-chain branching. Both modules carry a clear comment explaining this; templates that specifically need bridged WETH on BNB pass that address inline.

Catalog protocols deliberately NOT added on BNB

These don't deploy there:

  • Aerodrome (Base-only by design)
  • Compound V3 (probe at my guessed address failed; revisit if/when an official address surfaces)
  • Ethena sUSDe vault (L1-only)
  • Frax Ether, Lido, Rocket Pool, Sky, Spark, Morpho Blue (all Ethereum + sometimes Base, never BNB)

Tests

15/15 pass (yarn test:run). Three test updates:

  • it("AAVE V3 covers the same chain set on Pool/Oracle/WETH Gateway") relaxed to "... Pool + Oracle cover the same chains; WETH Gateway is a subset" — necessary because BNB has Pool + Oracle but no WETH Gateway. The relaxed invariant is still meaningful: gateway ⊆ pool.
  • it("ships SwapRouter02 on every covered chain") — added BNB row.
  • it("Permit2 is at the same address on every covered chain") — added BNB to the loop.

The address-shape walk and namespace-surface tests already cover the new addresses for free.

Downstream impact

Zero — every downstream consumer (@avaprotocol/sdk-js, context-memory, studio) reads Protocols.X[chainId] generically. Bumping the catalog dep is all that's needed; no code changes in any of them.

Operator-side prereqs (tracked separately)

The infra work for actually accepting requests on BNB lives in avs-infra/Adding_A_New_Chain.md, BNB Lessons subsection. Status as of this PR:

  • ✅ Arachnid CREATE2 deployer present (0x4e59…956C)
  • ✅ ERC-4337 EntryPoint v0.6/v0.7/v0.8 all at canonical addresses
  • ✅ Moralis natively supports BNB for token enrichment
  • ⚠️ Tenderly Simulation API requires a Request (chain 56 + 97 in the Request bucket of their Node column); workflows:simulate falls back to the deterministic summary until access lands

Smart wallet factory + paymaster on BNB are deferred per the runbook's "connectivity-only" rollout (Phase 0.5).

Test plan

  • yarn typecheck — clean
  • yarn test:run — 15/15 pass
  • yarn build — emits CJS 28.5 kB + ESM 27.0 kB + dist .d.ts
  • ESM smoke (node --input-type=module -e "...") — every BNB address resolves
  • npm pack --dry-run — 45 files, valid 0.2.0 tarball
  • After merge + npm publish, bump downstreams (@avaprotocol/sdk-js, context-memory, studio) to @avaprotocol/protocols@^0.2.0 to pick up BNB

🤖 Generated with Claude Code

… / Superfluid / WBNB

Adds Chains.BnbMainnet (56) plus per-protocol addresses across the
five catalog modules whose protocols have meaningful BNB deployments.
Every address was verified live via eth_getCode against a BNB RPC
before merge.

Per-protocol additions:

  aaveV3
    pool        0x6807dc923806fE8Fd134338EABCA509979a7e0cB
    oracle      0x39bc1bfDa2130d6Bb6DBEfd366939b4c7aa7C697
    (no wethGateway — native is BNB, not ETH)

  uniswapV3
    swapRouter02              0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2
    quoterV2                  0x78D78E420Da98ad378D7799bE8f4AF69033EB077
    factory                   0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7
    nonfungiblePositionManager 0x7b8A01B39D58278b5DE7e48c8449c9f4F5170613
    universalRouter           0x4Dae2f939ACf50408e13d58534Ff8c2776d45265
    permit2                   0x000000000022D473030F116dDEE9F6B43aC78BA3 (same address everywhere)
    tokens.WETH               WBNB (0xbb4C...95c) — see naming note below
    tokens.USDC               Binance-Peg USDC (0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d)

  chainlink
    ethUsdFeed  0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e
    btcUsdFeed  0x264990fbd0A4796A3E3d8E37C4d5F87a3aCa5Ebf
    bnbUsdFeed  0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE  (new — BNB-only field for the chain's native-asset feed)

  wrapped
    weth        WBNB (0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c)

  superfluid
    cfaForwarder  0xcfA132E353cB4E398080B9700609bb008eceB125 (same address as Ethereum / Base)

Catalog-wide naming decision: `wrapped.weth[Chains.BnbMainnet]` and
`uniswapV3.tokens.WETH[Chains.BnbMainnet]` both map to WBNB, not to
Binance-Peg WETH (0x2170Ed0880ac9A755fd29B2688956BD959F933F8). The
field name stays `weth` so chain-agnostic consumers can write
`Protocols.wrapped.weth[chainId]` without per-chain branching; the
semantic is "the canonical wrapper of the chain's native gas token,"
documented in both files. Templates that need bridged WETH on BNB
specifically should pass that address inline.

Catalog protocols deliberately NOT added on BNB (not deployed there):
Aerodrome (Base-only), Compound V3 (probe failed at the address I
expected — may not deploy on BNB at all; revisit when an official
address surfaces), Ethena (sUSDe vault is L1-only), Frax Ether,
Lido, Rocket Pool, Sky, Spark, Morpho Blue.

Test changes:
  - "AAVE V3 covers the same chain set" invariant relaxed: Pool +
    Oracle must match chain sets, but WETH Gateway is now subset
    of Pool (gateway absent on BNB).
  - SwapRouter02 + Permit2 per-chain tests extended with BNB.
  - Pool-has-addresses-on-every-covered-chain test extended.
  - All 15 tests pass; no new tests needed for the additions
    themselves since the address-shape walk already covers them.

Bumps to 0.2.0 (minor — new chain is additive, never patch).

Downstream consumers (ava-sdk-js, context-memory, studio) pick up
BNB by bumping the catalog dep; no code changes required in any of
them since they all consume Protocols.X[chainId] generically.

Operator-side prereqs verified separately and tracked in
avs-infra/Adding_A_New_Chain.md's BNB Lessons subsection:
  - Arachnid CREATE2 deployer present (0x4e59...956C)
  - ERC-4337 EntryPoint v0.6/v0.7/v0.8 all canonical
  - Moralis natively supports BNB for token enrichment
  - Tenderly Simulation API requires a Request for BNB
    (chain 56 + 97 in the Request bucket of their Node column);
    workflows:simulate falls back to deterministic summary until
    Tenderly grants access. Request filing tracked separately.
@chrisli30 chrisli30 merged commit 2ef7947 into main May 30, 2026
6 checks passed
@chrisli30 chrisli30 deleted the feat/bnb-mainnet branch May 30, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant