Scientists in Action: Hunting the Front-Running Bots in the Ethereum Dark Forest
This article was published on December 29, 2020, on the cryptocurrency wallet Zengo blog, authored by Alex Manuskin, and compiled by ChainNews.
Monsters in the dark forest are no laughing matter. These front-running bots can analyze smart contract instructions and functions that have never been used in smart contracts before to extract potential profits.
To better understand these bots, this article provides a journey into the dark forest of Ethereum. Let’s delve deeper into this dark forest and see how rampant they are.
We managed to "set a trap" to capture some common types of front-running bots and analyze their behavior.
In this journey, we studied the efficiency of these front-running bots and examined the likelihood of various trades being hunted by them. Of course, we also tested different methods to evade them.
Below, enjoy.
What is front-running?
Generally speaking, front-running refers to the act of jumping the queue to execute trades before known future transactions occur.
A simple example of front-running is bidding on an exchange. Suppose someone is about to buy a large amount of ETH on Uniswap, enough to push the ETH price up. One way to benefit from this situation is to front-run and buy ETH just before this large purchase, while the price is still low. Then, after the ETH price skyrockets, sell immediately to lock in profits.
In addition to this arbitrage trading example, there are many ways to extract value using front-running, including liquidation, purchasing rare NFTs, or simply creating user errors. (The extractable value from the order of trades or executions is known as "Miner Extractable Value (MEV)".)
Front-running on Ethereum can be achieved by paying gas prices slightly above normal levels, which encourages miners to prioritize the arrangement of their transactions when building blocks. The higher the transaction fee paid, the earlier the execution order. Therefore, if two transactions would profit from the same instruction calling a smart contract in the same block, only the first executed transaction will ultimately profit.
Animal Behavior
Dan Robinson and Georgios Konstantopoulos described in their co-authored blog post "Ethereum is a dark forest" their experience of being intercepted by arbitrage bots during an attempt to save a smart contract containing $12,000 worth of tokens. These super predator bots are highly advanced and can track any valuable transaction in the Ethereum transaction pool, intercepting them through front-running.
The story of the dark forest is so "chilling" that it was hard to believe when I first read the article. In fact, there are reasons to question the existence of such super predator bots. Why can someone extract funds from the Uniswap protocol? Isn’t this platform being monitored by countless bots? Are these bots just a group of ordinary "arbitrageurs"?
Earlier this year, we published an analysis confirming that they are not ordinary "arbitrage bots." As far as we know, they can manage to call smart contract functions that have never been called before. Even if the transactions are obfuscated through proxy smart contracts, these bots can still siphon off funds through such operations.
At the very least, this is shocking. The ability to monitor any transaction in the transaction pool is a powerful weapon. Disturbingly, some service providers have begun to openly offer "dark pool" trading layers.
The "dark pool" trading layer does not require services like Infura or even private nodes, directly sending transactions to miners who promise not to broadcast them to the remaining nodes in the network, thus ensuring that transactions evade the predators' radar.
The famous white hat samczun collaborated with several partners to rescue $9.6 million from a vulnerable smart contract using a similar method. It is not hard to imagine that miners might start manipulating front-running bots while providing a safe passage for traders willing to pay extra fees.
These bots differ from other elements of Ethereum and can only operate on the Ethereum mainnet, while smart contracts can be tested in development environments or testnets. Aside from conducting some preliminary experiments, it makes no financial sense to have these bots attempt to front-run transactions in the testnet. Moreover, since the logic is hidden, the operational rules of these bots may vary.
We are unclear about the conditions under which these leading trading predators decide to launch attacks. Therefore, in some respects, tracking these predators is akin to chasing rare animals.
We do not target all front-running bots, but only specific ones, namely the generalized types of such bots.
To ensure that the front-running bots we capture are "real" generalized front-runners, we need a unique "trap." The trap is a newly created smart contract initiated with a secret string of SHA256 hash and accompanied by some funds. Anyone who provides the correct secret contract can withdraw the locked funds. The funds will be sent directly to the sender of the withdrawal transaction.
The idea behind this trap is to send a "decoy" transaction in a way that provides the correct secret contract to see if anyone attempts to replicate and provide the secret contract themselves to intercept the funds. If someone intercepts the funds before the decoy transaction, it indicates that someone can analyze the transaction pool while transactions are in the pool, replicate their relevant content, and provide the secret contract themselves.
Interestingly, the bots can provide a secret contract in a previously unknown smart contract to intercept funds—this confirms they are indeed true generalized front-running bots.
Mechanism of Generalized Front-Running Bots
An indispensable part of this experiment is to understand the mechanism of generalized front-running bots. However, if someone has built a money-making machine, they are unlikely to share it on GitHub. Therefore, we can only observe and reverse engineer the behavior of predatory bots.
Building a generalized front-running bot typically requires two components:
- The first component is an Ethereum account, with or without a smart wallet proxy, to which the tampered transactions will be sent.
- The second is the "backend," which is the brain of the operation, usually occurring off-chain.
The operators of these bots use some technology to scan every transaction in the transaction pool, parse it, replace its parameters (e.g., the transaction caller), and determine whether intercepting it would be profitable.
Workflow of front-running bots
Rational bots will not initiate interception attacks on trades where transaction fees exceed potential profits. The total transaction fees can be quite high, especially when gas prices are elevated, so to make the front-running bots attack our decoy transaction, a certain minimum profit is required.
Additionally, since bots need to analyze every transaction in the transaction pool (which contains many transactions), time is also crucial. Ethereum takes an average of 12 seconds to produce a block. If the gas price of the transaction is high enough, it must be analyzed and replaced quickly before the next block is produced.
This is a probabilistic process; after the transaction is broadcast, there may be a block mined immediately, preventing the bot from successfully analyzing the transaction and broadcasting a front-running transaction.
Considering these factors and some ideas, we tested the conditions under which front-running bots would attempt to intercept the decoy.
Setting the Trap
Our smart contract (payer Giver) was initially set up with a balance of 0.035 ETH, worth about $20 at the time. Anyone who provides the correct secret contract to the stored hash in the contract can take these funds. The transaction that withdraws these funds will trigger the predator's front-running action, and another account (receiver taker) will attempt to provide the appropriate secret contract to extract the funds.
Round One: Directly Calling the Contract
To ensure the baseline trap was functioning correctly, we first used the receiver account to call the contract. During the first attempt, the gas price was relatively high (determined by the Ethereum framework), and we were able to successfully recover the funds.
Our success may have been due to the profit of intercepting this transaction being too low, insufficient to entice the predator, or because the transaction was quickly written into a block, leaving the bot no time to act. Clearly, this was not the result we were hoping for; our goal was to lure the predator into our trap.
Round Two: Allowing Time for the Predator to Think
In this round, we addressed the issues encountered previously. We increased the potential profit and lowered the gas price, so the transaction would not be written into a block too quickly, allowing the bot time to find it. The balance of the contract increased to 0.04 ETH (an increase of 0.005 ETH from before).
This time, we were attacked. The transaction lingered for about 3 minutes before being written into a block, ultimately failing to extract value from the trap smart contract. We examined the internal transactions of the contract and found that the funds were intercepted by someone else.
This front-running transaction cost 25.000001111 Gwei (higher than the Gwei we used by .000001111 Gwei) and was written into the same block as our transaction, clearly indicating an interception.
Implanting a Tracker
Since our trap has successfully captured a bot (at a certain cost), we can extract some interesting insights.
First, the transaction showed that it did not directly execute a call to the smart contract. The bot did not blindly copy the transaction and send it from its own account, but instead passed the transaction through a proxy smart contract, which acted as the smart wallet executing these transactions.
We can now track previous and future transactions to closely examine just how powerful this bot is and how it operates.
This bot uses its own proxy contract
Reverse engineering this contract reveals two main functions:
The "Withdraw" function primarily sends all funds in the contract to the bot's operator. The other function accepts several parameters: the contract to call, a list of parameters, and a value parameter.
With this function, the proxy contract acts as the smart wallet for the bot operator. In addition to executing calls to external functions, it also ensures that the balance at the start of the transaction is at least equal to the balance at the end, or else it can revert the transaction, thus avoiding potential loss of funds when calling unknown contracts (excluding gas, of course).
Using Dune Analytics, we can see that this bot has been operating since May 2018 and has profited significantly.
Assuming this bot has consistently used the same smart proxy and receiving address to initiate front-running transactions, we can estimate that it has earned approximately 17 ETH.
Funds earned by the bot over different time periods (in ETH)
Round Three: How Smart Are These Bots?
Now that we are convinced this bot program actively attacked us, we wanted to test whether we could confuse our contract call through a second contract (proxy contract) to successfully extract the decoy funds, with the proxy calling a function to extract the decoy funds from the decoy contract (giver). (This contract also has a "withdraw" function to return funds to us).
We deployed the ProxyTaker contract, called the appropriate function, and attempted to extract the funds. Since the cost of the action through the proxy was slightly higher than before, the giver contract's balance was raised to 0.055 ETH. The result was that our transaction was immediately front-run by another bot.
This time, the bot's technique was even more astonishing. The bot not only detected our withdrawal transaction but also identified the transaction from an entirely different smart contract's internal call! And all of this was accomplished in record time; our withdrawal transaction was written into a new block just seconds later, as was the predator's front-running transaction.
The identity of this bot is also interesting. The smart contract of this bot is primarily operated by this account. This account commented on a post on Etherescan discussing the white hat's efforts to rescue funds from a vulnerable Bancor smart contract.
Information from the operator's account (source: etherscan)
Given the similar behavioral traits of this bot (using account A to call the proxy and transferring funds to account B), along with the proximity of the aforementioned transaction, there is reason to suspect that this bot also engaged in generalized front-running during the white hat's fund rescue operation here.
This bot is much smarter than the one we encountered earlier. It not only targets ETH transactions but also engages in various arbitrage trades.
Judging solely by its account balance, its earnings are significantly higher. Currently, this account has a balance of about 300 ETH (worth $180,000). We can also calculate all inflows and outflows from the contract address to estimate its earnings, totaling approximately 900 ETH.
This is just a rough estimate, as the account may have conducted transactions unrelated to its front-running activities. Here is a list of all profitable trades made by this bot.
To make the challenge more exciting, we conducted a more obfuscated attempt, this time using only the proxy contract OwnedTaker that we could use.
This trap is very similar to the third round. The giver contract balance is 0.05 ETH. The same transaction also includes a transaction to return the funds to us, rather than leaving them in the contract.
In the first attempt, the transaction that paid the funds to the OwnedTaker contract took about 1 minute to be written into a block, and we ultimately recovered the funds.
We then repeated this experiment, this time raising the giver contract balance to 0.06 ETH, the highest balance we have used so far, ensuring that the value would not be too low to deter the front-running bots.
The gas value was also deliberately set to a lower value. The transaction lingered for about 7 minutes, but we still successfully extracted the funds.
By incorporating the Owned proxy contract, which can only forward transactions by the contract owner, both of the known front-running bots were unable to successfully parse the data and intercept in the two transactions.
Successful withdrawal
Perhaps the requirement that only the contract owner can execute calls, or the fact that funds were sent to a different target address than the calling contract, helped avoid the bots' front-running attempts.
The bots are likely programmed to prioritize self-preservation. After all, they are calling unknown contracts that could execute arbitrary code. It is reasonable to assume that if they cannot guarantee profits, they will avoid unnecessary risks or losses in transaction fees.
It depends on how you view it. We used a new contract, but only we knew this secret contract. It is clear that both front-running bots we discovered are conducting all transactions in the transaction pool, and judging by their profits, they are doing quite well.
Why did we avoid the misfortune of being front-run in our final attempt?
The specific reason is hard to determine. It could be that the bots are unwilling to risk communicating with authenticated contracts, or the fact that funds were transferred to another address was unexpected.
This certainly does not mean that this is a completely viable method to avoid being front-run. Most likely, there are more complex bots lurking in the Ethereum transaction pool that simply do not want to risk obtaining such small profits.
In this brief experiment, we were able to demonstrate the existence of generalized front-running bots and their high level of intelligence.
Of course, we are well aware that our experiment is neither complete nor definitive. There are many other bots with trigger mechanisms and operational methods that differ significantly, and factors such as potential profitability, communication characteristics, and minimum complexity (e.g., through gasLimit) may affect their operation.
However, we are confident that our work provides a proof of concept for further understanding the methods employed by these generalized front-running bots.
The shocking reality is that if there are any trades that anyone can call on smart contracts to profit from, even if they are very obscure, it is highly likely that some front-running bot will swoop in and seize the funds.
Therefore, understanding these bots and how they operate is crucial for building safer systems now and in the future. Projects like Flashbots are attempting to achieve this by democratizing MEV extraction and making it a public resource. We hope this research contributes to that goal.