Skip to content

feat: upgrade to 4.2.0-aztecnr-rc.2 + testnet deployment + smart swap routing#11

Open
alejoamiras wants to merge 25 commits into
holonym-foundation:mainfrom
alejoamiras:feat/testnet-4.1.0
Open

feat: upgrade to 4.2.0-aztecnr-rc.2 + testnet deployment + smart swap routing#11
alejoamiras wants to merge 25 commits into
holonym-foundation:mainfrom
alejoamiras:feat/testnet-4.1.0

Conversation

@alejoamiras

Copy link
Copy Markdown
Contributor

Summary

Upgrade from 4.0.0-devnet.24.2.0-aztecnr-rc.2 targeting Aztec testnet (rpc.testnet.aztec-labs.com). Includes everything from PR #10 (wallet-sdk, Uniswap V4 fuel swap, Permit2) plus the full version upgrade, testnet deployment, and smart swap routing.

What's new since PR #10

Aztec 4.2.0-aztecnr-rc.2 Upgrade

  • All @aztec/* packages upgraded from 4.0.0-devnet.24.2.0-aztecnr-rc.2
  • Wonderland standards (prerelease-1ad0e28) and fee-payment (prerelease-07982ed) updated
  • Noir contracts compiled with v4.2.0-aztecnr-rc.2 aztec-nr
  • Transaction API migration: .send(){ receipt }, .simulate(){ result }, deploy → { contract }
  • computeL2ToL1MembershipWitness updated to new (node, msgLeaf, txHash) signature
  • getL1ToL2MessageBlockgetL1ToL2MessageCheckpoint
  • Account deployment uses NO_FROM pattern (workaround for PXE entrypoint simulation issue)

Smart Swap Routing

  • buildCandidateRoutes() generates multiple candidate routes per token
  • getBestRoute() quotes all candidates in parallel via V4 Quoter, picks highest output
  • Supports both direct (1-hop) and via-WETH (2-hop) routes
  • Non-existent pools gracefully fail and are skipped
  • Direct USDC/FeeJuice pool on testnet for cheaper fuel swaps

Deployment Pipeline Integration

  • Renamed devnettestnet (scripts, configs, file names)
  • UniswapFuelSwap + SwapBridgeRouter deployment integrated into main deploy script
  • Trusted forwarder auto-set on all portals after token deployment
  • BridgedFPC address auto-computed and saved to deployment JSON
  • Single command: AZTEC_ENV=testnet pnpm run deploy-testnet:compliant
  • Pool seeding remains a separate forge script step (requires Solidity callback)

Cleanup

  • Removed BridgeAndFuel/MockFuelSwap (replaced by SwapBridgeRouter)
  • Removed old devnet deployment files and config
  • Removed stale deployments from version selector
  • registerBridgedContract updated for new salt parameter
  • Allowance check uses publicClient instead of WAAP eth_call

Tested on testnet ✅

Flow Status Notes
Public bridge (L1→L2) ✅ Working Via SwapBridgeRouter with Permit2
L1→L2 + public fuel swap ✅ Working Smart routing picks best path
L1→L2 + private fuel (BridgedFPC) ✅ Working skipFeeEnforcement required for PXE sync lag
L2→L1 withdrawal Ready Both public and private paths
Wallet-SDK connection ✅ Working Discovery + emoji verification
Multi-token support ✅ Working 7 tokens deployed (USDC, USDT, DAI, HUMN, GOAT, WBTC, WETH)
Smart swap routing ✅ Working Direct USDC/FJ pool wins over multi-hop

Known Issues

  • SponsoredFPC PXE bug: The wallet's PXE can't simulate FeeJuice.claim during fee payment setup because its L1→L2 message tree lags behind the sequencer. Workaround: skipFeeEnforcement: true on claim transactions.
  • BridgedFPC no-refund: The FPC deducts ~32 FJ max gas cost upfront but actual fee is ~3.76 FJ. No refund mechanism — Wonderland design tradeoff.
  • L2 SBT minting: Still a stub (useL2MintSoulboundToken does nothing). L1 SBT works.
  • Pool seeding: Not integrated into the TS deploy script (requires Solidity unlockCallback). Run SeedUniswapPools.s.sol separately.

Deployment

# 1. Deploy everything (tokens + fuel infra + forwarders)
AZTEC_ENV=testnet pnpm run deploy-testnet:compliant

# 2. Seed Uniswap V4 pools (separate step)
cd l1-contracts
source .env
# ETH/AZTEC + USDC/WETH + USDC/AZTEC direct
ERC20_TOKEN=<usdc-address> SEED_DIRECT_POOL=true \
  forge script script/SeedUniswapPools.s.sol --rpc-url $RPC_URL --broadcast

# 3. Start frontend
cd frontend && pnpm dev

Also vibe coded 🤖

Built with Claude across a marathon session. The contracts, routing logic, and deployment pipeline should get a proper review — the logic is solid from testing but fresh eyes always help.

🤖 Generated with Claude Code

alejoamiras and others added 25 commits March 17, 2026 17:33
- Add trusted forwarder pattern to TokenPortal for delegated deposits
- SwapBridgeRouter: witness-bound Permit2 bridge with optional fuel swap
- UniswapFuelSwap: Uniswap V4 integration for automatic L2 gas funding
- Deploy scripts and comprehensive test suites for all contracts
- Remove deprecated BridgeAndFuel and MockFuelSwap contracts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mit2

Frontend integration for the full bridge upgrade:
- Migrate from @azguardwallet/client to @aztec/wallet-sdk
- BridgedFPC private fuel payment with automatic fee juice claims
- FuelToggle component with real-time Uniswap V4 price quotes
- Witness-bound Permit2 flow for secure bridge parameter binding
- Withdrawal auth witness for private L2-to-L1 exits
- CoinGecko + V4 Quoter dual pricing for fuel estimates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update bridge-script for SwapBridgeRouter and UniswapFuelSwap
- Add redeploy-permit2 utility script
- Update deployment registry and README with new contract details

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Deploy all 7 tokens with custom TokenPortal (compliant script)
- Deploy SwapBridgeRouter at 0x9E21891e2a3a7A366C1bbAB18a2B88Fd72C5D6D7
- Set trusted forwarder on all portals
- Add BridgedFPC deterministic address (salt=0)
- Add saveFuelInfraToDeployment to save_contracts utility
- Fix duplicate fee juice display in BridgeSection
- Generate L2 codegen artifacts for compliant bridge

Public L1→L2 bridge tested and working.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standalone Forge script to seed ETH/FeeJuice and ERC20/WETH pools
without redeploying UniswapFuelSwap. Supports configurable amounts,
skip flags, and transfers deployer's existing FJ balance to the seeder.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…uel claim

- Replace hardcoded "USDC" with selected token symbol on progress page
- Show fuel amount in USD (from CoinGecko prices) instead of token units
- Smart decimal formatting: shows meaningful digits for small amounts (0.003 WETH not 0.00)
- Private fuel (BridgedFPC) now correctly triggers claim_private on L2
  and isPrivate on L1 deposit — the whole chain is private when private fuel is selected

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ate deposit)

Private fuel (BridgedFPC) flow:
- L1: depositToAztecPublic for both token and FeeJuice (no attestation needed)
- L2: claim_public for token + BridgedMintAndPayFeePaymentMethod handles
  FeeJuice.claim (private) + mint_and_pay_fee (private) as fee setup calls

Reverts the isPrivate || !!privateFuel change — private deposit requires
attestation signatures which aren't available for the fuel-only flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Upgrade all @aztec/* packages from 4.0.0-devnet to 4.2.0-aztecnr-rc.2.
Deploy all 7 tokens (USDC, USDT, DAI, HUMN, GOAT, WBTC, WETH) on Aztec testnet
with L1 portals, SwapBridgeRouter, UniswapFuelSwap, and V4 pool liquidity.

Key changes:
- TX API migration: .send() returns { receipt }, .simulate() returns { result },
  deploy returns { contract }, .send().wait()/.deployed() removed
- computeL2ToL1MembershipWitness now takes (node, msgLeaf, txHash)
- getL1ToL2MessageBlock replaced with getL1ToL2MessageCheckpoint
- Switch to Wonderland token standards (prerelease-1ad0e28)
- Switch to Wonderland fee-payment (prerelease-07982ed)
- Noir contracts compiled with v4.2.0-aztecnr-rc.2 aztec-nr
- Account deployment uses NO_FROM pattern (workaround for PXE entrypoint bug)
- BridgeAndFuel/MockFuelSwap removed (replaced by SwapBridgeRouter)
- registerBridgedContract updated for new salt parameter
- Allowance check uses publicClient instead of WAAP eth_call
- Forge scripts updated with testnet portal addresses
- BridgedFPC address computed and added to deployment
- Aztecscan URL updated to testnet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cript

- Rename index-devnet-compliant.ts → index-testnet-compliant.ts
- Rename index-devnet.ts → index-testnet.ts
- Update all package.json scripts (start-devnet → start-testnet, etc.)
- Remove old devnet config and deployment files
- Clean registry to only keep active testnet deployment
- Integrate UniswapFuelSwap + SwapBridgeRouter deployment into main script
- Auto-set trusted forwarder on all portals after token deployment
- Auto-compute and save BridgedFPC address (salt=0)
- Add saveFuelInfraToDeployment() to save_contracts.ts
- Extend DeploymentFile type with fuel infra fields

Deployment is now: AZTEC_ENV=testnet pnpm run deploy-testnet:compliant
Pool seeding remains a separate forge script step (requires Solidity callback).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Catch "Existing nullifier" error during account deploy and skip gracefully
- Verified full pipeline: account skip → token skip → fuel infra deploy →
  trusted forwarder → BridgedFPC compute → save → sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Public bridging with public fuel swap verified working.
Private fuel (BridgedFPC) has "Amount too low to cover gas cost" error — needs investigation.
Forwarder set on all 7 portals with new SwapBridgeRouter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two issues identified:
1. Gas cost too high: fuel swap yields ~20 FJ but estimated max gas cost is ~49 FJ
2. FeeJuice L1→L2 message hash mismatch during claim — secret hash derivation issue

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The wallet's PXE simulates FeeJuice.claim locally during the fee payment
setup phase, but its L1→L2 message tree may lag behind the sequencer's.
This caused "No L1 to L2 message found" errors even though the message
was confirmed in the tree via polling.

Adding skipFeeEnforcement to send options when a fee payment method is
present lets the claim TX through to the sequencer, which has the latest
state and can validate the message correctly.

Verified: private fuel bridge works end-to-end on testnet.
Actual tx fee ~3.76 FJ, BridgedFPC deducts ~32 FJ (no refund by design).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Narrow tick ranges caused liquidity to become inactive after large swaps,
requiring constant reseeding. Switched to full range (-887220 to 887220,
tick spacing 60) for both ETH/AZTEC and USDC/WETH pools — UniV2-style.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Confirmed: without skipFeeEnforcement, the wallet's PXE always fails with
"No L1 to L2 message found" during FeeJuice.claim simulation. This is a
wallet PXE sync lag issue — the sequencer has the message, the PXE doesn't.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded multi-hop USDC→WETH→FeeJuice route with smart routing
that generates candidate routes and quotes them in parallel:
- Route A (direct): inputToken → FeeJuice (1 hop)
- Route B (via WETH): inputToken → WETH → FeeJuice (2 hops)

Picks the route with the best FeeJuice output. Non-existent pools
(e.g. no direct pool on mainnet) gracefully fail and are skipped.

Also:
- Add USDC/FeeJuice direct pool to SeedUniswapPools.s.sol
- Add SKIP_ERC20_WETH and SEED_DIRECT_POOL env flags
- Full range ticks for direct pool (-887220 to 887220)
- Direct pool seeded with 50k USDC + 200k FJ on testnet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Show FuelToggle in privacy mode (contracts already support isPrivate + fuel)
- Add NEXT_PUBLIC_DEV_ATTESTATION env var to bypass Holonym/Gitcoin APIs
- Mock checkCleanHands() and fetchPassportScore() in dev mode
- Attestation signing still uses real .env keys (match deployed portals)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- @defi-wonderland/aztec-fee-payment (tarball) → @wonderland/aztec-fee-payment@4.2.0-aztecnr-rc.2 (npm)
- @defi-wonderland/aztec-standards (tarball) → @defi-wonderland/aztec-standards@4.2.0-aztecnr-rc.2 (npm)
- Update renamed exports: BridgedFPC → PrivateFPC, registerBridgedContract → registerPrivateContract,
  BridgedMintAndPayFeePaymentMethod → PrivateMintAndPayFeePaymentMethod

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
.env.local was not gitignored and at risk of being committed.
Merged all env vars into .env (which is already gitignored) and
added .env.local + .env*.local to .gitignore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align naming with official @wonderland/aztec-fee-payment release:
- BRIDGED_FPC_ADDRESS → PRIVATE_FPC_ADDRESS
- bridgedFpcAddress → privateFpcAddress
- bridged_fpc → private_fpc
- hasBridgedFpc → hasPrivateFpc
- All comments updated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Private claims (claim_private) go through TokenBridge → TokenMinterProxy.
The wallet's PXE needs the proxy artifact registered to simulate the call
chain locally. Without it: "Unknown contract" error on claim_private.

Added 'proxy' type to contract registration in initializeContracts().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TokenMinterProxy methods (mint_to_public, mint_to_private, burn_public,
burn_private) were missing from the transaction scope, causing the wallet
to prompt for approval on each nested call during bridge operations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts c218e28: the FuelToggle visibility in privacy mode and dev
attestation mocks need proper testing before merging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The official @wonderland/aztec-fee-payment has a different artifact than
the prerelease, producing a different deterministic address (salt=0):
- Old (prerelease): 0x0c13e6d3...
- New (official):   0x1d6d7973...

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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