Offline Build - Official Ethereumjs Libraries

This directory contains the build system to create offline1.html using official ethereumjs libraries.

Libraries Used

All libraries are from the official Ethereum ecosystem:

  • @ethereumjs/tx - Transaction signing (legacy + EIP-1559)
  • @ethereumjs/util - Utilities (address validation, checksums, etc.)
  • @ethereumjs/rlp - RLP encoding
  • @ethereumjs/wallet - Wallet utilities
  • ethereum-cryptography - Official cryptographic primitives (secp256k1, keccak256)
  • @scure/bip39 - BIP39 mnemonic (used by ethereumjs)
  • @scure/bip32 - BIP32 HD derivation (used by ethereumjs)

Build Instructions

# Navigate to this directory
cd offline-build

# Install dependencies
npm install

# Build offline1.html
npm run build

The output file offline1.html will be created in the parent directory.

What Gets Bundled

The build process uses esbuild to:

  1. Bundle all ethereumjs libraries and their dependencies
  2. Minify the code for smaller file size
  3. Inline everything into a single HTML file

Typical bundle size: ~400-600 KB (varies by version)

Features

All features match the CLI tool:

  • Wallet Generation - Random keypair generation
  • Mnemonic Support - Create/restore BIP39 mnemonics, derive accounts
  • Vanity Addresses - All vanity options (prefix, suffix, regex, etc.)
  • Message Signing - EIP-191 personal_sign
  • Signature Verification - Recover signer from signature
  • Validation - Address and key validation
  • Keystore - V3 keystore encrypt/decrypt (PBKDF2)
  • Transactions - Sign legacy and EIP-1559 transactions offline
  • EIP-712 - Typed data signing and verification

Security

  • The generated HTML file is completely self-contained
  • No external network requests
  • Can be saved and used on an air-gapped machine
  • Uses official, audited Ethereum libraries

MCP Servers

This repository includes 5 Model Context Protocol (MCP) servers that expose Ethereum wallet functionality to AI assistants like Claude.

Documentation

Overview

Server Purpose Tools Tests
ethereum-wallet-mcp Wallet generation, HD wallets, mnemonics 6 111
keystore-mcp-server Encrypted keystore files (Web3 Secret Storage) 9 74
signing-mcp-server Message signing, EIP-191, EIP-712 12 34
transaction-mcp-server Transaction building, encoding, signing 15 65
validation-mcp-server Address/key validation, checksums, hashing 15 64

Total: 57 tools, 348 tests

Quick Start

Installation

Each server is a standalone Python package:

# Install all servers
pip install -e ./ethereum-wallet-mcp
pip install -e ./keystore-mcp-server
pip install -e ./signing-mcp-server
pip install -e ./transaction-mcp-server
pip install -e ./validation-mcp-server

Claude Desktop Configuration

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "ethereum-wallet": {
      "command": "ethereum-wallet-mcp"
    },
    "keystore": {
      "command": "keystore-mcp-server"
    },
    "signing": {
      "command": "signing-mcp-server"
    },
    "transaction": {
      "command": "transaction-mcp-server"
    },
    "validation": {
      "command": "validation-mcp-server"
    }
  }
}

Server Details

ethereum-wallet-mcp

Wallet Generation & HD Wallets

Tools:

  • generate_wallet - Random Ethereum wallet
  • generate_wallet_with_mnemonic - BIP39 mnemonic wallet
  • restore_wallet_from_mnemonic - Restore from seed phrase
  • restore_wallet_from_private_key - Restore from private key
  • derive_multiple_accounts - HD wallet derivation
  • generate_vanity_address - Custom prefix/suffix addresses

Resources:

  • wallet://documentation/bip39 - BIP39 spec
  • wallet://documentation/derivation-paths - HD paths
  • wallet://wordlist/{language} - BIP39 wordlists

keystore-mcp-server

Encrypted Keystore Files (Web3 Secret Storage)

Tools:

  • encrypt_keystore - Create encrypted keystore from private key
  • decrypt_keystore - Decrypt keystore to get private key
  • change_keystore_password - Re-encrypt with new password
  • validate_keystore - Verify keystore structure
  • get_keystore_address - Extract address without decryption
  • generate_encrypted_wallet - Create new wallet as keystore
  • read_keystore_file - Read keystore from filesystem
  • write_keystore_file - Save keystore to filesystem

Supports:

  • scrypt and pbkdf2 key derivation
  • AES-128-CTR encryption
  • UUID and version validation

signing-mcp-server

Message & Data Signing

Tools:

  • sign_message - EIP-191 personal_sign
  • verify_message - Verify signed message
  • hash_message - Create message hash
  • sign_typed_data - EIP-712 structured data
  • verify_typed_data - Verify typed data signature
  • encode_typed_data - Encode without signing
  • recover_signer - Recover address from signature

transaction-mcp-server

Transaction Building & Signing

Tools:

  • build_transaction - Create unsigned transaction
  • sign_transaction - Sign with private key
  • decode_transaction - Parse raw transaction
  • encode_transaction - RLP encode transaction
  • estimate_gas - Calculate gas requirements
  • calculate_transaction_hash - Pre-signing hash
  • build_eip1559_transaction - Type 2 transactions
  • build_legacy_transaction - Type 0 transactions
  • build_access_list_transaction - Type 1 transactions
  • serialize_transaction - Convert to wire format
  • parse_transaction_input - Decode calldata
  • validate_transaction - Check transaction validity

validation-mcp-server

Validation & Cryptographic Utilities

Tools:

  • validate_address - EIP-55 checksum validation
  • validate_private_key - Key range checking
  • to_checksum_address - Convert to checksummed
  • derive_address_from_private_key - Key → address
  • derive_address_from_public_key - Pubkey → address
  • validate_signature - Check v, r, s values
  • validate_hex_data - Hex string validation
  • compare_addresses - Address equality
  • batch_validate_addresses - Bulk validation
  • generate_vanity_check - Pattern matching
  • keccak256_hash - Compute Keccak-256
  • encode_function_selector - Signature → selector
  • decode_function_selector - Lookup selectors
  • validate_ens_name - ENS format validation
  • calculate_storage_slot - Storage slot computation

Resources:

  • validation://eip55-specification - EIP-55 docs
  • validation://secp256k1-constants - Curve params
  • validation://function-selectors-db - 500+ selectors
  • validation://address-patterns - Known patterns

Testing

Run all server tests:

# Individual servers
pytest ethereum-wallet-mcp/tests/ -v
pytest keystore-mcp-server/tests/ -v
pytest signing-mcp-server/tests/ -v
pytest transaction-mcp-server/tests/ -v
pytest validation-mcp-server/tests/ -v

# All at once
./run_all_tests.sh

Architecture

All servers follow a consistent pattern:

server-name/
├── pyproject.toml          # Package config
├── README.md               # Server docs
├── src/
│   └── package_name/
│       ├── __init__.py
│       ├── __main__.py     # Entry point
│       ├── server.py       # MCP server setup
│       ├── tools/          # Tool implementations
│       ├── resources/      # Static resources
│       └── prompts/        # Interactive prompts
└── tests/
    └── test_*.py           # Pytest tests

Each tool has:

  1. An *_impl() function with pure business logic (for testing)
  2. A registered async wrapper for MCP compatibility

Security Considerations

  • No network calls - All operations are offline
  • No key storage - Keys are passed through, never persisted
  • Auditable - All code uses official Ethereum Foundation libraries
  • Test coverage - 348 tests across all servers

⚠️ Warning: These tools handle sensitive cryptographic material. Review the code and understand the implications before using with real assets.

Dependencies

All servers use official Ethereum Foundation libraries:

  • eth-account - Key generation, signing
  • eth-keys - ECDSA operations
  • eth-utils - Utility functions
  • eth-rlp - RLP encoding
  • mnemonic - BIP39 implementation
  • mcp - Model Context Protocol SDK

License

All rights reserved. See LICENSE.

Prompt Examples for Ethereum Wallet MCP Servers

This guide provides real-world prompt examples for interacting with the Ethereum Wallet Toolkit MCP servers through AI assistants like Claude.

Table of Contents


Wallet Operations

Generate a New Wallet

Simple:

Generate a new Ethereum wallet for me

With mnemonic:

Create a new Ethereum wallet with a 24-word seed phrase

For development/testing:

Generate a test wallet for Sepolia testnet development

Restore Wallets

From mnemonic:

Restore my wallet from this seed phrase:
abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about

From private key:

Import this private key and show me the wallet address:
0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318

HD Wallet Derivation

Derive multiple accounts:

Derive 5 accounts from this mnemonic using the standard Ethereum path:
[your 12/24 word mnemonic]

Custom derivation path:

Derive an account at path m/44'/60'/1'/0/0 from my seed phrase

Vanity Address Generation

Simple prefix:

Generate a vanity address starting with "cafe"

Case-insensitive suffix:

Find me an address ending with "1337" (case insensitive)

Message Signing

Sign a Simple Message (EIP-191)

Basic signing:

