T24 · MEV
Who saw your transaction before it entered a block?
- Capabilities practiced
- BuilderProtocol Literacy
- Hands on
- Sandwich your own trade in a fork environment and quantify the user's loss.
- AI Lab
- Have AI list user-side protections and assess, one by one, whether each is feasible in your product.
A Real-World Problem
Two months after your swap interface launches, users repeat one complaint: “The execution price is always a little worse than your quote.”
You check every item from T20. Quotes use current reserves, routing chooses the best path, minimum output is in the user's signature, and there is a deadline. Crucially, trades do not revert. Slippage protection works; users receive at least their signed minimum.
Then you open one trade in a block explorer.
It is transaction 47 in its block. Transactions 46 and 48 have the same sender and touch the same pool: one buys, one sells, and your user is between them.
Replay the three locally and calculate the user's shortfall. The number is familiar: almost exactly the front end's default slippage tolerance.
The user was not tricked. The contract has no bug. Every check passed. Their transaction was simply placed in the middle.
The real question is: who chose the order of those three transactions, and why?
Thought Experiment
Shrink a blockchain to a village.
At its entrance stands a public notice board. Anyone wanting a task done posts a note. Every twelve seconds a packer takes a batch of notes and completes them in whatever order they choose.
Those two rules imply three things.
First, the board is public before the work is done. Your note says what you want to buy, how much, and the worst price you accept. The whole village can read it before execution. This is not a leak; publicity lets others verify the packer followed the rules.
Second, the packer chooses the order and may add their own note. They can put yours at position 47 and their own just ahead.
Third, they do not have to act personally. They can announce: “Whoever pays most gets the first position in the next batch.”
The third rule changes everything. “Who goes first” becomes something with a price, an auction, and willing buyers, not a mere technical detail.
Three businesses appear. For now, leave them unnamed:
A sees the same item sold at different prices on two stalls. They buy at the cheap stall and sell at the expensive one. Prices converge, seemingly without harm, but the price difference came from the people stocking the stalls.
B sees your note announcing a large buy. They buy first, let your order push the price higher, then sell to you. Your visible intention creates their profit.
C sees collateral just cross the seizure threshold from T22 and races everyone else to take the reward.
All three share one important property: none requires an exploit. Every action is permitted and every check passes.
They exploit the structure of the system, not a mistake in its code.
Your Decision
The user has signed. Your code must now send the transaction.
Where do you send it?
What Happens
Each option asks how long and to how many parties the intent is visible, and who may profit from that visibility.
| Approach | Who sees the intent? | Whom do you trust? | Main cost | Failure mode |
|---|---|---|---|---|
| Public mempool, tight tolerance | Everyone | No new party | High failure rate | Repeated failure pressures users to widen it |
| Public mempool, wide tolerance | Everyone | No new party | Invisible extraction | Persistent user loss goes unnoticed |
| Private channel | One operator | Operator's promise | New counterparty | Broken promise is hard to verify |
| Intent and executor auction | Group of executors | Strength of competition | Delay and concentration | Weak competition quietly worsens prices |
The trust column carries the lesson:
MEV cannot simply be eliminated; it can be shifted. Each defense changes who may profit from your transaction's order instead of making that value zero.
Any claim that a particular service makes you “safe” leaves out the new party whose behavior you now depend on.
A second lesson is a calculable threshold for whether an attacker targets a trade:
Attacker gross gain ≈ trade amount × slippage room they can use
Attacker cost ≈ fees on two swaps + gas on two transactions + bid for position
Positive net gain: act. Zero or negative: ignore the trade.Read this in reverse: your slippage tolerance is the bounty you post. Multiplying tolerance by trade size gives the prize. Once it exceeds attack costs, the trade becomes a target.
Thus, transaction ordering is itself a saleable resource.
No software version can patch that away. Somebody must decide the order. You can only measure its value and identify who receives it.
Build a Model
1. Who has seen your transaction?
- Your front end
- Wallet
- RPC provider
- Public mempool
- Searchers
- Block builder
- Block proposer
- Block inclusion
| Stage | What it sees | What it can do | Can you verify? |
|---|---|---|---|
| RPC provider | Full transaction | Delay forwarding or share it | No |
| Public mempool | Full transaction | Make it globally readable | Yes; that is its purpose |
| Searcher | Full transaction | Construct sandwiches, frontruns, or arbitrage | No |
| Block builder | Full transaction and bids | Choose final ordering | Afterward, not beforehand |
| Block proposer | Assembled block | Accept or replace it | Afterward |
The first row is often ignored. People assume skipping the public mempool is enough, but an RPC provider sees the transaction first. It is directly configured in your code and rarely examined.
2. Four forms with two different properties
| Form | Who provides its profit? | What if nobody does it? | Does the user lose? |
|---|---|---|---|
| Arbitrage | Liquidity providers | Prices across markets remain different | No, though LPs lose |
| Liquidation | Liquidated user | T22-style bad debt | No; the bonus was already owed |
| Frontrunning | Transaction sender | Nothing special | Yes |
| Sandwich | Transaction sender | Nothing special | Yes |
The third column divides them:
The first two are work someone needs to do. Without arbitrage, market prices diverge. Without liquidation, lenders accumulate bad debt. They extract value that already exists, though someone captures it.
The last two exist only because your transaction is visible. If nobody acts, the loss does not exist. It is a newly created cost borne entirely by the sender.
Use this distinction when judging an MEV remedy. Moving arbitrage proceeds from A to B does not help the user; reducing frontrunning and sandwiches does.
3. Sandwich arithmetic: your tolerance sets the attack size
You can calculate this section completely. For a constant-product pool from T19, these functions need no external library and can go straight into a test:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// Constant-product quote, with feeBps charged on input; a typical value is 30
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut,
uint256 feeBps
) pure returns (uint256) {
uint256 inAfterFee = amountIn * (10_000 - feeBps);
return reserveOut * inAfterFee / (reserveIn * 10_000 + inAfterFee);
}
/// Difference in user receipts without and with a sandwich
/// This subtraction is the number you will measure yourself
function sandwichLoss(
uint256 userIn,
uint256 attackerIn, // Amount supplied by attacker's first trade
uint256 reserveIn,
uint256 reserveOut,
uint256 feeBps
) pure returns (uint256) {
uint256 clean = getAmountOut(userIn, reserveIn, reserveOut, feeBps);
// Attacker buys first, moving reserves
uint256 got = getAmountOut(attackerIn, reserveIn, reserveOut, feeBps);
uint256 newIn = reserveIn + attackerIn;
uint256 newOut = reserveOut - got;
// User executes farther along the moved curve
uint256 sandwiched = getAmountOut(userIn, newIn, newOut, feeBps);
return clean - sandwiched;
}How does the attacker choose attackerIn? They face one hard constraint: the minimum output in the user's signature. Push too far and the user's trade reverts; the attacker's trades then cost fees without the intended gain.
The optimal target is clear:
Optimal attackerIn = the amount making sandwiched exactly equal amountOutMin
Therefore:
Maximum user loss = trade amount × slippage tolerance
The attacker aims to take precisely that maximum, no more or lessPause on that point. The attacker need not guess. Your tolerance tells them how much to trade. Moving from 0.5% to 5% multiplies the target gain by ten.
Whether they act depends on costs:
Gross gain ≈ user loss - pool fees on the attacker's own two swaps
Cost ≈ gas for two trades + bids to surround the user
Act only when net profit is positive.
So there is a minimum attackable size; below it, nobody bothers.The Lab calculates that minimum. It is more useful than a generic defense tip because it identifies which trade sizes are at risk.
4. Three defenses and the authority each grants
| Method | What it reduces | Who gains authority? | What cannot you verify? |
|---|---|---|---|
| Tighten tolerance | Extractable value | Nobody new | Nothing new; it adds no trust |
| Private channel | Exposure | Channel operator | Whether it inspected or resold the opportunity |
| Intent with competing executors | Exposure and returns some proceeds | Executor group | Whether competition remains strong |
The second column distinguishes reducing the value available to extract from reducing the number of people who see it. The first requires no new trust; the second inevitably adds a counterparty.
In practice, combine the three. A reasonable default dynamically sets tolerance from trade size and pool depth, sends large trades through a private channel or competitive execution, and shows estimated price impact clearly to users. The last costs nothing yet many products omit it.
What It Is Called
Extra value obtainable by choosing which transactions enter a block, which are omitted, and their order.
The keyword is ordering, not exploits. No version removes it, because someone must order transactions. Your task is to measure that value and identify who receives it now.
Profit from a price difference between venues.
It is the one form here with a clear positive externality: prices across fragmented markets converge. But its profits come from liquidity providers. Much LP impermanent loss appears in this form.
Trades placed before and after a user's transaction to move price to the edge of their tolerance and capture the difference.
Unlike arbitrage, this loss is created, not simply transferred. Without the attack it would not exist. The user's own tolerance determines its ceiling.
The power to choose the sequence in which a batch of transactions executes.
It is this chapter's central resource. Once it can be sold, a supply chain appears: searchers find opportunities, builders assemble blocks, and proposers sell positions. Ordering has value, and valuable resources develop markets.
A channel delivering transactions to block producers without public broadcast.
It trades “visible to everyone” for “visible to one operator.” That reallocates trust rather than erasing risk. Before using one, ask who operates it, what they promise, what enforces the promise, and whether you would detect a breach.
A competing participant who finds and executes a way to fulfill a user's intent.
Competition for ordering value can return part of it to the user as better execution. The cost is a naturally concentrated executor layer needing capital, infrastructure, and algorithms. Ask where solver revenue comes from; the answer exists even if documentation omits it.
Hands-on
The Lab's output is a number you measured, not merely an explanation. Afterward you should know how much a 10,000-unit swap loses under your product's default settings.
Prepare the environment and align the quote first.
Fork a chain locally, choose a constant-product pool, and record both reserves and its fee rate. Copy getAmountOut above into the test. Compare its result with the pool's actual call. The values must match exactly, down to the last unit. Any mismatch means rounding or fee placement is wrong; revisit T19's rounding table. Every later loss calculation depends on this baseline.
Run a clean baseline, then one sandwich. Have a test address swap 10,000 in pool units and record its actual receipt as clean, the denominator for later comparisons.
Then execute three trades in order within one block:
Trade 1 Attacker buys amount a ← lifts the price
Trade 2 User swaps ← executes on the moved curve
Trade 3 Attacker sells everything bought in Trade 1Record the user's receipt (sandwiched), the attacker's final receipt, and their profit over input. User loss is clean minus sandwiched. Convert it to a percentage and put it beside your default slippage tolerance.
Scan for the optimal attacker size.
Fix user size and tolerance and sweep a from small to large. Record user loss and attacker net profit at each point. User loss rises with a until the user's minimum-output check fails. Attacker profit first rises and then falls: push too far and the user reverts, leaving the attacker paying fees for nothing.
Find the a that maximizes profit. Check whether the user's output at this a nearly equals the signed minimum. If it does, you have demonstrated directly that user tolerance defines the attacker's profit target.
Fill a two-dimensional table.
Put tolerance on one axis and trade amount on the other. In each cell record user loss as a percentage and attacker net profit.
0.1% 0.5% 1% 5%
1,000 ... ... ... ...
10,000 ... ... ... ...
100,000 ... ... ... ...Draw a boundary around cells where attacker profit is positive. Below and to the left is “safe,” not because of a special defense but because the trade is not worth attacking.
Calculate attack cost and the minimum attackable size. This is the chapter's quantitative exercise.
Known: depth D on one side, pool fee f, user tolerance s, gas price g
Step 1: Use optimal a from the scan to calculate gross attacker gain
Gross gain ≈ user loss - fees on the attacker's two swaps
(They pay f twice; many estimates omit this.)
Step 2: Calculate costs
Gas for two swaps = 2 × gas per swap × g
Ordering bid = gross gain given up to get before and after the user
(conservatively estimate half the gross gain)
Step 3: Net profit = Step 1 - Step 2
Step 4: Set profit to zero and solve for user trade size V
V is the minimum attackable size in this pool at this toleranceCalculate V, then make three comparisons:
- Multiply gas price by ten and recalculate. Congestion raises V substantially, making small trades safer.
- Change tolerance from 5% to 0.5% and see how V changes.
- Measure what share of your actual product trades exceed V.
The third turns abstract risk into a percentage you could report to the team.
Try another defense and record its cost.
Simulate a private channel on the fork by omitting Trades 1 and 3 and executing only the user's trade. Loss falls to zero. The useful part is answering:
| Question | Your answer |
|---|---|
| Who operates this channel? | |
| What exactly do they promise, and where? | |
| What enforces the promise? | |
| Could you detect a breach? | |
| What happens when the channel goes down? |
If you cannot fill every row, the defense is incomplete. It introduces a new counterparty rather than merely flipping a switch.
Use only a local fork and attack only your own test address. Never connect real funds. Real funds enter only the capstone after Stage 5 security acceptance.
AI Lab
Ask in three steps; the second and third are most valuable:
Step one:
List user-facing MEV defenses for an onchain swap product. For each, say
whether it reduces extractable value or exposure, its implementation cost,
user experience impact, and the party to whom it transfers trust.
List fully before recommending anything.
Step two:
My product has (fill in): user scale, trade-size distribution, chain,
default slippage tolerance, and RPC source. Assess each option's feasibility
and give measurable expected effects and measurable costs.
Step three:
For your top two recommendations, state when each fails, what signal I can
observe on failure, and the fallback if its provider stops operating.Models often list the options in step one, but treat “use a private channel” as a complete solution. Ask who operates it and what enforces its promise. In step two, reject vague “significant reduction” claims. Ask how much of your actual trade distribution is covered and how much loss is avoided. Without numbers, this is not an assessment.
Step three gives a general test for any protection: when does it fail, and how will I know? A control whose failure is invisible can be worse than no control if it leads you to relax other safeguards.
Compare every step-two recommendation with your Lab's two-dimensional table. Does it cover the cells where your real trades fall?
Verify these points yourself after using AI
- For every defense, does it identify who gains authority? Without the new trust party, assessment is incomplete
- Does it distinguish reducing extractable value from reducing exposure? They are different
- Is its slippage advice a fixed percentage or a formula responsive to size and pool depth?
- Does it treat a private channel as a final answer instead of a trust reallocation?
- For intent and executor auctions, does it say where executors earn revenue?
- Does it recognize the RPC provider as a party that sees transactions?
- Did you verify every named service, interface, and parameter it offers rather than trusting memory?
Real-World Case
On public mempools, sandwiching is an industry: some participants scan for targets, others optimize position bidding, and still others supply capital.
Its scale can be measured directly. This is one of the few parts of the industry whose actions are publicly reconstructable from onchain history.
For a product team, the point is concrete: default tolerance is not just a user-experience setting. It is a public variable read and priced by professionals in real time.
A group of block proposers was expected to include a searcher's submitted content unchanged. After receiving the block, they replaced transactions and captured the opportunity themselves. The sum involved was large.
The useful lesson is not its exact size. Private-channel protection is a promise, not a cryptographic guarantee. It depends on a party following rules even when violating them pays handsomely.
Recall the Lab table's question about enforcement. For many channels, the real answer is reputation. Reputation can be cashed out against one sufficiently large opportunity.
Some layer-two networks let one sequencer determine transaction order. There may be no public mempool and fewer public sandwich opportunities.
But ordering power remains concentrated in one process. It sees every transaction and chooses every order, while users have little ability to verify its internal choices.
This is a clear case of relocation, not removal: risk changes from “unknown strangers can sandwich me” to “I trust one operator.” Which is preferable depends on the failure you are willing to accept and should be decided explicitly.
Return to T22's last stage. Ten liquidators discover one opportunity; one wins and nine pay for failed attempts.
Those costs enter each liquidator's calculation. To remain profitable after expected failed attempts, they demand a larger liquidation bonus, paid by the liquidated user.
Thus the cost of competing for order appears indirectly as a harsher liquidation penalty on ordinary users. This path is less visible than a sandwich but still MEV's user impact.
Change One Variable
Public sandwiches disappear, execution improves, and support complaints may fall.
Record three new risks. First, a new single point of failure: if the channel goes down, the product either stops or silently falls back to the public mempool. Silent fallback is worse because users think protection remains. Second, the operator sees everything, without verifiable limits on its behavior. Third, arbitrageurs also stop seeing the trade, which can slow price discovery in some settings.
Fallback must be explicit, observable, and visible to users. Quietly reverting to an unprotected path is worse than an outright failure.
At first glance, exposure time falls thirtyfold.
Two things change. Attackers have less reaction time, favoring faster infrastructure and fewer participants. But those remaining may compete more fiercely, while fewer transactions fit each block and a front position can become scarcer and more valuable.
More importantly, recalculate every time or block-count assumption: expiry, tolerance, and expected inclusion time depend on the chain's cadence. The conclusion matches T21 and T22: derive time-related parameters again after moving chains.
This changes the mechanism itself. Within one batch, there is no before and after, removing a sandwich's prerequisite.
Three costs appear. Latency while waiting for the batch; slower price discovery because one clearing price may be stale during sharp moves; and a valuable batch boundary, where inclusion in this batch versus the next becomes worth competing for.
Mechanism design often works this way: removing one extractable position creates another scarcity elsewhere. Judge the change by whether the new one is materially less valuable.
Of these methods, this is the only one requiring no new trusted party, and it is inexpensive frontend arithmetic.
Small trades can use looser tolerances because their profit will not cover attack costs. Large trades tighten automatically and, beyond a threshold, prompt splitting or a different execution route.
The hard part is knowing pool depth in real time. That returns you to T17 and T18: use a reliable indexer and real-time channel, not stale cache. A tolerance calculated from stale depth is more dangerous than a fixed one, because it appears intelligent.
Takeaway Questions
The most important cost here is hidden: users pay for transaction ordering through a worse execution price, absent from any invoice. It appears as a slightly poorer rate and usually goes unnoticed.
A useful habit: when you see “zero fees” or “gas-free,” ask who owns the ordering right. Removing visible fees often just moves the cost.
Every layer in the MEV chain has a revenue source: searchers earn spreads, builders collect bids, proposers sell position, private channels earn fees or revenue share, and executors retain auction surplus.
Draw the chain and write “how do they earn?” at each step. Any step you cannot explain is a piece of the proposed solution you do not yet understand.
Risk appears in three places with different visibility: users receive worse prices invisibly, LPs lose some value to arbitrage with partial visibility, and protocols lose reputation and users only later.
The first matters most: these losses occur in “successful transactions.” Users report failures, not a 5% extraction hidden inside success. A team relying only on support tickets will miss this category entirely.
The incentive is plain: if order has value, someone will pay for it. That follows from rational behavior, not necessarily malice.
For any protection depending on people obeying rules, ask: what if a one-time gain from breaking the rule exceeds the future gain from keeping it? The 2023 case supplies an answer.
Chapter Check
The distinction is whether value was already there to transfer or newly created as a cost.
Arbitrage captures a preexisting difference between markets, paid by LPs, while helping prices converge. Without arbitrage, the gap remains.
Without a sandwich, the user's loss does not exist. It corrects nothing; it adds a cost solely because the user's pending trade was visible.
Use that distinction to judge MEV proposals: moving arbitrage proceeds from A to B does not help the user; reducing frontrunning and sandwiches does.
It is a precise constraint, not a vague correlation.
If an attacker moves price too far, minimum-output protection reverts the user's trade and the attacker pays fees without the expected gain. Their best strategy is to land the user's execution at the tolerance boundary.
Thus the loss ceiling equals trade amount times tolerance, and the attacker targets that ceiling. Raising tolerance from 0.5% to 5% multiplies the target by ten.
Whether they act depends on two pool fees, two gas payments, and an ordering bid. The Lab computes the corresponding minimum attackable amount.
It describes a transfer of trust as the removal of risk.
The public no longer sees the trade, but the operator does. They decide if and when to include it and could pass the opportunity to another party. You replace an open market with a trusted counterparty.
Ask five things: who runs it, what they promise, where that promise is written, what enforces it, and whether you can detect a violation. For many channels, enforcement ultimately means reputation, which the 2023 case showed can be spent for a large enough opportunity.
Also remember the RPC provider sees the transaction before any mempool does.
No. They auction ordering value and return some of it to users through better prices.
That is a real improvement, but executors still retain value. The user's share depends on competitive pressure that cannot be verified solely onchain, and the capital and infrastructure needed tend to concentrate execution.
Ask where executor revenue comes from, whether competition is strong, and what signal would show it weakening.
There is no single answer. Include:
- Every party that sees a transaction between signing and inclusion, including the RPC provider you may never have inspected.
- Your default tolerance, whether fixed or dynamic, and its value multiplied by the typical trade amount.
- Your minimum attackable trade size and what share of real trades exceeds it.
- The trusted party introduced by each defense and signals that would show it failing.
- Fallback behavior when a private channel fails, executors exit, or depth data lags, including what users see.
- A monitor for the distribution of execution-price deviation from quotes. Users will not report successful but extracted trades, so this is how you detect them.
Point 6 is least often built and the most actionable. These losses look like successful transactions and trigger no alert unless you explicitly measure them.
Stage 4 ends here. T19's curve, T20's execution layers, T21's price source, T22's liquidation speed, T23's ledger, and T24's ordering rights connect into one lesson: DeFi risk often sits where a contract meets the outside world, even when its internal logic is correct. Stage 5 turns those boundaries into testable acceptance checks.
Key idea
Transaction order is itself a resource that can be sold.