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: 62/72
Findings: 1
Award: $11.32
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
univ3pool
.To check univ3pool
is uninitialized, use s_AddrToPoolIdData[univ3pool] == 0
instead of univ3pool == IUniswapV3Pool(address(0)
.
683: if (univ3pool == IUniswapV3Pool(address(0))) revert Errors.UniswapPoolNotInitialized();
addXXX
function familys may be used in a wrong way, reuslting unexpected tokenId
value.Check that the properties of tokenId
are zero before addding that properties to tokenId
.
173: function addUniv3pool(uint256 self, uint64 _poolId) internal pure returns (uint256) { 189: function addAsset 204: function addOptionRatio( 220: function addIsLong( 234: function addTokenType( 248: function addRiskPartner( 262: function addStrike( 276: function addWidth(
L173 | L189 | L204 | L220 | L234 | L248 | L262 | L276
TokenId.countLongs
should count legs first and then count the longs for active legscountLongs
should count the longs only for active legs and ignores the inactive legs.
363: return self.isLong(0) + self.isLong(1) + self.isLong(2) + self.isLong(3);
tickSpacing
when adding a tokenId.Strike price is not guaranteed to be multiples of tickSpacing
when adding a tokenI, resulting the tokenId cannot be used to create position (SemiFungiblePositionManager._createPositionInAMM
=> PanopticMath.getLiquidityChunk
=> TokenId.asTicks
=> revert). Validate the strike price early while adding a tokenId.
388: // The width is from lower to upper tick, the one-sided range is from strike to upper/lower 389: int24 oneSidedRange = (selfWidth * tickSpacing) / 2; 390: 391: (legLowerTick, legUpperTick) = (selfStrike - oneSidedRange, selfStrike + oneSidedRange); 392: 393: // Revert if the upper/lower ticks are not multiples of tickSpacing 394: // Revert if the tick range extends from the strike outside of the valid tick range 395: // These are invalid states, and would revert silently later in `univ3Pool.mint` 396: if ( 397: legLowerTick % tickSpacing != 0 || 398: legUpperTick % tickSpacing != 0 || 399: legLowerTick < minTick || 400: legUpperTick > maxTick 401: ) revert Errors.TicksNotInitializable();
The first word at L739 should be "If" instead of "It".
739: /// It that position is burnt, then we remove a mix of the two tokens and swap one of them so that the user receives only one.
tokenType
is also used to calculate positionKey
, which is missed in the comments for s_accountLiquidity
and s_accountFeesBase
.175: /// @dev mapping that stores the liquidity data of keccak256(abi.encodePacked(address poolAddress, address owner, int24 tickLower, int24 tickUpper)) // @audit comment miss tokenType 292: /// @dev mapping that stores a LeftRight packing of feesBase of keccak256(abi.encodePacked(address poolAddress, address owner, int24 tickLower, int24 tickUpper))
of the
) in comment.350: /// @param fee The fee level of the of the underlying Uniswap v3 pool, denominated in hundredths of bips
[N-01] Use <=
and >=
instead of ==
when checking strike price of option legs.
482: if ( 483: (self.strike(i) == Constants.MIN_V3POOL_TICK) || 484: (self.strike(i) == Constants.MAX_V3POOL_TICK) 485: ) revert Errors.InvalidTokenIdParameter(4);
#0 - c4-judge
2023-12-14T16:56:11Z
Picodes marked the issue as grade-b