Skip to content

Instantly share code, notes, and snippets.

@roninjin10
Created January 15, 2026 12:08
Show Gist options
  • Select an option

  • Save roninjin10/a2e7059049a273649377ffc3029d1a71 to your computer and use it in GitHub Desktop.

Select an option

Save roninjin10/a2e7059049a273649377ffc3029d1a71 to your computer and use it in GitHub Desktop.
Simulation design doc

Fork Mode & Resimulation (Phase 1 - Live)

Status: ✅ Phase 1 Live - Core fork infrastructure and simulation features are implemented and functional. Phase 2+ (persistent sessions, Tevm Black) are planned.

For Phase 2+ specifications, see Fork Mode Engineering Spec.


Overview

Fork Mode transforms tevm.app from a read-only blockchain explorer into an interactive simulation environment. Users can fork from any historical block to create a local EVM sandbox, resimulate transactions with modified parameters, and preview transaction effects before execution.

Key Capability: "What-if" analysis for any transaction or contract interaction.


Phase 1 Features (Live)

✅ Fork Creation

  • Fork from any block via block page "Fork" button
  • Fork session metadata persisted client-side (localStorage)
  • Automatic fork initialization on first resimulation
  • Fork configuration (modal):
    • Fork point: end-of-block or pre-state (block - 1)
    • Optional session label
    • Chain + block are derived from the current page context

✅ Transaction Simulation

  • Page: /simulate - Single transaction simulation UI
  • Results Page: /simulate/results/[encoded] - Shareable simulation results
  • Multiple input formats:
    • Transaction hash (resimulate historical tx)
    • Contract address + function call
    • Raw transaction data
  • Parameter modification before simulation:
    • Caller address
    • Transaction value (ETH)
    • Gas limit
    • Function arguments
  • Safety verdicts:
    • 🟢 Safe - No warnings detected
    • 🟡 Review Needed - Approval changes or moderate warnings
    • 🔴 High Risk - Unlimited approvals, unverified contracts

✅ Simulation Results Display

  • Balance Diffs: Before/after comparison for all affected addresses
  • Approval Changes: Token approval modifications (ERC20, ERC721)
  • Event Logs: Raw emitted logs (topics + data)
  • Gas Metrics: Gas used (and simulated vs actual on resimulations)
  • Warnings Panel: Risk indicators with severity levels

✅ Fork State Management

  • Client-side fork state persistence (localStorage)
  • Fork session tracking:
    • Session ID
    • Chain ID
    • Fork block number + block hash
    • Optional label + acting-as address
    • Simulation count
  • State serialization/deserialization for persistence
  • Fork reset capability
  • State cache thresholds exist (warn at 50MB, max 100MB), but current UI reports 0 until backend stats are wired.

✅ UI Components

  • ForkStatusPill - Header indicator showing active fork state
  • ForkButton - Entry point for fork creation
  • ForkModal - Fork configuration dialog
  • ForkDrawer - Fork management panel (session info, reset)
  • SimulationTab - Main simulation interface (20KB component)
  • SimulationPreview - Results preview card
  • SimulationResults - Detailed results display
  • SimulationSummary - Quick summary view
  • VerdictBanner - Safety verdict display
  • BalanceDiffTable - Balance comparison table
  • WarningsPanel - Risk warnings list
  • SimulationQueuePanel - Batch simulation queue (implemented, not wired in UI yet)
  • SimulationParamsEditor - Parameter editor (implemented, not wired in UI yet)

✅ SimLinks (Shareable Simulations)

  • Encode simulation parameters into a URL-safe string
  • Results are re-simulated on load using the encoded spec
  • URL formats: /simulate/results/[base64-encoded-spec] and /s/[encoded]

⚠️ Multi-Transaction Queue (not wired in UI)

  • Queue utilities and panel exist in code
  • Not currently surfaced in the /simulate UI

Architecture

Components Structure

apps/explorer-astro/src/
├── pages/
│   └── simulate/
│       ├── index.astro                   # Simulation entry page
│       └── results/[encoded].astro       # SimLink results page
├── components/
│   ├── fork/
│   │   └── ForkStatusPill.astro          # Static fork indicator
│   └── islands/
│       ├── ForkStatusPillIsland.tsx      # Interactive fork status
│       ├── ForkButton.tsx                # Fork creation trigger
│       ├── ForkModal.tsx                 # Fork config dialog (18KB)
│       ├── ForkDrawerIsland.tsx          # Fork management panel
│       ├── SimulationTab.tsx             # Main simulation UI (20KB)
│       ├── SimulationPreview.tsx         # Preview card (19KB)
│       ├── SimulationResults.tsx         # Detailed results (14KB)
│       ├── SimulationSummary.tsx         # Summary display (11KB)
│       ├── SimulationQueuePanel.tsx      # Batch queue (20KB)
│       ├── SimulationParamsEditor.tsx    # Params editor (20KB)
│       ├── BalanceDiffTable.tsx          # Balance comparison
│       ├── VerdictBanner.tsx             # Safety verdict
│       └── WarningsPanel.tsx             # Risk warnings
├── lib/fork/
│   ├── fork-store.ts                     # Fork state management
│   ├── fork-session.ts                   # Session tracking
│   ├── fork-worker-client.ts             # Worker communication
│   └── fork-serialization.ts             # State persistence
└── workers/
    └── simulator.worker.ts               # Simulation execution worker

