Platform: Code4rena
Start Date: 27/11/2023
Pot Size: $60,500 USDC
Total HM: 7
Participants: 72
Period: 7 days
Judge: Picodes
Total Solo HM: 2
Id: 309
League: ETH
Rank: 27/72
Findings: 2
Award: $219.65
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: hash
Also found by: 0xCiphky, Neon2835, Topmark, Udsen, critical-or-high, lanrebayode77, ptsanev
208.3324 USDC - $208.33
The _createLegInAMM()
function is used to create AMM positions using the legs of a specific tokenId.
The function uses an unchecked block to save on gas by manually checking for over/underflows, but there's a scenario where the removedLiquidity
could underflow.
The block of code we are looking at is:
if (_isBurn) { removedLiquidity -= chunkLiquidity; }
Upon burning a position with a isLong=0, this means we are closing a long position, so we should remove short liquidity. Of course, we can only burn liquidity if we have provided it first, which happens when we mint a isLong=1 position where removedLiquidity += chunkLiquidity
. The problem is in the value of chunkLiquidity. As stated by the LiquidityChunk library: "A liquidity chunk is an amount of liquidity
(an amount of WETH, e.g.) deployed between two ticks: tickLower
and tickUpper
into a concentrated liquidity AMM".
The value of chunkLiquidity between calls can easily fluctuate, since it tracks total liquidity between ticks for a specific leg of a tokenId, but since any user can use any tokenId, some users are bound to use the same tokenId and move the liquidityChunk's liquidity inbetween calls.
A simple scenario on the top of my head is a user1 mints, his removedLiquidty = x. Then another user2 mints and his removedLiquidity = y, but the liquidity in the chunk would have increased, meaning if user1 tries to burn his long position removedLiquidity
would underflow, breaking user accounting.
Manual Review
Remove the unchecked field or manually check if the chunkLiquidity does not exceed the removedLiquidity, just like it is done in if (startingLiquidity < chunkLiquidity) revert Errors.NotEnoughLiquidity();
Under/Overflow
#0 - c4-judge
2023-12-14T14:39:25Z
Picodes marked the issue as duplicate of #332
#1 - c4-judge
2023-12-26T21:53:43Z
Picodes changed the severity to 2 (Med Risk)
#2 - c4-judge
2023-12-26T21:59:29Z
Picodes marked the issue as satisfactory
#3 - c4-judge
2023-12-26T22:00:51Z
Picodes marked the issue as partial-50
#4 - Picodes
2023-12-26T22:01:44Z
No medium-severity impact (and in particular no loss of funds scenario although this report was initially submitted as high) is described in this report so I'll give only partial-50
🌟 Selected for report: osmanozdemir1
Also found by: 0xCiphky, Audinarey, Banditx0x, CRYP70, Cryptor, D1r3Wolf, KupiaSec, LokiThe5th, Sathish9098, Skylice, ThenPuli, Topmark, Udsen, ZanyBonzy, baice, ether_sky, fatherOfBlocks, foxb868, grearlake, hihen, hubble, hunter_w3b, lanrebayode77, leegh, lsaudit, minhtrng, nocoder, onchain-guardians, ptsanev, ro1sharkm, seaton0x1, sivanesh_808, t4sk, tapir, tpiliposian, ustas
11.3163 USDC - $11.32
[L-01] - usage of slot0
to get spot data of Univ3 pool is prone to manipulation:
(, newTick, , , , , ) = univ3pool.slot0(); if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow)) revert Errors.PriceBoundFail();
Use observe()
instead
[L-02] - rebasing tokens would work against the users in events of negative rebases, as stated by the uniswap docs. This detail was probably missed, but due to not being mentioned in the README - Low
[L-03] - the ERC1155Minimal does not implement a balanceOf()
, only a balanceOfBatch()
function, possibly tampering with potential external integrations that would use it's balanceOf()
. Incompliance to ERC1155
[L-04] - tokens with blacklists would not allow users to burn their already opened positions, consider creating a mechanism for removing such users' liquidity, compensating the protocol with their fees.
[L-05] - Slippage tolerance values should be inclusive. Consider rewriting
if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow))
to
-> if ((newTick > tickLimitHigh) || (newTick < tickLimitLow))
in order to allow the edge-cases to be accepted.
#0 - c4-judge
2023-12-14T17:04:33Z
Picodes marked the issue as grade-b