Ethereum extends the concept of the blockchain transaction to more easily encompass a wide variety of operations. The formal specification for the Ethereum protocol outlines a series of built-in low-level opcodes. These opcodes amass to a turing complete programming language, enabling users to push arbitry computation onto the blockchain. Ethereum miners, just like Bitcoin miners, exhaust computational resources to process these transactions. The difference is that on Ethereum, transactions can take the form of any valid operations sent to the miners. That means single transactions on Ethereum often differ in terms of how much memory in a given block is required. In the case of bitcoin, transactions function in such a way that each occupies a relatively consistent space in memory. On Ethereum, the amount of space occupied by a given transaction is dynamic with an upper bound at the current block’s gas limit (transaction ordering is inconsistent between clients, making it somewhat difficult to sustainably flood blocks from one account, but I get into that later). The first ethereum miner to find the solution to the proof of work puzzle is rewarded with the block reward (currently 3.5 eth) and any fees paid for the transactions in that block.

Referring to appendix G of the Ethereum yellow paper, we can start to figure out how much a miner might make in fees. Appendix G contains a list of valid operations in Ethereum. For a given operation miners expend a certain amount of computational resources. The term gas is used to approximate how computationally “costly” operations are relative to one another. The cost of an operation in gas remains fixed because its difficulty is not expected to deviate. The gas limit represents a block’s operational capacity, similar to the Bitcoin blocksize. The gas limit imposes a dynamic restriction on the amount of computation a sender can request in one transaction, so programs with infinite loops are not processed. Additionally, it lets the miners know how much of their computation they should dedicate to transaction processing in order to optimize their returns.

Left to right: Type of operation, gas cost, description. Source: http://gavwood.com/paper.pdf

The gas value only loosely coincides with the real monetary value of fees. The value of an operation in terms of gas is constant, but the value of gas in terms of ether (the token) is dynamic. Consider the following example:

Suppose the transaction pool is currently populated with two transactions. The first transaction has account A sending 1 ether to account B. The second transaction has account C sending 1 ether to account D. These transactions are identical in terms of the amount of computation necessary to process them. Suppose further, that the current gas limit restricts the next block such that there is only room for one of these transactions. How then, should a miner differentiate between them? They could, for example, just process whichever one they received first. However, if we assume all miners are profit maximizers, (in practice, they behave as such for the most part) then they will ignore time altogether and select whichever one offers the highest fee. To determine their return, the miner looks to the unique parameter called gas price. Gas price is a value denominated in fractional quantities of ether that corresponds to a single unit of gas. Ether can be converted into GWei, where 1 ether == 10⁹ GWei or 1000000000 GWei == 1 ether.

Back to our example… Let’s say account A decides to set a gas price of 20 GWei whereas account C chooses a price of 25GWei. For the sake of simplicity, let’s assume that the transaction requires a total of 10 gas. If a miner decides to process account A’s transaction their return will be 200 Gwei. If that same miner chose to process account C’s transaction, they would have received 250GWei. Since we can be relatively safe in assuming miners are profit maximizers, they’ll always choose to process the transaction sent by account C. In reality, miner’s reserve the right to process transactions in whatever order they see fit. The assumption that miner’s will order transactions based solely on gas price holds true in reality for the most part but is not always true. I’ll get into this more in part II.

The ability for miners to discriminate and arbitrarily order transactions gives rise to some interesting properties. Currently, a new block is added to the Ethereum blockchain every 12 seconds or so. Swende’s frontrunning exploit takes advantage of the long block time and discriminatory transaction ordering by rational miners.

Transaction Ordering and Frontrunning