Data Flow

/simulate (standalone simulation)
User Input → SimulatorIsland → useSimulator → simulator.worker.ts (RPC eth_call)
        → Effects extraction → SimulationResults
Resimulation (Fork Mode)
ResimulateButton → fork-worker-client.ts → /api/fork/* → EXPLORER_DO
               → SimResult → SimulationTab / VerdictBanner

Note: The client-side simulator.worker.ts uses RPC-based eth_call for lightweight simulation. For full guillotine-mini-powered fork sessions with persistent state, the external explorer-do Durable Object service uses the guillotine runtime. See Fork Mode Resimulation for architecture details.

State Management

Fork Store (lib/fork/fork-store.ts):

interface ForkSession {
  id: string
  chainId: number
  forkBlock: bigint
  simulations: SimulationRun[]
  stateSize: number  // Memory usage tracking
  createdAt: number
}

interface SimulationRun {
  id: string
  input: SimSpec
  result: SimResult | null
  timestamp: number
  status: 'pending' | 'success' | 'error'
}

Workers

Client-Side Simulation Worker (simulator.worker.ts):

  • Uses RPC-based eth_call for lightweight simulation (not full guillotine runtime)
  • Executes simulations via RPC to fork source
  • Extracts effects (balance changes, approvals, logs)
  • Calculates safety verdict
  • Returns structured results to main thread

Server-Side Fork Sessions (apps/explorer-do):

  • Uses guillotine-mini runtime for full EVM simulation
  • Runs in Cloudflare Durable Objects for persistence
  • Supports RPC endpoint for external tools (Phase 2+)
  • See Fork Mode Resimulation for details

Usage Patterns

Basic Simulation Workflow

  1. Navigate to Simulation Page

    • Click "Simulate" in header
    • Or use /simulate URL
  2. Input Transaction

    • Paste transaction hash for resimulation
    • Or enter contract address + function name
    • Or paste raw transaction data
  3. Modify Parameters (Optional)

    • Change caller address
    • Adjust transaction value
    • Modify function arguments
    • Set gas limit
  4. Run Simulation

    • Click "Simulate" button
    • Fork auto-creates if needed
    • Transaction executes in sandbox
  5. Review Results

    • Check safety verdict (Safe / Review / Risk)
    • Review balance diffs
    • Inspect approval changes
    • Read warnings panel
    • View event logs
  6. Share Results

    • Copy SimLink URL
    • Share with others for review

Resimulation from Transaction Page

  1. Navigate to Any Transaction

    • Example: /tx/0xabc...
  2. Click "Resimulate" Button

    • Opens simulation modal with prefilled data
  3. Modify Parameters

    • Change caller to test different senders
    • Adjust value to test edge cases
    • Modify args to test different scenarios
  4. Run & Compare

    • Original transaction effects vs modified simulation
    • Identify impact of parameter changes

Fork from Block Page

  1. Navigate to Any Block

    • Example: /block/12345
  2. Click "Fork" Button

    • Fork modal appears with block prefilled
  3. Configure Fork

    • Confirm chain (Base Mainnet / Sepolia)
    • Confirm block number
    • Create fork
  4. Fork Indicator Appears

    • ForkStatusPill shows in header
    • All simulations use this fork state
  5. Reset Fork

    • Click fork pill → "Reset Fork" button
    • Clears all simulation state

Safety Verdict Logic

🟢 Safe

  • No warnings detected
  • No approval changes
  • Known contract patterns
  • All state changes expected

🟡 Review Needed

  • Has approval changes (limited amounts)
  • Moderate warnings present
  • Unverified contract interactions
  • Unusual state changes

🔴 High Risk

  • Unlimited approval (type(uint256).max)
  • Unverified contract with state changes
  • Suspicious patterns detected
  • Multiple high-severity warnings

Warning Categories

  1. Approval Warnings

    • Unlimited ERC20 approval
    • ERC721 setApprovalForAll
    • Approval to unverified contract
  2. Value Warnings

    • Large ETH transfer
    • Transfer to unverified contract
    • Unusual value for function type
  3. State Warnings

    • Ownership transfer
    • Proxy upgrade
    • Critical storage modifications
  4. Contract Warnings

    • Unverified contract interaction
    • Proxy contract detected
    • Selfdestruct operation

Technical Details

Simulation Engine

  • Runtime: guillotine-mini (WASM EVM)
  • Fork Source: Base RPC (Mainnet or Sepolia)
  • State Isolation: Each simulation runs in isolated fork
  • Persistence: localStorage (client-side, per-browser)

Performance

  • Fork Creation: ~1-2s (downloads block state)
  • Simulation Execution: ~100-500ms typical
  • Memory Usage: ~5-50MB per fork (depends on state size)
  • Storage Limits:
    • Warn at 50MB
    • Hard limit at 100MB
    • Auto-cleanup on limit exceeded

Data Extraction

Balance Diffs:

  • Pre-flight balance query for all affected addresses
  • Post-simulation balance query
  • Diff calculation with percentage changes

Approval Changes:

  • Parse Approval and ApprovalForAll events
  • Extract spender, amount, token type
  • Flag unlimited approvals

Event Logs:

  • ABI decoding via WhatsABI
  • Topic extraction and indexing
  • Parameter formatting

State Changes:

  • Storage slot diffs
  • Account nonce changes
  • Code deployments

Known Limitations (Phase 1)

State Persistence

  • ❌ Fork state is client-side only (localStorage)
  • ❌ Fork resets on browser close/clear data
  • ❌ No cross-device sync
  • ❌ Limited to ~5MB localStorage quota

Fork Sessions

  • ❌ Cannot share live fork sessions (SimLinks are read-only)
  • ❌ No persistent fork URLs
  • ❌ Single fork per browser (no multiple concurrent forks)

Integration

  • ❌ Fork state not visible in global explorer navigation
  • ❌ Simulated transactions don't appear in feeds/search
  • ❌ No RPC endpoint for external tools

Advanced Features

  • ❌ No time travel (block forwarding/rewinding)
  • ❌ No account impersonation (fixed test account)
  • ❌ No batch simulation UI for complex flows
  • ❌ No simulation history persistence

Phase 2+ Roadmap (Planned)

See FORK_MODE_ENGINEERING.md for full Phase 2+ specifications.

Phase 2: Persistent Fork Sessions (Tevm Black)

  • Cloudflare Durable Objects backend
  • Persistent fork URLs: /fork/<account>/<fork>/...
  • Cross-device sync
  • RPC endpoint for external tools (/fork/<account>/<fork>/rpc)
  • Multiple concurrent forks per account
  • Fork session management dashboard

Phase 3: Full Explorer Integration

  • Simulated transactions appear in all feeds
  • Search integration (find simulated txs)
  • Global fork indicator across all pages
  • Fork-aware data fetching everywhere

Phase 4: Advanced Features

  • Time travel (forward/backward block navigation)
  • Account impersonation (simulate as any address)
  • Complex simulation flows (multi-tx scenarios)
  • Simulation history with replay
  • Collaboration (multiplayer forks)

Related Documentation


Code Location

  • Pages: apps/explorer-astro/src/pages/simulate/
  • Components: apps/explorer-astro/src/components/fork/, components/islands/
  • State Management: apps/explorer-astro/src/lib/fork/
  • Workers: apps/explorer-astro/src/workers/simulator.worker.ts

Testing

Unit Tests

  • Fork state serialization/deserialization
  • Safety verdict calculation
  • Balance diff computation
  • Approval detection logic

E2E Tests

  • Create fork from block page
  • Resimulate transaction with modified params
  • SimLink encoding/decoding
  • Fork reset functionality
  • Multi-transaction queue

Dependencies

{
  "tevm": "latest",
  "lz-string": "^1.5.0"
}

FAQ

Q: Does my fork state persist across browser sessions? A: In Phase 1, fork state is stored in localStorage and persists across tabs but is lost if you clear browser data. Phase 2 (Tevm Black) will introduce persistent cloud-backed forks.

Q: Can I share my fork session with others? A: In Phase 1, you can only share read-only SimLinks (simulation results). Phase 2 will enable shareable live fork sessions via persistent URLs.

Q: Can I use my fork as an RPC endpoint for MetaMask/Foundry? A: Not in Phase 1. Phase 2 (Tevm Black) will expose fork sessions as JSON-RPC endpoints.

Q: How many simulations can I run? A: Unlimited simulations in Phase 1, but fork state is limited to ~100MB. Phase 2 removes limits for Tevm Black subscribers.

Q: Can I fork from any chain? A: Currently Base Mainnet (8453) and Base Sepolia (84532) only. Other chains may be added in the future.

Q: What happens if my fork exceeds the memory limit? A: You'll see a warning at 50MB and the fork will reset at 100MB to prevent browser performance issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment