Platform: Code4rena
Start Date: 01/04/2024
Pot Size: $120,000 USDC
Total HM: 11
Participants: 55
Period: 21 days
Judge: Picodes
Total Solo HM: 6
Id: 354
League: ETH
Rank: 39/55
Findings: 1
Award: $32.96
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: DadeKuma
Also found by: 0xStalin, 0xhacksmithh, 99Crits, Aymen0909, Bauchibred, CodeWasp, Dup1337, IllIllI, John_Femi, K42, KupiaSec, Naresh, Rhaydden, Rolezn, Sathish9098, Topmark, ZanyBonzy, albahaca, bareli, blockchainbuttonmasher, cheatc0d3, codeslide, crc32, d3e4, favelanky, grearlake, hihen, jasonxiale, jesjupyter, lanrebayode77, lirezArAzAvi, lsaudit, mining_mario, oualidpro, pfapostol, radin100, rbserver, sammy, satoshispeedrunner, slvDev, twcctop, zabihullahazadzoi
32.9585 USDC - $32.96
CollateralTracker.totalAssets
doesn't follow the documentsfunction CollateralTracker.totalAssets
is defined in CollateralTracker.sol#L370-L374
370 function totalAssets() public view returns (uint256 totalManagedAssets) { 371 unchecked { 372 return s_poolAssets + s_inAMM; 373 } 374 }
But quoting from API documents:
the amount of funds moved from the PanopticPool to Uniswap (_inAMM()), and the amount of fees that have been collected but are currently locked (_lockedFees()).
CollateralTracker.maxMint's
implementation isn't correctWhile containing COMMISSION_FEE
, in CollateralTracker.maxMint, the function is implementation as:
function maxMint(address) external view returns (uint256 maxShares) { unchecked { return (convertToShares(type(uint104).max) * DECIMALS) / (DECIMALS + COMMISSION_FEE); } }
which means:
maxShares = Math.mulDiv(assets, totalSupply, totalAssets()) * DECIMALS / (DECIMALS + COMMISSION_FEE);
But all others functions calculates shares as
shares = Math.mulDiv(assets * (DECIMALS - COMMISSION_FEE), totalSupply,totalAssets() * DECIMALS);
SemiFungiblePositionManager.swapInAMM
uses constant as slippage protectionIn SemiFungiblePositionManager.sol#L837-L845, Constants.MIN_V3POOL_SQRT_RATIO
and Constants.MAX_V3POOL_SQRT_RATIO
is used as slippage protection, which might cause sandwich attack
PanopticFactory.minePoolAddress
might return wrong results.In PanopticFactory.minePoolAddress,while calculates maxSalt
, unchecked is used to wrap maxSalt = uint256(salt) + loops;
The issue is that if uint256(salt) + loops > type(uint).max
, the function will not revert because of unchecked, instead, it'll overwrite the slot.
In such case, the function will not fall into the for loop
#0 - c4-judge
2024-04-26T17:16:40Z
Picodes marked the issue as grade-b
#1 - crazy4linux
2024-05-07T14:52:51Z
Hi, @Picodes
I think [L-02]CollateralTracker.maxMint's implementation isn't correct
is dup of https://github.com/code-423n4/2024-04-panoptic-findings/issues/501
#2 - Picodes
2024-05-09T23:13:42Z
Indeed - but #501 was downgraded to QA in the meantime