DERP Example 3: Uniswap MEV

Dr. Sebastian Bürgel
HOPR
Published in
7 min readMar 23, 2022

The HOPR DERP tool replicates a standard RPC provider but makes it transparent to the user exactly how many requests are made and how much potentially revealing and exploitable data and metadata is shared.

Our first showcase explained how MetaMask exposes the links between all your accounts, even before you input the password. The second showed how easy it is to perform a frontrunning attack in NFT marketplaces and other services, simply by copying the data payload shared during a function call to estimate gas prices.

Our third DERP showcase explores how using Uniswap and other DEXs exposes you to potential exploits, including a particular type of MEV (maximal extractable value) attack.

DEXs like Uniswap are complicated, and a lot of work has been done to streamline the UI to make swapping easy to understand and use. But as with all of our DERP examples, this streamlining can obscure exactly how much information is being passed to and from various RPC endpoints.

When you make a swap, the UI needs to know how to populate the various fields. While it seems simple, a LOT of work goes into this behind the scenes. The app needs to know the relative prices of the tokens you want to swap, and the amount of slippage that you are willing to accept. Because the slippage is dependent on the ratio between the size of your trade and the total liquidity available, this figure needs to be recalculated with every keystroke. All this information needs to be fetched from the chain in near real time, and then updated with every new block.

When it’s time to make a transaction, your wallet needs to estimate the gas you’ll need to spend for it to complete. To do this, the full details of your planned transaction are sent to the RPC provider.

That means every time you use Uniswap, you’re blasting identifying information into the world, including your wallet addresses, balances, and — crucially — your IP address.

Let’s look at a typical eth_estimateGas call here, when planning to swap ETH for HOPR tokens.

[

{

“value”: “0x2386f26fc10000”,

“from”: “0x2402da10a6172ed018aeea22ca60ede1f766655c”,

“to”: “0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45”,

“data”: “0x5ae401dc000000000000000000000000000000000000000000000000000000006239d5f00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000124b858183f000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000002402da10a6172ed018aeea22ca60ede1f766655c000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000082350d2bca3206beb0000000000000000000000000000000000000000000000000000000000000042c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb86b175474e89094c44da98b954eedeac495271d0f000bb8f5581dfefd8fb0e4aec526be659cfab1f8c781da00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000”

}

]

To understand this, we need to break it up into chunks (generally 64 characters long).

0x5ae401dc
000000000000000000000000000000000000000000000000000000006239d5f0
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000124
B858183f
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000002402da10a6172ed018aeea22ca60ede1f766655c
000000000000000000000000000000000000000000000000002386f26fc10000
0000000000000000000000000000000000000000000000082350d2bca3206beb
0000000000000000000000000000000000000000000000000000000000000042
C02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
000bb8
6b175474e89094c44dA98b954eedeac495271d0f
000bb8
F5581dfefd8fb0e4aec526be659cfab1f8c781da
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000

And stripout the leading zeroes and the lines ending in just a few numbers (these are just used for padding and alignment).

0x5ae401dc
6239d5f0
B858183f
2402da10a6172ed018aeea22ca60ede1f766655c
2386f26fc10000
82350d2bca3206beb
C02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
000bb8
6b175474e89094c44dA98b954eedeac495271d0f
000bb8
F5581dfefd8fb0e4aec526be659cfab1f8c781da

Looking up 0x5ae401dc in the 4byte directory isn’t very informative. It’s just a multicall function, used to call multiple functions of the smart contract simultaneously. For some reason Uniswap uses this even if only one function is being called.

6239d5f0 is 1647957488 in decimal. This is the Unix timestamp for Tue Mar 22 2022 13:58:08 GMT+0000, and represents the time when this transaction would expire if uncompleted.

b858183f is the actual function being called, called exactInput(tuple params).

2402da10a6172ed018aeea22ca60ede1f766655c is the sending address

2386f26fc10000 converted from hexadecimal is 10000000000000000, or the 0.01 ETH of the swap.

82350d2bca3206beb is 150118718086773238763. This is a bit of a mystery, because the actual HOPR amount estimated is over 187. If anyone can enlighten us about this discrepancy, we’d love to hear from you!

The next lines are the instructions for the route between the pairs, since there’s no direct ETH / HOPR pairing on Uniswap

c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 is the WETH contract

6b175474e89094c44da98b954eedeac495271d0f is the DAI contract

F5581dfefd8fb0e4aec526be659cfab1f8c781da is the HOPR token contract

