Crates.io | mevlog |
lib.rs | mevlog |
version | 0.7.1 |
created_at | 2025-03-08 12:10:46.262269+00 |
updated_at | 2025-09-15 23:12:48.101976+00 |
description | EVM transactions monitoring and querying CLI powered by Revm |
homepage | |
repository | https://github.com/pawurb/mevlog-rs |
max_upload_size | |
id | 1584362 |
size | 1,900,739 |
Rust-based CLI tool for querying Ethereum (or any EVM-compatible chain) transactions, with flexible filtering and EVM tracing capabilities.
When working on an MEV bot, I could not find a simple way to search for specific transactions. I wrote one-off query scripts, and wanted to generalize them in an easy to reuse tool. So I started building mevlog
to work as an "SQL for blockchain".
mevlog
allows you to find and analyze transaction details via a simple CLI interface. It currently offers the following features:
It works on public RPCs thanks to leveraging EVM tracing via Revm.
You can check out this article for technical details on how this project is implemented.
There's also a beta web version available.
⚠️ Note
This README reflects the latest development on themain
branch. For documentation matching the current release, see crates.io — it stays in sync with the published crate.
Mevlog uses cryo CLI for fetching data. Please install it first by running:
cargo install cryo_cli
and then:
git clone https://github.com/pawurb/mevlog-rs
cd mevlog-rs
cargo install --path .
or install from the crates.io:
cargo install mevlog
mevlog watch --rpc-url https://eth.merkle.io
You can connect to chains using either a direct RPC URL or by specifying a chain ID:
Using RPC URL:
mevlog watch --rpc-url https://eth.merkle.io
Using Chain ID:
mevlog watch --chain-id 1 # Ethereum mainnet
mevlog watch --chain-id 137 # Polygon
mevlog watch --chain-id 56 # BSC
When using --chain-id
, mevlog automatically fetches available RPC URLs from ChainList, benchmarks them, and selects the fastest responding endpoint. Please remember that --trace rpc
will likely not work with public RPC endpoints. And --trace revm
could be throttled.
To discover available chain IDs, use the chains
command:
mevlog chains --filter arbitrum # Find Arbitrum-related chains
mevlog chains --filter base # Find Base-related chains
mevlog chains --chain-id 1 --chain-id 137 # Show specific chains by ID
mevlog chains --limit 10 # Show only first 10 chains
On initial run mevlog
downloads ~80mb openchain.xyz signatures, and ChainList data database to ~/.mevlog
. Signatures data allows displaying human readable info instead of hex blobs.
To avoid throttling on public endpoints watch
mode displays only the top 5 transactions from each block.
You can change it using the --position
argument:
## display the top 20 txs from each new block
mevlog watch -p 0:19
Here's a complete list of currently supported filters:
Options:
--limit <LIMIT>
Limit the number of transactions returned
--sort <SORT>
Sort transactions by field (gas-price, gas-used, tx-cost, full-tx-cost, erc20Transfer|<token_address>)
--sort-dir <SORT_DIR>
Sort direction (desc, asc) [default: desc]
-f, --from <FROM>
Filter by tx source address or ENS name
--to <TO>
Filter by tx target address or ENS name, or CREATE transactions
-t, --touching <TOUCHING>
Filter by contracts with storage changed by the transaction
--rpc-url <RPC_URL>
The URL of the HTTP provider [env: ETH_RPC_URL]
--chain-id <CHAIN_ID>
Chain ID to automatically select best RPC URL
--event <EVENT>
Include txs by event names matching the provided regex or signature and optionally an address
--not-event <NOT_EVENT>
Exclude txs by event names matching the provided regex or signature and optionally an address
--method <METHOD>
Include txs with root method names matching the provided regex, signature or signature hash
--calls <CALLS>
Include txs by subcalls method names matching the provided regex, signature or signature hash
--show-calls
Show detailed tx calls info
--tx-cost <TX_COST>
Filter by tx cost (e.g., 'le0.001ether', 'ge0.01ether')
--real-tx-cost <REAL_TX_COST>
Filter by real (including coinbase bribe) tx cost (e.g., 'le0.001ether', 'ge0.01ether')
--gas-price <GAS_PRICE>
Filter by effective gas price (e.g., 'ge2gwei', 'le1gwei')
--real-gas-price <REAL_GAS_PRICE>
Filter by real (including coinbase bribe) effective gas price (e.g., 'ge3gwei', 'le2gwei')
--value <VALUE>
Filter by transaction value (e.g., 'ge1ether', 'le0.1ether')
--erc20-transfer <TRANSFER>
Filter by Transfer events with specific address and optionally amount (e.g., '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' or '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48|ge1000gwei')
--erc20-transfer-amount
Display transfer amounts in ERC20 Transfer event logs
--ens
Enable ENS name resolution for addresses (increases RPC calls)
--erc20-symbols
Enable ERC20 token symbol resolution (increases RPC calls)
--failed
Show only txs which failed to execute
--format <FORMAT>
Output format ('text', 'json', 'json-pretty', 'json-stream', 'json-pretty-stream')
Both search
and watch
support the same filtering options.
A few examples of currently supported queries:
jaredfromsubway.eth
transactions from the last 20 blocks that landed in positions 0-5:mevlog search -b 10:latest -p 0:5 --from jaredfromsubway.eth --chain-id 1
mevlog search -b --method "<Unknown>" -p 0 --chain-id 1
mevlog search -b 50:latest --event "Transfer(address,address,uint256)|0x6982508145454ce325ddbe47a25d4ec3d2311933" --chain-id 1
Swap
events:mevlog search -b 22034300:22034320 -p 0 --not-event "/(Swap).+/"
rebase
and Transfer
keywords:mevlog search -b 22045400:22045420 --event "/(?i)(rebase).+/" --event "/(Transfer).+/"
mevlog search -b 22045400:22045420 --to CREATE
mevlog search -b 10:latest --value ge1ether
mevlog search -b 10:latest --erc20-transfer "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48|ge100gwei"
mevlog search -b 10:latest --erc20-transfer "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" --erc20-transfer-amount
mevlog search -b 20:latest --sort gas-price --limit 10
mevlog search -b 10:latest --sort full-tx-cost --limit 5 --trace rpc
mevlog search -b 10:latest --sort gas-price --sort-dir asc --limit 10
mevlog search -b 50:latest --sort "erc20Transfer|0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" --limit 1 --chain-id 1
The --event
and --not-event
options allow filtering transactions based on emitted events. The filter criteria can be:
0x6982508145454ce325ddbe47a25d4ec3d2311933
Transfer(address,uint256)
/(?i)(rebase).+/
Transfer(address,uint256)|0x6982508145454ce325ddbe47a25d4ec3d2311933
You can supply mutiple --event
and --not-event
flags for precise control over which transactions are included or excluded.
The --erc20-transfer
option allows filtering transactions that emitted ERC20 Transfer events. The filter criteria can be:
0xa0b86a33e6ba3bc6c2c5ed1b4b29b5473fd5d2de
0xa0b86a33e6ba3bc6c2c5ed1b4b29b5473fd5d2de|ge1000
(transfers >= 1000 tokens)ge
(greater or equal), le
(less or equal)ether
, gwei
, etc.You can supply multiple --erc20-transfer
flags to match transfers from different tokens or with different amount criteria.
By default, transfer amounts are not displayed in the logs. Use the --erc20-transfer-amount
flag to show transfer amounts alongside the Transfer events.
You can enable ENS name resolution and ERC20 token symbol lookup for transfers and Uniswap swaps using the --ens
and --erc20-symbols
flags:
# Enable ENS name display for addresses
mevlog search -b 10:latest --ens --chain-id 1
# Enable ERC20 token symbols display
mevlog search -b 10:latest --erc20-symbols --chain-id 1
# Enable both ENS and token symbols
mevlog search -b 10:latest --ens --erc20-symbols --chain-id 1
Performance considerations:
⚠️ Warning: Enabling these flags increases RPC calls and may cause throttling on public endpoints.
Recommended usage pattern:
# Cache popular symbols and ENS names from recent blocks
mevlog search -b 10:latest --ens --erc20-symbols --chain-id 1
# Use cached ENS/symbol data only (no additional RPC calls)
mevlog search -b 100:latest --chain-id 1
The tool maintains persistent caches in ~/.mevlog/.ens-cache
and ~/.mevlog/.symbols-cache
. Once populated, cached values are used automatically even when the flags are disabled.
All the above queries use only standard block and logs input. By enabling --trace [rpc|revm]
flag you can query by more conditions:
mevlog search -b 5:latest -p 0 --real-tx-cost ge0.02ether --trace revm
mevlog search -b 10:latest --touching 0xba12222222228d8ba445958a75a0704d566bf2c8 --trace rpc
You can also filter by real (including bribe) gas price:
mevlog search -b 5:latest -p 0:5 --real-gas-price ge10gwei --trace rpc
It's possible to search txs by their sub method calls:
mevlog search -b 5:latest -p 0:5 --calls "/(swap).+/" --trace rpc
Mevlog supports different output formats via the --format
option:
text
(default): Human-readable colored output, displays results block by block as they are processedjson
: Compact, oneline JSON output, displays all results at once after processing all blocksjson-pretty
: Pretty-printed JSON output, displays all results at once after processing all blocksjson-stream
: Compact, oneline JSON output, displays results block by block as they are processedjson-pretty-stream
: Pretty-printed JSON output, displays results block by block as they are processedStreaming vs Batch behavior:
text
, json-stream
, json-pretty-stream
): Display results block by block as they are processed, useful for real-time monitoring and large block rangesjson
, json-pretty
): Collect all results in memory and display them at once after processing all blocks, useful for piping to other tools or when you need all results in a single JSON arrayExamples:
# Default human-readable output (streaming)
mevlog search -b 10:latest --format default
# Compact JSON, all results at once
mevlog search -b 10:latest --format json
# Pretty JSON, streaming block by block
mevlog search -b 10:latest --format json-pretty-stream
--trace rpc
This mode uses the debug_traceTransaction
method. It's usually not available on public endpoints.
--trace revm
This mode leverages Revm tracing by downloading all the relevant storage slots and running simulations locally. If you want to trace a transaction at position 10, Revm must first simulate all the previous transactions from this block. It can be slow and cause throttling from public endpoints.
Subsequent revm
simulations for the same block and transaction range use cached data and should be significantly faster.
mevlog tx 0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660 --chain-id 1
This command displays info for a single target transaction. By adding --before
--after
arguments you can include surrounding transactions:
mevlog tx 0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660 -b 1 -a 1 --chain-id 1
You can reverse the display order by adding the --reverse
flag.
mevlog chains # List all available chains
mevlog chains --filter ethereum # Filter chains containing "ethereum"
mevlog chains --filter polygon # Filter chains containing "polygon"
mevlog chains --chain-id 1 --chain-id 137 # Show specific chains by ID
mevlog chains --limit 5 # Show only first 5 chains
mevlog chains --format json # Output as JSON
mevlog chains --format json-pretty # Output as pretty JSON
Sample text output:
Available chains (7 total):
# Chain ID Name
------------------------------------------------------------
1 1 Ethereum Mainnet
2 61 Ethereum Classic
3 1617 Ethereum Inscription Mainnet
4 52226 Cytonic Ethereum Testnet
5 513100 EthereumFair
6 560048 Ethereum Hoodi
7 11155111 Ethereum Sepolia
Sample JSON output:
[
{
"chain_id": 1,
"name": "Ethereum Mainnet",
"chain": "ETH"
},
{
"chain_id": 137,
"name": "Polygon Mainnet",
"chain": "Polygon"
}
]
Options:
--filter <TEXT>
: Filter chains by name (case-insensitive substring match)--chain-id <ID>
: Filter by specific chain IDs (can be used multiple times)--limit <NUMBER>
: Limit the number of chains returned--format <FORMAT>
: Output format ('text', 'json', 'json-pretty')mevlog chain-info --chain-id 1 # Ethereum mainnet
mevlog chain-info --chain-id 56 # BSC mainnet
mevlog chain-info --chain-id 137 # Polygon mainnet
Sample output:
Chain Information
================
Chain ID: 1
Name: Ethereum Mainnet
Currency: ETH
Explorer URL: https://etherscan.io
RPC Timeout: 1s
This command displays detailed information about a specific chain, including current token price and RPC endpoint benchmarks. You can also get JSON output:
mevlog chain-info --chain-id 1 --format json # Compact JSON
mevlog chain-info --chain-id 1 --format json-pretty # Pretty JSON
By default, the command filters RPC endpoints responding under 1000ms (1 second). You can adjust this timeout for networks with slower connections:
mevlog chain-info --chain-id 1 --rpc-timeout-ms 5000 # 5 seconds
You can limit the number of RPC URLs returned (default is 5):
mevlog chain-info --chain-id 1 --rpcs-limit 3 # Return only first 3 responding URLs
mevlog chain-info --chain-id 1 --rpcs-limit 10 # Return up to 10 responding URLs
If you only need basic chain information without RPC URL benchmarking (which is faster), use the --skip-urls
flag:
mevlog chain-info --chain-id 1 --skip-urls
This will display only the core chain information:
Chain Information
================
Chain ID: 1
Name: Ethereum Mainnet
Currency: ETH
Explorer URL: https://etherscan.io
The project currently supports over 2k EVM chains by reading the metadata from ChainList. But only a few chains display $USD txs prices from integrated ChainLink oracles. I'm planning to work on improving the coverage.
If you use it with an unsupported chain, explorer URL and currency symbol is not displayed.
tokio-console
feature adds support for tokio-console:
RUSTFLAGS="--cfg tokio_unstable" cargo run --features=tokio-console --bin mevlog watch
seed-db
feature enables action to populate signatures and chains metadata SQLite database:
cargo run --features=seed-db --bin mevlog seed-db
Benchmark using hotpath lib:
Time:
cargo build --release --features=hotpath
QUIET=1 ./target/release/mevlog search -b 23263469:23263489 --chain-id 1 --skip-verify-chain-id --native-token-price 3000 --rpc-url https://eth.merkle.io
Run once to cache all relevant data. Subsequent invocations won't trigger any RPC calls, so you can profile performance without network overhead. Annotate more methods with [cfg_attr(feature = "hotpath", hotpath::measure)]
if needed.
Allocations:
cargo build --features 'hotpath,hotpath-alloc-bytes-max' --release
QUIET=1 ./target/release/mevlog search -b 23263469:23263489 --chain-id 1 --skip-verify-chain-id --native-token-price 3000 --rpc-url https://eth.merkle.io
WIP, feedback appreciated. I'm currently seeking a sponsor to help cover archive node costs for mevlog.rs. My goal is to make a hosted search web UI publicly available.