Panoptic - d3e4'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: 34/55

Findings: 1

Award: $32.96

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

32.9585 USDC - $32.96

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
satisfactory
sponsor confirmed
:robot:_61_group
duplicate-501
Q-06

External Links

Lines of code

https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/CollateralTracker.sol#L446

Vulnerability details

Impact

CollateralTracker.maxMint() is incorrect and violates EIP-4626.

Proof of Concept

In CollateralTracker.sol

function maxMint(address) external view returns (uint256 maxShares) {
    unchecked {
        return (convertToShares(type(uint104).max) * DECIMALS) / (DECIMALS + COMMISSION_FEE);
    }
}

whereas mint() is only limited by

assets = previewMint(shares);

if (assets > type(uint104).max) revert Errors.DepositTooLarge();

where previewMint() is

function previewMint(uint256 shares) public view returns (uint256 assets) {
    unchecked {
        assets = Math.mulDivRoundingUp(
            shares * DECIMALS,
            totalAssets(),
            totalSupply * (DECIMALS - COMMISSION_FEE)
        );
    }
}

This means that maxMint() should rather return type(uint104).max * totalSupply * (DECIMALS - COMMISSION_FEE) / (totalAssets() * DECIMALS).

There are several errors in the original maxMint(): the + in DECIMALS + COMMISSION_FEE, the inversion of DECIMALS / (DECIMALS - COMMISSION_FEE), and the use of convertToShares(). The latter causes a rounding error from a multiplication on a division.

CollateralTracker is an ERC4626 vault. Since DECIMALS / (DECIMALS + COMMISSION_FEE) > (DECIMALS - COMMISSION_FEE) / DECIMALS maxMint() returns too much. This can also be seen in the test case below which on the current code reverts due to DepositTooLarge(). This means that maxMint() violates "MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary)".

Paste the below test case into CollateralTracker.t.sol and run with forge test --match-test test_maxMint. This test should pass. It fails with the current code, but passes with the recommended fix below.

function test_maxMint() public {
    // initalize world state
    _initWorld(0);

    // Invoke all interactions with the Collateral Tracker from user Bob
    vm.startPrank(Bob);

    // give Bob the max amount of tokens
    _grantTokens(Bob);

    // approve collateral tracker to move tokens on the msg.senders behalf
    IERC20Partial(token0).approve(address(collateralToken0), type(uint256).max);

    // change the share price a little so we know it's checking the assets
    collateralToken0.deposit(836459287459287647, Bob);

    uint256 maxMint = collateralToken0.maxMint(Bob);

    uint256 id = vm.snapshot();
    collateralToken0.mint(maxMint, Bob);

    vm.revertTo(id);
    vm.expectRevert(Errors.DepositTooLarge.selector);
    collateralToken0.mint(maxMint + 1, Bob);
}
function maxMint(address) external view returns (uint256 maxShares) {
    unchecked {
-        return (convertToShares(type(uint104).max) * DECIMALS) / (DECIMALS + COMMISSION_FEE);
+        return type(uint104).max * totalSupply * (DECIMALS - COMMISSION_FEE) / (totalAssets() * DECIMALS);
    }
}

Assessed type

ERC4626

#0 - c4-judge

2024-04-25T20:45:51Z

Picodes marked the issue as primary issue

#1 - dyedm1

2024-04-29T14:10:23Z

This is correct but EIP-4626 is not listed in the compliance requirements, so unsure whether Medium or Low severity would be most appropriate (the impact of this is very limited given that it is only an issue in the maxMint function, which is not used anywhere in the protocol or periphery).

#2 - c4-judge

2024-04-29T21:38:10Z

Picodes marked the issue as satisfactory

#3 - c4-judge

2024-04-29T21:38:13Z

Picodes marked the issue as selected for report

#4 - c4-judge

2024-04-29T21:42:07Z

Picodes marked issue #501 as primary and marked this issue as a duplicate of 501

#5 - c4-judge

2024-05-09T19:15:20Z

Picodes changed the severity to QA (Quality Assurance)

#6 - c4-judge

2024-05-10T00:09:09Z

Picodes marked the issue as grade-b

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