# mevlog-rs - explore EVM chains from your terminal
[](https://crates.io/crates/mevlog) [](https://crates.io/crates/mevlog) [](https://github.com/pawurb/mevlog-rs/actions)

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:
- regexp search by emitted event names
- search by ENS domain names
- filter txs based on their position in a block
- search by root and internal method calls
- track smart contract storage changes
- detect validator bribes
- filter by the amount of a specific ERC20 token sent
- filter txs by value and real (including bribe) gas prices and cost
- JSON output formats (compact, pretty, streaming)
- [ChainList](https://chainlist.org/) integration to automatically select RPC endpoints
- TUI dashboard - browse and analyze EVM chains through a terminal-native visual interface (powered by [ratatui.rs](https://ratatui.rs))
It works on public RPCs thanks to leveraging EVM tracing via [Revm](https://github.com/bluealloy/revm).
You can [check out this article](https://pawelurbanek.com/long-tail-mev-revm) for technical details on how this project is implemented.
There's also [a beta web version](https://mevlog.rs/) available.
## Getting started
> **⚠️ Note**
> This README reflects the latest development on the `main` branch.
> For documentation matching the current release, see [crates.io](https://crates.io/crates/mevlog) — it stays in sync with the published crate.
Mevlog uses [cryo CLI](https://github.com/paradigmxyz/cryo) for fetching data. Please install it first by running:
```bash
cargo install cryo_cli
```
and then:
```bash
git clone https://github.com/pawurb/mevlog-rs
cd mevlog-rs
cargo install --path crates/mevlog
```
or install from the [crates.io](https://crates.io/crates/mevlog):
```bash
cargo install mevlog
mevlog search -b 10:latest --rpc-url https://eth.merkle.io
```
### TUI mode
For a more interactive experience, you can use the TUI (Terminal User Interface) mode:
```bash
cargo install mevlog --features=tui
mevlog tui
```
Visit [mevlog.rs/tui](https://mevlog.rs/tui) for more information.
### MCP server
mevlog includes an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that exposes its tools to AI assistants like Claude, Cursor, and others. See [docs/MCP.md](docs/MCP.md) for setup instructions, client configuration, and a full reference of available tools.
### Connection options
You can connect to chains using either a direct RPC URL or by specifying a chain ID:
**Using RPC URL:**
```bash
mevlog search -b 10:latest --rpc-url https://eth.merkle.io
```
**Using Chain ID:**
```bash
mevlog search -b 10:latest --chain-id 1 # Ethereum mainnet
mevlog search -b 10:latest --chain-id 137 # Polygon
mevlog search -b 10:latest --chain-id 56 # BSC
```
When using `--chain-id`, mevlog automatically fetches available RPC URLs from [ChainList](https://chainlist.org/), benchmarks them, and selects the fastest responding endpoint. Please remember that `--evm-trace rpc` will likely not work with public RPC endpoints. And `--evm-trace revm` could be throttled.
To discover available chain IDs, use the `chains` command:
```bash
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](https://openchain.xyz/signatures), and [ChainList data](https://chainlist.org/) database to `~/.mevlog`. Signatures data allows displaying human readable info instead of hex blobs.
## Filtering options
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
--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
--evm-calls
Show detailed tx calls info (requires --evm-trace)
--evm-ops
Display EVM opcodes executed by the transaction (requires --evm-trace)
--evm-state-diff
Display storage slot changes (state diff) for the transaction (requires --evm-trace)
--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
--logs
Include event logs in output
--format <FORMAT>
Output format ('json', 'json-pretty') [default: json-pretty]
--batch-size <SIZE>
Batch size for data fetching (default: 100)
```
The `search` command supports the following filtering options.
A few examples of currently supported queries:
- find `jaredfromsubway.eth` transactions from the last 20 blocks that landed in positions 0-5:
```bash
mevlog search -b 10:latest -p 0:5 --from jaredfromsubway.eth --chain-id 1
```
- unknown method signature contract call in a top position (likely an MEV bot):
```bash
mevlog search -b --method "<Unknown>" -p 0 --chain-id 1
```
- query the last 50 blocks for transaction that transferred [PEPE](https://etherscan.io/token/0x6982508145454ce325ddbe47a25d4ec3d2311933) token:
```bash
- blocks between 22034300 and 22034320, position 0 transaction that did not emit any `Swap` events:
```bash
mevlog search -b 22034300:22034320 -p 0 --not-event "/(Swap).+/"
```
- blocks range for events containing `rebase` and `Transfer` keywords:
```bash
mevlog search -b 22045400:22045420 --event "/(?i)(rebase).+/" --event "/(Transfer).+/"
```
- query by transactions that created a new smart contract:
```bash
mevlog search -b 22045400:22045420 --to CREATE
```
- find transactions that transferred more than 1 ETH:
```bash
mevlog search -b 10:latest --value ge1ether
```
- find transactions that transferred over 100k USDC
```bash
- find transactions that emitted any Transfer events for USDC and display amounts:
```bash
mevlog search -b 10:latest --erc20-transfer "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" --erc20-transfer-amount
```
- find the top 10 transactions from the last 20 blocks sorted by gas price:
```bash
mevlog search -b 20:latest --sort gas-price --limit 10
```
- find the 5 most expensive transactions by total cost from recent blocks:
```bash
mevlog search -b 10:latest --sort full-tx-cost --limit 5 --evm-trace rpc
```
- find the 10 cheapest transactions by gas price (ascending order):
```bash
mevlog search -b 10:latest --sort gas-price --sort-dir asc --limit 10
```
- find transaction that transferred the most USDC in the last 50 blocks:
```bash
### Event filters
The `--event` and `--not-event` options allow filtering transactions based on emitted events. The filter criteria can be:
- a contract address matching on any emitted events `0x6982508145454ce325ddbe47a25d4ec3d2311933`
- a full event signature `Transfer(address,uint256)`
- a regular expression pattern `/(?i)(rebase).+/`
- a combination of an event signature and a contract address `Transfer(address,uint256)|0x6982508145454ce325ddbe47a25d4ec3d2311933`
You can supply mutiple `--event` and `--not-event` flags for precise control over which transactions are included or excluded.
### Transfer filters
The `--erc20-transfer` option allows filtering transactions that emitted ERC20 Transfer events. The filter criteria can be:
- a contract address matching any transfer amount: `0xa0b86a33e6ba3bc6c2c5ed1b4b29b5473fd5d2de`
- a contract address with amount filtering: `0xa0b86a33e6ba3bc6c2c5ed1b4b29b5473fd5d2de|ge1000` (transfers >= 1000 tokens)
- amount operators: `ge` (greater or equal), `le` (less or equal)
- amount units: raw numbers, `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.
### ENS and ERC20 token symbols resolution
You can enable ENS name resolution and ERC20 token symbol lookup for transfers and Uniswap swaps using the `--ens` and `--erc20-symbols` flags:
```bash
# 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:**
1. **Initial cache population**: Enable flags for a small range of recent blocks to cache popular ENS names and ERC20 symbols:
```bash
# Cache popular symbols and ENS names from recent blocks
mevlog search -b 10:latest --ens --erc20-symbols --chain-id 1
```
2. **Regular usage**: Disable flags to use only cached values, reducing RPC calls:
```bash
# 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.
### EVM tracing filters
All the above queries use only standard block and logs input. By enabling `--evm-trace [rpc|revm]` flag you can query by more conditions:
- query last 5 blocks for a top transaction that paid over 0.02 ETH total (including coinbase bribe) transaction cost:
```bash
mevlog search -b 5:latest -p 0 --real-tx-cost ge0.02ether --evm-trace revm
```
- find txs that changed storage slots of the [Balancer vault contract](https://etherscan.io/address/0xba12222222228d8ba445958a75a0704d566bf2c8):
`mevlog search -b 10:latest --touching 0xba12222222228d8ba445958a75a0704d566bf2c8 --evm-trace rpc`
You can also filter by real (including bribe) gas price:
```bash
mevlog search -b 5:latest -p 0:5 --real-gas-price ge10gwei --evm-trace rpc
```
It's possible to search txs by their sub method calls:
```bash
mevlog search -b 5:latest -p 0:5 --calls "/(swap).+/" --evm-trace rpc
```
## Output formats
Mevlog supports different output formats via the `--format` option:
- `json-pretty` (default): Pretty-printed JSON output
- `json`: Compact, oneline JSON output
Both formats collect all results in memory and display them at once after processing all blocks as a single JSON object with `result`, `result_count`, `duration`, `chain`, and `query`.
Examples:
```bash
# Default pretty JSON
mevlog search -b 10:latest
# Compact JSON
mevlog search -b 10:latest --format json
```
Batch JSON example:
```json
{
"result": [
{
"tx_hash": "0x..."
}
],
"result_count": 1,
"duration": "123ms",
"chain": {
"chain_id": 1,
"name": "Ethereum",
"currency": "ETH",
"explorer_url": "https://etherscan.io"
},
"query": {
"command": "search",
"blocks": "10:latest"
}
}
```
## EVM tracing modes
### `--evm-trace rpc`
This mode uses the `debug_traceTransaction` method. It's usually not available on public endpoints.
### `--evm-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.
## Analyzing a single transaction data
```bash
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:
```bash
mevlog tx 0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660 -b 1 -a 1 --chain-id 1
```
You can reverse the display order by adding the `--reverse` flag.
### EVM Opcodes tracing
You can trace the EVM opcodes executed by a transaction using the `--evm-ops` flag. This requires enabling tracing with either `--evm-trace rpc` or `--evm-trace revm`:
```bash
# Trace opcodes using Revm (works on public RPCs)
mevlog tx 0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660 --chain-id 1 --evm-trace revm --evm-ops
# Trace opcodes using RPC (requires debug API access)
mevlog tx 0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660 --evm-trace rpc --evm-ops
```
```json
{
"result": [
{
"evm_opcodes": [
{"pc": 0, "op": "PUSH1", "cost": 3, "gas_left": 545253},
{"pc": 2, "op": "PUSH1", "cost": 3, "gas_left": 545250},
{"pc": 4, "op": "MSTORE", "cost": 3, "gas_left": 545247}
]
}
],
"result_count": 1,
"duration": "123ms",
"chain": {
"chain_id": 1,
"name": "Ethereum",
"currency": "ETH",
"explorer_url": "https://etherscan.io"
},
"query": {
"command": "tx",
"tx_hash": "0x06fed3f7dc71194fe3c2fd379ef1e8aaa850354454ea9dd526364a4e24853660",
"evm_trace": "revm",
"evm_ops": true
}
}
```
The opcode trace shows:
- **PC**: Program counter (position in bytecode)
- **OP**: Opcode name (e.g., PUSH1, MSTORE, CALL)
- **COST**: Gas cost of this opcode execution
- **GAS_LEFT**: Remaining gas after this opcode executes
### EVM State Diff
You can view storage slot changes made by a transaction using the `--evm-state-diff` flag. This requires enabling tracing with either `--evm-trace rpc` or `--evm-trace revm`:
```bash
# View state diff using Revm (works on public RPCs)
mevlog tx 0x00bbfd50ead7e90e7edaa707cdc402ba9f4b5ff5d74d6dd7348bc7033fea9d44 --chain-id 1 --evm-trace revm --evm-state-diff --format json-pretty
# View state diff using RPC (requires debug API access)
mevlog tx 0x00bbfd50ead7e90e7edaa707cdc402ba9f4b5ff5d74d6dd7348bc7033fea9d44 --chain-id 1 --evm-trace rpc --evm-state-diff --format json-pretty
```
```json
{
"result": [
{
// ...
"evm_state_diff": {
"0x1234...abcd": {
"0x0000...0001": ["0x0000...0000", "0x0000...0064"],
"0x0000...0002": [null, "0x0000...00c8"]
}
}
}
]
}
```
The state diff shows:
- **ADDRESS**: Contract address where storage was modified
- **SLOT**: Storage slot that changed
- **BEFORE**: Value before the transaction (`null` if slot was empty)
- **AFTER**: Value after the transaction
## Listing available chains
```bash
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 compact JSON
```
Sample output:
```json
[
{
"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 ('json', 'json-pretty') [default: json-pretty]
## Getting chain information
```bash
mevlog chain-info --chain-id 1 # Ethereum mainnet
mevlog chain-info --chain-id 56 # BSC mainnet
mevlog chain-info --chain-id 137 # Polygon mainnet
```
This command displays detailed information about a specific chain, including current token price and RPC endpoint benchmarks. RPC endpoints are benchmarked using `eth_getLogs`, which filters out providers that don't support this method. This ensures that returned RPCs are compatible with [cryo](https://github.com/paradigmxyz/cryo) for fetching transaction and log data.
By default, the command filters RPC endpoints responding under 1000ms (1 second). You can adjust this timeout for networks with slower connections:
```bash
mevlog chain-info --chain-id 1 --rpc-timeout-ms 5000 # 5 seconds
```
You can limit the number of RPC URLs returned (default is 5):
```bash
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-rpcs` flag:
```bash
mevlog chain-info --chain-id 1 --skip-rpcs
```
## Checking debug tracing support
Before using `--evm-trace rpc` mode, you can check if an RPC endpoint supports debug tracing:
```bash
mevlog debug-available --rpc-url https://eth.llamarpc.com
# Output: false
mevlog debug-available --rpc-url http://localhost:8545
# Output: true
```
This command tests the `debug_traceTransaction` RPC method by fetching a recent transaction and attempting to trace it. Returns `true` if debug tracing is supported, `false` otherwise.
## Supported EVM chains
The project currently supports over 2k EVM chains by reading the metadata from [ChainList](https://chainlist.org/). But only a few chains display $USD txs prices from integrated [ChainLink oracles](https://docs.chain.link/data-feeds/price-feeds/addresses). 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.
## Development
`tokio-console` feature adds support for [tokio-console](https://github.com/tokio-rs/console):
```bash
RUSTFLAGS="--cfg tokio_unstable" cargo run --features=tokio-console --bin mevlog search -b 10:latest
```
`seed-db` feature enables action to populate signatures and chains metadata SQLite database:
```bash
cargo run --features=seed-db --bin mevlog seed-db
```
### Benchmark
Benchmark using [hotpath](https://github.com/pawurb/hotpath) lib:
Time:
```
QUIET=1 cargo run --features 'hotpath' --release --bin mevlog search -b 23263469:23263489 --chain-id 1 --skip-verify-chain-id --native-token-price 5000 --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 `[hotpath::measure]` if needed.

Allocations:
```
QUIET=1 cargo run --features 'hotpath,hotpath-alloc' --release --bin mevlog search -b 23263469:23263489 --chain-id 1 --skip-verify-chain-id --native-token-price 5000 --rpc-url https://eth.merkle.io
```
Live profiling:
```bash
HOTPATH_EXCLUDE_WRAPPER=true QUIET=1 cargo run --release --features='hotpath,hotpath-alloc' --bin mevlog search -b 10:latest --rpc-url $ETH_RPC_URL --ens --erc20-symbols
```
In another terminal:
```bash
cargo install hotpath --features=tui
hotpath console
```