Bancor by Mark B Richardson

ETHDubai 2025 · 29 Apr 2025 · 25:58

Mark B. Richardson presents Bancor at ETHDubai.

Speakers

Topics

From ETHDubai 2025, hosted by DeFi Dubai.

Transcript

So yes, uh my name is Mark Richardson. Um I'm the project leader at Bangor and I'm going to be giving a generic presentation today. So this is much less about our products and a little bit more about information in the space that I think more people should be aware of or have a poor understanding of um already. So, we'll start with sandwich attacks 101. Um, who knows what a sandwich attack is or is convinced they know what a sandwich attack is or could you describe how one is performed? So, we need to go over a little bit of notation before we get into the guts of this talk. And so this is notation that's borrowed directly

from the white paper literature or the patent literature depending on your perspective. And so here we have a liquidity pool and it has two tokens in it. Token zero and token one. And these could be ETH and wrap Bitcoin or USDC die. It doesn't really matter. And I'm denominating both of these tokens with uh X and Y and subscripting P to um designated as belonging to a liquidity pool. And then we have a user and then they have a wallet that also has tokens X and Y. and I'm subscripting it with U to denote that this belongs to the user and not the liquidity pool. And then we use this convention that there is some delta xu that comes into the liquidity pool and gets added to its balance and then some delta yu that is then returned

to the user. Um so we're making sure that both of these numbers are positive, right? So these are in the reals. Um and uh the pool balance is always being uh having the delta x you added to it and having delta yu subtracted from it and vice versa for the user. Um and so yeah, we're always using positive numbers in the in the reels at least in these conventions and there's more than one competing um convention that you might see published elsewhere. So that's the end of the notation slide.

I'm happy to get that out of the way very quickly. Now we need to describe the exchange model and a lot of people are going to be familiar with some aspects of this but there are going to be nuances that I think are probably new to you. So the most common the canonical example or the prototypical example is the x yals k liquidity pool which was released sort of around the end of 2016. Um and there's two different ways that you can monetize a pool like this. Um and one is to uh collect a fee which is very badly named um but is still the um prevailing nmanllete in the um in the industry and you can do it in one of two predominant ways. One is that you can either subtract the fee amount from the

user's input right from the dx amount or you can subtract it from the dy amount. um and they have slightly different uh calculations associ associated with them and they're going to change the way that a sandwich attack is performed and also how arbitrage is performed. So these are basically the two models, right? Or actually this is the the fee from amount in model only compared with the feeless amount. And if you compare them heads up, um one of the things I want you to see here is that you can actually refactor this equation um so that you basically have the pool's liquidity reserve in X tokens as just being artificially represented as if it's slightly higher than the amount that it

actually has. So now we're no longer saying we're taking a fee from anywhere. Um, but mathematically it gives you exactly the same result. And this kind of leads into some of the other criticisms I have about the words that we use to describe finances in DeFi more generally. So there it is. The felis model is just XP there in the numer in the denominator, excuse me. And then on the left, we've just um artificially amplified it by dividing it by a number between zero and one. And then the same is true um if we're reversing that transaction. So instead of using f of dx, we're now we're using f of dy. Okay, so that's the fee from amount in. Uh let's talk about fee from amount out. So again, here's the the feeless

model for um a heads up and we're going to compare it with the fee from amount out. Now, similar to the fee from amount in, we're going to adjust one of those token reserves by a small amount. But instead of making the one of the token reserves look larger than it actually is, instead we're going to make one of the token reserves look slightly smaller. And um again, this is uh exactly the same intuition as saying we're taking a fee from the amount that the user should be receiving in lie of a particular fee being applied. Um but I still prefer to think of it in terms of augmenting a token balance.

And so these are the two models that we have, right? Fee from amount in, feed from amount out. And then in general, um the same notation applies. So we can in any four of these cases refer to the token that the user is sending and receiving from the liquidity pool the same way. And these are symmetric. So you can invert these calculations or swap the symbols X and Y and still get exactly the same formulas out. So that's the end of our exchange model. Um let's see an example of a trade being performed. So relatively simple example.

We have a liquidity pool with 100 of each token and a fee of 0.3% or 0.03. And we're going to use the fee from amount in example to calculate this trade. And so all you do is take one of those equations that I've already shown you and start substituting in the values that are associated with the state of this pool. So we have um XP is equal to 100, YP is equal to 100 and the little uh Greek letter delta is equal to 0.03. And after we process that calculation, we can see exactly how many Y tokens or one token one the user is receiving in exchange from the liquidity pool for the uh 10 token zeros that they