Let’s say we’re looking at the ETH-BNT Bancor exchange. While looking intently at the transaction pool, (that’s what I usually do in my free time) I notice a market order for 10000 ETH worth of BNT at a gas price of 20 GWei. Since this order will probably put upward pressure on the price of BNT in terms of ETH, I decide that it might be in my best interest to try and frontrun it. In order to ensure that I can get an order of my own processed before the original 10,000 ETH one, I enter my own market order for $10,000 worth of Ford shares at a gas price of 40 GWei. If my transaction propagates the transaction pool before the large order is successfully mined into a block, there’s a really good chance that my order will get processed first. We know from before that the Bancor protocol will programmatically adjust the exchange rate based on order fulfillment, so assuming my order was successfully processed prior to the large one, I just made some hefty profit in a matter of seconds.

A Quick Intro to Decentralized Exchange

As you can see, this technique is quite trivial. Most cryptocurrency exchanges implement some mechanism to combat frontrunning. Centralized exchanges (Poloniex, Shapeshift, Bitfinex, etc.) control order matching on their own servers and do not rely on on-chain transactions for users to execute trades. Decentralized exchanges (Etherdelta, 0x, KyberNetwork, etc.) are forced to either employ some novel strategies to combat frontrunning or risk exposure Bancor-esque frontrunning. For example, Etherdelta and 0x, two decentralized exchanges solutions chose to centralize the order matching component of trades by moving it off chain. So trades are processed serially in the order that they’re received, but Etherdelta and 0x aren’t completely decentralized. Orders are matched off chain then enforced on an on-chain escrow contract. This method has two advantages. Orders can be adjusted or canceled seamlessly through the centralized orderbook without paying for fees associated with on-chain work, and exchange rates adjust dynamically off-chain, making 0x and Etherdelta frontrunning resilient to the methods of frontrunning we’re concerned with. At the same time, 0x and Etherdelta intentionally introduce a single point of failure into their protocol design. What that means is, when a system or network as a whole relies on the existence and good behavior of a single actor. If that single actor fails or is corrupted the entire network suffers. By moving the orderbook off-chain, traders are forced to trust whoever it is that’s running the service. Although this actors incentives are less misaligned relative to completely centralized exchanges, you can still make the case that this solution is suboptimal.

KyberNetwork, an alternative decentralized exchange solution, offers a unique protocol architecture that might maintain decentralization in a more pure sense. Every aspect of the Kyber exchange is handled on chain and thus gains a significant edge in terms of security and transparency from the trader’s perspective. The protocol employs a system of reserves. Reserves can be an individual, a group, a smart contract — basically, anyone that holds some fungible crypto-asset that’s exchangeable on the Ethereum blockchain. Reserves deposit their tokens into the Kyber smart contract, select the tokens they accept for exchange, and set exchange rates. Users can then request trades through the smart contract, get matched with a reserve, and settle their transaction on chain.

A quick example might help understand how it works: Suppose I’ve got 10,000 ether. I can deposit that 10,000 ether into a Kyber smart contract to register myself as a reserve. Let’s say I only want to accept MKR in exchange for my ether soI set my exchange rate to 1,000 MKR for 1 ether. Now users can get my ether for MKR just as long as there’s some left in the reserve. As the reserve operator, I can update the exchange rate in MKR for ether as the price of ether fluctuates. To do so, I just update the exchange rate parameter on the Kyber smart contract. I can even charge a premium relative to the market exchange rate for my on-chain services. I make a profit, users can securely exchange their digital assets, everyone’s happy, right?

Before I go on, I’d like to put forth a short disclaimer. I’m not writing this article glorify/denounce decentralized exchanges. As far as I’m concerned, it’s still an open problem. In the next section I’m going to elaborate on a unique style of frontrunning that uses everything we just learned. It’s important to note that this vulnerability is not specific to decentralized exchange protocols or any apps I discuss. It’s an inherent flaw that exists in the current PoW style of Ethereum that will become less and less relevant as scalability improves. The following is just a few examples of what’s possible.

Denial-of-Service Frontrunning

DoS frontrunning involves an entity, be it an individual, a group, or a smart contract, taking advantage of the block gas limit restriction. If we draw from analysis done in Vitalik’s recent gasprice market analysis, the decile variables contain some important informational cues for our frontrunner.