Centralized Exchanges and Order Books
When most users are onboarding into the crypto ecosystem, they do so through a centralized exchange like Coinbase, Kraken, or Binance. These exchanges serve an important purpose. They increase the accessibility of cryptocurrencies by providing educational resources and simple interfaces, and you can link your bank account to deposit fiat directly. But they also have a critical limitation: you need to trust someone else to handle your money, negating one of the most important features of blockchains. Users don’t own the private keys to their accounts, so they can’t send or receive money without the exchange’s permission. CEXs (centralized exchanges) track user deposits and withdrawals and store them in their own database, and the user trusts them to do so securely and accurately. For many users this is an acceptable trade off. But there are alternatives that preserve the security and privacy of the blockchain.
CEXs use the order book model, which is standard in the traditional financial system. In this model, the exchange tracks all live orders to match buyers and sellers and to execute trades. Users can specify a range of buy and sell types: market, limit, stop loss, trailing stop, and more. The book has live price quotes derived from bid and ask orders. A “matching engine” matches buyers and sellers, but the trader’s counterparty is the exchange itself. These order books are highly efficient; there’s a reason they’re so popular in financial markets today.
Unfortunately, replicating order books on-chain via smart contracts is extremely difficult. Order books require market makers that maintain price quotes with near instantaneous updates. Due to the constraints imposed by gas prices and 15 second block times, the model doesn’t convert well to Ethereum Layer 1. The constraints vary by implementation, but users may have to pay gas prices to record their bids and asks without guarantees that they’d ever be filled; on top of that, 15 second block times don’t lend well to recording transactions and updating prices in real time. In fact, Loopring initially tried to implement an on-chain (Layer 1) order book, but quickly pivoted to a Layer 2 solution using zkRollups. Layer 1 & 2, rollups, and scaling solutions are a topic for another post. In short, developers will be able to build applications on Layer 2 that massively increase scalability and speed without sacrificing the security of the Ethereum backend. While L2 solutions are being built out, traders still need a decentralized way to exchange their tokens.
Decentralized Exchanges and Automated Market Makers
Enter Automated Market Makers. AMMs are an alternative model to the order book that integrates well with smart contracts and the DeFi ecosystem. When implemented on the blockchain, they are autonomous, permissionless, incentive driven protocols with which any individual can interact. The concepts have existed for years in academic research, but Uniswap pioneered the model on the blockchain.
Aside from Uniswap, other popular AMMs include SushiSwap, Curve, and Balancer. They each serve slightly different purposes. SushiSwap was a direct fork of Uniswap, but has been iterating quickly to implement new features and is a formidable competitor today. Curve is focused on stablecoins, where volatility between assets is low (and therefore so is impermanent loss, to be discussed below), enabling lower fees and slippage. Balancer is a generalized n-dimensional version of the pair based Uniswap, acting as an ETF creator.
You can check out all of these protocols’ metrics on Defi Pulse. While still small compared to their centralized counterparts, AMMs are growing at an alarming rate. Uniswap was deployed in late 2018, and today is averaging over $1 Billion in daily transaction volume with around $4 Billion total value locked in the protocol.
AMM Functionality
Note: When referring to AMMs in this post, I’m specifically talking about pair-based constant product market makers. The other types are important too, but they’re mostly just variations on this one, which is the most popular.
A few important terms:
A liquidity pool is some collection of tokens that are managed by a smart contract.
A token reserve is the amount of some token in a liquidity pool.
A token pair liquidity pool is a liquidity pool that consists of two tokens.
The ERC-20 Token Standard is just a set of rules on how tokens should operate on the Ethereum blockchain, making it easy to write code that functions for all ERC-20 tokens. Most important tokens built on Ethereum are ERC-20s.
The underlying mechanism of AMMs is a liquidity pool of token pairs from which users can swap their tokens. These pools are managed by smart contracts that live on the blockchain, so they don’t require any central entity to run. Each pool consists of a pair of tokens of equivalent value; the ratio between the reserves of the token is the active price quote (denominated by the other token), and the ratio changes as traders swap their tokens, reflecting price movements. In Uniswap and most other AMMs, the tokens listed on the exchanges are all ERC-20s, since their standardized functionality enables the deployment of modular code. If someone mints a new ERC-20 token, they can easily deploy a new liquidity pool on Uniswap with their new token and any other ERC-20.
There are two main functions that make AMMs work: supplying liquidity and swapping tokens.
To supply liquidity, users send some amount of two tokens to the smart contract that represents that token pair’s liquidity pool. It’s a requirement that the value of token 1 sent equals that of token 2 based on the current market rate; this ensures that the ratio between the token reserves in the pool is still representative of the market price. These funds are then managed by the smart contract and used to provide liquidity to traders who want to swap their tokens. The funds can be withdrawn at any time.
To swap tokens, traders send some amount of a token to the smart contract representing the pool of that token and the one they want to acquire. (If I want to swap ETH for DAI, I send ETH to the ETH-DAI pool). In response, the smart contract sends back an approximately equivalent value of the other token, drawn from the liquidity pool.
AMM Incentives
Why would users provide liquidity to the pools? When traders swap their tokens in a pool, they are charged a trading fee. On Uniswap, this fee is 0.3% of the trade value (although, in the future this will most likely be reduced to 0.25%). These fees are redistributed to the reserves and function as a reward for the LPs (liquidity providers). When LPs initially submit their tokens to the pool, they are allocated a share of ownership in the pool. It’s like equity in a company. So when they withdraw their ownership, they are entitled to the same share of the total pool, which grows in value because of trading fees. Because arbitrageurs can trade across different exchanges, trades are actually guaranteed to happen. If the price diverges between an AMM and other exchanges, these arbitrageurs will swap assets until prices are reflective of the market rate. So LPs are guaranteed to receive rewards.
A 0.3% fee is relatively high compared to the traditional financial system (not necessarily Crypto CEXs, but market makers like Virtu or Citadel). This is a trade off. Instead of being managed by large, sophisticated capital allocators that can execute trades with razor thin margins, DEXs are entirely incentive based. Replacing centralized control with incentive driven peer-to-peer protocols is a fundamental theme in the crypto ecosystem, and there will always be trade offs.
The Constant Product Formula
As described to this point, the market could be easily exploited. It’s important that the price can’t be manipulated and that a reasonable amount of liquidity remains in the pool. So, AMMs use the “constant product formula” to determine the cost of a trade.
Expressed simply, the formula is:
x * y = k
Let’s say we’re looking at the xToken-yToken liquidity pool. In the formula, x
represents the amount of xToken in the pool, likewise for yToken. We call these amounts the reserve of each token. At any given time, the market price for xToken denominated by yToken is y/x
. Any trade that happens in this pool must not change the value k. Said another way, the reserve of xToken times the reserve of yToken remains constant. This is the “invariant” of the constant product formula.
As you can see below, the constant product function forms a hyperbola when we plot potential values for X and Y (assuming k = 1e9 as an example). This displays the useful property that there is always liquidity, even as prices approach infinity on either side.
We can represent a generalized formula for a swap with the following equations:
(x + dx) * (y - dy) = k
so,
dy = y - k / (x + dx)
where dx
and dy
represent the change in reserve from the swap, assuming the trader is sending xToken to receive yToken. dy
is the amount of yToken received by the trader after sending dx
.
We ignored the trading fee here, but that can be included. We use the same formula to solve for dy
. Then the new balance of xToken, and the new value for k
are defined by:
t = 1 + fee
x_new = x + t * dx
k_new = (x + t * dx) * (y - dy)
In reality, because of the trading fee, k actually increases over time. As long as LPs don’t withdraw their funds, the hyperbola continues to grow outward.
Here’s a concrete example, using the ETH-DAI pool. Let’s assume that the price of 1 ETH is 1,000 DAI. LPs have sent large equivalent amounts of each token to the smart contract, so there is currently 1,000 ETH and 1,000,000 DAI in the pool. The current value of k is 1,000 ETH * 1,000,000 DAI => 1e9. When a trader swaps one token for the other, k must remain at 1e9. Let’s say Alice wants to swap 2 ETH and receive DAI. She’ll send her 2 ETH to the smart contract. In turn, the contract must calculate the fair amount of DAI to return to Alice (in reality, this value is estimated before the trade is executed so the trader knows what they’ll receive). We can plug in our numbers to the formula and solve for the new amount of DAI.
(1,000 ETH + 2 ETH) * (1,000,000 DAI - returnedDAI) = 1e9
Solving for “returnedDAI”, we get a value of ~1996, so Alice exchanged 2 ETH for 1,996 DAI.
She doesn’t automatically receive the 2,000 DAI that you may expect. This is because of liquidity constraints, and we refer to the difference in value as slippage. If there’s less liquidity in the pool, slippage increases. For example, if there were only 10 ETH and 10,000 DAI in the pool, a trader who swaps 2 ETH would only receive 1,666 DAI. On the other hand, as the amount of total reserves in the pool increases, the returned amount of DAI approaches the exact value of 2,000 DAI. Continuing with this example, if there are 10,000 ETH and 10,000,000 DAI, the trader is returned 1999.6 ETH for 2 DAI.
As a trade represents a larger percentage of the liquidity pool, the cost of slippage is higher and higher. This constraint is an inherent limitation (or feature) of the constant product model, but it serves as a safeguard against manipulation, and it prevents liquidity from being drained from the pool. Below, I’ve plotted the premium paid for a trade vs. the percent of the total share of the pool that the trader wants to receive. This varies based on some parameters, but the general trend is clear.
Bottom line: constant product market makers are great for small trades, but not as effective for large ones. But this isn’t unique to DEXs or AMMs, it’s a problem faced by order books as well. Fortunately, most trades made on these exchanges are very small relative to the total size of the pool.
Impermanent Loss (or, Divergence Loss)
Sending tokens to a liquidity pool and earning rewards sounds like a no brainer. However, LPs risk impermanent loss and should be aware of the potential consequences. Impermanent loss happens when prices of the two assets in the pool fluctuate from the initial prices at which an LP submitted their funds, and the LP’s representative share has less relative value than if they had simply held onto their assets.
Going back to the same example, there is 1,000 ETH and 1,000,000 DAI in the ETH-DAI pool. This time, Bob is an LP. He has submitted 10 ETH and 10,000 DAI, so he has a 1% share in the pool. Let’s say the price of ETH increases, such that 1 ETH = 4,000 DAI. The new reserves in the pool, preserving the invariant, are 500 ETH and 2,000,000 DAI. If Bob wants to withdraw his funds, he’s entitled to his 1%, or 5 ETH and 20,000 DAI. Let’s calculate how the total value of these assets has changed, and we’ll measure the total value in DAI because this is pegged to the US Dollar.
At t0 (the beginning), Bob had 10,000 DAI and 10 ETH valued at 1,000 DAI/ETH. His total value was 20,000 DAI.
When he withdraws his funds at t1, Bob now has 20,000 DAI and 5 ETH valued at 4,000 DAI/ETH. His total value is now 40,000 DAI.
If Bob had simply held his 10,000 DAI and 10 ETH, the total value at t1 would have been 10,000 DAI + 10 ETH * 4,000 DAI/ETH => 50,000 DAI.
So, he missed out on 20% of value by providing liquidity instead of holding the assets. We can model impermanent loss as a function of price fluctuation. In the plot below, the x axis is the percent change of the price ratio – if the ratio doesn’t change, this value is 100% and there is no loss. Note that the loss at 20% is equivalent to that at 500%, the only difference is which asset increased in price.
This doesn’t account for trading fees, which always increase the amount of reserves as liquidity is provided. Note then that an LP’s total amount in the pool, when measured by the two tokens themselves, is monotonically increasing – if I put in 1 ETH and 1,000 DAI, I will always receive a value of more than 2,000 DAI when I exit the pool. The risk is in the opportunity cost of having the assets in the pool instead of holding them. Additionally, if prices return to their initial values, the impermanent loss is removed, and LPs strictly profit from trading fees. But as an LP it’s important to be aware of this phenomenon. For more detailed analysis on the payoff curve for LPs, check out this post.
Summary
The underlying mechanics of Automated Market Makers like Uniswap are sometimes complex, and can result in high slippage costs for traders and impermanent loss for liquidity providers. But they’re highly valuable to the new decentralized economy. They’re secure, on-chain, permissionless, and autonomous entities that function without any centralized control. Any individual can interact with the smart contracts regardless of the value of their assets. They offer a passive way for token holders to generate a return on their assets, and they provide liquidity for traders who want to exchange their tokens, even in typically fragmented and illiquid markets.
Caveat emptor.
Thanks to Jeff Balkanski and Chris DeBiase for reading drafts of this post.