This past summer, a proposal was kicked off in Uniswap governance to assess whether and how to turn on the protocol fee switch. Because Avantgarde is a Uniswap delegate, I followed the conversation and debate as it evolved. As I considered how we should vote, I realized that there was not much information available on what “turning on the fee switch” actually meant from a technical perspective. I didn’t feel comfortable evaluating the downstream effects of turning on the fee switch with incomplete information, so I went digging.
My research led me to write this Twitter thread, and now this blog post. Below, I provide a quick primer on Uniswap fees in general and then dive into the topic of protocol fees.
A Uniswap pool is a smart contract that enables the swapping of one token for another. It’s trivial to create a pool, and anyone can do it by specifying three variables: the two tokens they want to enable swapping for (let’s call them ABC and XYZ) and the fee, in basis points, that will be charged to do so (let’s say 30 bps).
There are two types of user for every pool, Liquidity Providers and Swappers. Liquidity Providers deposit both tokens from the pair into the pool contract, allowing Swappers to exchange tokens from one side of the pair for tokens of the other. The Swapper pays the fee in the token they’re selling for the privilege, and the pool contract is smart enough to divvy the fee up pro rata between all Liquidity Providers who helped to make the trade happen.
Fees accrue in both of a pool’s tokens, assuming that there are trades in both directions, and are held separately from the liquidity provided to the pool. A Liquidity Provider can claim the fees they’re owed whenever they’d like, and send them wherever they like.
Taking the hypothetical ABC/XYZ pool above, I’ll walk through a transaction step by step:
Beginning Balances: Swapper: 2000 XYZ. Liquidity Provider: 10,000 ABC, 20,000 XYZ
Spot ABCXYZ is 2. The Liquidity Provider deposits her 10,000 ABC and 20,000 XYZ to the pool in a single tick (for convenient math)
The Swapper sees the available liquidity and sells his 2000 XYZ to the pool. The pool reserves the fee in the amount of 6 XYZ (0.003 * 2000). The balance of the sell order (1994 ABC) gets executed at 2.00 spot, and the swapper receives 997 ABC (1994 / 2)
The Liquidity Provider removes liquidity and claims the fee. Fees can be claimed separately without removing liquidity, but in this case it is useful to withdraw the whole balance to examine the impact of the fee on the total value of the Liquidity Provider’s holdings.
Ending Balances: Swapper: 997 ABC. Liquidity Provider: 9,003 ABC and 21,994 XYZ from LP, 6 XYZ from fee
By default, Liquidity Providers currently capture all fees paid by Swappers in a pool. However, each pool has a function that, if called by Uniswap Governance (specifically,
setFeeProtocol, described here), slices off a fraction of every fee paid by a Swapper. This particular function is what has come to be known as the Fee Switch. The protocol fee is initialized to 0, but can be changed to any of the following values, each representing a percentage of the total fee: ¼, ⅕, ⅙, 1/7, ⅛, 1/9, or 1/10.
These slices are reserved for the protocol, and can only be claimed by Governance calling another function on the pool contract. This would require another distinct vote. In other words, it is a separate discussion and decision to determine how the fees will be used - they are not just streaming into some amorphous “Uniswap Treasury” contract.
Expanding on the example above, I’ll show the impact on Liquidity Provider economics if the lowest protocol fee setting (1/10) was enabled:
Beginning Balances: Swapper: 0 ABC, 2000 XYZ. Liquidity Provider: 10,000 ABC, 20,000 XYZ, Uniswap: 0 ABC, 0 XYZ.
Spot ABCXYZ is 2. The Liquidity Provider deposits her 10,000 ABC and 20,000 XYZ to the pool in a single tick
The Swapper sees the available liquidity and sells his 2000 XYZ to the pool. The pool reserves the fee in the amount of 6 XYZ (0.003 * 2000). 1/10 of the fee (0.60 XYZ) is allocated to the protocol and the balance to the Liquidity Provider. The balance of the sell order (1994 ABC) gets executed at 2.00 spot, and the swapper receives 997 ABC (1994 / 2)
Liquidity Provider removes liquidity and claims fee
Uniswap Governance votes to claim fee from ABC/XYZ 30bps pool
Ending Balances: Swapper: 997 ABC, 0 XYZ. Liquidity Provider: 9,003 ABC and 21,994 XYZ from LP, 5.40 XYZ from fee. Uniswap: 0 ABC, 0.60 XYZ
Many community members have offered up different approaches to turning on the fee switch: criteria for choosing various pools or a certain fee percentage. However it is key to note that “turning on the fee switch” alone does one thing and one thing only: changes the breakdown of fees per liquidity pool. It does not do anything else, like determine where the protocol fees will go after they are collected. That is for a separate analysis and discussion within the community. I hope this post has been helpful, and has clarified some of the mystery around the fee switch for the community.