Skip to content

Repository files navigation

SignGuard

SignGuard logo

Pre-signing transaction review for MetaMask users, powered by Sourcify verified contract intelligence.

License MIT Node.js 18.6 or newer TypeScript 5.7 Sourcify powered Hackathon prototype

SignGuard is a browser-extension-first transaction safety layer. It pauses a MetaMask-compatible request before the final wallet confirmation, analyzes the transaction with deterministic evidence, explains the result at the right depth for the user, and then lets the user either continue in MetaMask or stop the request.

The current MVP focuses on one practical signing problem: MetaMask can show calldata and contract prompts, but users still need a clear answer to questions like "What am I allowing?", "Who is the spender?", "Is this a proxy?", "Was the contract verified?", and "Does verified source expose risky privileged capabilities?" SignGuard answers those questions with Sourcify data, RPC simulation, deterministic risk rules, and optional AI narration that never becomes the source of truth.

Table of Contents

Why This Matters

In 2025, Web3 losses again showed that the weak point is often the signing moment, not the chain itself. CertiK reported more than $3.35B lost across hacks, scams, and exploits, with phishing as the most frequent attack vector: 248 incidents and more than $722M in losses. Scam Sniffer also reported wallet-drainer phishing affecting more than 106K users, including a $6.5M single theft through a Permit signature.

SignGuard focuses on this moment before confirmation. Instead of asking users to understand selectors, approval calldata, proxy contracts, and raw addresses, it gives them a structured review of what the request can do and what evidence supports that conclusion.

Sources: CertiK 2025 Web3 Security Report, Scam Sniffer 2025 phishing report.

Current Product Snapshot

The current version is centered on the browser extension in apps/browser-extension.

Main capabilities:

  • Intercepts MetaMask-compatible eth_sendTransaction requests before MetaMask continues.
  • Opens a SignGuard transaction review popup or reuses the main extension surface.
  • Lets the user select expected intent before analysis, such as approve, swap, bridge, mint, send, stake, claim, connect/login, or not sure.
  • Compares expected intent with detected operation and surfaces mismatches.
  • Runs the analyzer through @analyzer/sdk with Sourcify lookup and RPC simulation.
  • Shows three explanation levels:
    • Beginner: plain language and minimal technical burden.
    • Regular: wallet-user details about assets, permissions, simulation, and contract identity.
    • Developer: deterministic evidence, decoded calldata, trace graph, effect graph, Sourcify data, ENS, risks, raw evidence, and copyable technical values.
  • Adds a floating transaction Q&A panel for all explanation levels.
  • Stores local Activity history and opens full details for past reviews.
  • Saves and restores audit reports through Swarm when Bee is available, with local fallback when it is not.
  • Uses optional backend AI only for explanation wording and Q&A. Deterministic analysis remains usable without an LLM.

Sourcify Fit

Sourcify is a central component of SignGuard, not a cosmetic "verified" label.

The analyzer uses Sourcify's verified contract data for:

  1. ABI decoding

    SignGuard fetches verified ABI data from Sourcify and decodes calldata against the target contract. If Sourcify exposes proxy resolution, the analyzer also tries the implementation ABI and marks the decode source as sourcify-implementation.

  2. Proxy resolution

    The analyzer uses Sourcify proxy data to identify when the user is interacting with a proxy shell and to fetch implementation contract metadata.

  3. Source-level capability detection

    Verified source files are scanned for risky capabilities such as privileged token recovery, selfdestruct, blacklist/blocklist controls, pause controls, minting logic, tx.origin authentication, and signature replay patterns.

  4. Contract metadata and identity

    Compiler metadata, match status, contract name, optimizer settings, verification timestamp, ABI functions, and Sourcify source URLs become part of the normalized ContractInfo.

  5. Source-grounded AI explanation

    When AI narration is enabled, the backend receives compact deterministic evidence and relevant source excerpts. It can explain verified source findings, but it cannot invent risk severity, amounts, addresses, or final recommendations.

Relevant implementation:

Area File
Browser Sourcify provider packages/sdk/src/providers/sourcifyProvider.ts
Backend Sourcify provider packages/sdk-backend/src/providers/sourcify.ts
Contract metadata normalization packages/core/src/analysis.ts
Source-pattern risk rule packages/core/src/risks/sourcePatterns.ts
Analyzer orchestration packages/core/src/explainer.ts

The Sourcify request shape is:

GET /v2/contract/:chainId/:address?fields=all

User Flow

