MEV, or maximal extractable value, is the profit that block producers and other network participants can capture by choosing which transactions to include, exclude, or reorder within a block, beyond standard block rewards and fees. It exists because block space is scarce and the order of transactions changes their economic outcome. This article explains the mechanism, walks through common strategies such as DEX arbitrage, liquidations, and sandwich attacks, and shows how to measure ordering effects with a reproducible RPC-based procedure. It also covers the tradeoffs of mitigation approaches and how to choose infrastructure that gives you a consistent view of pending transactions.
Definition and scope of MEV
Maximal extractable value (MEV) is the maximum profit that can be captured from block production by including, excluding, or reordering transactions, over and above the standard block reward and gas fees. The term originally stood for miner extractable value because proof-of-work miners controlled block contents. After Ethereum's move to proof-of-stake, validators took over that role, so the broader term maximal extractable value is now standard.
MEV is not a bug in a specific smart contract. It is an economic property of any blockchain where a party has discretion over transaction ordering and where pending transactions are visible before inclusion. That makes it relevant to Ethereum, Solana, L2 rollups with centralized sequencers, and most other execution environments, even though the mechanics differ.
This article focuses on the mechanism, the common strategies, and a reproducible way to measure ordering effects using standard JSON-RPC calls. It does not recommend a specific MEV strategy or endorse extraction as a business model.
Assumptions and prerequisites
The explanation assumes you understand how transactions enter a mempool, how gas price and priority fees influence inclusion, and how blocks are assembled. If you need a refresher on transaction sequencing, the guide to nonces and transaction ordering is a useful starting point.
You should also have access to an archive-capable or full RPC endpoint for the network you want to inspect. Public endpoints often rate-limit the calls needed to reconstruct block contents and pending transactions, so a dedicated or paid endpoint is more reliable for measurement work.
- A JSON-RPC endpoint for the target network, stored as RPC_URL
- Basic familiarity with curl or a scripting language such as Python
- An archive or full node if you need historical block data
- Awareness that mempool visibility differs by network and client
How transaction ordering creates extractable value
Every block is an ordered list of state transitions. If two transactions touch the same liquidity pool, the first one executes against the pool's current reserves and the second executes against the updated reserves. The difference in execution price between those two orderings is the value at stake. A block producer who can choose the order can, in principle, capture that difference.
In practice, the value is usually captured by searchers: independent participants who run algorithms over pending transaction data to find profitable orderings. Searchers submit bundles of transactions to builders, who assemble blocks and bid for the right to propose them. Validators then propose the winning block. This separation of roles is often called the proposer-builder separation, and it changes who captures MEV and how much of it flows back to validators.
The key mental model is that MEV is a function of (1) the set of pending transactions, (2) the discretion of the party choosing order, and (3) the economic sensitivity of the affected contracts. Remove any one of those and the opportunity shrinks.
Common MEV strategies and their mechanics
Most MEV activity falls into a small number of recognizable patterns. Understanding them helps you recognize when your own transactions are exposed.
DEX arbitrage: when two pools price the same asset differently, a searcher buys on the cheaper pool and sells on the more expensive one in the same block. This is generally considered benign or even beneficial because it pushes prices toward parity.
Liquidations: lending protocols allow anyone to repay an unhealthy borrower's debt in exchange for a liquidation bonus. Searchers compete to be first when a position crosses its threshold, which is a race for ordering.
Sandwich attacks: a searcher places a buy before a large pending swap and a sell after it, profiting from the price impact the victim's trade creates. The victim receives a worse execution price than they would have without the surrounding transactions.
Frontrunning and backrunning: generalized versions of the same idea, where a transaction is inserted immediately before or after a target transaction for advantage. NFT mint sniping and first-come-first-served claims are common examples.
Measuring ordering effects with JSON-RPC
You can build a reproducible measurement of ordering effects without relying on any third-party dashboard. The procedure below reconstructs a block, identifies swaps against a known pool, and compares the executed price of each swap to the pool's mid-price before the block. The difference, aggregated per block, is a lower bound on the ordering value present in that block.
First, fetch the block and its receipts. The following curl call retrieves a block by number with full transaction bodies:
- Replace 0x1312D00 with the hex block number you want to inspect
- Set RPC_URL to an endpoint that supports full transaction bodies
- For historical blocks, use an archive endpoint
curl -s -X POST "$RPC_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x1312D00", true]}'A runnable Python diagnostic for swap ordering
The script below extends the manual call into a repeatable diagnostic. It fetches a block, filters for Swap events on a specified pool address, and prints each swap's position in the block alongside its sender. Run it across a range of blocks to see how often the same sender appears immediately before and after a large swap, which is a signature of sandwich activity.
The script uses only the standard library and a single RPC_URL environment variable. It does not require an API key from any specific provider.
- Set POOL_ADDRESS to the pool you want to inspect
- Swap topic hashes differ by DEX; confirm the topic for your target protocol
- Run across consecutive blocks to distinguish noise from repeated patterns
import json, os, urllib.request
RPC_URL = os.environ["RPC_URL"]
POOL = os.environ.get("POOL_ADDRESS", "0x0000000000000000000000000000000000000000")
SWAP_TOPIC = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822"
def rpc(method, params):
body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
req = urllib.request.Request(RPC_URL, body, {"Content-Type":"application/json"})
return json.loads(urllib.request.urlopen(req).read())["result"]
def scan_block(block_hex):
block = rpc("eth_getBlockByNumber", [block_hex, True])
print(f"block {int(block_hex,16)} txs={len(block['transactions'])}")
for i, tx in enumerate(block["transactions"]):
if tx.get("to", "").lower() == POOL.lower():
print(f" pos={i} from={tx['from']} input={tx['input'][:10]}")
if __name__ == "__main__":
scan_block("0x1312D00")Expected verification results and how to read them
A successful run prints the block number, transaction count, and every transaction that targets the pool, with its position and sender. If you see the same sender at positions i-1 and i+1 around a large swap at position i, that is consistent with a sandwich pattern. If the same sender appears only once, it may be a legitimate liquidity operation.
Record your observations in a results table so the measurement is reproducible. A suggested structure is shown below; fill in values from your own runs rather than copying any figures.
| Block range | Blocks scanned | Pool swaps | Repeated-sender patterns | Notes |
|---|---|---|---|---|
| 0x1312D00–0x1312D0F | 16 | (your count) | (your count) | (endpoint, timestamp) |
The table is a measurement template, not a benchmark. Any numbers you publish should come from your own runs against a documented endpoint and block range.
Troubleshooting common measurement problems
If the script returns null for a block, the endpoint is likely pruned and does not serve historical state. Switch to an archive endpoint or a provider that explicitly supports archive queries. If the transaction list is empty, confirm you passed true as the second parameter to eth_getBlockByNumber.
If you see rate-limit errors, batch your requests or move to a dedicated endpoint. Public endpoints often cap requests per second, which makes block-by-block scanning unreliable. For high-volume measurement, a dedicated node or a paid RPC plan is the practical choice.
If swap events are missing, verify the topic hash for the specific DEX. Uniswap V2, V3, and other protocols use different event signatures, and a mismatched topic will silently return no matches.
- null block: use an archive-capable endpoint
- empty transactions: pass true for full bodies
- rate limits: batch requests or use a dedicated endpoint
- no swaps found: confirm the event topic for the target DEX
Mitigation approaches and their tradeoffs
There is no single fix for MEV, and each mitigation shifts costs rather than eliminating them. Slippage limits reduce sandwich losses but can cause failed transactions. Private transaction relays hide pending transactions from searchers, which reduces frontrunning but depends on the relay's trust assumptions and coverage. Batch auctions and fair sequencing aim to remove ordering discretion, but they require protocol-level changes and can introduce latency.
For users, the practical levers are slippage tolerance, transaction timing, and choosing venues that route through private mempools or batch settlement. For developers, the levers are contract design (for example, commit-reveal schemes) and infrastructure choices that give a consistent view of pending state.
For node operators and RPC providers, the relevant question is whether the endpoint exposes a public mempool and how quickly pending transactions propagate. A slow or inconsistent view of the mempool makes measurement unreliable and can cause your own transactions to be outcompeted.
Infrastructure considerations for MEV-aware workloads
If you are building searchers, analytics, or MEV-aware trading systems, endpoint behavior matters as much as strategy. You need low-latency access to pending transactions, consistent block data, and archive support for backtesting. Public endpoints rarely provide all three at scale.
OnFinality's API service provides managed RPC access across multiple networks, and dedicated nodes give you isolated throughput for latency-sensitive workloads. For a concrete endpoint recommendation for your target network, the RPC Assistant can match you to a provider; this article deliberately stays on the methodology side.
When comparing endpoints, measure the same block range on each and record propagation latency, error rates, and archive coverage. Treat any published performance claim as a hypothesis to verify against your own workload.
- Confirm archive support before backtesting historical blocks
- Measure pending-transaction propagation latency on each candidate endpoint
- Check rate limits against your expected request volume
- Prefer isolated throughput for latency-sensitive strategies
Next steps for further study
Start by running the diagnostic across a small block range on a network you already use. Compare the results against a second endpoint to see how much of the observed pattern is endpoint-dependent. Then extend the script to compute realized slippage per swap and aggregate it per block.
For broader context on node operations and endpoint selection, see the guide to blockchain node hosting and the multi-chain RPC endpoints overview. If you are evaluating providers for a specific network, the RPC Assistant can narrow the choice, while the pricing page helps you compare plans against your expected request volume.