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 utilitiesethereum-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:
- Bundle all ethereumjs libraries and their dependencies
- Minify the code for smaller file size
- 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
- Prompt Examples - Real-world prompts for interacting with the servers
- Testing Guide - How to run and write tests
- Integration Guide - Setting up with Claude Desktop and other tools
- Workflows & Recipes - Common workflows combining multiple servers
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 walletgenerate_wallet_with_mnemonic- BIP39 mnemonic walletrestore_wallet_from_mnemonic- Restore from seed phraserestore_wallet_from_private_key- Restore from private keyderive_multiple_accounts- HD wallet derivationgenerate_vanity_address- Custom prefix/suffix addresses
Resources:
wallet://documentation/bip39- BIP39 specwallet://documentation/derivation-paths- HD pathswallet://wordlist/{language}- BIP39 wordlists
keystore-mcp-server
Encrypted Keystore Files (Web3 Secret Storage)
Tools:
encrypt_keystore- Create encrypted keystore from private keydecrypt_keystore- Decrypt keystore to get private keychange_keystore_password- Re-encrypt with new passwordvalidate_keystore- Verify keystore structureget_keystore_address- Extract address without decryptiongenerate_encrypted_wallet- Create new wallet as keystoreread_keystore_file- Read keystore from filesystemwrite_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_signverify_message- Verify signed messagehash_message- Create message hashsign_typed_data- EIP-712 structured dataverify_typed_data- Verify typed data signatureencode_typed_data- Encode without signingrecover_signer- Recover address from signature
transaction-mcp-server
Transaction Building & Signing
Tools:
build_transaction- Create unsigned transactionsign_transaction- Sign with private keydecode_transaction- Parse raw transactionencode_transaction- RLP encode transactionestimate_gas- Calculate gas requirementscalculate_transaction_hash- Pre-signing hashbuild_eip1559_transaction- Type 2 transactionsbuild_legacy_transaction- Type 0 transactionsbuild_access_list_transaction- Type 1 transactionsserialize_transaction- Convert to wire formatparse_transaction_input- Decode calldatavalidate_transaction- Check transaction validity
validation-mcp-server
Validation & Cryptographic Utilities
Tools:
validate_address- EIP-55 checksum validationvalidate_private_key- Key range checkingto_checksum_address- Convert to checksummedderive_address_from_private_key- Key → addressderive_address_from_public_key- Pubkey → addressvalidate_signature- Check v, r, s valuesvalidate_hex_data- Hex string validationcompare_addresses- Address equalitybatch_validate_addresses- Bulk validationgenerate_vanity_check- Pattern matchingkeccak256_hash- Compute Keccak-256encode_function_selector- Signature → selectordecode_function_selector- Lookup selectorsvalidate_ens_name- ENS format validationcalculate_storage_slot- Storage slot computation
Resources:
validation://eip55-specification- EIP-55 docsvalidation://secp256k1-constants- Curve paramsvalidation://function-selectors-db- 500+ selectorsvalidation://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:
- An
*_impl()function with pure business logic (for testing) - 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, signingeth-keys- ECDSA operationseth-utils- Utility functionseth-rlp- RLP encodingmnemonic- BIP39 implementationmcp- 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
- Message Signing
- EIP-712 Typed Data
- Transaction Operations
- Keystore Management
- Validation & Utilities
- Advanced Workflows
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
- Generate/import wallet
- Sign a message
- Verify the signature
- Confirm the recovered address matches
Safe Keystore Pattern
- Generate wallet with mnemonic (backup #1)
- Create encrypted keystore (backup #2)
- Verify both backups work
- Securely delete temporary private key
Transaction Preparation Pattern
- Build unsigned transaction
- Validate all fields
- Estimate gas costs
- Sign transaction
- Verify signed transaction decodes correctly
Security Reminders
⚠️ When using these prompts:
- Never use real private keys in examples - Always use test keys
- Clear conversation history after sharing sensitive data
- Verify addresses independently before sending real funds
- Use test networks first (Sepolia, Goerli) for experimentation
- 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
- Introduction
- What Are Vanity Addresses?
- Generation Methods
- Security Vulnerabilities
- Address Poisoning Attacks
- Arbitrage Ecosystem Context
- Cryptocurrency Derivatives & Market Context
- Safe Usage Guidelines
- Notable Incidents
- 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
-
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).
-
Protocol Branding: Companies use vanity addresses for easy recognition. For example, protocols often use addresses starting with recognizable patterns like
0x1111...or0x0000...for branding. -
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:
- A "random" private key is generated
- The corresponding Ethereum address is calculated
- The address is compared against the user's desired pattern
- If not matched, the private key is incremented by one and the process repeats
- 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:
- Transfers scam tokens mimicking legitimate ones
- Or sends low/no value coin transfers
- These transactions "poison" the target's transaction history
- 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:
- Spoof transactions to appear as if the target is sending zero value
- Create vanity addresses mimicking legitimate recipients
- 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
3BMEXprefix 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:
- Rule-based clustering using deposit transaction patterns
- Community detection via Label Propagation algorithm
- 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:
- Use a CREATE2 factory contract
- Choose a salt that produces desired address characteristics
- Salt can be made public without security implications
- 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
- Always double-check full addresses before sending funds
- Use address books/whitelists in wallet software
- Be suspicious of unfamiliar tokens in transaction history
- Verify addresses through multiple sources
- 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:
- Create deployment transaction
- Generate fake signature (e.g., all 2's)
- Recover public address from signature
- Send ETH to that address
- 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
- Use strong passwords: Minimum 12 characters with mixed case, numbers, symbols
- Never reuse passwords: Each keystore should have a unique password
- Use a password manager: Store passwords securely
- 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
- Backup keystores: Keep multiple copies in secure locations
- Encrypt backups: Use additional encryption for cloud storage
- Control access: Restrict file permissions (chmod 600)
- 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
No comments yet
Be the first to share your take.