flowchart TD
    dapp["dApp calls window.ethereum.request"]
    hook["SignGuard MAIN-world hook pauses request"]
    content["Content script forwards request"]
    bg["Background worker stores request"]
    review["Transaction Review opens"]
    intent["User selects expected intent"]
    analyze["SignGuard analyzes request"]
    ui["Beginner / Regular / Developer review"]
    qa["Optional transaction Q&A"]
    decision{"User decision"}
    mm["Continue in MetaMask"]
    stop["Reject original request"]

    dapp --> hook --> content --> bg --> review --> intent --> analyze --> ui
    ui --> qa
    ui --> decision
    decision -->|Continue| mm
    decision -->|Stop| stop
Loading

The key product behavior is that MetaMask remains paused until the user decides. If the user continues, SignGuard returns the original provider request back to the dApp and MetaMask opens normally. If the user stops, the original request is rejected.

System Architecture

flowchart LR
    subgraph Browser["Browser extension"]
        inject["MAIN-world provider hook"]
        content["Isolated content script"]
        worker["Service worker"]
        popup["Popup / side panel UI"]
        history["Local activity history"]
    end

    subgraph Analyzer["Analyzer stack"]
        sdk["@analyzer/sdk"]
        core["@analyzer/core"]
        presentation["Presentation model"]
    end

    subgraph Backend["Optional backend"]
        proxy["@analyzer/sdk-backend"]
        ai["OpenAI / Anthropic compatible LLM"]
    end

    subgraph External["External evidence"]
        sourcify["Sourcify API"]
        rpc["JSON-RPC simulation endpoint"]
        swarm["Swarm Bee node"]
    end

    inject --> content --> worker --> popup
    popup --> sdk --> core --> presentation --> popup
    sdk --> sourcify
    sdk --> rpc
    popup --> proxy --> ai
    popup --> swarm
    popup --> history
Loading

The core analyzer is pure TypeScript. It does not perform network calls directly. Runtime packages inject providers for Sourcify, RPC simulation, optional selector registry lookups, optional ENS enrichment, optional phishing lists, and optional narration.

Analyzer Pipeline

The diagram below shows the internal analyzer flow: contract intelligence, ENS checks, Sourcify source verification, simulation analysis, evidence synthesis, risk analysis, and explanation generation.

SignGuard analyzer pipeline

Core guarantees:

  • Deterministic fields are the source of truth: effects, risks, recommendedAction, auditLog, and auditHash.
  • LLM output is presentation only.
  • Sourcify failures do not abort analysis; they reduce confidence.
  • Selector-registry fallback is conservative and does not decode arguments.
  • The audit hash is independent of audience-specific wording.

Repository Layout

.
|-- apps/
|   |-- browser-extension/    Current primary SignGuard UX
|   |-- drainer-demo/         Demo dApp and analyzer graph surface
|   |-- metamask-snap/        MetaMask Flask Snap demo
|   |-- metamask-site/        Local Snap install/config site
|   `-- contracts/            Foundry scenarios and exploit/safe-path tests
|-- packages/
|   |-- core/                 Pure deterministic analyzer engine
|   |-- sdk/                  Browser-safe SDK
|   |-- sdk-backend/          Server SDK, AI proxy, CSV/audit helpers
|   `-- sdk-swarm/            Swarm audit storage and verified fetch helpers
|-- scripts/dev/              Local demo orchestration scripts
|-- docs/
|   `-- signguard-analysis-architecture.svg
|-- package.json
`-- README.md

Quick Start

Requirements:

  • Node.js >=18.6.0 (.nvmrc currently uses Node 20)
  • Yarn 3.2.1
  • Chrome or Chromium for the browser extension demo
  • MetaMask installed in the browser
  • Optional: Bee CLI for Swarm upload demos
  • Optional: MetaMask Flask for the Snap demo
  • Optional: Foundry for Solidity scenario tests

Install dependencies:

yarn install

For Windows PowerShell, use yarn.cmd if script execution blocks yarn.ps1:

yarn.cmd install

Browser Extension Demo

Build the Chrome extension:

yarn build:extension:chrome

Windows PowerShell:

yarn.cmd build:extension:chrome

Load the extension:

  1. Open chrome://extensions.
  2. Enable Developer mode.
  3. Click Load unpacked.
  4. Select apps/browser-extension/dist.
  5. Reload the dApp tab after loading the extension.

Run the extension dev stack:

yarn dev:extension

This starts the extension build/watch flow, SDK backend, optional local Swarm Bee, and demo dApp.

Useful extension commands:

yarn workspace @analyzer/extension build:chrome
yarn workspace @analyzer/extension build:firefox
yarn workspace @analyzer/extension watch:chrome
yarn workspace @analyzer/extension watch:firefox

After every rebuild, reload the unpacked extension in chrome://extensions.

Backend And AI Proxy

The backend package is optional for deterministic analysis, but required for AI-generated beginner/regular copy and Q&A.

Run the local backend:

