Uniswap was launched by Hayden Adams in November 2018 as a fully decentralized protocol for exchanging ERC20 tokens. Anyone could trade tokens already added or add new ones, and no one owned it: there was no controller address, nor any upgradability mechanism. In this sense, Hayden wanted it to be an “example of an application that truly embodied Ethereum”, and it became that.
So, how does Uniswap works?
Note: I’m going to focus in Uniswap v1 for this article. That being said, many things are still valid for v2.
Constant Product Market Makers
Say we have two tokens, for example ETH and DAI, and we want people to be able to trade them. The classic approach is the order book: someone creates an order saying “I want to sell 1 ETH for 300 DAI” and somebody else can fill that order (that is, send the DAI and receive the ETH). But doing this in a decentralized way is challenging.
Instead, Uniswap implements what it’s called a Constant Product Market Maker, which sounds fancy but it’s actually pretty simple. The core idea goes like this: you create a smart contract that holds a pair of tokens (ETH and DAI in our example), and anyone can send some amount of one token to receive some amount of the other. The number of tokens you receive is computed so that the product between the amounts remains constant, hence the name. This smart contract is called a pool.
What about other tokens? Well, you can just create a different pool for each pair of tokens. Uniswap (v1) only lets you create pairs of some ERC20 and ETH actually, but this is more of an implementation detail and it’s not really relevant for this explanation.
Let’s see an example to make all of this clearer.
Suppose our pool has 1000 DAI and 3 ETH, and someone wants to use 10 DAI to buy some ETH. The product between the amounts is 3 * 1000 = 3000, and that’s what you want to keep constant. Since 10 DAI are being added to the pool, some amount of ETH needs to be removed to keep the product at 3000 (and to pay the person sending the DAI!). In this case the amount is around 0.03. Now the pool has 1010 DAI and 2.97 ETH and the product remains at 3000. From the user’s perspective, they bought 0.03 ETH at 10 DAI (alternatively, you can interpret it as they selling 10 DAI for 0.03 ETH).
There’s a lot to unpack here. First, why would you do that trade? Well, at the moment of writing this, ETH is trading at almost 400 USD, so buying 0.03 ETH for 10 DAI is a good purchase. In fact, it would make sense to buy even more. What happens if we had used 100 DAI instead? In that case we would’ve received 0.272 ETH. Notice something?
When we used 10 DAI we received 0.03 ETH, but when we used 100 DAI we received “just” 0.272. So, in a way, the price of ETH increased. In the first scenario the effective price of 1 ETH was 333 DAI, but in the second one it was 367. Note, though, that if ETH is trading at 400 USD, then a price of 367 is still worth it. (Also note that if you want to buy all the 3 ETH, the price becomes infinite.)
So, this being a fully permissionless protocol, a pool like this will incentivize users to buy ETH —up to a point. In our example, with ETH trading at 400, users can sell up to 200 DAI before the price moves over 400 and stops making sense. In practice, this means that people will trade in this pool and eventually the balance of ETH/DAI will reflect the market price of the tokens.
Edit: While you can use up to 200 DAI without losing money, the rational thing to do is to maximize your profit. And, it turns out, the amount of DAI that maximizes your profit is the amount of DAI that makes the pool reflect the market price! In this scenario, the number is approximately 95.44 DAI. This takes the holdings of the pool to 2.7386 ETH and 1095.44 DAI, which has a ratio of 400.
Uniswap is an implementation of this basic idea. But we still have some pieces missing. We understand why people would trade on a pool like this, but why someone would create it? After all, they are giving up on the opportunity cost of whatever tokens they are using.
Fees
When someone adds tokens to a Uniswap pool (that is, they provide liquidity), they receive in return some amount of “pool tokens” (also called liquidity tokens) that represents how much of the pool belongs to them. At any point in the future they can burn these liquidity tokens and take back their share of the pool.
Let’s return to our example of a pool with 3 ETH and 1000 DAI. If I want to add liquidity to this pool, I have to send some amount of ETH and DAI in the same proportion that the pool has. For example, I can send 1 ETH and 333 DAI (keeping the product constant). In return, I receive an amount X of liquidity tokens, where X represents 25% of the total supply of liquidity tokens. This means that I don’t lose anything by adding liquidity (well, not really, see next section), but I don’t get anything in return either.
To incentivize users to add liquidity to a pool, Uniswap has a fee structure. It works like this: when a user makes a trade, some amount of the token they are sending is subtracted. The calculation of how many tokens they will receive in exchange is then done with this reduced amount. They receive those tokens in return and then the subtracted fees are added to the pool. This means that the total value of the pool increased, and so the liquidity tokens are worth more. (If this sounds confusing, check this section of the v1 paper that shows a step-by-step example.)
But adding this fee also means that the product is no longer the same constant! This is by design: the “constant product” is only constant when the fee is zero. If there is some fee, the product increases with each trade, benefiting the liquidity providers.
To add or not to add liquidity
It may be worth noting that you can lose money by being a liquidity provider. Take this extreme case as an example:
Suppose ETH is trading at 400 USD. You create a pool with 10 ETH and 4000 DAI. Now imagine the price of ETH suddenly crashes to 100 USD. Immediately, someone sells 10 ETH to our pool. With a fee of 0.3% (the value for Uniswap in both versions), the person selling that ETH would receive 1997 DAI, and the pool would end up with 20 ETH and 2003 DAI.
So, the pool was worth 8000 USD when we created it and now it’s worth 4003 USD. If we hadn’t created the pool, our 10 ETH + 4000 DAI after the crash would be worth 5000 USD instead. So we lost almost one thousand dollars in the process.
Again, this is in an extreme example, but it illustrates the point: if you are a liquidity provider, and the relative prices of the tokens in the pool change, you are losing money. But if the prices moves back to where they started, then you gained all the accumulated fees for the trades that happened during those movements.
Further reading
I highly recommend this short history of Uniswap by Hayden Adams himself.
If you want to know more about how liquidity providers’s returns work, this article and its second part provide a more in depth analysis.
Questiosn? Suggestions? Things I got totally wrong? Reply to this and let me know!