An analysis of Ethereum front-running and its defense solutions
This article aims to provide a comprehensive analysis of a common attack on the Ethereum blockchain: front-running, examining its characteristics to find the most effective solution and ultimately helping DeGate users avoid this seriously damaging attack.
Front-Running and Mempool
To put it simply, front-running is an attack in which a bot pre-empts a normal transaction while it is waiting to be packaged by setting a higher gas cost to complete a transaction at a preferential rate before the attacked transaction happens. Mempool is a set of Ethereum transactions that have been broadcast to the network and are waiting to be packaged into blocks. It is the premise for the implementation of front-running. The front-running robot analyzes and finds targets that can be attacked by continuously scanning transactions in the Mempool. The image below shows a Mempool browser that allows you to subscribe to transactions in Mempool and view all the details of those transactions by setting various filters.
Among all front-running attacks, the most typical and most dangerous is “Sandwich Attacks” against AMM (Automated Market Maker) transactions. In addition, there are also front-running attacks against arbitrage, clearing trades, flash loans, etc., which exploit system vulnerabilities to profit. There are a large number of attackers controlled by automated scripts. They are essentially automatic and indefatigable, so any profitable deal is subject to their saturation attacks, with seemingly little chance of escape.
Let’s take a closer look at Sandwich Attacks.
A real attack case
Let’s start with a sandwich attack case.
In the image above, three transactions are packaged in the same block, with a normal transaction sandwiched between two attack transactions (marked by hackers). The specific process is as follows:
- The user first initiated a normal transaction, buying DG with 23,700.705 USDC, and setting the Gas Price to 40.5 Gwei.
- After detecting the lucrative transaction, the bot then attacked the user by initiating a buy transaction and setting the Gas Price at 49.9 Gwei. It successfully jumped ahead of the user’s normal transaction under the Gas competition mechanism.
- At the same time, the bot launched another sell trade, setting Gas Price at 40.5 Gwei again, which was completed immediately after the user’s normal trade due to the chronological order.
With a perfect attack done, the robot will earn 1,6448.012–16,310.3–15.2–10.61 = $111.9 after accounting for fees. This attack, in which two attack transactions are mixed with one normal transaction, is known as a sandwich attack.
Underlying Principles Behind the Attack
To understand the underlying principle behind the attack better, let’s provide some background knowledge.
As we know, today’s mainstream Decentralized Exchanges (DEXs) such as Uniswap, adopt the AMM mechanism and its price follows the constant product formula. For example, if a liquidity pool of A tokens and ETH is created in Uniswap, with 1000 A and 100 ETH, the product of the two quantities is 100,000 and the current price of A is 0.1 ETH. When Alice tries to buy A from the pool with 10 ETH, the amount of A, denoted by X, that she gets can be derived by the following formula (note: for simplification, the transaction fee is not taken into account in the following):
（1000-X）*（100+10）= 100000，X = 90.9
In this transaction, the price of A is 10/90.9 = 0.11 ETH. Compared with the original price of A, the decrease in price is:
（0.11–0.1）/0.1*100% = 10%
A single transaction caused the currency price to slide by 10%. It can be seen that for pools with low liquidity, there is a large slide in the price for large transactions. However, if you can buy A before a normal large transaction (which is expected to generate large slippage), and then sell the A you just bought after the normal transaction, you can make a significant gain from that. Using the example from earlier, suppose Bob spends 5 ETH to buy A before Alice’s transaction, and then sells the A after Alice’s transaction is completed. Let’s see what would happen.
First, Bob’s pre-emptive trade:
(1000-X)*(100+5) = 100000, X = 47.62
That is, Bob buys 47.62 A’s for 5ETH
Next would be Alice’s normal transaction. Notice that the number of A in the flow pool becomes 952.38 and the number of ETH becomes 105:
(952.38-X)*(105+10) = 100000, X = 82.81
Finally, Bob sells 47.62 A. At this time, the number of A in the mobility is 869.57 and the number of ETH is 115:
（869.57+47.62）*（115-Y）= 100000，Y = 5.97
With this front-running attack, Bob makes A net gain of 5.97–5 = 0.97 ETH, while Alice loses A net loss of 90.9–82.81 = 8.09 A. Bob gains by making Alice suffer greater slippage loss!
Of course, the actual ahead attack would be more complex, and requires more sophisticated calculations to achieve two goals:
- To make the user’s trading result as close as possible to the max_slippage set by the user, to achieve the maximum theoretical arbitrage space
- To balance between fee competitiveness and revenue, and try to win as much as possible against other bots
Let’s describe this process better with the following diagram:
- A user at point A, intends to invest in_amount(user) USDT to buy ETH, which normally pushes the current state to B, and the user sets the maximum slippage to B(max_slippage);
- The bot monitors the transaction and makes a buy transaction of in_amount(robot) USDT before users trade, pushing the current state to A’.
- The user’s transaction then executes, reaching the maximum slippage B(MAX_SLIPPAGE) set by the user;
- The bot sells the ETH bought in step 2, reaches C, and gets out_amount(robot) USDT
- The bot gains out_amount(robot) — in_amount(robot) — charging fees.
Now that we’ve seen how deadly front-running can be, so what can we do to stop a pre-emptive attack?
As a general user, there are several ways to deal with front-running:
- To set a low slippage on trades, such as 0.1%, which would leave the front-running robot with no room to make a profit. Disadvantage: A low slippage makes it very easy for large trades to fail and still incurs high fees for failed trades.
- Increase the gas fee, which increases the attack cost of the bots. Disadvantage: this also increases transaction costs
It can be seen that the above solutions are flawed. Fortunately, many teams recognize the dangers of front-running and have come up with several constructive solutions. First of all, by analyzing the entire process, we can conclude that several elements are needed to implement front-running:
- Transaction publicness: Details of transactions can be obtained in Mempool
- Ethereum trade execution mechanism: Pre-empt transactions through gas competition
- AMM transaction curve mechanism: Constant product mechanism can cause large slippage points
The countermeasures work on each of these elements in turn.
Since bots analyze transactions in Mempool to decide whether to launch an attack, wouldn’t it be better to encrypt the transaction information so that bots can’t see or understand it?
There are proposals in the community to use zk-SNARKs, a zero-knowledge-proof technique, to achieve this goal. In other words, zk-SNARKs would be used to encrypt and hide the information of each transaction, so that the bot could not do anything about it.
However, this approach is not mature enough at this time and has drawbacks such as higher gas costs and the possibility that it can be used to perform blocking attacks that result in the reduction of overall liveness.
Ethereum Transaction Execution Mechanism
The current Ethereum transaction execution mechanism is done through gas competition, in which miners prioritize verifying the transactions of those who pay the highest gas bill. So if we bypass this mechanism and send the transactions directly to the miners for packaging, we can eliminate the possibility of a front-running bot attacking in the middle of the process.
Therefore, a Layer 0-like solution has also found some applications, such as the Taichi service of SparkPool, where the user can directly set the Ethereum node of Taichi in MetaMask so that the transaction can be packaged directly without appearing in Mempool. But the disadvantage is that there is some uncertainty about the time limit of packaging.
In addition, a solution similar to ArcherSwap’s concept builds a bridge between traders and miners, where traders can request miners to package their transactions directly in the form of a reward, which avoids the possibility of front-running. Although it feels like paying a protection fee to avoid being attacked, it lowers the trader’s costs and has the advantage of not being charged a fee for failed trades.
AMM Algorithm Optimisation
Under the AMM mechanism, large transactions would cause excessive price slippage (which can be understood as a temporary wrong price), a profit margin for front-running attacks. If there is an AMM mechanism that can reduce the impact of large transactions on subsequent transaction prices, it can effectively prevent front-running attacks.
Back in 2018, Vitalik offered a solution in the Ethereum research community that when an exchange transaction occurs, the pool price does not immediately adjust to the real price, but instead slowly moves toward the real price within a few minutes. As if the pool has gained a lot of liquidity out of thin air, hence we term this technique as “Virtual Balance”. This new mechanism can greatly reduce the profit of arbitragers, effectively defend against front-running attacks, and at the same time increase the returns of mobility market makers. It can be said that the 1inch Mooniswap is an implementation version of this scheme.
There is also an idea of maximizing the liquidity of a particular price range in a trading pool. The greater the liquidity, the smaller the slippage, and when the mobility reaches a certain point. The bots lose their profitability, and the liquidity-focused nature of Uniswap’s V3 version is an effort to do just that.
Outlook for the future
We have every reason to believe that with the persistent efforts of our teams, we will soon be able to provide a fairer and safer on-chain trading environment for our users, as the various solutions continue to evolve and technologies such as the next generation AMM and Ethereum Layer 2 are implemented one after another.