Panoptic - Joshuajee's results

Permissionless, perpetual options trading on any token, any strike, any size.

General Information

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

Panoptic

Findings Distribution

Researcher Performance

Rank: 12/55

Findings: 1

Award: $2,812.96

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: petro_1912

Also found by: Joshuajee

Labels

bug
2 (Med Risk)
satisfactory
duplicate-469

Awards

2812.9554 USDC - $2,812.96

External Links

Lines of code

https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/CollateralTracker.sol#L121 https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/CollateralTracker.sol#L249 https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/CollateralTracker.sol#L262 https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/CollateralTracker.sol#L1110

Vulnerability details

Vulnerability Details

Currently uniswap has 4 fee tier

  • 1.00% - 10000
  • 0.3% - 3000
  • 0.05% - 500
  • 0.01% - 100

The 0.01% fee tier is currently the lowest fee tier on uniswap, it was added through a governance vote in Nov 2021. In summary Uniswap fees can go below 100 and when this happens the CollateralTracker.sol:s_ITMSpreadFee will become zero for that pool.

    function startToken(
        bool underlyingIsToken0,
        address token0,
        address token1,
        uint24 fee,
        PanopticPool panopticPool
    ) external {
        ...
        uint24 _poolFee;
        //@audit pool fee can be accidentally set to zero
        unchecked {
@->         _poolFee = fee / 100;
        }
        s_poolFee = _poolFee;

        // Stores the addresses of the underlying tracked tokens.
        s_univ3token0 = token0;
        s_univ3token1 = token1;

        // store whether the current collateral token is token0 (true) or token1 (false; since there's always exactly two tokens it could be)
        s_underlyingIsToken0 = underlyingIsToken0;

        // Additional risk premium charged on intrinsic value of ITM positions
        unchecked {
@->          s_ITMSpreadFee = uint128((ITM_SPREAD_MULTIPLIER * _poolFee) / DECIMALS);
        }
    }

_poolFee will evaluate to zero if fee is less than 100, since s_ITMSpreadFee is calculated based on _poolFee it will evaluate to zero too.

s_ITMSpreadFee = uint128((ITM_SPREAD_MULTIPLIER * _poolFee) / DECIMALS);

Impact

Swap commission will not be paid for affected pools

Proof of Concept

Deploying a pool with fee tier less than 100 i.e 0.01%.

When the PanopticFactory.sol:deployNewPool is called with a fee of let say 50, it calls the collateralTracker0.startToken(true, token0, token1, fee, newPoolContract) with the fee amount. This is where the division happens and the CollateralTracker.sol:s_ITMSpreadFee get stored as zero

Tool Used

Manual Analysis

Recommendation

Donot divide the fee by 100, use the direct value instead.

Assessed type

Error

#0 - c4-judge

2024-04-26T18:24:32Z

Picodes marked the issue as duplicate of #469

#1 - c4-judge

2024-04-29T21:44:18Z

Picodes marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter