Type: #dex #logicFlow
Project: Kyberswap
Date: 17/04/23
Blockchain: Multichain
Problem: Double-adding liquidity because of the incorrect tick handling.
For this hack it's important to understand how CLMM works, visit a link for a full hack description. In short:
* Users provide liquidity at a certain price range.
* The price range is discretely subdivided into ticks.
In Kyberswap the trick was to get the system in a state where currentTick was sitting on a valid tick range boundary and nearestCurrentTick == currentTick - 1. You then mint liquidity in the range (currentTick, currentTick + n) for some n. When a one-for-zero swap is executed in the current state, the nearestCurrentTick == currentTick - 1 (the next tick) will be calculated as currentTick, but it should be calculated as the next initialized tick.
This causes the liquidity just added to be added again:
- Before minting, crossing the tick boundary would have added l0 liquidity.
- Minting adds l1 liquidity, but it also adds liquidity to the tick range. This means crossing the tick boundary will now add l0 + l1 liquidity.
- We then cross the tick boundary with a small one-for-zero swap. In total, l1 + l0 + l1 liquidity has been added by minting and crossing (because two ticks are the same).
The Hacker:
1) Starts with a pool containing 1000 ETH and 2,000,000 USDC. Using a flash loan swaps 5000 ETH for USDC, getting the price down to $1 (tick 0). There are now 6000 ETH tokens in the pool and no USDC.
2) Calculates how much liquidity would need to be in the range (0,n) for some small n in order to completely drain the pool of 6000 ETH (in this tick range).
3) Mints half that liquidity and then performs the double-add exploit. Since the price of ETH is $1 this doesn’t require a whole lot of ETH and USDC.
4) Swaps 6000 USDC for 6000ETH.
5) Pays back the flash loan and keep approximately 1000 ETH as profit as well as the USDC received in step 1.
Discoverer: 100proof
Harm: 100 M $, 1.1 M payout
link
Project: Kyberswap
Date: 17/04/23
Blockchain: Multichain
Problem: Double-adding liquidity because of the incorrect tick handling.
For this hack it's important to understand how CLMM works, visit a link for a full hack description. In short:
* Users provide liquidity at a certain price range.
* The price range is discretely subdivided into ticks.
In Kyberswap the trick was to get the system in a state where currentTick was sitting on a valid tick range boundary and nearestCurrentTick == currentTick - 1. You then mint liquidity in the range (currentTick, currentTick + n) for some n. When a one-for-zero swap is executed in the current state, the nearestCurrentTick == currentTick - 1 (the next tick) will be calculated as currentTick, but it should be calculated as the next initialized tick.
This causes the liquidity just added to be added again:
- Before minting, crossing the tick boundary would have added l0 liquidity.
- Minting adds l1 liquidity, but it also adds liquidity to the tick range. This means crossing the tick boundary will now add l0 + l1 liquidity.
- We then cross the tick boundary with a small one-for-zero swap. In total, l1 + l0 + l1 liquidity has been added by minting and crossing (because two ticks are the same).
The Hacker:
1) Starts with a pool containing 1000 ETH and 2,000,000 USDC. Using a flash loan swaps 5000 ETH for USDC, getting the price down to $1 (tick 0). There are now 6000 ETH tokens in the pool and no USDC.
2) Calculates how much liquidity would need to be in the range (0,n) for some small n in order to completely drain the pool of 6000 ETH (in this tick range).
3) Mints half that liquidity and then performs the double-add exploit. Since the price of ETH is $1 this doesn’t require a whole lot of ETH and USDC.
4) Swaps 6000 USDC for 6000ETH.
5) Pays back the flash loan and keep approximately 1000 ETH as profit as well as the USDC received in step 1.
Discoverer: 100proof
Harm: 100 M $, 1.1 M payout
link