Skip to content

Repository files navigation

Project Independence

A trustless smart-contract explorer — a desktop app that lets you inspect and interact with Ethereum contracts without trusting any external service. Data may be downloaded, but every security-relevant fact is verified locally:

  • Chain state is read through an embedded Helios light client — every value (code, storage, balances, call results) is Merkle-proof-verified against an Ethereum consensus checkpoint. No trusted RPC.
  • Source verification happens on your machine: sources are downloaded from Sourcify, recompiled in-process with web-solc, and compared byte-for-byte against the Helios-verified on-chain bytecode using lib-sourcify. Sourcify's claim of verification is never trusted — we reproduce it.
  • Transactions are signed on a hardware wallet (Ledger). Because WebHID/WebUSB don't exist in a system WebView, signing is done in the Rust backend.
  • Transactions are previewed in human-readable form before signing, using the ERC-7730 "clear signing" standard via @ethereum-sourcify/clear-signing.
  • Transactions are simulated locally before signing — a dry-run (eth_call) for the return value / revert reason, plus a full effects preview (emitted events and balance / named storage changes) by running the tx in a local EVM whose state comes from Helios. The EVM pulls code + storage for every contract the tx touches (any call depth) through Helios, so the outcome is consensus-verified; each touched contract is then verified locally so variable/event names are trustless too, and any contract that can't be verified is flagged rather than guessed. No third-party simulation service.
  • Transactions are verified after mining, too. Every sent tx lands in a local Activity history; its page shows what you signed (the clear-signing preview, rebuilt from calldata stored at send time) next to what actually happened: the consensus-verified receipt, the actual events decoded with the same locally-verified ABIs as the simulation, and the simulation's predicted storage/balance changes re-checked against Helios-verified state (the sender's balance gas-adjusted from the receipt). Each prediction gets a ✓ matches / ≠ differs verdict; anything that can't be read says "Helios cannot get this" — never a guess.

A contract page does not open until local verification succeeds. Proxies and EIP-2535 diamonds are resolved on-chain and their implementations/facets are verified locally too.


How it works (trust model)

┌──────────────────────── Tauri WebView (React + viem) ────────────────────────┐
│  Home (chain + address)                                                       │
│      │                                                                        │
│      ▼  GATE — page stays closed until this passes                            │
│  lib-sourcify + web-solc  ── recompile locally, compare bytecode ──┐          │
│      │ (ABI taken from the LOCAL recompilation, not Sourcify)       │          │
│      ▼                                                              │          │
│  Read fns (eth_call) · Write fns → clear-signing preview → Ledger   │          │
└───────────────────────────────┬──────────────────────────────────┼──────────┘
       JSON-RPC (viem + lib-sourcify)                                │  HTTPS (untrusted,
                                 ▼                                   ▼   re-verified locally)
        http://127.0.0.1:8545  ┌──────────────────────┐     Sourcify API · ERC-7730 registry
        (CORS proxy)           │  Rust backend         │     · solc binaries
                               │  • Helios light client│
   consensus RPC (BLS) ─────►  │  • CORS JSON-RPC proxy│
   execution RPC (eth_getProof)│  • Ledger signer      │
   checkpoint (trust anchor) ► └──────────────────────┘

The only trust anchor is the Helios checkpoint. Everything the UI shows about chain state is verified against it. Sourcify/registry data is treated as untrusted input and re-checked locally. Helios' built-in JSON-RPC server has no CORS headers, so the backend runs a small loopback CORS proxy in front of it that both viem and lib-sourcify talk to.


Features

  • Embedded Helios light client (Ethereum mainnet + Sepolia) exposed as a local JSON-RPC (one per chain).
  • Local Sourcify verification gate (exact_match / match) — no trust in the server.
  • Proxy & diamond aware: EIP-1967 / beacon / legacy-OZ / EIP-1167 / Aragon implementation() / Safe (Gnosis Safe) masterCopy() and EIP-2535 diamonds are resolved from Helios-verified state; each implementation/facet is verified locally and its functions routed to the proxy.
  • ABI → interactive UI with three tabs: Clear Signing (descriptor-driven forms), All methods (read/write), and Sources (the verified source files + compiler settings we recompiled).
  • ERC-7730 clear-signing preview, with token/NFT/ENS/chain metadata resolved through Helios; falls back to viem ABI-decoding when no descriptor exists.
  • Connect Ledger to set the active account (address read only — no login signature), used as msg.sender for simulations and as the signer.
  • Trustless transaction simulation on every write: a dry-run (revert/return) and a local-EVM effects preview — decoded events + ETH balance + named storage-variable changes, reconstructed by capturing the EVM's KECCAK256 slot computations. Every contract the tx touches is verified locally before its names are shown; unverifiable contracts are flagged.
  • Ledger signing (EIP-1559 + EIP-712) over USB-HID from Rust, on a dedicated worker thread; the signed tx is broadcast via Helios.
  • Local transaction history with post-mining verification: an Activity page of every tx sent from the app (clear-signing intent, contract, live status — pending entries are re-checked through Helios when you open it), and a per-transaction page showing what you signed vs what actually happened — receipt status/gas, actual events decoded via locally-verified ABIs, and the simulation's predicted storage/balance changes re-read from verified state with ✓ matches / ≠ differs / "Helios cannot get this" verdicts.
  • A local address book (Settings) that names addresses in clear-signing previews.