are providing. Okay. Now, if we swatch if we switch from the fee from amount in to fee from amount out, we get a slightly different um result. So again, we're doing exactly the same substitutions, but now we're switching models. And what you'll find is that you get a slightly smaller amount um in this particular fee model than in the last one. Um so if we compare for example the user state um in the fee from amount in to the fee from amount out, what you'll see um is that in the feed from amount in they were given 9.066 tokens whereas in the fee from amount out they were only given

9.063 tokens or four if you're rounding up. So they get a slightly better deal on the fee from amount in which makes it seem like it's a better deal, right? Maybe this is the the model that we should be adopting everywhere. Um, but there is some problems with it and I'm going to show you that in just a few slides. First, let's talk about sandwich attacks. So a sandwich attack takes a transaction that a user has already submitted against the pool and then rearranges it to get a result that allows the attacker to extract value. So this is exactly what it's going to look like. We take the example that we just processed, right? So these are the calculations that we just went through in the slides leading up to this one and we're going to, you know, imagine that

the user performed this simulation themselves. You know, this is an agreement effectively that they have with the liquidity pool. And so you might naively think that this is the result that they're going to get. But you can't make that assumption because the calculation is contingent on knowing the state of the pool at the time the transaction is actually processed. So in this particular situation when a user is sending 10 tokens into the the DEX smart contract, that's when the calculation occurs. And if that transaction hasn't been included in a block yet, then that means that someone can rearrange these transactions in order to extract value from it. and I'm going to show you exactly how to perform that attack. Okay, so this is basically how

it's going to look like in the mele, right? You have the user um has 10 tokens in their uh in their wallet and they've already committed to send them, right? That's the the transaction that they signed. And we're going to forget about things like um min returns and that kind of thing so that we can really explore exactly how sandwich attacks work. So, it's because that state of the contract being able to change after the user has already signed it um that enables this kind of attack to be performed and you can perform it very precisely. But before we get into the precision of it, I'm first going to show you just a very basic sort of naive example of it. So, here's the the mouse, the one that's being prayed on, um

expecting to send 10 tokens in and receive about 9.06. And we're going to go with the fee from amount in model for this demonstration. Okay. So this is what the attacker does. They see that last row, right, the one with the star next to it as the transaction that the user has already expected to commit to. And what they effectively um accomplish is that they cut that transaction out of the block and then they paste their own transaction before it. Okay. So here we're going to, like I said, this is just a naive example of a sandwich attack where the attacker is just swapping the same amount as the user.

The user is swapping 10 tokens. So I'm going to swap 10 tokens in front of them. I'm going to frontr run their transaction with the same amount. And then only after the attacker's transaction has been processed by the liquidity pool. Do we then let the user transact against that changed state in the liquidity pool? And because I control the ordering in the block, I have this flexibility to move the transactions around. So then we paste the user's transaction immediately after the attacker's transaction and then we can just look here at the difference in the token output that they got from that liquidity pool. So compare the unattacked state to the attack state. When no one was sandwich attacking them, they got nine

and a bit tokens and now they're getting about seven and a half, right? Which is a pretty pretty dramatic change already. Um that's from the users perspective. they're actually being charged almost 20% more on the value of the tokens that they bought which is surprising that's not the end of the attack. So what we've done is we've excised the user's transaction we've front run them and then the sandwich is we then backun both trades together. So here what the cat has done right the attacker is that they've already received um something like um you know 11 tokens from the trade that they got out of the front run and then they just dump everything back into the pool right they never wanted those tokens in the first place. So they then trade it back

and if you have a look at just their wallet state and these are bundled transactions remember this happens atomically. So all they did was go from a a wallet balance of 10 of token0 to a wallet balance of 11.7. And they managed to do this completely risk-free, right? They got 1.7 odd tokens out of this transaction for doing literally nothing. Okay, this is how a sandwich attack is performed. Now what I said was that this is a naive case only and what we should look at is what we refer to as the maximum extractable value. Okay, so that's the the MEV acronym that you may hear people throwing around without really knowing exactly what it means. So this is the challenge given that that

state of the pool and given that you know that a user is trying to trade 10 of token zero into that pool, how much should you front run with and how much are you going to get after back running it? So let's go over that. Okay, this is exactly the situation that's kind of made diagrammatic. Um and hopefully this video will live on YouTube or someone uh somewhere where someone can study it uh later for the details. But the information that we have, all the information that we have is the state of the pool at the time that we're including it in a block and the users's input amount. You can get to a symbolic solution for this. And again, we're only going to be referring to the

equations that I've already presented at the beginning of this talk that ex that describe like 99% of the decentralized exchanges that you know about. And remember that these equations are symbolically reversible. Okay, so this is basically how you set up the equations. You know what the attacker's front writing trade um should be in terms of its symbols. And I'm going to use the subscript a here to distinguish the user from the attacker. And remember the subscript P refers to the pool balance. So if we just take a look at whatever that trade is, let's say we don't know what it is yet, but we know that the attacker is going to get a certain amount of these DYA tokens out of that front running transaction. And that DYA is immediately

what we're feeding into the pool state that the user is then going to interact with. And then after we do that calculation, which is again just nesting some of these swap formulas together, we can then get the amount y that the user is going to receive, which is what we then have to subtract from the pool state afterwards. And so we get this enormous nested equation, but it is symbolically compact, right? Everything that is in here will tell you exactly how the amount out um from this transaction and from the attackers's perspective is related to how much they front ran with. And so after a little bit of work simplifying that, you can actually get it into a pretty wellescribed um and uh easy to follow form. And then all you need to do is

take the derivative of this um with respect to the amount that the attacker is is sending into that pool. So you know if you're going to do calculus at least, you know, let it be a derivative. So in this case, it's not too difficult. Um and so we can actually pack this equation down a little bit farther. um and just extrapolate all of the uh the constants that we know that we're going to be working with. So in this particular case, after a little bit of extra work, we can substitute these A B CDE E F and G constants for other constants that are associated with the calculation. And note that all of these remain constant from the attackers's perspective, right? They after they're reordering this inside their block, all of these are already known. And this is

not difficult to compute. You can get this in a few micros secondsonds if you've got a um you know access to a normal cloud server or something like that. So after we've got that derivative, um, we want to set it to zero because this is effectively where the attackers profits are leveling out, which means that we can simplify this expression a little bit farther. Right? The d constant gets cancelled. All of everything in the denominator gets canled and so we end up with a relatively simple quadratic and a couple of those constants get borrowed over from the rest of that calculation. Okay? And we only care I should note about the cases where the delta xa is is greater than zero.

Otherwise the attacker is effectively donating money to the pool. Okay. And so that gives us an amount 3386 u which is I claim the optimum frontunning amount. This is the maximum extractable value amount. So let's go over what that example would then look like. We then have the user who is naively committed to send 10 tokens into the pool. an attacker comes in, front runs their trade with an an amount 30 times greater than that. Okay? Um actually 300 times greater than that. Um and then the users transaction is processed afterwards and they only get 0.08. Um and then the attacker swaps back all of the 97 odd tokens that they got back into the pool to get 3396

tokens back out. Okay. So from the users's perspective, the price that they paid for the token has now increased by 110,540%. Right? This is what a sandwich attack does to naive users. And this is why things like setting slippage tolerance is so important to keep it as close to zero as you can because whatever you set the slippage tolerance to be, I can now uh adjust this exact formula to take exactly what it is you want to donate to me. If you set your slippage to 5%, I promise you I will take all 5% of what you set. Okay. Now, that was all from the fee from amount out. And I'm not going

to go through all of the details again, but just know that if the fee from uh sorry, that was the fee from amount in. If we swap it to fee from amount out, you get a completely different um equation that you have to resolve symbolically. Um but after you do that, what you find is that it's not quite as bad, right? the amount that the attacker can actually extract out of that transaction is reduced somewhat. Um, and it suggests that the industry has actually set itself up to make sandwich attacks as profitable as possible, which is worth asking yourself, who made those decisions, right? Why would if you had the option to create a dex with just a

very simple code chains, right? Instead of taking fee from amount in, you take it from fee from amount out. It's an it's an interesting thing to think about, right? If you were designing these things, you would think that they you might have a defensive programming mandate to make sure that naive users are exploited as little as possible. That in fact, the industry has gone the other way and made sure that when someone is exploited, it's exploited to the, you know, to the nth degree, sometimes hundreds of times more than how we made a slightly different design choice. And so comparing uh that's comparing the two situations. So fee from amount in which is what the m majority of the industry uses um instead of getting you know 9ish tokens the user is getting 0.08 08 um and if we switch

to me fee from amount out it's um at least 100 times greater than that something to think about okay if you want to study these things further um I do have um some additional text here that you know again I refer you to the YouTube um recording of this if you want to uh dig into details but I've also actually spent a lot of time digging into even more of the theoretical frameworks and potentially um you know defensive programming strategies that you can implement ment to protect users against this and I actually have developed you know I run at a decentralized exchange um that is actually sandwich attack immune because it result it it operates predominantly on users quoting prices rather than accepting the prices that

the the liquidity pool quotes to them. So that's the end of um performing sandwich attacks. Let's talk about arbitrage. Arbitrage is similar in the sense that arbitrage is um defined as being a risk-free trade and certainly sandwich attacks are risk-f free trades on at least from the attacker's perspective. But I think generally when we're referring to arbitrage, we're talking about two different pools being out of equilibrium with each other um and that you can process a transaction against both of them in order to extract value somehow. So let's go over that example just quickly. Again, we're using the same equations that I introduced earlier in the talk. We're just going to process a trade against the yellow pool to get delta y0 and then we take delta y0 and

feed that back through the blue pool in order to get a different delta y or sorry excuse me in order to get delta x back. So again we can nest these together um and again you know going through some algebraic rearrangements here which can take you a little bit of time but at the end you get to effectively this result. And I haven't optimized this. This might pack down a little bit farther, but I really like the idea of having this huge equation streamed out along the the top of the screen. And this is what you get by evaluating the derivative of this at zero. And so that tells you exactly how much you need to swap against these pools in order to bring them back into equilibrium. And after you've done that, what you will find is that you get an amount of tokens out of this for free.

Right? So all I've done is buy tokens from one pool and then sell it to the other pool. And now I'm up 4.6 six tokens that I didn't have before. That's it. And I can again do this atomically. So there is no risk to performing this transaction. So that's how you perform arbitrage. Who did that value get extracted from? Okay. And there's a very deep misconception um that I think a lot of commentators in in DeFi talk about which is that arbitrage trading extracts value from liquidity providers. Okay, this is generally how it's um it's sold to us and this is the misconception. I'm going to show you exactly how these arbitrage opportunities arise and then who is

actually losing out in some of these things. So this is actually what happens if you have uh these two liquidity pools and their prices that are at equilibrium with each other and you have a naive user who trades on one of these pools let's say via the front end that the DEX gives them to use. After they have traded the market then falls out of equilibrium at least with respect to these two different pools because they didn't use uh trade routing or aggregation in order to keep these things uh trading fairly. And that difference, right, how much they pushed that market out of equilibrium is exactly the amount they overpaid by.

Right? This is the trader, no one's making them do anything, tricked into paying more for those tokens than they otherwise would have been able to achieve had they used something like, you know, 1 in or ODOS or something to correctly route those trades. So, this is the demonstration, right? The user has overpaid by not using all of the available liquidity. Now the arbitrageer can come in and do something and it's not you know it's not malicious in nature. All they have done is notice that there are now two pools out of balance and they then bring them back into balance by trading against them both and that means that they're now quoting the same marginal rate um give or take and they get to extract a

little bit of value from that process. So the overpaid amount is basically equal to whatever the arbitrageer is extracting and liquidity providers do not lose any value here. And there's an elegant proof for the fact that liquidity providers don't lose out from um from arbitrage trading by considering the fact that arbitrage gets closed all the time by people who aren't arbitrageers, right? Or who don't actually extract any value from the system. So consider that these two trades may be performed by different people. So in the first instance you have someone trading you know 18.8 8 of the X0 token against liquidity pool one.

And then in a second trade, someone completely different who isn't in collusion with the first person um trades uh in the opposite direction is trading 60.5, you know, of the Y tokens back on liquidity pool two to get some of those X tokens back out. Here the market is still going to be put back in equilibrium and in effect they have arbitrageed the system, but no one has extracted any value from anywhere. It's just that these two different users have now identified better trading opportunities, but they have no interest in closing the arbitrage themselves. Um, but you know, without knowing who each other are, have still managed to close an arbitrage. And so if the outcome is the same, then it doesn't matter who's

doing it, right? Arbitrage isn't something that is being done maliciously to a liquidity pool. It's just something that happens. Okay? and it's generally the result of the trader who caused the market to fall out of equilibrium that's losing the value. The liquidity providers don't lose any value at all. Um so that's the end of the misconception. If you would like to know a little bit more about how to perform complex arbitrage, right? So the beyond the symbolic examples that can be performed algebraically um we've recently published a paper to the archive called marginal price optimization um which is uh competing with another industry standard called Clarabel which is a convex optimizationbased algorithm um and our model is about 200 times faster is

significantly less uh computationally um has significantly less computational overhead um and can be executed against any number of dexes simultaneously which is really helpful. Um so a little bit about me uh I currently run the the project Bangor um and the product that we've built that runs decentralized exchanges now on Ethereum mainet and a whole bunch of other places is called carbon defi which is an orderbook style deck doesn't res doesn't have the same kind of vulnerabilities to the uh the attacks that I've demonstrated here. If you would like to discuss with me anything I've presented here um or anything else you know that you that you might like to discuss in in DeFi decentralized exchange you can reach me at telegram is probably the um the

easiest but um please be patient with me as I get a lot of messages um my Twitter handle is here I generally don't respond to messages there um the email um is a very good secondary source of of contact if telegram fails um so thank you so much um for being here I thought that this was uh I hope that this was informative and that uh you learned something and maybe even enjoyed it. Um I hope you're enjoying the conference and um thank you for your attention so much. Um amazing presentation and a great deep dive.