Sign this message with my private key:
Message: "Hello, Ethereum!"
Private key: 0x...

For verification:

Sign a message that proves I own wallet 0xABC... 
The message should be: "I authorize login to MyDApp on 2024-01-15"

Verify a Signature

Verify message:

Verify this signed message:
- Message: "Hello, Ethereum!"
- Signature: 0x...
- Expected signer: 0x...

Recover signer:

Who signed this message?
- Message: "I agree to the terms"
- Signature: 0x...

Signature Operations

Decompose signature:

Break down this signature into v, r, s components:
0x...

Normalize v value:

Convert this signature's v value from 0/1 format to 27/28 format:
0x...

EIP-712 Typed Data

Sign EIP-712 Permit (ERC-20)

Permit signature for token approval:

Sign an EIP-712 permit for USDC on Ethereum mainnet:
- Owner: 0x... (my address)
- Spender: 0x... (Uniswap router)
- Value: 1000000000 (1000 USDC, 6 decimals)
- Nonce: 0
- Deadline: 1735689600 (Unix timestamp)
- Private key: 0x...
- Contract address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48

Sign Custom Typed Data

NFT marketplace order:

Sign this EIP-712 typed data for an NFT listing:

Domain:
- Name: "OpenSea"
- Version: "1.4"
- Chain ID: 1
- Verifying Contract: 0x00000000006c3852cbEf3e08E8dF289169EdE581

Message (Order):
- offerer: 0x... (my address)
- zone: 0x0000000000000000000000000000000000000000
- offer: [{ token: 0x..., identifier: 1234, amount: 1 }]
- consideration: [{ token: 0x0, amount: 1000000000000000000 }]
- orderType: 0
- startTime: 1704067200
- endTime: 1735689600

Private key: 0x...

Hash Typed Data (Without Signing)

Compute the EIP-712 hash for this typed data without signing:
[typed data structure]

Transaction Operations

Build and Sign Transactions

Simple ETH transfer:

Build and sign a transaction to send 0.5 ETH:
- To: 0x742d35Cc6634C0532925a3b844Bc9e7595f5b4E2
- Chain ID: 1 (mainnet)
- Nonce: 42
- Max fee per gas: 30 gwei
- Max priority fee: 2 gwei
- Private key: 0x...

ERC-20 token transfer:

Create a signed transaction to transfer 100 USDT:
- Token contract: 0xdAC17F958D2ee523a2206206994597C13D831ec7
- To: 0x...
- Amount: 100000000 (100 USDT with 6 decimals)
- From nonce: 5
- Chain ID: 1
- Gas limit: 65000
- Max fee: 50 gwei
- Private key: 0x...

Contract interaction:

Build a transaction to call the 'approve' function:
- Contract: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 (USDC)
- Function: approve(address spender, uint256 amount)
- Spender: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D (Uniswap)
- Amount: max uint256 (unlimited approval)
- Sign with: 0x...

Decode Transactions

Decode raw transaction:

Decode this raw signed transaction and show me what it does:
0x02f8730180843b9aca00850...

Decode calldata:

Decode this calldata and tell me what function it calls:
0xa9059cbb000000000000000000000000...

Analyze Transactions

Estimate cost:

Estimate the total cost in ETH for this transaction at current gas prices:
- Gas limit: 21000
- Max fee: 30 gwei
- Priority fee: 2 gwei

Compare transactions:

Compare these two transactions and highlight the differences:
Transaction 1: 0x...
Transaction 2: 0x...

Keystore Management

Create Encrypted Keystore

From private key:

Create an encrypted keystore file for this private key:
- Private key: 0x...
- Password: MySecurePassword123!
- Use scrypt (more secure)

Generate new encrypted wallet:

Generate a new wallet and immediately encrypt it as a keystore:
- Password: MySecurePassword123!
- Return the keystore JSON

Decrypt Keystore

Get private key:

Decrypt this keystore to get the private key:
[paste keystore JSON]
Password: MySecurePassword123!

Just get the address:

What's the address in this keystore? (don't decrypt)
[paste keystore JSON]

Keystore Operations

Change password:

Change the password on this keystore:
[paste keystore JSON]
Old password: OldPassword123
New password: NewSecurePassword456!

Validate keystore:

Is this a valid Web3 Secret Storage keystore?
[paste keystore JSON]

Validation & Utilities

Address Validation

Single address:

Is this a valid Ethereum address? 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed

Check checksum:

Does this address have a valid EIP-55 checksum?
0x5aaEB6053f3e94C9b9A09f33669435e7ef1beaed

Convert to checksum:

Convert this address to checksummed format:
0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed

Batch validation:

Check which of these addresses are valid:
- 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
- 0x1234
- 0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359
- invalid

Private Key Validation

Validate key:

Is this a valid Ethereum private key?
0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318

Security check:

Check if this private key is secure (not a known weak key):
0x0000000000000000000000000000000000000000000000000000000000000001

Hashing & Selectors

Keccak256 hash:

Compute the keccak256 hash of "Hello, Ethereum!"

Function selector:

What's the function selector for transfer(address,uint256)?

Decode selector:

What function does selector 0xa9059cbb correspond to?

Storage Slots

Calculate mapping slot:

Calculate the storage slot for a mapping at slot 2 with key 0xABC...

Dynamic array slot:

Calculate the storage slot for the first element of a dynamic array at slot 5

Advanced Workflows

Complete Wallet Backup Flow

Help me create a complete backup of my wallet:
1. Generate a new wallet with mnemonic
2. Create an encrypted keystore as additional backup
3. Show me how to verify I can restore from both

Token Permit Flow (Gasless Approval)

Walk me through creating a gasless ERC-20 permit:
1. I want to approve Uniswap to spend my USDC
2. Generate the EIP-712 typed data
3. Sign it with my private key
4. Show me the permit parameters to submit on-chain

Multi-Account Setup

Set up a hierarchical wallet structure:
1. Generate a master seed phrase (24 words)
2. Derive 3 accounts:
   - Account 0: Main spending wallet
   - Account 1: Savings (cold storage)
   - Account 2: DeFi interactions
3. Create keystores for each with different passwords

Security Audit

Audit the security of this private key:
0x...

Check for:
- Known weak keys
- Proper entropy
- Valid curve point

Transaction Debugging

I have a transaction that failed. Help me debug it:

Raw transaction: 0x...

Please:
1. Decode the transaction completely
2. Validate all fields
3. Identify potential issues
4. Suggest fixes

Tips for Effective Prompting

Be Specific About Networks

✅ "Sign a transaction for Ethereum mainnet (chain ID 1)"
❌ "Sign a transaction"

Include All Required Data

✅ "Sign message 'Hello' with private key 0x..."
❌ "Sign a message"

Specify Formats When Needed

✅ "Return the signature in v/r/s format as well as the packed format"
❌ "Sign and give me the signature"

Use Appropriate Security Practices

✅ "Generate a test wallet for development"
❌ "Generate a wallet" (when just testing)

Chain Operations When Useful

✅ "Generate a wallet, then create a signed message proving ownership"
❌ Two separate prompts that lose context

Common Patterns

Verification Pattern

  1. Generate/import wallet
  2. Sign a message
  3. Verify the signature
  4. Confirm the recovered address matches

Safe Keystore Pattern

  1. Generate wallet with mnemonic (backup #1)
  2. Create encrypted keystore (backup #2)
  3. Verify both backups work
  4. Securely delete temporary private key

Transaction Preparation Pattern

  1. Build unsigned transaction
  2. Validate all fields
  3. Estimate gas costs
  4. Sign transaction
  5. Verify signed transaction decodes correctly

Security Reminders

⚠️ When using these prompts:

  1. Never use real private keys in examples - Always use test keys
  2. Clear conversation history after sharing sensitive data
  3. Verify addresses independently before sending real funds
  4. Use test networks first (Sepolia, Goerli) for experimentation
  5. Keep seed phrases offline - Only use encrypted keystores for regular access

Vanity Address Research & Security Resources

DISCLAIMER: FOR EDUCATIONAL PURPOSES ONLY

This software is provided for educational and research purposes only. DO NOT USE WITH REAL FUNDS. The author accepts NO LIABILITY for any damages. All example addresses shown are for illustrative purposes only.

A comprehensive compilation of research papers, technical articles, and security analyses related to cryptocurrency vanity addresses, their generation, vulnerabilities, and associated attack vectors.


Table of Contents

  1. Introduction
  2. What Are Vanity Addresses?
  3. Generation Methods
  4. Security Vulnerabilities
  5. Address Poisoning Attacks
  6. Arbitrage Ecosystem Context
  7. Cryptocurrency Derivatives & Market Context
  8. Safe Usage Guidelines
  9. Notable Incidents
  10. Works Cited

Introduction

Vanity addresses are custom cryptocurrency wallet addresses created using specific algorithms to incorporate user-chosen character sequences. While they serve legitimate purposes such as gas optimization, protocol branding, and multichain reproducibility, they have also been associated with significant security vulnerabilities and attack vectors.

This document compiles research from academic papers, security analyses, and technical blog posts to provide a comprehensive understanding of vanity addresses in the cryptocurrency ecosystem.


What Are Vanity Addresses?

Definition

When generating a cryptocurrency wallet, the system produces an address composed of a random string of characters. These default addresses lack personal significance. A vanity address is a custom address generated using specific algorithms that incorporate a user-chosen sequence of characters into the wallet address.

Common Use Cases

  1. Gas Optimization: Transaction gas costs decrease if an address has leading zeros. According to the Ethereum yellowpaper, leading zeros are cheaper for gas calculations. Wintermute reportedly saved $15,000 in gas costs due to their EOA having leading zeros (foobar).

  2. Protocol Branding: Companies use vanity addresses for easy recognition. For example, protocols often use addresses starting with recognizable patterns like 0x1111... or 0x0000... for branding.

  3. Multichain Reproducibility: Protocols can deploy to multiple EVM chains with the same contract address, simplifying documentation and user experience.

Technical Characteristics

Creating vanity addresses is computationally intensive. The algorithm must try many combinations before finding an address that includes the chosen string of characters. The higher the number of prefixes and suffixes requested, the more time and computational resources required.

For reference, using optimized GPU mining (RTX 3090 at ~2 billion attempts/second):

  • 5-leading-zero-byte address: ~8 minutes
  • 6-leading-zero-byte address: ~36 hours
  • 7-leading-zero-byte address: ~387 days

Generation Methods

Profanity Generator

Profanity is an open-source vanity address generator. The basic workflow:

  1. A "random" private key is generated
  2. The corresponding Ethereum address is calculated
  3. The address is compared against the user's desired pattern
  4. If not matched, the private key is incremented by one and the process repeats
  5. GPUs accelerate this process to hundreds of millions of checks per second

Critical Flaw: The profanity code uses a pseudo-random number generator called mt19937, which only outputs 8 bytes at a time and takes a 4-byte unsigned int seed (fed by a random_device call). Since Ethereum private keys are 32 bytes, the code must combine 4 outputs. The mt19937_64 generator is only seeded once, so outputs don't change if the input seed is reused. This reduces complexity from 2^256 to 2^32 (James).

CREATE vs CREATE2 Deployment

CREATE (Default):

new_address = hash(sender, nonce)
  • Address determined by hashing contract creator address with creator nonce
  • Nonce increments with each transaction
  • Vulnerable to ordering mistakes across chains

CREATE2 (Recommended for Vanity):

new_address = hash(0xFF, sender, salt, bytecode)
  • Uses a user-chosen salt for vanity address generation
  • Salt can be made public without security risk
  • Enables permissionless deployment across chains
  • Bytecode parameter ensures identical functionality across chains

Safe Generation Tools

  • create2crunch: GPU-optimized tool for finding CREATE2 salts
  • CREATE2 Factory: A common CREATE2 factory contract is deployed on many EVM chains

Security Vulnerabilities

The Profanity Vulnerability (CVE-2022-XXXXX)

The fundamental flaw in Profanity's random number generation:

// Vulnerable code from Dispatcher.cpp
// Uses mt19937 with only 4-byte seed
// Reduces keyspace from 2^256 to 2^32

Impact: All starting private keys that could be generated by this program can be generated and saved in just a few hours using less than 2TB of hard drive space (James).

EOA vs Smart Contract Safety

EOAs (Externally Owned Accounts):

  • UNSAFE for vanity generation
  • Private key controls funds
  • If randomness is compromised, entire account is ruined

Smart Contract Accounts:

  • SAFE for vanity generation
  • Only requires iterating through public seeds
  • Seeds do not grant admin permissions

As stated by foobar: "EOA vanity is the road to bankruptcy, smart contract vanity is the road to success."

Exchange Attribution in Arbitrage Research

Research from UCSB identified 50,081 addresses as decentralized exchanges through arbitrage detection. Attribution was done by:

  • Checking for smart contract source code
  • Vanity address labels added to Etherscan
  • Automated scanning for Uniswap v2 clone factory event logs

This research revealed 180 unique Uniswap v2 factories, demonstrating how vanity addresses can be used for exchange identification (McLaughlin et al. 3299).


Address Poisoning Attacks

Overview

Address poisoning aims to create a vanity address resembling a legitimate wallet that the target frequently interacts with. The attacker then:

  1. Transfers scam tokens mimicking legitimate ones
  2. Or sends low/no value coin transfers
  3. These transactions "poison" the target's transaction history
  4. The victim may copy the wrong address for future transactions

Typically, the first 4-6 characters and last 4-6 characters are made to resemble the target address.

Example (FAKE illustrative addresses):

  • Legitimate: 0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234
  • Attacker: 0xABCD5678000056780000567800005678ABCD5678

(Notice first 4 and last 4 characters match)

Attack Techniques

Fake Token Transfers

Attackers send fake tokens (e.g., fake USDT) to wallets with addresses similar to ones that received legitimate tokens. These fake token contracts may:

  • Allow transfers without owning the token
  • Have token balances stored in contract storage without mint transactions
  • Use unverified contracts

Zero Value Spam

With tokens like USDT, transferring 0 amount records on the ledger. Scammers:

  1. Spoof transactions to appear as if the target is sending zero value
  2. Create vanity addresses mimicking legitimate recipients
  3. Sometimes send small amounts (<$10 USDC) to avoid detection flags

Major Incident: May 3, 2024

A victim lost 1,155 WBTC (~$72M) by copying the wrong address from their transaction history. Remarkably, the stolen funds were eventually returned to the victim (CertiK).


Arbitrage Ecosystem Context

DEX Arbitrage and Vanity Addresses

Research from McLaughlin et al. at UCSB conducted a 28-month study (February 2020 - July 2022) analyzing the Ethereum arbitrage ecosystem. Key findings relevant to vanity addresses:

Exchange Identification

  • 50,081 addresses identified as DEXs
  • Manual examination used vanity address labels on Etherscan
  • 180 unique Uniswap v2 factories discovered

Arbitrage Statistics

  • 3.8 million arbitrages identified
  • $321 million in total profit
  • 4 billion arbitrage opportunities detected
  • Weekly profit potential: 395 Ether (~$500,000)

Exchange Distribution (by frequency in arbitrage)

Exchange Usage %
Uniswap v2 44.9%
Uniswap v3 15.2%
Sushi Swap 13.5%
Balancer v1 10.8%
Unknown 5.4%

Arbitrage Cycle Properties

  • 98% contain exactly one exchange cycle
  • 91% use either two or three exchanges
  • 92% use Wrapped Ether (WETH) as profit token

Security Implications

The research identified threats to consensus stability:

  • Increasing percentage of arbitrage revenue paid to miners/validators
  • This could incentivize "time-bandit attacks" where block producers fork the blockchain to capture high-value MEV blocks

Cryptocurrency Derivatives & Market Context

BitMEX Case Study

Research from Soska et al. at Carnegie Mellon University provides context on how vanity addresses are used in the broader cryptocurrency trading ecosystem.

Platform Characteristics

  • Trades over $3 billion daily volume
  • Up to 100x leverage on Bitcoin
  • Over 600,000 trader accounts
  • All operations in Bitcoin (no fiat conversion)

Vanity Address Usage

BitMEX uses vanity addresses for customer deposit accounts:

  • Unique 3BMEX prefix for all customer addresses
  • 610,000+ addresses with this prefix identified
  • Used for automated account identification and filtering

Clustering Analysis

The researchers developed methods to cluster BitMEX accounts:

  1. Rule-based clustering using deposit transaction patterns
  2. Community detection via Label Propagation algorithm
  3. Service detection to filter exchanges and dusters

Results showed sophisticated traders operating multiple accounts:

  • 90% of accounts are singletons
  • <1% belong to clusters of 5+ accounts
  • Largest clusters contain 50+ accounts

Trader Sophistication Indicators

Analysis of vanity address clusters revealed:

  • Larger clusters have higher average deposits
  • Multiple accounts used to circumvent leverage restrictions
  • API rate limit multiplexing
  • Flow obfuscation to prevent front-running

Safe Usage Guidelines

For EOAs (Externally Owned Accounts)

DO NOT use vanity generators for EOAs. The only truly reliable method is to generate addresses yourself with cryptographically secure randomness. Even then, vulnerabilities in generation software can compromise security.

For Smart Contracts

Smart contract vanity addresses are safe when using CREATE2:

  1. Use a CREATE2 factory contract
  2. Choose a salt that produces desired address characteristics
  3. Salt can be made public without security implications
  4. Verify bytecode matches across all chain deployments

Proper Random Number Generation Fix

To fix the Profanity vulnerability, proper seeding is required:

// Instead of single 4-byte seed
// Use 624-word seed for mt19937
// Or use cryptographically secure RNG

The fix requires feeding a random seed sequence of at least 32 bits to ensure mt19937 produces cryptographically secure outputs (James).

User Protection Against Address Poisoning

  1. Always double-check full addresses before sending funds
  2. Use address books/whitelists in wallet software
  3. Be suspicious of unfamiliar tokens in transaction history
  4. Verify addresses through multiple sources
  5. Use blockchain explorers that flag suspicious addresses

Notable Incidents

Wintermute Hack (September 2022)

  • Loss: $160 million
  • Cause: Bad randomness in Profanity vanity address generator
  • Method: Attacker replayed search iteration to recreate (private key, public address) pair
  • Target: EOA with leading zeros for gas optimization

Indexed Finance Exploiter (October 2021 → September 2022)

  • Initial Exploit: $16 million stolen
  • Address: Started with 0xba5ed... ("based")
  • Irony: Same Profanity vulnerability exploited
  • Result: All funds stolen again by another attacker

Address Poisoning Victim (May 3, 2024)

  • Loss: 1,155 WBTC (~$72 million)
  • Cause: Copied wrong address from transaction history
  • Outcome: Funds eventually returned

Technical Appendix

CREATE2 Salt Mining

Using create2crunch on vast.ai (RTX 3090):

# Install
sudo apt install build-essential -y
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
git clone https://github.com/0age/create2crunch && cd create2crunch
sed -i 's/0x4/0x40/g' src/lib.rs

# Run search
export FACTORY="0xYourFactoryAddress"
export CALLER="0xYourCallerAddress"
export INIT_CODE_HASH="0xYourInitCodeHash"
export LEADING=5
export TOTAL=7
cargo run --release $FACTORY $CALLER $INIT_CODE_HASH 0 $LEADING $TOTAL

Keyless Transaction Deployment

The CREATE2 Factory uses ENS founder Nick Johnson's "keyless transaction" approach:

  1. Create deployment transaction
  2. Generate fake signature (e.g., all 2's)
  3. Recover public address from signature
  4. Send ETH to that address
  5. Submit signed transaction to mempool

This creates a single-use EOA that can only ever deploy one transaction.


Works Cited

CertiK. "Vanity Address and Address Poisoning." CertiK Resources, 29 July 2024, www.certik.com/resources/blog/vanity-address-and-address-poisoning.

foobar. "Vanity Addresses: The Only Safe Way to Do Permissionless Multichain Deployments." 0xfoobar Substack, 10 Jan. 2023, 0xfoobar.substack.com/p/vanity-addresses.

Garreau, Marc. "Web3.py Patterns: Address Mining." Snake Charmers (Ethereum Foundation), 4 Oct. 2021, snakecharmers.ethereum.org/web3-py-patterns-address-mining/.

James. "Fixing Other People's Code." Oregon State University Blogs, 6 Feb. 2023, blogs.oregonstate.edu/james/2023/02/.

McLaughlin, Robert, et al. "A Large Scale Study of the Ethereum Arbitrage Ecosystem." 32nd USENIX Security Symposium, 9-11 Aug. 2023, Anaheim, CA, USA, pp. 3295-3312. USENIX Association, www.usenix.org/conference/usenixsecurity23/presentation/mclaughlin.

Soska, Kyle, et al. "Towards Understanding Cryptocurrency Derivatives: A Case Study of BitMEX." Proceedings of the Web Conference 2021 (WWW '21), 19-23 Apr. 2021, Ljubljana, Slovenia. ACM, New York, NY, USA, doi.org/10.1145/3442381.3450059.


Additional References

From McLaughlin et al. Paper

  • Daian, Philip, et al. "Flash Boys 2.0: Frontrunning in Decentralized Exchanges, Miner Extractable Value, and Consensus Instability." 2020 IEEE Symposium on Security and Privacy (SP), 2020, pp. 910-927.

  • Qin, Kaihua, et al. "Quantifying Blockchain Extractable Value: How Dark Is the Forest?" 2022 IEEE Symposium on Security and Privacy (SP), 2022, pp. 198-214.

  • Wang, Ye, et al. "Cyclic Arbitrage in Decentralized Exchanges." Companion Proceedings of the Web Conference 2022 (WWW '22), 2022, pp. 12-19. ACM.

  • Zhou, Liyi, et al. "On the Just-in-Time Discovery of Profit-Generating Transactions in DeFi Protocols." 2021 IEEE Symposium on Security and Privacy (SP), 2021, pp. 919-936.

From Soska et al. Paper

  • Gandal, Neil, et al. "Price Manipulation in the Bitcoin Ecosystem." Journal of Monetary Economics, vol. 95, 2018, pp. 86-96.

  • Meiklejohn, Sarah, et al. "A Fistful of Bitcoins: Characterizing Payments Among Men with No Names." Proceedings of the 2013 Internet Measurement Conference, 2013, pp. 127-140.

  • Nakamoto, Satoshi. "Bitcoin: A Peer-to-Peer Electronic Cash System." 2008.


Document compiled: January 2026

For the ethereum-wallet-toolkit project

Keystore Operations

DISCLAIMER: FOR EDUCATIONAL PURPOSES ONLY

This software is provided for educational and research purposes only. DO NOT USE WITH REAL FUNDS. The author accepts NO LIABILITY for any damages. All example addresses and keys shown are FAKE - never use them for real funds.

This document covers the keystore encryption and decryption features of the Ethereum Wallet Toolkit.

Overview

Keystores are encrypted JSON files that securely store private keys. They follow the Web3 Secret Storage Definition (Version 3) and are compatible with all major Ethereum wallets including MetaMask, Geth, and MyEtherWallet.

Security Model

Key Derivation Functions

The toolkit supports two KDF algorithms:

KDF Security Speed Recommended
scrypt Higher Slower Yes (default)
pbkdf2 Good Faster For compatibility

scrypt (default):

  • Memory-hard function resistant to ASIC attacks
  • Parameters: N=262144, r=8, p=1
  • More secure against brute-force attacks

pbkdf2:

  • Uses HMAC-SHA256
  • Default iterations: 262144
  • Faster but less resistant to hardware attacks

Encryption

  • Cipher: AES-128-CTR
  • Key derivation produces a 256-bit key
  • First 128 bits used for encryption
  • Last 128 bits used for MAC verification

CLI Usage

Using keystore.py (Standalone)

# Encrypt a private key
python keystore.py encrypt --key 0x... --password mypassword --output wallet.json

# Encrypt with secure password prompt
python keystore.py encrypt --key 0x... --output wallet.json

# Use PBKDF2 instead of scrypt
python keystore.py encrypt --key 0x... --password secret --kdf pbkdf2 --output wallet.json

# Decrypt a keystore
python keystore.py decrypt --file wallet.json --password mypassword

# Decrypt with password prompt (more secure)
python keystore.py decrypt --file wallet.json

# View keystore info without decryption
python keystore.py info --file wallet.json

# Change keystore password
python keystore.py change-password --file wallet.json

Using eth_toolkit.py (Main Toolkit)

# Encrypt
python eth_toolkit.py keystore --encrypt --key 0x... --password secret --output wallet.json

# Decrypt
python eth_toolkit.py keystore --decrypt --file wallet.json --password secret

Keystore File Format

{
  "version": 3,
  "id": "uuid-here",
  "address": "abcdefghijkabcdefghijklmnopqrstuvwxyz",
  "crypto": {
    "ciphertext": "encrypted-private-key",
    "cipherparams": {
      "iv": "initialization-vector"
    },
    "cipher": "aes-128-ctr",
    "kdf": "scrypt",
    "kdfparams": {
      "dklen": 32,
      "salt": "random-salt",
      "n": 262144,
      "r": 8,
      "p": 1
    },
    "mac": "message-authentication-code"
  }
}

Python API

from keystore import (
    encrypt_keystore,
    decrypt_keystore,
    save_keystore,
    load_keystore,
    get_keystore_info
)

# Encrypt a private key
keystore = encrypt_keystore(
    private_key='0x...',
    password='my-secure-password',
    kdf='scrypt'
)

# Save to file
filepath = save_keystore(keystore, 'my-wallet.json')

# Load from file
keystore = load_keystore('my-wallet.json')

# Get info without decryption
info = get_keystore_info(keystore)
print(f"Address: {info['address']}")
print(f"KDF: {info['kdf']}")

# Decrypt
private_key = decrypt_keystore(keystore, 'my-secure-password')

Best Practices

Password Security

  1. Use strong passwords: Minimum 12 characters with mixed case, numbers, symbols
  2. Never reuse passwords: Each keystore should have a unique password
  3. Use a password manager: Store passwords securely
  4. Avoid command-line passwords: Use the prompt feature instead of --password
# Good - password prompted securely
python keystore.py encrypt --key 0x... --output wallet.json

# Avoid - password visible in shell history
python keystore.py encrypt --key 0x... --password secret --output wallet.json

File Storage

  1. Backup keystores: Keep multiple copies in secure locations
  2. Encrypt backups: Use additional encryption for cloud storage
  3. Control access: Restrict file permissions (chmod 600)
  4. Never share: Keystore + password = full access to funds

Testing

Always test decryption after creating a keystore:

# Create keystore
python keystore.py encrypt --key 0x... --output test.json

# Verify decryption works
py