Prerequisites

  • Rust (stable) + Cargo. The first build compiles Helios from a pinned git commit and is slow (several minutes) — this is normal.
  • Node.js ≥ 22 and npm.
  • Tauri v2 system dependencies for your OS — see tauri.app/start/prerequisites (macOS: Xcode Command Line Tools; Linux: webkit2gtk, libusb, etc.).
  • An execution RPC that supports eth_getProof (a sensible public default is bundled; override in Settings — Alchemy/Infura recommended for reliability).
  • (Optional, for signing) a Ledger device with the Ethereum app.

Getting started

# 1. Install JS dependencies
npm install

# 2. Run the app in dev mode (builds the Rust backend, launches the window)
npm run tauri dev

On first launch the Helios light client syncs against the consensus checkpoint (usually a few seconds once a checkpoint is cached). The Home screen shows a Helios status badge; wait for running before opening a contract.

The Home screen lists example contracts (Lido, Aave V3, wstETH, USDC, …) you can open with one click, or enter any verified address yourself.

Production build

npm run tauri build

Configuration

Open Settings in the app (stored as JSON in the OS app-data directory; the frontend only touches it via Rust commands). Defaults:

Setting Default Notes
Execution RPC https://ethereum-rpc.publicnode.com Untrusted; must support eth_getProof.
Consensus RPC https://ethereum.operationsolarstorm.org Beacon light-client API (Helios' default).
Checkpoint (auto) checkpoint-sync fallback Optionally pin a weak-subjectivity block root.
Local RPC port 8545 CORS proxy; Helios binds port+1 internally.

Changing RPCs/checkpoint restarts Helios; changing the port needs an app restart.


Using a hardware wallet (Ledger)

First click Connect Ledger in the top bar (this only reads your address — no signature). Then on a contract's write function: Build transaction → review the clear-signing preview, the dry-run, and the simulated effects → Sign & send with Ledger.

  1. Connect and unlock the Ledger, then open the Ethereum app.
  2. The app fetches nonce/gas/fees via Helios, sends the full transaction to the device, and you confirm on-device. The signed tx is broadcast via Helios.
  3. After broadcast, View transaction → opens the transaction's page, which tracks the receipt, decodes the actual events, and re-checks the simulation's predictions against verified state. Activity (top bar) keeps the history.

OS notes:

  • macOS / Windows — works over the built-in HID driver, no extra setup. If a contract call has no on-device ERC-7730 descriptor, enable Blind signing in the Ledger Ethereum app settings.
  • Linux — install the Ledger udev rules or the device is root-only:
    curl -sSL https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh | sudo bash

Project structure

src-tauri/src/
  helios.rs    # embedded Helios light client (managed state, internal JSON-RPC)
  proxy.rs     # CORS proxy in front of Helios for the WebView
  wallet.rs    # Ledger signer on a dedicated worker thread (alloy-signer-ledger)
  config.rs    # persistent settings (RPCs, checkpoint, port)
  commands.rs  # Tauri commands (config, status, ledger_*)
src/
  pages/       # Home (chain/address + example contracts), Contract (gate),
               #   Activity (sent-tx history), Transaction (signed vs actual), Settings
  lib/         # rpc (viem→Helios), account (connected Ledger), sourcify (download +
               #   web-solc), verify (gate, proxy/diamond), proxy (resolution),
               #   clearsign (ERC-7730 + coverage), simulate (eth_call dry-run),
               #   evmSim (local-EVM effects + receipt-log decoding),
               #   storageLayout (slot naming), txHistory (sent txs, receipt
               #   polling, prediction re-check), ledger (sign+broadcast), abiForm
  components/  # ContractUI (tabs), Read/WriteFunction (+ SimPanel/EffectsPanel),
               #   AbiInput (recursive), TxPreview, TxStatusBadge, AddressBook

Tech stack

Tauri v2 · React 19 · Vite · TypeScript · viem / abitype · @ethereum-sourcify/lib-sourcify + web-solc · @ethereum-sourcify/clear-signing · @ethereumjs/evm + statemanager (local simulation) · Rust: Helios (helios-ethereum) · alloy (signer-ledger) · axum + tower-http (proxy).


Status & limitations

  • Ethereum mainnet + Sepolia (the backend is multi-chain; OP-stack/Linea aren't available because helios-ethereum is L1-only and the OP-stack crate fails to build).
  • Simulation is a local preview, not consensus — it runs a local EVM (@ethereumjs/evm) over Helios-verified state; it doesn't set a block context, so block.timestamp/number read 0 for time-gated logic.
  • Post-mining checks read state at latest — Helios serves no pinned-block state, so a predicted-vs-actual "≠ differs" can simply mean later transactions touched the value (the UI says so). It's a spot-check of the predicted changes, not a full actual-state diff — that would need a trace API (debug_traceTransaction), which Helios doesn't serve and whose output couldn't be proof-verified anyway.
  • Ledger only (Trezor's Rust EIP-712 support is incomplete).
  • CSP is currently disabled (csp: null) to let web-solc's Web Worker + WASM run freely — tightening it to a minimal policy is a planned hardening step.
  • solc binary integrity: web-solc downloads the compiler from binaries.soliditylang.org; verifying its checksum against the official list is a planned hardening step.
  • Clear-signing descriptors are fetched from the public ERC-7730 registry; they are display hints — the real safety is the on-device review when signing.

---

🤖 Built with [Claude Code](https://claude.com/claude-code).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages