1/ 📖 Just read @Uniswap v3 whitepaper 🦄 and wanted to share some thoughts.
👀 There are some pretty neat tricks in the paper that we @AlphaFinanceLab also use. 👀
Thread below 👇
2/ Overall, 🦄 V3 is a huge upgrade from and much more complex than V2. V3 introduces:
👩💻 User Flexibility: Users can supply within a specified price range.
💻 Protocol Flexibility: Configurable swap fee & governance fee
💡 Features: Built-in TWAP & liquidity oracle
3/ The most interesting feature is that users can supply liquidity to any desired price range, which then enables the __Concentrated Liquidity__ feature, as advertised.
🤔 This is a challenge in terms of technical implementation, since gas limits may explode if done naively.
4/ So, what’s needed to be cracked?
1️⃣ Swapping mechanism
2️⃣ Fee distribution to users (can no longer done by LP token share)
5/ 1️⃣ Swapping mechanism. The challenge is how to account for swapping with different liquidity depth since users can now arbitrarily supply in any desired price range.
Answer: Exponential Ticks.
6/ Ticks limit the possible price range’s endpoints while giving users sufficiently many choices. Exponential ticks allow higher tick spacing when tick value is higher, which perfectly fits with how prices often scale multiplicatively, e.g. prices go up 1.5x or down 1.2x.
7/ Between each pair of consecutive ticks, normal x * y = k calculation can be performed since i is guaranteed that either the whole tick interval liquidity changes or no change.
So, this allows simple swap computation within a single tick interval.
8/ We @AlphaFinanceLab has also explored the exponential “strike” idea already in #AlphaX. The higher the strike value, the higher the spread. Again, this idea allows sufficiently many choices to users while we optimize for gas.
9/ One further optimization to exponential ticks is to only keep track of only “initialized” ticks by skipping the uninitialized ones. __TickBitMap__ is used here, where 1 is initialized and 0 is uninitialized. This allows efficient data storage and next initialized bit look-up.
10/ On this bitmap very idea, #AlphaHomoraV2 also leverages bitmaps to keep track of a user’s non-zero debts. This is how simple the code can look with bitmaps:
11/ Another possible solution was to use a doubly linked list. DLLs can then be efficiently traversed only on initialized ticks/debts. However, it may require much more data storage, reads, and writes to maintain the linked list.
12/ 2️⃣ User fee distribution!
Since each user can provide liquidity over different ranges, fee accrual may be different for each user’s position. The same LP token as share approach no longer works here.
So, how to keep track of fees?
13/ One key observation is that each user’s position is a contiguous range from lower tick L to upper tick U. So, the question becomes, how much fee accrues between ticks [L, U).
Answer: Prefix sum & suffix sum.
14/ Just subtract the prefix and suffix sum from global fees. To maintain prefix & suffix sum for each tick, it’s again easier to keep track of the non-active side (where no swaps occur). This is why __feeGrowthOutside__ is stored in Tick-Indexed State.
15/ Keeping track of the fee’s non-active side is one neat trick. The “outside” side is switched whenever the tick is crossed when large swapping occurred.
However, this also means that each swap needs to update the state of every tick it passes.
16/ It seems possible that large swaps can pass an unbounded number of ticks, which would make the gas limit unbounded. A malicious attacker can pay gas fees to initialize new ticks, so swaps would cost extra gas.
17/ This seems to align with what @trailofbits found and suggested. I’d be interested to see how these parameters turn out to be, and how the pools will play out.
Would also be interested in how concentrated liquidity will be maintained for volatile asset pairs.
18/ Lastly, just want to congrats @haydenzadams and @Uniswap team, and may the force be with you on the launch 💪
• • •
Missing some Tweet in this thread? You can try to
force a refresh
2/ Flash loan lets anyone borrow a very large amount of assets (as long as the amount + fee are paid back in the same transaction), which can be used to temporarily skew asset prices or balances.
3/ A typical flash loan attack pattern is a form of sandwich attack: (1) Skew price/balance (2) Main protocol uses the skewed price/balance (e.g. to open a position, deposit into AMM all at bad prices) (3) Un-skew price/balance