 Welcome everybody. Thank you so much for joining us for today's Protocol Labs Research Seminar. Today, we have ETHSERC PhD candidate, Lioba Heimbach, who will be presenting her work Eliminating Sandwich Attacks with the Help of Game Theory. Lioba is particularly interested in both the analytical and empirical analysis of decentralized exchanges for her research. Before starting her PhDs, she received both her bachelor's and master's degrees from ETHSERC and spent a semester at the Chinese University of Hong Kong during her master's studies. Thank you so much for joining us today, Lioba. I'm really excited for your presentation. I look forward to learning about your research. Thank you and welcome also from here, from me and also welcome for the opportunity to be, for me to be able to present here today. So the work that I will present here today focuses on the possibility of eliminating sandwich attacks, which are common front-running attack on decentralized exchanges with the help of Game Theory. And it was done together with Roger Wattenhofer at ETHSERC. So I'll start with an introduction of a broad introduction of decentralized finance and then in particular decentralized exchanges. Even though cryptocurrencies are decentralized, they were mainly traded on what is referred to as centralized finance until recently. But then in the past years, decentralized finance has surfaced mainly on the Ethereum blockchain and has replaced many traditional finance services pertaining to cryptocurrencies, such as payments, lending and foreign. Decentralized finance makes financial products basically available to anyone on the blockchain, such as Ethereum, which I mentioned previously, and anyone can use. So if you want to participate in decentralized finance, you don't have to go through a middleman like banks or brokerages, but can directly interact with the protocols. And we focus on one service in particular, decentralized exchanges. So in centralized finance or traditional finance, and when you want to buy cryptocurrencies, this generally goes to the limit order book mechanism, and this is typically just used to match buyers and sellers. So here you see a picture of an order book and the transactions are then processed through a financial intermediary, such as Binance, for instance, when we're talking about cryptocurrencies. And then recently, however, decentralized exchanges have emerged and they are basically just smart contracts on the blockchain that allow users to trade cryptocurrencies without the needs for any financial intermediaries. So if we have Alice and Papia and they want to exchange Bitcoin for Ether, they can do this directly with decentralized exchange without evolving any intermediary. Note that in reality, it's generally not Alice that exchanges her assets directly with Bob. The Ethereum transaction fees, which is the home for most decentralized exchanges, the fees that are charged by Ethereum pay for the consumption of computational resources and complicated transactions can get expensive very quickly. And therefore decentralized exchanges generally function in what is known as automated market makers or AMMs for short. And basically AMMs, they do not maintain an order book and this simplicity allows them to have a relatively low execution cost. So in the later analysis, we focus on a particular subclass of AMMs and also the biggest one of them that is currently implemented which are Consent Product Market Makers. And basically what Consent Product Market Makers do is they aggregate liquidity in what is referred to as liquidity pools. And so anyone can participate as a liquidity provider in such a pool and then earn fees from the transactions that execute with a pool. So if we go back to Alice who wants to exchange Bitcoin for EFA directly with the liquidity pool, she does this just by interacting with the respective smart contract. So let's dive into the actual specifics of these Consent Product Market Makers. They are some of the biggest or the biggest in particular decentralized exchanges are Consent Product Market Makers or variation thereof such as Uniswap, Sushi Swap and Pancake Swap for instance. And we in the analysis in particular focus on Uniswap v2 in the following, but the functionality of these exchanges is identical and also for exchanges that implement a different variation of Consent Product Market Makers a similar analysis would apply. So basically in a Consent Product Market Maker we have a liquidity pool for every token pair. And in this example, we have a liquidity pool for Bitcoin and EFA. So this pool basically just aggregates from individual liquidity providers and liquidity of the two assets. So any liquidity provider can come and deposit both assets in this pool. The pool then basically just holds the reserves of both these assets. So now we consider such a pool between a token X and a token Y. And in the case of a Consent Product Market Maker trading that happens along the price curve which is drawn here. Basically this price curve just ensures that the product of the two amounts of tokens stays constant which is where the name comes from. So we look at an example trade in such a market. We have a trade that wants to exchange tokens X for tokens Y with the current pool state being indicated in the graph. So we have 90 X and 118 Y in the pool currently. This means that the pool's current marginal price is that there is one X that you receive for every two Y which basically follows from the pool's reserves, the ratio between the two. And then we have a trade that comes in that wants to exchange 30 tokens X for token Y. And according to the price curve, the trader would now receive 45 tokens Y for the 30 token X. Note however that liquidity providers also get a bit for providing liquidity. And in the case of Uniswap B2, this is a percentage fee that is charged on the input amount of 0.3%. And basically for each trade that executes for the pool, this is charged on the input. So our trade needs to put in an additional 0.9 X in order to receive the full 45 Y. And further, we also notice here that even though these markets are commonly referred to as constant product market makers, the product in fact does not stay entirely constant in reality due to these fees that are also fed back into the pool and that then steadily increase the pool's constant product. Okay, so I mentioned earlier that at the start, the price of the pool was one X for two Y. But this is not what our trader received. And this is basically because every trade is associated with what is known as expected slippage, which basically just measures the expected decrease in price based on trading volume and available liquidity. So the more the trade moves the pool across the price curve, the higher the slippage, which follows from the convexity of the price curve. And in our case, we had a very large trade and compares into the pool reserve. So there was a lot of expected slippage. So instead of receiving the initial price, which was one X is worth two Y, our trade only received four Ys for the three Xs. And basically we refer to this phenomenon or this decrease in price as expected slippage because it's only dependent on the pool's liquidity as well as the trade size. But there's something else that might change the price of the trade, which is the unexpected slippage. And this is an unexpected increase or decrease in the price based on previous trades. So transactions are not executed when they are submitted, but only upon inclusion in a blog. So other transactions might change the pool state before the transaction actually executes. So we go through an example here again and we have one trade, which trades in the opposite direction. So we were selling X for Y and this trade does the opposite. And the new starting state when our trade and executes is also now indicated as having 75 Xs in the pool and 260 Y. And now our trade, which has the same input amount of 30 Xs only received 62 Y, which is quite a lot more than we previously received because of this change in the pool states before the execution. But the entire opposite can also happen and this is maybe what we don't want. So if a trade comes before us, that trades in the same direction, this further increases the price of Y and then our trade again with the same input amount of 30 Xs when our only receive 34 Y. And this is something that traders do not want. We want to be able to say, oh, when my trade executes, this is sort of the worst price that I am willing to accept. And for that you can specify a slippage tolerance which basically just denotes the maximum acceptable price movement to you. And if this trade were to pass your maximum acceptable price movement, then it would automatically fail. And basically, as part of this research, we were finding ways to set the slippage and such that trade optimally for traders. And before I go into that into more details and there are benefits to both setting the slippage tolerance high and low. So basically higher slippage tolerances avoid automatic trade failure if the pool's price just naturally moves between the time of the transaction submission and the actual execution. So if we have a pool that has a lot of volume or the crypto prices are very volatile, then the price might move a bit and we don't want our trade to just fail them. But on the other hand, a low slippage tolerance lets you avoid that your trade really executes as an unwanted price, but a low slippage tolerance also lets you avoid an AMN specific front-running attack, the sandwich attack which will be the focus of this presentation. So our goal in this work was to let traders avoid the sandwich attacks by setting the slippage tolerance in a way that for one avoids the attack, but also at the same time avoids unnecessary transaction failures if the pool's price just moves naturally in the meantime. So then I will detail the mechanism of the sandwich attack and why it is possible and what it really does. So the sandwich attacks make use of exactly this sort of unknown state of the pool at the execution time of a transaction when the transaction is actually submitted. So we don't know what the state of the pool is when we're submitting a transaction eventually. So, and they make use of this for one thing, for one, but also make use of the price curve convexity. So let's consider a trade which is shown here and a trader wants to execute it, which is the same as before. We have a trader that wants to exchange token X for token Y and if the trade were to execute ex-inspected, this is what would happen. But now there's a sandwich attack which comes and the trade will execute as shown on the right now. We'll quickly also note that how this is possible. So here in the sandwich attack we have both a front-running and a back-running transaction and how would the attacker achieve such a transaction ordering? So basically the attacker sees our victims' transaction in the member prior to the actual execution of the transaction. And then the attacker just strategically places its transaction around the victim's transaction. And there are various ways of doing this and even services have surface that make it a lot easier for attackers. So it's quite simple for attackers to achieve such an ordering. So they have their front-running transaction and their back-running transaction which sandwich the victim's transaction, hence the name of the attack. So then the first attack, the first transaction that we'll now execute is the attacker's front-running transaction. So the transaction TA1 here, which is shown in red. And this increases the price of token Y by also buying token Y, which then the victim has to buy in the second step then and will receive a worse price for it. And then finally the attack is concluded with the attacker back-running the victim's transaction and profiting from Y's inflated price by then again selling the tokens Y that it previously bought. And basically due to the convexity of the price curve, the attacker can make a net profit with such a sandwich attack. And let's quickly look at it. So if we compare the victim's trades, how it executes with and without the sandwich attack, we find that for the same input of token X. So if you look at the Delta VX, which is shown in red here, this is the same. It receives a vastly different number of tokens Y which is shown in yellow here. So without the sandwich attack, the victim receives many more tokens Y than with the sandwich attack, but the input is the same. And if we look at the attacker now, we observe that the attacker receives more tokens X and from the back-running transaction, then it's put into the initial transaction. So you see that the Delta AX in is much smaller than the Delta AX out. So the attacker receives more Delta X in the end than it put in initially. Additionally, the attacker in between only puts in the Delta AY, so the tokens Y that it received from the first front-running transaction into the second back-running transaction. So the difference between the Delta IN and Delta OUT is the profit that the attacker is making here. Then what we did is we studied the sandwich attacks and the possibility to avoid them. And for that we consider both the incentives of the attacker as well as those of the victim in what we refer to as the sandwich attack game. So while the attacker's incentives are generally to maximize profit, the victim's incentives are to avoid both sandwich attacks as well as unnecessary failures by and the victim tries to achieve this by setting the slippage tolerance. And note that most decentralized exchanges have a standard auto slippage tolerance that they suggest that traders to use when you go through the API, for instance. And we want to, in this work, we want to set the slippage on the victim size, such that it avoids sandwich attacks and then see how it compares to this constant auto slippage. So we start by going through the attacker's incentives, which are quite simply purchased to maximize profit. But the attacker needs to, there are a couple of relevant parameters that the attacker needs to track in order to maximize this profit. So first, there's the victim's transaction and the parameters that are unique to it. So that is for one, the victim's transaction size, delta VX, as well as the slippage tolerance that the victim indicated. And for both, we can generally say that the higher they are, the higher the profit of a potential sandwich attacks. This makes sense intuitively because if there's a large transaction size, there's more to attack. And if the slippage tolerance is large and the price can be moved more by the attacker, so the victim is willing to accept more price changes, which then again increase the profitability of the attack. And further, the attacker must also pay fees, which obviously influence their profit. So for one, the attacker must pay a transaction fee to the liquidity pool when doing a trade. This transaction fee is charged on the input amount of every trade and is proportional to it. So basically, when the attacker does the front-running transaction and when it does the back-running transaction, both times it pays this transaction fee or charged on the input amount relatively. And then there's also the Ethereum block fee that the attacker must pay. So this block fee is approximately absolute for the same type of transaction. So for the Ethereum fee, you pay for the computation as opposed to for the transaction size. And therefore, if there are two identical swaps in the decentralized exchange, we can assume that the block fee in the same block for both of them will be the same. So this is an absolute fee, at least to some extent that is charged for every transaction that the attacker does. And basically putting all of this together, we can analytically determine the optimal sandwich attack and then simulate the attacker's profits in the following. So here, we sort of simulate the profit of an optimal sandwich attack, depending on the transaction fee on the x-axis, which is charged as a percentage of the transaction input and the slippage tolerance S, which we see on the y-axis. And the slippage tolerance is what the victim is setting in our setup and also known to the attacker. So the shade of green in this plot visualizes the attacker's profits. And basically the darker the green, the higher the profit. And as if we would expect, this is especially a high the profit when the slippage tolerance is high and the transaction fee is low. Additionally, we see that there are some white areas in this plot and here the no profit with sandwich attack would exist. And therefore the attacker would not execute any attack. Also note here that this simulation disregards the block fee, so we just set it to zero. This is the absolute fee that the attacker pays for every transaction, but it would just remove a constant amount from the profit. Then basically we also simulated the same for this wearing the slippage tolerance and the transaction size of the victim relative to the reserves that are currently in the group. And basically a similar picture appears and we observed that the attacker's profit increases with both the slippage tolerance and transaction size as one would have expected. But the general takeaway that we have here is that we were then able to conclude by having analytically determined the attacker's optimal transaction size that the attacker's profit cannot exceed the victim's loss, which is also an intuitive finding. And this will also help us later. Note here that we say that the attacker's profit cannot exceed the victim's loss, but in most cases it will be lower because the attacker also has to pay liquidity providers, for instance, who then receive a share of the potential profit from such a sandwich attack. This basically concludes the side of the attacker and brings us to the other side of the sandwich game, which is the victim side. So what our victim is trying to do, it is just trying to set the slippage tolerance in a way to, for one, avoid sandwich attacks and to avoid transaction failures. So if she sets a simple way would be if we want to just avoid sandwich attacks, we also will set our slippage tolerance to zero, but then we might have very frequent transaction failures and it would not be a very optimal situation. So the process of setting the slippage is a bit more involved on the victim side. And she considers these two things. So first she calculates for which slippage tolerance her trade is not attackable. And she can basically simply do this by comparing her maximum loss if a sandwich attack would incur to the total block fees that the attacker needs to pay. Previously I mentioned that the attacker's profit cannot exceed the victim's loss and thus this is a way for her to determine whether a profitable sandwich attack would exist. And then if the block fees would exceed her maximum loss, her trade is not attackable. And this is a quite simple computation on her side. And then she basically is able to quantify or to find an SA, which quantifies the slippage tolerance when her trade is attackable. So most specifically, as long as her slippage tolerance is smaller than SA and her trade is not sandwich attackable. However, as we mentioned previously, she must also consider the cost that might be involved with her having to recent a transaction that fails when the pool's price naturally shifted in the meantime. These natural shifts can just be ordinary traders that trade in a time of higher volume in a pool for instance, or when there's high crypto price volatility and a lot of trades are going into the same direction, then we might see very high natural price movements. Basically she also calculates SR, which is a lower bound for a slippage tolerance and basically it specifies the limit for the slippage tolerance at which the estimated cost of her transaction failing to execute does not exceed the cost of a possible sandwich attack. And so basically what SR allows us to do is or allows our victim to do is to avoid having to potentially pay more for constantly resubmitting her trade than to just accept the sandwich attack and be done with it. So as long as the slippage tolerance is larger than SR, the expected cost of redoing the transaction is smaller than the cost of the sandwich attack. And then putting these two together, we get this fairly simple algorithm on the victim side to set the slippage tolerance. So first she calculates SA, which I mentioned previously is quite simple to calculate. So this is the slippage tolerance that specifies the upper bound for the slippage in order to avoid a sandwich attack. And she also calculates SR, which specifies the lower bound for the slippage tolerance, such that the expected costs which are related to some potential transaction failures do not exceed the cost of a sandwich attack. And I mentioned that this SA is simple to compute but SR is a bit more involved to compute and needs to be estimated, but I'll go into that in a moment. And then she just compares SA and SR. And if SR is smaller than SA, the victim simply sets the slippage tolerance to SA or slightly smaller and in that way is able to avoid a sandwich attack. And otherwise she sets the slippage tolerance to SR and basically accepts the cost of potential sandwich attacks because her cost would be higher otherwise. Okay, and then I'll move on to basically how we compute the lower bound for the slippage tolerance which is quite an involved process, at least a little bit more involved where we first need to estimate the expected price changes in a pool within a block. So more specifically, the trader basically needs to be able to estimate the required slippage tolerance and the slippage tolerance she requires such that the probability of her transaction failing is P. So basically for simple computation, the way we did is we just estimated the required slippage tolerance such that this probability of transaction failure is P to be the P percentile of these observed price changes in a pool in a given sliding window. So in the next slide here, I plot some estimations of this required slippage in the USDC, which is a stable contract to the US dollar and EFA pool. And this is for various window sizes used for the estimation. So the window sizes here go from 200 blocks to 20,000 blocks, 200 is shown in the lightest blue and 20,000 is shown in the darkest blue. So these are the window sizes that are used to make this estimation. And we also make this estimation for various transaction failing probabilities. So this is 1% in the left plot and 10% in the right plot. And basically to do these estimations, as I mentioned, we just look at a sliding window and then at the 1% percentile of the price change and then set this to the required slippage tolerance such that our trades will only fail in 1% of the cases. This is just something that is needed in order to then eventually be able to compute this lower bound for the slippage tolerance. And basically what you can see here is that for a 1% transaction failure probability, so if we say, okay, we're fine with our transaction failing 1% of the time in this high volume pool, so USDC EFA, the required slippage is only around 0.4%. And if we say, oh, we accept 10% transaction failures, which is maybe a bit high, but just for visualization now, it would be 0.02% as a required slippage. And then because this is a sort of simple estimation that we do here, and I also, we evaluated the accuracy of this required slippage and show here the mean of the estimation, so mu, as well as the relative error eta for four pools. So we have again, USDC EFA, and then USDC, USDT, Bitcoin EFA and DPI EFA. And basically the first table now shows the estimation, accuracy for failure probability, which is 1%, and the second table shows this accuracy for failure probability, which is 10%. And we find that our estimation is reasonably accurate for window sizes of 2,000 blocks, and after that a larger window doesn't add more. But we also see that our relative error of this sort of simple estimation can be quite large, especially in lower volume pools, such as DPI Ethereum, for instance, but this is also due to not even being able to achieve higher failure probabilities when there is a low volume in the pools and there is no price shift and no transactions would fail even if the slippage was set to zero, which is why we see some of these bigger relative errors. But the relative errors remain sort of small for the USDC Ethereum pool. So we note that in general here, this estimation is not very accurate, but it does its job, it is simple to compute on the victim's sides and it overestimates the required slippage rather than underestimating it. So the victims will not sort of, this will not cause any unnecessary transaction failures on the victim's sides, but just make them more careful. And then putting it all together, we then computed this SR. So this is the lower bound for the slippage tolerance on the victim size, which specifies at what point the expected cost of having to redo transactions equal the cost of just accepting a sandwich attack. And we did this estimation over 120,000 blocks in late December of 2020, which was a time at which Uniswap B2 was the main decentralized exchange on Ethereum and did it in eight pools, which are shown here. And basically this lower bound for the slippage tolerance adapts to the current pool characteristics. And we then computed for different values for, and we then computed different values for every block as it's different even with every block in the same pool and just plot the results as a box plot here. And on the left, you can see the results for a very small transaction size of only 10 US dollars. And on the right for a very large transaction size of 100,000 US dollars, or USBC, but just computed all to US dollar. And note that this lower bound, we see a decreasing with the transaction size, which is basically mainly due to the cost of having to redo a transaction. So the fee that we pay to the Ethereum network just becoming comparatively slower as our transaction size grows, which is the main reason why we see this as lower bound for the slippage tolerance decreasing as our transaction size increases. But even though our transactions, this year varies by a factor of 10,000, the difference in this lower bound is only a factor of 10 approximately. And other than that, for both transactions sizes, we see quite similar patterns between both of them. So SR tends to be smaller for pools with lower volumes, such as link Ethereum, for instance, which is the third pool from the left right in both plots. And so here we see such a low required slippage tolerance and the largest is for USBC, Ethereum, for instance, which has the most volume. To some extent, this is a bit counterintuitive because we would expect the prices of some more exotic cryptocurrencies to fluctuate more, but this is generally true on larger timescales when we're talking in months, for instance, but not within a block because the volume is just not barely split. There are many blocks in which no trade executes. So there are also no price fluctuations to observe in any of these blocks. Additionally, the lower bound for the slippage tolerance, we also see it vary within a pool of VC variations of more than a factor of five, as the pool itself might also go for periods of lower and higher volume. And basically what we conclude is that due to this vast difference in the lower bound for the slippage tolerance that we observed both within and across pools that this constant auto slippage, which is suggested by several AMMs, cannot be suitable and cannot capture all trades because a lot varies depending on the specific pool characteristics as well as the transaction size. And then basically what we finally did in this analysis is that we did a cost comparison. So we basically simulated our algorithm to set the slippage tolerance over 120,000 blocks and compared then its performance to the common auto slippage. So the same slippage for every trade independent of pool and independent of transaction size, which is commonly suggested by many decentralized exchanges. I want to note here quickly that since the time of this writing, Uniswap has suggested the slippage, but we compared to the past auto slippage that they were suggesting of 0.5%. So then these tables here show a cost comparison. So the costs that are incurred, if we simulate a trade per block in these 120,000 blocks in these four pools for the various transaction sizes and the costs measure both the costs that there are to redo transactions that might fail as well as the costs created by sandwich attacks. And what we are basically able to observe is that the ratio of the costs between the auto slippage which was suggested by Uniswap as well as the slippage that are quite simple algorithm calculated is quite significant that our algorithm always exceeds the performance of the auto slippage. And basically to just a bit of intuitively explain the results is that for very small transaction sizes our algorithm basically picks a bit higher slippage tolerances to avoid completely unnecessary transaction failures as these trades are not sandwich attackable anyways which is why the ratio of the costs between the auto slippage is measured by Uniswap as well as our algorithm is infinite there. And then for large transaction sizes on the other hand the opposite is true. So our algorithm picks a bit smaller slippage tolerances and is therefore able to avoid very many sandwich attacks while the console auto slippage basically has a sandwich attack occurring in every block. And what is not shown here but what I would also like to mention is that with this algorithm giving this parameter configuration where we just put in a realistic gas price for Ethereum it was able to avoid all sandwich attacks for trades that were smaller than $100,000 and only needed to accept them for trades of size 100,000 in about 10% of the cases it depended on the pool a lot. And this basically also brings me to the end of this presentation. But before I go right to the conclusion I quickly want to mention that Uniswap B2 is currently not the newest sort of decentralized exchange or not the current implementation. There is Uniswap B3 now which has concentrated liquidity. So while in B2 we had the same liquidity for the entire price. So we show the price here from zero to infinity in B2 the liquidity was the same all the way across. In B3 liquidity providers basically choose where they want to provide liquidity they can specify a price range. And then in the end the liquidity over pool which is sort of all these positions together from various liquidity providers might look like this. So the liquidity varies depending on the price rate which then again makes this if we were then to apply this analysis again Uniswap B3 makes the estimation especially of the low amount of the slippage a bit more involved but in general the same should hold. So this brings me to the conclusion of this work which is that we were able to generalize the sandwich attack problem to include both traders and attackers until the most works before we're just focusing on the attackers but our goal was really to look what the traders can do to protect themselves. And what we were able to highlight is that contrary to popular beliefs traders are able to avoid sandwich attacks by simply adjusting their slippage tolerance. And this is sufficient at least in most cases and they do not face an unnecessary high risk of transaction failures. But as was mentioned or asked previously as well most traders will not know about this for instance or some traders might also just be willing to accept this sandwich attack and not have to worry about resubmitting their attacks. But there are options sort of for services to come in and to offer some help here but even more so this is more of a simple approach which fixes the problem sandwich attacks without on the trader size but there are many more sort of preparatory trading behaviors on decentralized exchanges and other platforms as well which involve front running. So I think that the research or developing protocol which is broader and can does not only focus on this one particular case but can avoid front running in general for instance is a very interesting and also highly researched topic currently. Okay with that thank you for your attention. Thank you very much.