Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
# Optional. The app uses https://rpc.testnet.miden.io by default.
# VITE_MIDEN_RPC_URL=https://rpc.testnet.miden.io

# Random bridge runner. Copy this file to .env and fill in your wallet values.
# RUNS is the number of attempts; INTERVAL_SECONDS is the delay between them.
RUNS=3
INTERVAL_SECONDS=5
EPOCH_API_URL=https://testnet-dev.epochprotocol.xyz

# EVM wallet and testnet token settings
EVM_PRIVATE_KEY=0x
EVM_RPC_URL=https://ethereum-sepolia-rpc.publicnode.com
EVM_CHAIN_ID=11155111
EVM_TOKEN_ADDRESS=0x2BB4FfD7E2c6D432b697554Efd77fA13bdbefd69
EVM_TOKEN_DECIMALS=18
# Optional: defaults to the address derived from EVM_PRIVATE_KEY.
EVM_RECIPIENT_ADDRESS=

# Miden account and token settings
# Hex account ID or full mtst... wallet address.
MIDEN_ACCOUNT_ID=
# Hex encoding of AuthSecretKey.serialize() for this account's auth key.
MIDEN_AUTH_SECRET_KEY=0x
MIDEN_FAUCET_ID=0x5b043dcb48d5721106f7a1ceb2b804
MIDEN_TOKEN_DECIMALS=6
# Optional endpoint overrides; leave unset for Miden testnet defaults.
# MIDEN_RPC_URL=https://rpc.testnet.miden.io
# MIDEN_FEE_FAUCET_ID=0x4cbdcaffe75f0a317482224dae6436
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Reference dapp showing how to use [`@epoch-protocol/epoch-intents-sdk`](https://
Two flows:

- **Cross-chain** — Miden → EVM. Lock a Miden note, receive tokens on the selected EVM testnet chain.
- **Withdraw** — EVM → Miden. Pay ERC-20 on a connected EVM testnet chain, receive a Miden note.
- **Withdraw** — EVM → Miden. Pay native ETH or an ERC-20 on a connected EVM testnet chain, receive a Miden note.

## Supported testnet chains

Expand All @@ -18,6 +18,19 @@ Two flows:

Testnet tokens (USDC, DAI, USDT, etc.) share the same contract addresses across all EVM testnet chains. See [Supported Chains & Tokens](../docs/docs-new/supported-chains-and-tokens.md).

Native ETH is available as **ETH · Native** in both EVM token selectors,
separately from WETH. ETH uses 18 decimals and the zero address
(`0x0000000000000000000000000000000000000000`). EVM → Miden uses the SDK's
native Compact deposit, with no ERC-20 approval. Miden → ETH uses Miden note
collateral and delivers native ETH to the EVM recipient. Quotes still depend
on solver liquidity for the selected pair.

When running the local stack, use the matching `smallocator`, `dex-solver`,
and `epoch-inventory-ts` changes. Native quotes use the Pragma ETH/USD feed
with the same freshness checks as Miden asset prices. Miden → ETH requires
native ETH in the inventory treasury on the selected EVM testnet; ERC-20
balances cannot fund a native payout.

## Stack

- React 19 + Vite + TypeScript + Tailwind v4
Expand Down Expand Up @@ -63,3 +76,41 @@ Testnet tokens (USDC, DAI, USDT, etc.) share the same contract addresses across
- `MIDEN_DESTINATION_CHAIN_ID = 999999999` is the virtual chain id used as `tokenOut.chainId` when Miden is the intent output. Do not set this to a real EVM chain id.
- The app uses Miden testnet and the Epoch testnet allocator by default. Set `VITE_MIDEN_RPC_URL` only to override the Miden RPC URL.
- Build: `pnpm build` (`tsc -b && vite build`). Lint: `pnpm lint`.
- Regression tests: `pnpm test`.

## Random bridge runner

The CLI runs a finite number of bridge attempts, immediately starts the first
one, then waits `INTERVAL_SECONDS` between attempts (5 seconds by default). Each
run picks Miden → EVM or EVM → Miden at random and requests a random whole-token
output from 1 to 10.
Both directions use the example's reverse-quote helpers: the allocator quotes
the required source amount before the runner signs or submits anything.
Both wallet keys are loaded from `.env`.

1. Copy `.env.example` to `.env` and set `RUNS`, `INTERVAL_SECONDS`, the EVM
wallet/network/token fields, and the Miden account/faucet fields. `.env` is
git-ignored.
2. Set `MIDEN_AUTH_SECRET_KEY` to the hex encoding of the Miden account's
serialized `AuthSecretKey` (`AuthSecretKey.serialize()`). The key must match
the auth component on `MIDEN_ACCOUNT_ID`.
3. Install dependencies with `pnpm install` (Node.js 22 or newer).
4. Run `pnpm bridge:check` to check the keys, account import, balances,
token decimals, allocator health, and quotes for both directions. This
command does not submit transactions.
5. Run `pnpm bridge:random` to start the configured number of attempts.

Miden token amounts use `MIDEN_TOKEN_DECIMALS`; EVM token amounts use
`EVM_TOKEN_DECIMALS`. Defaults are 6 and 18 for the example testnet tokens.
For native ETH, set `EVM_TOKEN_ADDRESS` to the zero address and
`EVM_TOKEN_DECIMALS=18`. The connection check reads the native ETH balance;
that balance also pays EVM gas.
`EVM_RECIPIENT_ADDRESS` defaults to the EVM signer; `MIDEN_ACCOUNT_ID` accepts
a hex account ID or the full wallet address, including its routing suffix.
The Miden account needs enough balance for every randomly chosen amount and
Miden transaction fees. Failed attempts are logged, counted, and the runner
continues until it reaches `RUNS`.

If both directions return `NO_QUOTE_AVAILABLE`, check the allocator's SIO and
bridge solver connections. A healthy allocator alone does not establish that
its bridge solver is reachable or has a quote for the requested token pair.
68 changes: 68 additions & 0 deletions bridge-random-run-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Random bridge run report

**Date:** 2026-10-27 (Asia/Calcutta)
**Command:** `pnpm bridge:random`
**Configured runs:** 1
**Result:** Completed successfully (`Finished 1 run(s); 0 failed.`)

## Run summary

- Random direction: **EVM → Miden**
- Random target amount: **8 Miden USDC** (6 decimals)
- Quoted EVM input: **8.004002001000500251 USDC** (18 decimals)
- The quote came from the configured ngrok bridge solver.
- Smallocator registered the compact, checked the deposit requirement, and returned the required claim calldata.
- SIO submitted the Miden transaction and then executed the EVM compact claim.

## Transactions

| Stage | Network | Transaction | Result |
| ----------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| Compact deposit | Sepolia | [`0x9f42bb4fae0fbb3db2dd0e240b7684fa3a5aa2b8994d8662b8051e5659c46a99`](https://sepolia.etherscan.io/tx/0x9f42bb4fae0fbb3db2dd0e240b7684fa3a5aa2b8994d8662b8051e5659c46a99) | Success, block 12005239 |
| Miden payout | Miden testnet | `0x41f09364fcf70fefa326ba298f1ec08ffd6e505f2c1c29a3a3603d641fd61cf5` | Submitted at height 601460; one output note |
| EVM compact claim | Sepolia | [`0xe6ac41ab116287c239d42373e1de08085aa15694cda2e0789badca754f0e5f53`](https://sepolia.etherscan.io/tx/0xe6ac41ab116287c239d42373e1de08085aa15694cda2e0789badca754f0e5f53) | Success, block 12005244 |

Smallocator confirmed the Miden payout note and logged `delivered: 8000000` (8 USDC at 6 decimals). SIO logged `CLAIM_SUCCESS` and removed the claim transaction from its queue.

## Service logs and observations

- **epoch-sio:** Accepted the quote-only check, selected the bridge quote, submitted the proven Miden transaction, queued the EVM claim, and logged `CLAIM_SUCCESS` after the Sepolia transaction succeeded.
- **smallocator:** `/suggested-nonce` and `/compact` returned HTTP 200. The first claim-calldata attempts reported `MIDEN_NOTE_NOT_YET_VISIBLE` as retryable; a later retry validated the note and completed successfully.
- The local fallback solver at `http://localhost:3010` returned `ECONNREFUSED`. The configured ngrok solver still responded and supplied the winning quote, so the run proceeded.
- SIO logged an Etherscan fee-data parsing error, then fetched fee data through its Infura fallback and sent the EVM claim successfully.
- SIO also logged older pending-claim monitor failures during startup; these were for unrelated earlier claim hashes, not this run.

## Identifiers

- Intent hash: `0x558cf8e6395cd09b812cfd06654320f8ddc301e4c4535ee89f44425f9aea622c`
- Miden payout note: `0x3b4e6a877ad7930233d275225c712dfcbbf8a37e1025387502e1af95862d1519`

## Follow-up run: 100-attempt configuration

**Date:** 2026-10-27 (Asia/Calcutta)
**Configuration:** `RUNS=100`, `INTERVAL_SECONDS=10`
**Outcome:** Stopped after 6 failed attempts; all six failed before transaction submission with `NO_QUOTE_AVAILABLE`.

SIO logs showed the local fallback solver at `http://localhost:3010` refusing connections and no valid quote from the configured ngrok solver. Smallocator's deposit checks failed when SIO could not return a quote. No transactions were submitted by these six attempts. The runner was stopped instead of repeating the same unavailable-quote requests for the remaining attempts. A later read-only `pnpm bridge:check` confirmed quotes for both directions, so the solver recovered. The local `.env` remains configured for 100 attempts with a 10-second delay.

## Restarted batch and stop

After both read-only quotes succeeded, the 100-attempt run was restarted. It was stopped at the user's request while attempt 18 was starting. The runner had logged intermittent Sepolia `eth_sendRawTransactionSync` timeouts and one `Nonce has already been used` error.

The Sepolia RPC timeouts did not mean the deposit transactions were absent: checking the chain showed **11 successful compact-deposit transactions**, all with successful receipts and no pending transaction from the EVM wallet at the time of the check. The runner could not reliably distinguish those confirmed transactions from RPC failures, so its failed-attempt count is not a reliable count of on-chain deposits. These receipts confirm the EVM deposits only; they do not by themselves confirm final cross-chain delivery.

| Sepolia compact-deposit transaction | Block | Receipt |
| -------------------------------------------------------------------- | -------: | ------- |
| `0xcccd01842d8b1cc17bd9ce1b204c1a57c271da41de5aa8073746b6dd3305cada` | 12005310 | Success |
| `0xbcef765c7fee15a61caec3a2a5bfa5d10cddfb7b103bc2edba31970551876805` | 12005322 | Success |
| `0x2de2b0ddaa5595299bfc6355480ecd96e19bcb656b810c51d7ba7eed9e0598e9` | 12005331 | Success |
| `0x654a9db5b8bdc60078a45df073c5067ab1e0aaf2da5337a6c930189f5514bcd4` | 12005337 | Success |
| `0x13fd0a9ff79250e5653dd9bd4bcb59677d8b10722ca13a3f297459d30ea648d1` | 12005339 | Success |
| `0xebd3c9377dbb0f6b4c490ffcbf5c38ed962acec6fe675bd7883544ad3a4663e3` | 12005341 | Success |
| `0x9dc7ac76fd7b15711eca28a8b16b457b911a45281119f44939269cf0bf74ba2a` | 12005347 | Success |
| `0x8ba21a8e942b4f124dec20c5ad5bac4e483b56e2bc95f0da7a23024248a40f6a` | 12005352 | Success |
| `0x605b94b5c7c66654ee5cf5d73f6bf02fa57c1b847014d2224078b4332ea340e1` | 12005357 | Success |
| `0x3c63a7d35313dcb8b70884f95fc25ab8a24e698a034313982ccba2f0b8f41c7d` | 12005360 | Success |
| `0xebcac2104854fd58cbfbb851dabf8436ffec88232ab417c4748ec2740c16681a` | 12005361 | Success |

The nonce error followed creation of a Miden collateral note (`0xe97a70534f538fde6d378e6062e1f3eb8be258c3a7a288cb992d69054af548d2`, reclaim height 607967). Its intent submission was rejected as already used; this note's later status was not checked.
110 changes: 110 additions & 0 deletions docs/superpowers/plans/2026-10-25-evm-mainnet-chains.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# EVM Mainnet Chains Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add Base, Arbitrum, Polygon, and Robinhood mainnet flows while retaining the existing EVM and Miden testnet setup.

**Architecture:** Keep a selected Mainnet/Testnet environment in the Miden network context. Derive EVM chain and token choices from the matching Epoch commons graph, configure wagmi for the union of supported EVM networks, and use the selected environment for the Miden provider and Epoch allocator.

**Tech Stack:** React 19, TypeScript, wagmi, RainbowKit, viem, Epoch commons and intent SDKs.

**Spec:** `docs/superpowers/specs/2026-10-25-evm-mainnet-chains-design.md`

## Global Constraints

- Mainnet EVM choices: Base (8453), Arbitrum One (42161), Polygon (137), Robinhood Chain (4663).
- Preserve testnet choices: Ethereum Sepolia (11155111), Base Sepolia (84532), Optimism Sepolia (11155420).
- Keep the existing testnet environment as the initial selection.
- Read chain and token IDs, addresses, and decimals from the corresponding Epoch commons graph.
- Robinhood selection does not imply that the Epoch allocator will quote every route.
- Preserve unrelated working-tree edits.
- Do not add or run tests unless the user asks for testing or verification.

## Review Focus

- Switching environment while a wallet is connected can leave the wallet on a chain from the other environment; the flow must require/select a chain from the active environment.
- Changing the destination chain must not retain a token address from the previous chain.
- Robinhood token choices must only include tokens with graph addresses for Robinhood.
- Switching the Miden network must update RPC, wallet adapter, allocator, faucet, and explorer together.
- Existing testnet defaults and token choices must remain intact.

---

### Task 1: Environment-aware network context and providers

**Files:**

- Modify: `src/hooks/useMidenNetwork.ts`
- Modify: `src/components/providers/MidenNetworkApp.tsx`
- Modify: `src/App.tsx` or `src/components/layout/Header.tsx` (place the network selector beside existing wallet controls)
- Modify: `src/config/miden.ts`
- Modify: `src/lib/epoch-sdk.ts`
- Modify: `src/lib/explorers.ts`
- Modify: `src/hooks/useIntentSettlementView.ts`
- Modify: `src/components/crosschain/IntentForm.tsx`
- Modify: `src/components/crosschain/IntentStatus.tsx`

**Interfaces:**

- Context exposes the active `MidenNetwork` and a setter.
- `MidenNetworkApp` uses the active environment to choose Miden RPC, wallet adapter network, allocator endpoint, and explorer config.
- App starts on the existing testnet environment.

- [x] Add state and setter to the Miden network context; start from `DEFAULT_MIDEN_NETWORK` (`testnet`).
- [x] Render a Mainnet/Testnet selector and verify its selected state changes context state.
- [x] Configure `MidenProvider` and `useEpochSdk` from the active context, using mainnet and testnet RPC/allocator URLs separately; key the signer provider by environment so a switch resets stale network state.
- [x] For mainnet, pass the wire value `"mainnet" as WalletAdapterNetwork`; the installed 0.17.5 enum only declares Devnet, Testnet, and Localnet, while the existing baseline used this cast for Miden Wallet mainnet.
- [x] Pass the active environment to Miden explorer URL helpers and update their consumers.
- [x] Run `pnpm build` and confirm the provider/context types compile.

### Task 2: Chain and token registries for both environments

**Files:**

- Modify: `src/config/deployment.ts`
- Modify: `src/constants/chains.ts`
- Modify: `src/config/wagmi.ts`
- Modify: `src/constants/evm-tokens.ts`
- Modify: `src/lib/explorers.ts`

**Interfaces:**

- Export `getEvmChains(network: MidenNetwork): readonly EpochEvmChain[]`.
- Export `getEvmTokensForChain(chainId: number, network: MidenNetwork): EvmToken[]`.
- Wagmi supports the union of the seven requested mainnet and existing testnet chains; form choices remain scoped to the active environment.

- [x] Derive mainnet chain metadata and per-chain tokens from `mainnetGraph`; derive existing testnet metadata and tokens from `testnetGraph`.
- [x] Use viem's `robinhood` chain definition (ID 4663); add its RPC transport and block explorer mapping.
- [x] Keep current testnet mock-token values and chain choices associated with testnet.
- [x] Verify `getEvmTokensForChain` only returns tokens with a graph address for the requested chain.
- [x] Run `pnpm build` and confirm chain definitions and registry types compile.

### Task 3: Scope flow choices to the active environment and chain

**Files:**

- Modify: `src/components/crosschain/IntentForm.tsx`
- Modify: `src/components/crosschain/intent/IntentDestinationFields.tsx`
- Modify: `src/components/crosschain/WithdrawForm.tsx`
- Modify: `src/components/crosschain/withdraw/WithdrawTokenFields.tsx`
- Modify: `README.md`

**Interfaces:**

- Destination options receive the active environment's chains and the selected destination chain's token list.
- Withdraw token options receive the connected EVM chain and active environment.
- Flow defaults select an available token for the current chain and refresh that selection when the chain changes.

- [x] Use `getEvmChains` to constrain Miden→EVM destination choices to the active environment.
- [x] Use `getEvmTokensForChain` for destination and EVM→Miden source tokens; update stale token selections when chain/environment changes.
- [x] Keep custom source-token entry available for EVM→Miden.
- [x] Update README's supported-chain table and explain the environment selector plus Robinhood allocator limitation.
- [x] Run `pnpm build` and inspect the UI choices for the four mainnets and retained testnets.

## Self-review

- Spec coverage: environment pairing is Task 1; supported chains, token addresses, and Robinhood metadata are Task 2; flow behavior and user-facing explanation are Task 3.
- No test commands are included, per the explicit constraint above; build and UI inspection are the planned checks.
- Implementation order is required because Tasks 2 and 3 consume the environment context and chain/token helpers defined earlier.
- Review follow-up: withdraw quotes are cleared when the EVM chain or Miden environment changes, and in-flight responses are discarded if their captured network/chain context is stale.
- Verification: `pnpm typecheck` and `pnpm build` pass. Browser inspection showed Base, Arbitrum One, Polygon, and Robinhood Chain on mainnet; Sepolia, Base Sepolia, and Optimism Sepolia remain on testnet. Robinhood token selection displayed graph-backed WETH.
Loading
Loading