AL #036: The Dangers of Concentrated Liquidity
The cautionary tale of KyberSwap and what it means for Uniswap V4.
When I was still in school I was a comfortable skiier but hadn't really tackled powder.
I recognized the black track marking ⚫️ but went ahead as it seemed fun.
The first ride down was tiring but fantastic so I went back for more.
My dad preferred to fork off on a simpler route so we agreed to meet at the bottom.
After a few minutes of skiing in the powder my ski ended up getting caught, I rolled a few times and lost sight of one of my skis completely.
All I could see below me was dense forest.
And then I noticed it.
My ski was sliding down and disappeared out of sight.
Luckily this story had a good ending.
After jumping a few meters down, I managed to find my ski caught next to a bush.
My dad must have worried quite a bit while waiting for me at the bottom.
The lesson is – expect to fall on your face if you ride the black track…
KyberSwap, a concentrated liquidity AMM recently got exploited for $54.7 million.
As the dust is settling on the attack, one wonders what it means for developers working on concentrated liquidity AMMs.
Working on one is as close to a “black track warning” as you get in crypto.
But let's recap what happened first...
KyberSwap uses a custom reinvestment curve
The first well-known and well-tested implementation of concentrated liquidity was Uniswap V3.
One of the drawbacks of liquidity concentration is that the fees were non-compounding.
Since any user could hold an entirely unique tick liquidity position, there wasn’t a simple way to keep reinvesting the fees.
Therefore LPs had to call a separate collect function on a regular basis to collect fees and keep reallocating them into desired ticks.
This only made ALM (active liquidity management) more attractive as protocols like Arrakis promised to handle the fee compounding.
(For a high level overview of how Uniswap evolved from V1 to V3, check out my previous post on this).
KyberSwap had a different idea.
What if all fee liquidity could automatically be allocated at the full range from 0 to infinity?
They call it the reinvestment curve.
This means that the fees could be translated back into liquidity, continuing to earn more LP fees (although as a lower than concentrated rate).
You can think of this as a Uniswap V3 style liquidity position slowly dripping its fee revenues into a Uniswap V2 style liquidity position.
The attack
Without diving too deep into the details (the best explanation is by SlowMist), the KyberSwap protocol enabled a scenario where a swap buying tokens and then selling them could result in lower slippage on the roundtrip back by incorporating more liquidity.
This happened due to a boundary check issue that arose from improperly accounting for the reinvestment curve.
The final attack was simple, after a flashloan, the attacker first moved the price into a range where the attack was possible (in particular out of any provided liquidity).
They then executed a forward swap combined with a swap back.
What makes tick liquidity is so complex
There are a number of reasons why concentrated liquidity AMMs with tick liquidity are so notoriously scary to build:
It’s essential to use square root prices and numerical analysis is always tricky
The number of states a given pool could be in is much larger for tick liquidity
Due to this state, attacks can have complex path-dependencies (like this attack)
Errors in one tick can have contagion (affect all other liquidity)
Any deviations from Uniswap V3 are very hard to reason about
Ultimately, any small error can be compounded into a substantial attack due to the MEV vulnerabilities and significant attack surface of AMMs, availability of flashloans and reversibility of swaps.
It’s hard to build any significant level of confidence without many overlapping audits.
And it's not even clear how easy it is for time-bounded auditing to identify issues like these:
Implications
So what can teams considering to build hooks on top of Uniswap V4 make of this?
I see three big lessons.
(If you're not familiar with V4, you may want to start with my post explaining it and then come back to this conclusion.)
It's more scary not to build on top of V4 if building a concentrated liquidity AMM. While the singleton already makes this true from a gas cost perspective, the reduction in auditing costs from using V4 cannot be understated.
It's scary to do anything that interacts with the tick logic. Any hook that aims to interplay with ticks will effectively inherit the audit surface of V4 on top of its own threats.
It’s even scarier to do hybrid designs that combine V4 ticks and add additional tick logic (for example negative liquidity or stop loss hooks). These surface in attempts to develop lending protocols on V4 and should be developed with great caution.
In short, don't go off piste if you can't handle it. ⚫️