yarn workspace @analyzer/sdk-backend serve

Windows PowerShell:

yarn.cmd workspace @analyzer/sdk-backend serve

Local endpoints:

Endpoint Purpose
GET /healthz Liveness check
POST /api/explain AI narration from analyzer evidence
POST /api/question Transaction Q&A
POST /api/beginner Beginner explanation
POST /api/regular Regular explanation
POST /api/full Full server-side analysis

LLM safety rule: API keys live only in the backend. Browser extension code never receives OpenAI, Anthropic, or OpenRouter keys.

Swarm Audit Storage

The current extension can save analyzed transaction reports to Swarm through packages/sdk-swarm.

Current behavior:

  • Uploads history entries to a Bee /bytes endpoint when Bee is reachable.
  • Creates a local Bee dev stamp automatically when possible.
  • Supports encrypted Bee upload for private storage.
  • Falls back to local extension storage when Bee is unavailable.
  • Shows verification state: verified, unverified, failed, or local.
  • Lets the Activity screen restore saved reports from the local Swarm index or by reference.

Start a local Bee dev node:

yarn swarm:dev

The default Bee URL is:

http://127.0.0.1:1633

MetaMask Snap Demo

The browser extension is the current primary demo. The repository still includes a MetaMask Snap demo surface for MetaMask Flask.

Start the full Snap stack:

yarn dev:start

Windows PowerShell:

.\scripts\dev\start-dev.ps1

The stack exposes:

Service URL
SDK backend http://127.0.0.1:3000
Drainer demo http://127.0.0.1:5174
Snap server http://localhost:8080
Snap install site http://127.0.0.1:8000
Swarm Bee, when enabled http://127.0.0.1:1633

Then open http://127.0.0.1:8000 in MetaMask Flask, install the Snap, and run demo transactions from http://127.0.0.1:5174.

SDK Usage

Browser SDK:

import { TxExplainer } from '@analyzer/sdk';

const explainer = new TxExplainer({
  rpcUrl: 'https://ethereum-sepolia.publicnode.com',
  sourcifyUrl: 'https://sourcify.dev/server',
  llmProxyUrl: 'http://localhost:3000/api/explain',
});

const result = await explainer.explain({
  from: '0x0000000000000000000000000000000000000001',
  to: '0x0000000000000000000000000000000000000002',
  data: '0x',
  value: 0n,
  chainId: 11155111,
  profile: 'regular',
});

console.log(result.recommendedAction.level);
console.log(result.risks);
console.log(result.auditHash);

Backend SDK:

import { TxExplainerBackend, llmConfigFromEnv } from '@analyzer/sdk-backend';

const llm = llmConfigFromEnv(process.env);
const backend = new TxExplainerBackend({
  rpcUrl: process.env.RPC_URL!,
  sourcifyUrl: process.env.SOURCIFY_URL,
  ...(llm ? { llm } : {}),
});

const result = await backend.explain({
  from,
  to,
  data,
  value: 0n,
  chainId,
  profile: 'expert',
});

Environment

Copy the example env file:

cp .env.example .env

Minimal local configuration:

SEPOLIA_RPC_URL=https://ethereum-sepolia.publicnode.com
VITE_SEPOLIA_RPC_URL=https://ethereum-sepolia.publicnode.com
SOURCIFY_URL=https://sourcify.dev/server

LLM_PROVIDER=openai
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4o
OPENAI_BASE_URL=

ANTHROPIC_API_KEY=
ANTHROPIC_MODEL=claude-sonnet-4-6

SWARM_MODE=dev
SWARM_BEE_URL=http://localhost:1633
SWARM_CREATE_DEV_STAMP=1
SWARM_DEV_FEED_FALLBACK=memory

Notes:

  • Restart @analyzer/sdk-backend after changing backend .env values.
  • Rebuild and reload the browser extension after changing extension build-time values.
  • Never commit .env.

Quality Checks

Common commands:

yarn typecheck
yarn test
yarn build

Focused checks:

yarn workspace @analyzer/core test
yarn workspace @analyzer/sdk test
yarn workspace @analyzer/sdk-backend test
yarn workspace @analyzer/extension build:chrome
yarn workspace @analyzer/metamask-snap test

Solidity scenarios:

cd apps/contracts
forge test

The Solidity scenario suite covers malicious and benign patterns such as reentrancy, honeypots, hidden admin drains, upgrade abuse, fake airdrop approvals, permit phishing, rug pulls, selfdestruct via delegatecall, governance token false positives, and multicall false positives.

License

SignGuard is released under the MIT License.

About

SignGuard: a pre-signing Ethereum transaction safety layer for MetaMask, using Sourcify verified contract intelligence, RPC simulation, deterministic risk rules, and optional AI narration.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages