MEV Tax in Action: Internalizing MEV in UniswapX | Alan Wu, Uniswap Labs | ETHTaipei 2025
ETHTaipei·Thu, Oct 9, 2025, 12:00 AM
MEV Tax in Action: Internalizing MEV in UniswapX | Alan Wu, Uniswap Labs | ETHTaipei 2025
Transcript
[Music] Good morning everybody. Taja. My name is Alan and I'm a protocol engineer at Uniswap Labs. And today I'll be talking about MEV taxes and how we implemented one in unis swap x to internalize me. So we're going through a case study of unis swap today.
So I'll just quickly go over what me looks like when you swap on chain. So on a blockchain transactions are processed in blocks at distinct timestamps. And so what that means is we don't have the continuous pricing like we do offchain. The result of that is that at the time of block proposal, AMMs are going to offer stale prices which create ME opportunities. And on mainet, block builders are going to order transactions in order to extract this value and pay it to block proposers.
And they do this by looking at swaps in the mempole or getting orders from other sources of order flow. On L2s, it's a little bit better. A lot of L2s have private meoles, but there's still opportunities for MEV because there's relatively less liquidity on L2s. Large swaps can create immediate back running opportunities to rearbit pool prices and extract value that way. So now let's go over unis swap x.
Uniswap x is a protocol that facilitates trades through intents. So when we think about normal unis swap, you're basically swapping through a series of pools. So you start off specifying what tokens you want to trade and then a routing algorithm is going to go through and give you the best path of trades to go through for the maximum output. That path is then packed into some call data and you send a transaction with that call data to execute the trade. On UNIS swap X it's a lot simpler.
You're not specifying any path or anything. All you do is you sign a message saying what you want to trade and some minimum amount that you want. So anam as an example, I can sign a message saying I want to swap one ETH for at least 3,000 USDC. And this is signing a message, not a transaction. So it's gasless.
You don't pay any gas for that. That's what it means when you see patterns like this being used. and they feature as gasless. What really happens is a filler can take your signed message and then execute a trade for you on your behalf in their own transaction. And that transaction will only go through if it meets the conditions that you specify.
So in the context of a swap, our conditions are getting a minimum output from the trade and that trade happening before some kind of deadline. And the very powerful unlock that we have is that these intents these this intent pattern breaks you free from a fixed execution path. So the consequence of that is that all sources of liquidity can be used to fill these trades. for onchain liquidity. You're not limited to just the unis swap pools anymore.
You can get liquidity from anywhere. But we're also starting to see opportunities for off-chain liquidity to be used. So, and as an example of that is a filler or market maker can fill your trade with their own inventory and then take the opposite side of the trade on a central exchange. And this is all made possible by permit 2. So part of what you're signing over when you sign this message is permit 2 information.
So this is saying the token you want some kind of minimum amount and a deadline. And so a filler can take your signature and then they can execute a trade for you giving you that output before some kind of deadline and then in the same trade in the same transaction if they can meet those conditions they can take your input. And so what happens is this trade is comput is completed both ways atomically in a single transaction. You may have seen this before when you swap on the unis swap interface. At the bottom you see that the transaction costs no gas and it's using unis swap x.
So what I just showed you is what's actually happening behind the scenes when you see this at the bottom of your screen. And we've had unis swap x live since July 2023. So it's been running for almost 2 years now. Now that you know about unis swap x, all you need to know is that it uses intense. So we'll get back to the problem.
Now when a swapper makes a trade with a certain amount of me, a filler who wants to fill that trade is going to bid bid bid priority fees in order to take your trade. And then those priority fees are going to go to the block proposer. And so if we think about a system where we have a swapper and a filler, the counterparties of our trade, this value that's going to the block proposer is a dead weight loss. So this is an economic inefficiency in the context of a trade. And so what this talk is about today is that there's an opportunity for us to take that value that was bound for the proposer and give it back to the swapper.
So today I'll be going over a MEV tax mechanism by which we can redirect me from block proposers back to swappers. And this is something that can be done at the application layer, which means that if you're building a D5 protocol, you can code this directly into your smart contract. And so the consequence of this is that we can return value back to the counterparties of the trade and thus improve their trade execution. If we look at the picture at the top, this is a world with no F tax. So the swapper makes a trade with a certain amount of me.
A filler is going to bid to take that trade, take a little bit of profit, and then all those priority fees they use to win that trade is going to go to the block proposer or sequencer. Now let's look at the bottom picture. This is a world where we have a MEV tax. What we can see is that the amount of value that's going to the proposer or sequencer is drastically reduced and then we have that value redirected back to the swapper. Let's go through a quick example.
If we have a trade where a swapper swaps 3,000 USDC for one ETH and there is 0.1 ETH worth of MEV for this order, that means that a filler, a competitive one, is willing to spend up to 1.1 ETH to fill the order. One to give the swapper and 0.1 as priority fees.
An important thing to note is that for a filler, all they care about is how much money leaves their pocket. So from their perspective, this trade for them is trading 1.1 ETH for 3,000 USDC. Now let's imagine two worlds. The first world is the one we expect.
The swapper gets one ETH. The proposer gets 0.1 ETH via priority fees. and the filler spends 1.1 ETH.
Now, let's imagine a world where we're able to take some of that value that was bound for the proposer and give that back to the swapper. So, that's what you see here. The swapper gets more than one ETH and the proposer gets less than 0.1 ETH. Let's look at the first counterparty of the trade, the filler.
So in both worlds, MAF tax or not, the filler is spending 1.1 ETH for this transaction to fill it. So in this case, this counterpart of the trade is indifferent to the world that they live in. Now let's look at the other counterparty of the trade, the swapper. In world one with no MEF tax, they get one ETH as output.
And the world with a MEV tax, they get more than one ETH. So this side of the trade is not indifferent. The swapper wants to live in world two because getting more than one ETH is better than just one. And if you are building a DI protocol, you can choose to live in world two by implementing a mevax. And this is the world where you maximize value to your users or markets participants instead of letting that value flow to whatever games are being played at a chain's block building or sequencing level.
And by taking this approach, we can capture 99% of the competitive ME on each transaction. And you might be wondering that this seems too good to be true. Why is this not used everywhere already? The caveat is that for this MEV tax mechanism to work, the block sequencing on a chain must enforce priority ordering. And so all this means is that transactions in a block are ordered by their priority fee.
We're able to do this today on chains like base and uni chain and we're also able to do this on any OP stack chain because on these chains the default sequencing is based on priority fee. One thing to note is that on these types of chains, the sequencer is the one that does block building and sequencing. And so they are effectively the block proposers that receive priority fees. So I'll refer to them as just sequencers. Now, now let's get into the MEV tax.
We originally got this idea from Dan and Dave from Paradigm when they released this paper called priority is all you need. And you might be able to guess that priority is referring to the chain doing priority ordering. They define mevaxes as a mechanism that arbitrary applications can use to capture their own me. And so a smart contract can charge a fee that's a function of the priority fee of the transaction. So in the context of unis swap x, the contract is going to charge a fee in the form of an extra output to the swapper and give that output to the swapper.
So as a filler's transaction increases in priority fee, the smart contract will force them to pay the swapper more output. But this can only work if block proposers order transactions by priority fee. If we know this to be true, then the priority fee on a transaction is a signal for how much me exists on it. And so because of that during execution a smart contract can look at what the priority fee is on a transaction and charge a fee based on that. And then the paper calls this fee a meth tax.
Why does this work? Let's get into the intuition of it. We just learned that a higher priority fee on a transaction is going to result in the swapper getting more output. Another observation we can make is that a trade can only be filled once. So once somebody fills your order, further attempts to try to fill it again will just revert.
Lastly, we're running under the assumption that the chain follows priority ordering. And so logically a higher priority fee transaction is the one that gets executed first. So if we put these facts together, we can come to a logical conclusion that the transaction that gets executed to fill a trade gives the user the most output. And since it is the first one to do so, it's the only one that can successfully fill the order. So if we look at these two transactions, the top one has a higher priority fee, so the output's higher.
It's 1.1. The bottom one has a lower priority fee, so the output's lower. It's only one. The higher priority fee transaction is going to be higher in the block, so it gets processed first.
So, by the time this transaction fills the order, when you get down the block to process the second one, that second one is going to revert. And so, the result is that the swapper naturally gets filled by the trade that gives them the most money. Isn't that great? Now, let's get into how we can implement this into Uniswap X. So here is the naive intent we had before.
Swapper gets one ETH. All the priority fees go to the sequencer. Filler sends 1.1 ETH to fill the order. So let's change our intent.
Instead of just asking for at least one ETH, we can express mathematically that the more priority fee that's used on the transaction, the more output they need to give to the swapper. So in this example, for every extra unit of priority fee that the filler uses, they have to give the swapper an extra 0.01 ETH. And that 0.01 is what we would call a scaling factor.
So what happens now is the money that was going to be priority fees now gets split up. Some of that value goes to the swapper as extra output and some of that value remains as priority fees. Let's go back to world two. We now know that the me value is me is being split between the swapper and the sequencer. So we can imagine this as a swapper getting 1 + C ETH and then the sequencer getting 0.
1 minus C because we are taking the value that was bound for their sequencer and giving it to the swapper. So if we want to optimize for the swapper experience, we just maximize C and that is maximizing the value that goes to the swapper and minimizing the value that goes to the sequencer. Now let's go back to a sentence from the paper. If this tax increases sufficiently fast as a function of priority fee per gas, then only a negligible amount of MEV will acrue to the proposer. So if we make the output amount increase more per priority fee used that's the scaling factor then we can make a disproportionately high amount of the value go to the swapper instead of the sequencer.
So the scaling factor is essentially the slope of the line. If we make the slope super steep then we can potentially capture 99% of the me on that transaction. Here's what I mean. On the left, we have a line with a lower slope, so it has a lower scaling factor. Out of the 0.
1 ETH of ME, 0.09 of it is going to go to the swapper and 0.01 of that will go to the sequencer. So, the swapper essentially got back 90% of the me. Now, let's increase the scaling factor.
So the slope is higher. Now what happens is the sequencer now gets 0.005 ETH and the swapper gets an extra 0.095 ETH. So in this world the swapper got back 95% of the me.
Now, you might be thinking logically, why not just make the slope super high and then make the line basically go vertical to get all of it? Here's what happens when you do that. You lose granularity. So, in this graph, we have a line that's super steep and then I've zoomed it in. And in this example, the output is USDC.
And every single extra unit, one way of priority fee that's used causes a 20 USDC change in the output. And because you can't go more granular than one way, you essentially cannot fill orders between these numbers. And so the lesson here is that when we design our MEV tax function, we need to account for granularity. Now let's go back to generalize our equation. Basically the highle concept is that a swapper is going to swap some asset for a minimum output plus a scaling factor multiplied by the priority fee used.
So we end up with a pretty simple expression. And that approach works, but it's not optimal. This bottom expression is what we actually use in our smart contracts. And it looks quite complex because it's multiplicative now instead of additive. But the intuition is very simple.
All this math is saying here is that for extra every extra way of priority fee specified in the transaction give the swapper one thousandth of a basis point of extra output. So, we had to come up with a term for this called MPS, which we call MYIPS. And all it means is um a thousandth of a basis point. And so, what this allows for is it lets the fillers compete on transactions down to a thousandth of a basis point. So, we're really getting them to fight down to the bone to fill these transactions.
So just to give you the best price, we also optimize in other ways practically. What I mean by that is we want this to be fast. We want this to feel not too different from instant AMM transactions. And because these are intents and messages you're broadcasting, they don't always get filled. So you can't be too aggressive with your pricing or else these intents would go unfilled and expire.
We also want you to get price improvement. So what that means is if you go through unis swap x you should get at least the AMM price but hopefully better or else why do it. And lastly, we want to have granularity in our MEF tax function in order to get room to facilitate strong filler competition. So like I showed earlier, we're able to get them to compete down to a thousandth of a basis point. So MEF taxes can be useful beyond unis swap as well.
So let's first consider liquidations on lending lending platforms like a or compound. Liquidators are going to compete to liquidate underwater positions and those often have a lot of me generated. By implementing MEV taxes here, we can redirect that value back to the application by either reducing liquidation penalties or simply increasing protocol revenue. Another application relates to AMMs themselves. So at the start of each block, AMMs are usually arbitrage arbitrageed to get advantage to take advantage of AMM price discrepancies and this is called LTV.
And if we can internalize this value, we can increase the capital efficiency for liquidity providers. And three, another ramification of this is now that we're essentially taking a bunch of money that was bound for sequencers and giving them back to users, this is going to have some kind of repercussions on sequencer economics. And lastly, perhaps the more ambitious one is having crosslication meth taxes. So a lot of the most lucrative me opportunities are the ones that span multiple protocols. So back in the day arbitrageing between unis swap and curve would be a lot of me.
And so if we can implement taxes across protocols, we can preserve value across the DTI ecosystem. And the really cool thing about this is that it changes the way we think about protocol design because instead of accepting these things as inevitable leakage to external actors, we can basically return this value back to the users and protocols that created it. That's all I have for you today. Thank you all. Okay, thank you Alan for the insightful talk.
Um, we're open, we have uh five minutes left and open to any questions from the audience. Anyone want to take one? Yeah, thanks thanks for the talk. Um, you mentioned that the sequencer is by default a a builder. Uh, how does this work with like when you have proposer builder separation?
Yeah. So on mainet we have proposer builder separation PBS and on mainet there is no strict rule for ordering of transactions in a block. Therefore unfortunately this mechanism can't be used on mainet. Good question. Uh how do you ensure that the intent can be failed quickly and also the price is lower for user?
Yeah, that's a really good question. So, one thing that we need to do is coordinate for all the market makers and fillers to bid at the same time because we want all of those we want this transaction to be filled in a determined amount of time. So, in practice what we do is we set a auction target block. So, we say this intent should be filled two blocks from now. And then what happens two blocks from now is a bunch of fillers, market makers are going to submit transactions trying to fill the order in two blocks from now.
And then the first one is going to be the one that fills the order and that's going to be the one that gives the swapper the most money. So in the uh when you give the code to the user, you ask all of the market maker that how much they can fill in the next Yeah, that's a really good question. So, what you could do is run sign some kind of RFQ to get a quote beforehand to kind of estimate it. Um, we don't do that. What we basically do is we show the AMM price and um once the intent actually fills, we actually don't know what they're going to be filled at, right?
Because it's in the future. Um, but this mechanism basically the worst case scenario is that a filler can just use onchain unis swap liquidity to fill the order. So at worst it's just going to be the AMM price but the advantage is that it can that is the minimum amount it can be and so there's a lot of room for price improvement as you mentioned earlier that this is based on the assumption that within a block the transactions are ordered by priority fee but it also assumes that the sequencer accepts all transactions, right? Otherwise, I can just ignore the ones that I don't like and I just add one into the block. So, is there any way to make this work in a decentralized sequencer system or mainet?
Um, or do you have to rely on an honest centralized sequencer? Yeah, excellent question. Because you're assuming that the sequencer is not censoring transactions because they can still order everything by priority fee but just purposely toss one out, right? That's the question. So, one way that we're doing this is actually with Uni Chain.
So, Uni Chain does do priority ordering, but the difference between Uni Chain and maybe other OP stack chains would be that we're running the Uni Chain sequencer in a TE. And so what that means is we can attest that these blocks are ordered based on priority fee, but also that it's not arbitrarily throwing out transactions that come in and it's honestly just doing its job in accordance to a set kind of code and then we can attest that we are actually following that code and not cheating. Uh have you guys explored something about like dynamic like dynamic design of the scaling factor because I feel like the scaling factor is probably the most important thing when it comes to uh like protocol implementing me right so ME tag sorry so yeah there's probably some room for optimization there but basically the approach we took was to have it granular down to a thousandth of a basis point. And when you get to that point, you're already past the 99% internalization. And so what that means is now you're kind of picking between like 99.
99 or 99.9. So yeah, there's some optimization to be done there, but um yeah, that's not something we've done because it's maybe less fruit to be um got there. Um does the efficiency of this uh auction or competition relies on the assumption that the transaction will remain private? Um not really.
The transaction starts off as an intent, right? That intent is broadcasted to the world. In that sense, it's being broadcasted to a bunch of fillers and market makers. The real assumption that we make though is that these fillers are competitive, which means that they're actually trying to compete with each other to give the best price. Because you can imagine if there was only like one filler or two or three, they could they could collude to purposely give you bad prices.
But the assumption that we run under is that there's competiti there's market competition when you fill these. Yep. Sorry, I'll follow up. Um so u from my understanding right now the sequencer synch centralized sequencer right now they are provide uh private transaction so the fillers transaction uh will will not be revealed to other fillers so without the assumption that you belong yeah I see where you're going with this so basically the fillers are all going to submit their transactions at the time that the target block is fulfill the order and then all those transactions are going to go to the sequencer. And then you you make a good point.
They can't see the other fillers transactions. And so this is really like a oneshot bid that they have and they should give their best foot straight up. Thank you. Okay, thank you Alan and thank you everyone for the good questions. Um there [Music]
Automatic transcript — names and jargon may be misspelled.