Skip to content

Feat/cross chain usdc sushi bridge#131

Merged
0xCardiE merged 10 commits into
mainfrom
feat/cross-chain-usdc-sushi-bridge
Apr 8, 2026
Merged

Feat/cross chain usdc sushi bridge#131
0xCardiE merged 10 commits into
mainfrom
feat/cross-chain-usdc-sushi-bridge

Conversation

@0xCardiE
Copy link
Copy Markdown
Collaborator

@0xCardiE 0xCardiE commented Apr 7, 2026

Added a new preferred path for cross-chain stamp purchases. Instead of asking Relay to bridge directly to BZZ (poor liquidity), the flow now bridges the source token to native Circle USDC on Gnosis via Relay, then atomically calls the SushiSwapStampsRouter (from PR #130) on the destination side to swap that USDC to BZZ and create/top-up the stamp — all in one Relay transaction bundle.

0xCardiE added 10 commits April 7, 2026 20:22
Add SushiSwapStampsRouter contract that swaps any Gnosis token → BZZ
via SushiSwap V3 and atomically creates/tops up a Swarm stamp batch in
a single transaction. Eliminates Relay dependency for same-chain swaps.

- contracts/SushiSwapStampsRouter.sol: new router with single-hop,
  multi-hop (callback chaining), native xDAI support, and quote
  functions callable via eth_call
- deploy/02_deploy_sushi_stamps_router.ts: deploy + auto-verify script
  (GnosisScan + Sourcify v2)
- scripts/verify_router.ts, verify_registry.ts: standalone post-deploy
  verification scripts for both contracts
- SushiQuotes.ts: frontend module for route discovery, quoting, and
  execution via the new router
- constants.ts: add SUSHI_STAMPS_ROUTER_ADDRESS, SUSHI_FACTORY_ABI,
  SUSHI_STAMPS_ROUTER_ABI, GNOSIS_USDC_ADDRESS
- SwapComponent.tsx: add Branch 2 (Gnosis + non-BZZ → SushiSwap);
  cross-chain traffic stays on Relay unchanged
- hardhat.config.ts: enable viaIR and Sourcify v2 verification
The BZZ/USDC pool fee was hardcoded as 10000 (1%) which caused
quoteSingleHop to revert because the Quoter looks up the pool via
factory.getPool(tokenIn, BZZ, fee) — wrong fee = pool not found.

- Read pool.fee() directly from the known pool address at runtime
- Keep the pool address constant (BZZ_USDC_POOL_ADDRESS) but never
  assume the fee tier
- Fall back to factory scan if the known address doesn't respond
- Reorder FEE_TIERS to try 3000/500 before 10000 (more common tiers first)
- Fix fee display: divide by 10000 not 100 (10000 bps = 1%, not 100%)
Two bugs in findSushiRoute broke non-BZZ Gnosis token routing:

1. ReferenceError: KNOWN_BZZ_POOLS reference was missed when renaming
   to bzzPoolCache in the previous commit — crashed immediately for
   any two-hop route (e.g. GBPe).

2. Case 3 (tokenIn → WXDAI → BZZ) used findWxdaiUsdcPool() for the
   tokenIn→WXDAI leg, which looked up a WXDAI/USDC pool instead of
   a tokenIn/WXDAI pool — completely wrong fee and path for any token
   that isn't USDC.

- Replace findWxdaiUsdcPool() with generic findPoolBetween(tokenA, tokenB)
  that scans all fee tiers for any pair, with pair-keyed caching
- Case 2: use findPoolBetween(tokenIn, USDC) + findDirectBzzPool(USDC)
  in parallel — both legs discovered correctly
- Case 3: use findPoolBetween(tokenIn, WXDAI) + findDirectBzzPool(WXDAI)
  in parallel — both legs discovered correctly
- Tokens like GBPe that route through WXDAI or USDC now work properly
The project tsconfig.json uses moduleResolution: bundler (Next.js),
which ts-node can't handle, causing all `hardhat run scripts/*.ts`
commands to fail with ERR_UNKNOWN_FILE_EXTENSION on Node 22.

- Add tsconfig.hardhat.json with module: CommonJS / moduleResolution: node
  scoped to deploy/ and scripts/ only, leaving the Next.js tsconfig untouched
- Set ts-node.project in package.json to point at the new tsconfig
- Add npm scripts (verify:router, verify:registry, deploy:router) that
  set TS_NODE_PROJECT=tsconfig.hardhat.json automatically so plain
  `npm run verify:router` just works
- Update script usage comments to show both the npm shortcut and the
  direct command with the required env var
- Filter Gnosis "from" tokens with findSushiRoute after LiFi balances; clear
  selection when nothing spendable remains.
- Require V3 pool liquidity() > 0 in discovery so empty pools (e.g. COW/USDC)
  are not treated as routable; Quoter no longer reverts on those paths.
- Add findSushiRoutes and try each candidate in getSushiQuote until a quote
  succeeds.
- Export gnosisFromTokenCanReachBzz (BZZ direct or Sushi path to BZZ).
Relay has reliable routes to USDC on every major chain but poor BZZ
routes.  The existing SushiSwapStampsRouter already handles any
Gnosis token→BZZ→stamp atomically.

New flow for cross-chain users:
  1. Relay bridges source token → USDC on Gnosis (EXACT_OUTPUT)
  2. Relay's Multicaller executes two destination txs atomically:
       a. USDC.approve(sushiRouter, maxUsdcIn)
       b. sushiRouter.createBatch / topUp(path, maxUsdcIn, bzzOut, ...)
  3. SushiRouter swaps USDC → BZZ via SushiSwap V3 and calls registry

No new contract needed — the deployed SushiSwapStampsRouter already
supports any ERC-20 payer (Relay's Multicaller in this case).

Changes:
- constants.ts: add RELAY_BRIDGE_TOKEN_ON_GNOSIS (default USDC),
  RELAY_BRIDGE_TOKEN_DECIMALS and RELAY_BRIDGE_TOKEN_SYMBOL —
  all overridable via env vars for future flexibility.
- RelayQuotes.ts: add getRelayCrossChainWithSushiQuote() that
  chains a Sushi quote (USDC→BZZ) with a Relay EXACT_OUTPUT quote
  (source→USDC) and builds the two-tx calldata bundle for Relay.
- SwapComponent.tsx: price estimation and handleSwap Branch 3 now
  use the new USDC+Sushi path when the router is deployed; legacy
  Relay→BZZ path kept as fallback when router address is empty.
… bridging

RELAY_BRIDGE_TOKEN_ON_GNOSIS was pointing at the old Ethereum-bridged USDC
(0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83) which Relay cannot route to.
Relay only has solver liquidity for the native Circle USDC on Gnosis
(0x2a22f9c3b484c3629090feed35f17ff8f88f76f0).

The SushiSwapStampsRouter still works because there is a Sushi V3 fee-100
pool between the two USDC tokens (liq ~2.4T) and the existing findSushiRoute
logic already checks token → GNOSIS_USDC_ADDRESS (bridged) → BZZ, producing
the two-hop path: native USDC → bridged USDC → BZZ.

Verified manually: Relay accepts the small failing amount ($1.85) with the
correct address from Base, Ethereum, Arbitrum, Optimism, and Polygon.
@0xCardiE 0xCardiE merged commit 99f521a into main Apr 8, 2026
1 check passed
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