Skip to content

jimmychu0807/semaphore-msa-modules

Repository files navigation

Semaphore Modular Smart Account Modules

ERC-7579 modules that plug Semaphore’s anonymous group proofs into ERC-4337 modular smart accounts—so members can co-author transactions without revealing which member approved each action on-chain.

Try it

What this repo delivers

Two complementary ERC-7579 modules (see validators and executors) backed by Semaphore:

Module Role
SemaphoreValidator Validates UserOperation signatures (EdDSA + identity commitment in the account’s Semaphore group). Restricts calls so the account can only drive the paired executor’s API surface.
SemaphoreExecutor Holds per-account state (group, threshold, pending txs, collected proofs). Exposes initiateTxsignTxexecuteTx so proofs act like threshold “signatures” while preserving member privacy.

Together they give a smart account anonymous threshold control: only group members can advance state, proofs are unique per signal (no replay as the same “vote”), and calldata does not deanonymize the prover.

Project code: FY24-1847 · Development supported by the PSE Acceleration Program (discussion).

Architecture

High-level data flow from a developer-built client through account abstraction to Semaphore on-chain.

sequenceDiagram

  autonumber
  actor App as Wallet or demo dApp
  participant Lib as @semaphore-msa-modules/lib
  participant ZK as Off-chain ZK prover
  participant SA as Smart account
  participant Val as SemaphoreValidator
  participant Ex as SemaphoreExecutor
  participant Sem as Semaphore contracts

  App->>Lib: Install modules, encode calls, build user ops

  Note over App,Sem: Anonymous threshold flow — each step is usually its own UserOperation

  App->>ZK: Identity + signal, proof for initiateTx
  ZK-->>App: Proof bytes
  App->>SA: initiateTx UserOperation (validate + execute)
  SA->>Val: validateUserOp
  Val->>Ex: Restrict to paired executor API
  SA->>Ex: initiateTx
  Ex->>Sem: Verify proof, nullifier, store pending tx (1st proof)

  Note over App,Sem: signTx UserOperation

  loop Until collected proofs >= M-of-N threshold
    App->>ZK: Proof for same txHash / signal
    ZK-->>App: Proof bytes
    App->>SA: signTx UserOperation (validate + execute)
    SA->>Val: validateUserOp
    Val->>Ex: Restrict to paired executor API
    SA->>Ex: signTx
    Ex->>Sem: Verify proof, nullifier, increment count
  end

  Note over App,Sem: executeTx UserOperation
  App->>SA: executeTx UserOperation (validate + execute)
  SA->>Val: validateUserOp
  Val->>Ex: Restrict to paired executor API
  SA->>Ex: executeTx
  Ex->>Sem: Final checks, then run the pending external call
Loading

How to read it: clients use the library (with Rhinestone Module SDK and viem under the hood) to install modules, encode calls, and assemble user ops; an off-chain prover produces Semaphore proofs; each UserOperation is validated and executed on the smart account (in a full ERC-4337 stack, EntryPoint orchestrates this via handleOps, often through a bundler, with an optional paymaster); the validator checks the user-op path and signature; the executor runs initiateTx (first proof, pending tx), then signTx in a loop until the account’s M-of-N threshold is met, then executeTx when proofs are sufficient (or earlier if execute is set so the contract auto-runs executeTx once the threshold is reached).

Who should integrate this?

Pick this stack when you are not satisfied with a plain on-chain multisig that reveals approvers, but you still want account abstraction (gas sponsorship, batched ops, smart accounts) and modular validation per ERC-7579.

If you are building… Why integrate
Modular smart account products (wallets, DAO tooling, team treasuries) Add a privacy-preserving threshold policy: M-of-N control without exposing which key approved each transaction.
dApps that already use Semaphore Reuse groups and proofs as the authorization layer for a 4337 smart account instead of only for app-specific claims.
Rhinestone / Module SDK workflows The published package exposes getSemaphoreExecutor and getSemaphoreValidator module descriptors compatible with @rhinestone/module-sdk, so you can treat these modules like other installable validators and executors.
Research and education End-to-end reference: Foundry tests (FFI + proofs), a Next.js demo, and Dockerized Alto + paymaster for local experimentation.

You will touch Solidity if you fork or redeploy the modules, TypeScript for proofs and user-ops (viem, Semaphore protocol packages), and 4337 infrastructure (bundler RPC, optional paymaster) for production UX.

Monorepo layout

Package Description
packages/contracts Foundry contracts: SemaphoreValidator, SemaphoreExecutor, tests, deployment scripts. Includes Base Sepolia deployment addresses in its README.
packages/lib @semaphore-msa-modules/lib: module installation helpers, ABIs, and transaction helpers built on viem and Rhinestone Module SDK.
packages/web Next.js demo UI for installing modules, managing identities, and sending demo transactions.
docker-containers Docker Compose: forked Anvil, Alto bundler, mock paymaster—used by pnpm dev at the workspace root.

Requirements: Node ≥ 22, pnpm (see root package.json for the pinned version).

Common commands:

pnpm install
pnpm dev          # Docker stack + package dev servers
pnpm ci-check     # build, test, lint across packages

Standards and further reading

ERC-4337 lifecycle

Source: ERC-4337 documentation

Acknowledgements

Thanks to everyone who shaped and supported this work: