DEX MEV - Mark B Richardson | Bancor
ETH Belgrade Community·Tue, Oct 7, 2025, 12:00 AM
DEX MEV - Mark B Richardson | Bancor
Transcript
Uh next in line we have Mark from Bunker and he's going to talk to us uh about DexMEV in closed form or minor extractable value in closed form. So please welcome him in. [Applause]
Good afternoon. Uh yes, my name is Mark Richardson. I'm the project lead at Bangor. Uh and this is going to be a slightly more generic talk. So I'm not going to be discussing uh our products or at least not directly.
Um and instead uh I thought we'd take the opportunity to uh explore a concept that has come to I'd say dominate the deck space um for the last few years which is called sandwich attacks. Um, and while I think that especially at a conference like this one, um, a lot of you are already going to be familiar heristically with what a sandwich attack is, um, I wonder how many of you have actually tried to sit down and calculate a sandwich attack or how to perform one. So, what I'm going to be doing is first introducing the topic for those who aren't uh, familiar with it. um that will require me to introduce some uh notation and then we will sort of go through some of these calculations together and then I can speak more generally um about sort of uh where there's I think still room um for for research here and how it might influence u dex protocol development. So let's get the most boring parts out of the way which is notation first.
Um obviously there are a large number of different um competing standards in the industry. Um I quite like this one. We're just going to consider the the canonical x * y= k liquidity pool which generalizes to um concentrated and n dimensional cases as well but let's keep it nice and simple so that we can um get through the the lecture in a reasonable amount of time. So this cylinder is going to represent a liquidity pool and it's got two token balances which are x and y. Um and I'm using the subscript p to refer to the pool.
Um and then of course it has a fee parameter which is something that I think is horribly named in the industry but um it's the um it's the nmanllete that the industry has adopted and so we're going to be stuck with it. Um and I'm going to be using the the small Greek letter delta to denote that value. And then um of course um you have a user who's then interacting with that liquidity pool. And so we're going to assume that they have a wallet that have um a balance of both X and Y as well. And I'm going to use the subscript u um to denote which balances belong to them.
And then the interaction is going to be the user sending some delta xu into that liquidity pool and then some delta yu comes back from the liquidity pool. And just to be clear, I'm going to use both positive numbers in these situations. Um, in some circumstances it does make sense to actually have an implicit negation on one of those, especially if you're examining the finances from the perspective of the concentrated liquidity pool or from the normal liquidity pool. Um, but in this case, um, the transaction is going to be explicitly signed, which means that all of these numbers are are positive and in the reals. Okay, so that's the end of the notation.
Uh let's quickly describe the exchange model which again I assume many of you are already um familiar with it. Um probably makes sense to examine this first from the the felis situation and these are the familiar swap equations that I'm sure you've all seen circulated since sort of circa 2016. Um and what the way that I am depicting it here you'll notice using sort of function notation and this is so that we can say explicitly which is the value that we are that we know um and then which combination of constants are we are we using to calculate the specific output. So for example, for delta xu given the convention that I've just introduced, this is a user who is requesting to send to the liquidity pool a certain number of X tokens. And so we need to calculate the number of Y tokens they're going to receive.
But that's not the only way that you can do it, right? The user could just as easily request to receive a certain number of Y tokens from the liquidity pool. And this means that we need to calculate the number of X tokens they're supposed to send into it, right? So the difference is basically I I want to sell a certain number of things or I want to buy a certain number of things and I need you know the the corresponding output. Um and so this is the convention I'm going to be using for that.
Okay. Now that's the feless model. Um let's talk about fees briefly and maybe a couple of notes on why I think it's a bad way to describe them. Usually um this is the one that's um the that's been most universally adopted which is called fee from amount in. Um this is one that's used by like balancer and unis swap.
Um and you'll see in the way that the algebra is written here, you can sort of get the idea that it is applying a modifier to the input amount. So if the user is sending in let's say 10 tokens, the fee modifier will simply reduce it by a certain amount and then compute the the swap according to that modification. And so this is huristically sort of extracting a fee from the transaction before the transaction is computed. Um but there's um I think a better intuition with that that sort of um doesn't result in the same sort of paradox as you get during financial analysis of these things. And that's to note here that in both of these equations, you can actually just factor out um the the fee term and realize that you're actually just augmenting the balance that the user is um interacting with.
So rather than subtracting a fee from the amount that's being sent to the liquidity pool, instead we can actually just say that if the user is sending X into the liquidity pool, we're going to pretend that the balance of X inside the liquidity pool is slightly larger than it actually was. And that gives you the exactly the same uh quote price, but now doesn't require any sort of uh handwavy illusions to uh to a fee that's being extracted. Um and you can see the comparison here between the feed from a mountain in and the feedless version there. And then of course um the same transformation applies when you're uh flipping this equation around and computing it from the reverse perspective. Okay, so that's fee from amount in and these are uh symmetric equations.
So you can flip the inputs and outputs no problem. Um now we're going to move to fee from amount out which actually has the same heristic right instead of removing uh a certain amount from the input amount instead we push everything through the exchange algorithm and then from the output amount that's where we extract the fee from. Um but even in this form without modification you realize that it actually is just augmenting the the Y balance or at least decrementing it making it appear slightly more scarce and that causes the price quote to become slightly larger. Um and this means that you're actually trading on a very welldefined curve um and one where you no longer need to refer to to fees at all. Um and so yeah this is the the setup right in all um AMMs um that use the these kinds of curves these kinds of system um there is always a fee being implemented and so we don't need to consider the the fearless version although we can use that as kind of a a base case through which we can compare some of the results and note that in all of these equations again they're symmetric and reversible so it doesn't really matter which one you use and you can swap the token balances for X and Y if you So that ends the exchange model.
Let's have a look at just some quick examples. So let's say that we have a liquidity pool with 100 X tokens, 100 Y tokens, and a fee of 0.003, which is akin to about 30 basis points, which again is pretty standard. Um, we're going to be using the fee from amount in model. All we have to do then is say, okay, assume that the user is swapping some number of X tokens, let's say 10.
um and then substitute all of these values into the equations that I've just presented and then this is the um you know effectively the the process that the smart contract would perform in order to compute the amount that we're sending back to the user. So in this specific circumstance um with a pool in that state and a user sending 10 tokens in they're going to be receiving uh nine and change of the Y tokens. Okay, but what about fee from amount out? Right, different set of equations and slightly different um sort of uh financial uh intuition being applied to it. The most important is is that the slippage has occurred first.
And so the fee that you're extracting after the um transaction is performed is usually slightly higher, right? meaning that if you're a liquidity provider to the pool, you would prefer the fee to be taken from the target token because the effective fee that you're taking is actually slightly higher. Um, and so I can show you what that looks like. Um, show you what that looks like here. So if you have a look just these bottom rows, the difference is subtle, right?
But significant. In the fee from amount in model, the user is receiving 9.066 066 and in the fee from amount out they're receiving um about 0.03 less than that. Okay.
And obviously for a transaction of this size it's not particularly significant. Um but if you're transacting you know millions of dollars at once or something then this becomes um a more important observation. Okay. The other thing that I want you to note here is that this is an ME talk and these fees and quote prices and things, they relate to the user, sure, but they're also going to relate to the person who is using the same system as them to exploit them. And there is a very subtle but important interplay between um the settings that you have on your liquidity pool and how exploitable naive users are.
And that's a a non-trivial conclusion and something that I'm going to at least show you how we're going to get at and prove for yourself. So let's have a look at sandwich attack basics. Um again um I I don't want to insult the intelligence of my audience here. I know Ethgrade has a highly technical community. Um but let's just examine it quickly so that we can um better contextualize some of the slides to follow.
So in the naive case, right, you can imagine a user simulating their transaction on a smart contract and you know working out whether or not this is in fact the exchange that they would like to commit to. Um, and I say that this is naive because it completely neglects the fact that the transaction that's going to be processed is contingent on the state that the pool is in at the time the transaction is mined, not at the time that the transaction is signed. And there in lies an opportunity for exploiters to take advantage of users that haven't set, for example, good min returns or slippage tolerances. And you'll find that strangely enough now more than today um slippage tolerances on on common user front ends um are becoming more and more liberal, right? Like 5% 10% 20% slippage tolerances and users are actually being told that this is necessary.
Um, and I stipulate that it's actually the people who are uh running these exchanges who are trying to make it as easy as possible for themselves to perform sandwich attacks on these users. Um, and so that's really the point. If the state of the contract can change, then we can manipulate the user's transaction amount after the um after they've signed that transaction. So imagine um that you are an exploer, right? I don't want you to become the sandwich attacker.
Um, and think about how would you maximally exploit this user. Okay? Like there's obviously some naive cases that we're going to go through, but this is the information that you have, right? You you have some time n, which is whenever your block is being proposed. You know that the user's transaction amount is um already signed.
And so given that information um you know what is the um what is the most profitable thing that you can do right how can you maximally damage that user okay so let's look at performing a sandwich attack first the non-optimal version um we've got the uh the user's uh transaction here and really what's happening is that this is um where the reorganization inside the block is occurring. So this is the state that the pool state of the pool that the user saw and then because we have uh access to the the uh ordering inside the um inside the blockchain inside the the block we actually cut their transaction out and then we're going to paste our own transaction in front of them. Right? This is called the front running step and I said that this is the naive nonoptimal case. So let's just frontr run them with exactly the same input that they had.
Right? So the user is swapping 10 tokens. So we're going to swap 10 tokens as well. Then after we've pasted our transaction ahead of theirs, that's where we paste their transaction after ours. Okay.
So now um we've transacted 10 tokens in front of them. We've extracted the nine and change uh Y tokens. Then the user um swaps their 10 tokens in and they now have only 7.5 tokens when they were expecting nine. Now let's just have a look at this um and try and analyze the users let's say disappointment.
Um the transaction that they were expecting is the one on the top of the slide and the transaction they received is the one on the bottom which is about a 20% increase in price relative to the the deal that they simulated as they were signing the transaction. Uh, now that's actually not the end of the sandwich attack because as the attacker, we don't really want to take exposure to the token that the user was was trying to take exposure to. So even though we front run them with a certain trade, we have no intent of keeping the tokens that we purchased. And so what we're going to do is basically um we uh we take all of the tokens that we bought here and then we feed them back through the liquidity pool after front running the user to extract the same token that we started with. And so this is why sandwich attacks are usually performed with something like USDC or USDT as a starting currency.
Um or something like ETH is also very common. And so if you have a look at the overall um the overall process here and remember this is an atomic trade, right? So there is no risk to trying this. Um we've extracted 1.73 of the of token zero effectively for free from that user um by way of this x yals k algorithm.
Um and the fact that it's risk-f free means that it's a type of arbitrage, right? It's just it's a a malicious, right? Um sort of terrorist style arbitrage. Okay, so that's just the naive version, right? We just said if the user is trading 10 tokens then we're going to frontr run them with 10 tokens but what's the maximum amount um of value that we can extract from that user.
Now setting this up um can take a little bit of effort but my ambition with this talk is to show you actually that it's it's very achievable. Um if you haven't tried these sort of algebraic processes before um I'm not trying to intimidate you with this. I'm actually going to hold your hand and walk you through it. Um so that you can find, you know, other exploits in um in ME. Um but not because I hope that you're going to weaponize them in in reality the people that would weaponize these things already have.
Um it's so that you have a better understanding of I think your defensive programming mandate when you come to design new protocols. So if we start with this exact same system, right, the 100 of um of the X tokens in the pool, 100 of Y tokens in the pool, user trading 10 tokens in, and we're taking a 30 basis point fee in the pool. What is the best way to set up this sandwich attack trade? And how would you even go about this process in an optimization setting? The only information we have is the state of the pool and what the user is going to be sending in.
There is a symbolic solution to this and I'm going to show you how to do it using just the equations that we started with at the beginning of this slide and these are you know you didn't have to come to my presentation to get these equations. I'm sure you've seen these in dozens if not hundreds of white papers already. And so let's just go through those steps. We know that we're going to perform a transaction in front of the user. Then the user is going to perform a transaction after us.
And then we're going to backun both of those transactions. So what I'm doing here is I'm using the subscript a to refer to the attacker. And you see that I'm basically just iterating the state of the pool algebraically. So every time we've got a new equation, it has sort of memory of the transaction that was processed um before it. And so now that we have these equations, what we're trying to do is to rearrange them in such a way that we can express it as a function of just the information that we have at the time that the transaction is being mined.
So here for example um delta xa is the thing that we're going to try and and optimize for and in this expression um is equal to delta ya right which is the amount that the attacker receives during that first part of the transaction. And so we can substitute that in to start nesting these equations together. Um and so now in the top of this slide we have um function of xu which is the amount that the user is trying to trade and x a which is the uh amount that the attacker is front running with. Um and this computation results in or collapses down to uh delta yu which is the last substitution that we need in order to uh fully nest these equations together which produces something that looks pretty intimidating. Um but this is deliberately like not optimized.
So you can see the structure right you can actually see these things nesting together. And so uh you can very very easily you know go through and um go through that cancellation and refactorization. And what I want you to see here is that we're basically calculating the difference between the amount of X tokens that the attacker sent into the pool and then got out of the pool at the end of the sandwich. So this is effectively the sandwich attacker's profits. And then this is expressed as a function of just the variables that the pool has and the amount that the user was looking to trade.
And so to optimize that we really have a point of flection problem, right? We just need to take the derivative of this side of the equation with respect to the amount that we're front running in. And then when that becomes zero, right, that will maximize the profits for this thing. Again, it looks horrendous until you realize that the derivative of this um is actually not so bad, right? We have um you know uh some simple quadratic looking equations and a lot of these are going to cancel out when we actually set this thing to zero.
Um now these constants I am hiding some of the complexity here because you know not any one of those um of uh a through g is you know intuitive but it's just algebra right at the end of the day these are just going to you know collapse down to um to single numbers and yeah more the most important thing is that everything here is constant from the perspective of the attacker. So at the time that the transaction is being mined, this is like a few microsconds of computation to get these out. Okay. So now um we've got our opt uh we've got our um optimization. Um we just need to set this to zero which means that everything in the denominator there and that you know constant u dcaler is uh immediately canceled out.
And so this thing really does reduce to a simple quadratic formula. And of all of those constants a to g we can actually throw out most of them. and we only need constants a through c. Um, of course, you know, there's a plus minus here, but we only care about solutions where we're sending in positive token quantities. Okay.
Um, so now that we've got this uh situation, we basically just need to evaluate it for um uh for the constants that we have for the information that we have. And this means that we calculate an amount of 3,386 uh x tokens. This is the optimal front running trade in the sandwich attack. So let's have a look at what the ramifications are in the user because that's a lot, right? This is 300 times, right?
The uh the amount that the user is um is trading in from the user's perspective, right? They were expecting to get um nine tokens in change and after an optimal sandwich attack, they're only receiving 0.08 08 um which is 110,540% increase in the relative price right compared to what they were expecting to pay. Um and so that's for the um fee from amount in. I want to now challenge you to think you know how would this change if we're doing fee from amount out.
you know, I've shown you the steps that, you know, using just the algebra that I presented on the original slides that you can just nest these together and there's a very intuitive sort of step-wise procedure that you can can get to in order to make this an optimization problem um that resolves very well in closed form algebraically. Um I'm not going to show you the u the steps to that because it is slightly more complicated. It results in a quartic equation that we need to be um solved, but I will refer you to some of the work that I've done that describes that. But in that particular case, the um the optimum front running amount is considerably lower. So with the fee from amount in model, you need like 3,000 tokens or whatever.
And you can do that with a flash loan or something. So it doesn't really matter. Um but notice as well that the uh amount that the user is receiving in the optimum attack is much higher than the amount that they receiving in the optimum attack with the fee from amount in model. So which fee model is better for the sandwich attacker, right? If you were an exploer and you wanted to uh mandate that the industry uses one of these two fee models, which one would you pick?
Well, it turns out you would pick the one that the entire industry has gravitated towards. And I I think that the chances of that being a coincidence is 0%. Okay. Yeah. So, this amount versus this amount.
Um if any of this has interested you and you would like to you know uh to work on some of these things on your own and I do think that there is a lot of uh intellectually nourishing um you know uh ideas and material here that you can further explore. This is by no means exhaustive right this is your uh uh very first introduction maybe to to performing these things in closed form. Um but one of the things that uh I would encourage you to to look at is that is there a value when you can set the swap amounts the fees so on where it becomes impossible to perform a sandwich attack and does that amount change when you're swapping from fee from amount in and fee from amount out I think that these are these are interesting questions um and I have answered them um but I don't want to you know if you're interested in investigating those things on your own then I encourage you to do so and if you'd like to compare it with the work that I've done um both of these um explore the feed from amount out model um and uh in particular the second one looks at those more complicated analyses where you know paradoxically setting a higher fee on a on one of these types of pools and um on uh AMM algorithms more generally um actually makes it prohibitively expensive for the attacker to attempt it and so users who are setting, you know, poor slippage tolerances actually tend to get a better transaction rate by paying by paying higher fees um than allowing themselves to be sandwich attacked, which I think is an interesting conclusion. I encourage you to uh to explore it with me further. Um yeah, I'm the project lead at Bangor.
Um Carbon DeFi is our flagship decks. These are anagrams of each other, by the way. Um, and carbon is interesting because, you know, at least dovetailing it together with the presentation that I've just given you. Um, it was built with me resistance as like one of its designing principles, right? One of its founding principles.
And so unlike conventional AMMs and carbon isn't necessarily an AMM. Um, but these sandwich attack techniques do not work. Um, because the assumptions that are required for sandwich attacks to work are uh broken in that context. uh if you would like to to speak to me about this or about anything else, um the best way to reach me is probably Telegram usually or my email. These two in the middle, don't uh I'm probably never going to read your message, so maybe ignore those two.
Um and of course, I'm going to be around the conference, so if you'd like to um if you'd like to to chat with me uh while I'm here, um I'm in Serbia for the next week. Thank you so much for your attention. I hope that this was um enriching for you and I'm happy to take any questions although I think I have also gone over time so I'll try and keep it short. [Applause]
Automatic transcript — names and jargon may be misspelled.