The repeated bb8 is 3000 in decimal, or the 0.3% fee levied by Uniswap.

So as you can see, estimating the gas required for this transaction is achieved by sending the full details of the planned swap.

Psychic MEV

Why does this matter?

This information is all essential to making Uniswap work, and not necessarily sinister, but there are some very unpleasant consequences of how Uniswap chooses to handle it. These come in two flavours:

  • Exploits based on the transaction you’re planning to make
  • Exploits based on your IP address

Because these calls contain all the information about your upcoming transaction before you even submit it, anyone with access to the information has the opportunity to perform advanced versions of common MEV attacks.

The first type of exploit is simple front-running: if I see that a large transaction is imminent that will move the price, I can get ahead of it and take advantage of the slippage.

This is unlikely to happen without collaboration with a miner, because the risk of the attack backfiring would be too high. You have to ensure your injected transaction comes before the target transaction, which at this point is still hypothetical.

But what if we were to collaborate? This could provide a whole extra avenue of exploitable information and transform the MEV landscape.

That’s because the now cutthroat world of MEV is all about speed. Here’s an excerpt from Return to the Dark Forest:

The fastest frontrunner always wins.

Due to Ethereum’s open market for fees, mining pools give transaction finality to the highest bidder. Frontrunners observe a transaction in the mempool, and send the same transaction with a higher fee, driving up the price of a trade.

However, even high gas fees aren’t a reliable way to have your transaction processed quickly. Transactions share a common bottleneck: the speed at which they are propagated.

At its basis, frontrunning is a race: a quick draw, played out on the quicksand of Ethereum’s peer-to-peer network. Frontrunners will pay a premium to play first.

Currently this battle is being brute forced: higher spending means more miner collaboration. D.E.R.P. highlights a new way to get an advantage in this high-stakes, high-speed war: seeing the future.

Not every RPC call leads to a transaction, but many will. And if you have an insight into what transactions are potentially going to hit the mempool, you can pre-calculate your MEV attacks. Then instead of having to work them out on the fly, all you have to do is verify your harvested data really did make the leap from idle UI clicking to a real signed transaction and you’re ready to exploit it, milliseconds after it appears.

As MEV competition increases and loopholes are closed, MEV searchers are going to take every avenue they can get to extract value. Sure, bribing an RPC provider like Uniswap might seem like a very different proposition than bribing a mining pool, but surely crypto is all about NOT having to make these kinds of trust assumptions? There are also other ways to access this RPC information beyond collaboration.

IP Linkability

It might seem hard to get worked up about MEV exploits from a slightly different angle. After all, every RPC call that was destined to become a real transaction would end up in the mempool anyway, ripe for the same kind of MEV attack.

But because each RPC call is also linked to an IP address, we can imagine a world where calls are assessed for their likelihood of leading to a transaction, based on previous transactions linked to the same IP. Now we have MEV, but targeted to particular individuals. Suddenly things are a lot more sinister.

Imagine building up a database of candidate IP addresses linked to profitable MEV attacks. Whenever an RPC call comes from a tagged IP, the entire MEV mechanism can spring to life, calculating the best way to exploit it. Of course not every call will result in a transaction, but for those that do, the attacker will be ready to exploit it the instant it hits the mempool.

Closing MEV loopholes is a long and maybe unwinnable struggle. It may not even be one we want to win: as we learn more about MEV, it’s clear there are certain types of arbitrage which are actually healthy for the DeFi ecosystem.

But it’s also clear that as we do remove the lowest hanging fruit, MEV searchers aren’t just going to pack up and go home. They’ll find increasingly ingenious ways to exploit the dark forest of the mempool, and would have no scruples about using IP metadata harvested from badly implemented RPC calls. We predict that the MEV battle will soon expand well beyond the mempool, and only a robust privacy-focused approach will be able to tackle it.

And this is on top of all the other dangerous risks of publicly exposed IP addresses: linking addresses together even if they’ve never interacted on chain, linking transactions to real world identity, and censoring transactions based on location. Transport-level security such as envisioned by HOPR is one way to make sure this rich vein of information is unminable.

This is the last of our D.E.R.P. showcases in the current series. Since we launched the tool, it’s been amazing to see how many people and projects have started to take this issue seriously. We’ll be working closely with some of them over the next months and years to ensure that privacy gets its rightful place at the forefront of web3 design.

Sebastian Bürgel,

HOPR Founder

--

--