Kunlun Yang
2023/02/21
As a veteran DeFi protocol, Uniswap v2 did a great deal to introduce the world to the idea of incentivized liquidity provisioning on decentralized exchanges. Liquidity in this context refers to a pair of tokens that are added to a pool so users can swap one of those tokens for the other.
While Uniswap v3 has overtaken much of v2’s market share, v2 remains active. It is still active on Uniswap and was forked to create SushiSwap and other decentralized exchanges (DEXes). Liquidity providers (LPs) still like v2 pools because of their simplicity. Some tokens only have v2-style pools.
LPs are rewarded for providing liquidity. Swaps generate fees that are shared pro rata amongst the LPs. Unfortunately, these fees are simply added to the LP’s position (which changes as tokens are swapped). This is called “impermanent loss.” The LP’s withdrawable amount changes with the price in the pool. which is only realized during withdrawal. Hence, the fees for V2 are not directly separatable. LPs may want to distinguish between the two in order to track their performance, or they may need to report them separately to a tax authority.
In this blog post, we propose a method for computing an LP’s fees.
v2 is a constant product market maker (CPMM). It uses the product L of the amount of two tokens as the invariant for exchange. L is also a measure of liquidity.
For a v2 pool with two tokens, a pool of reserve (X , Y) has a total liquidity of
(1) The pool’s price ratio is also related to the reserve (X , Y)
(2) When adding liquidity, the added token (x , y) is approximately, if not exactly, in proportion to the pool’s reserve (X , Y) at a specific block number. The approximation is due to the fact that a swap transaction that changes the reserve can take place in the same block as a transaction to add liquidity.
(3) The deposit tokens represents the below amount of liquidity L in the pool for the LP.
(4) The LP can withdraw tokens in the below amount based on the liquidity L added earlier, and the current ratio. The difference between the values, calculated using the current prices, in (x₁ , y₁) and (x , y) is the impermanent loss. We need to note that the liquidity for the LP is not tracked by the pool; instead, we obtain it by (4).
(5) The amount (x₁ , y₁) does not count when the fee is calculated. The amount the LP receives depends on the number of LP tokens redeemed.
Remember that when depositing tokens, the LP receives a number of new LP tokens proportional to the existing liquidity in the pool.
which is equivalent to...
(6) We combine (7) with (3) to take into account the possibility of the pool’s reserve changing in the block in which the liquidity is added. At this point we resolve the ambiguity (approximation) in (3) and select the minimum values for x and y. This gives us the number of LP tokens sent back to the LP.
(7) When redeeming tokens, the LP gets a fraction of the reserve which is determined by the ratio of LP tokens redeemed to the total number of LP tokens. This amount is inclusive of the transaction fees.
(8) If we then exclude the value that would have been withdrawn without a fee (see impermanent loss calculation (5), we are left with the fee itself.
Let’s consider the case below.
The table below shows the LP tokens being minted and sent to the user, and finally the user redeeming the LP tokens.
Each row represents a transaction for which we can calculate the following fields:
Using this method, we only need to fetch LP token balances to derive information about the tokens added to the pool. We can therefore avoid fetching more detailed transaction data about these underlying tokens. We want to do this for two reasons:
The result shows that we can restore the actual amount of funding tokens in close approximation.
The total fee for this LP is the sum of fees from all block ranges, USDC 0.428541381 and WETH 0.00034724257, for a total investment of $600 worth of USDC-WETH.
In this blog post, we described our method to calculate the current fee due a Uniswap v2 LP –including an LP who bought LP tokens from another party – at any point in time. We do this without requiring information about the original token deposits.
This output can be generated by running the model uniswap-v2.lp-fee-history by calling the script below:
credmark-dev run uniswap-v2.lp-fee-history -i '{"pool": "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc", "lp": "0x18196A32F99bD5feeAfd6bD6b55a63A0EeEf23a6"}' -j -b 16495331
The last row is added by the model in order to show the block number at which the model ran. It is not a transaction record.
Credmark runs a financial modeling platform powered by reliable on-chain data. We curate and manages DeFi data making it available via API and the Snowflake Marketplace around the globe and across industries.
Our community of quants, developers, and modelers actively build models for the DeFi community by leveraging our data API and tools. Join the growing community and together we will advance the next-generation financial system.
Sign up for our newsletter for the latest product updates, partnerships, and more.