Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maxMint() violates EIP-4626 #553

Open
c4-bot-2 opened this issue Apr 22, 2024 · 7 comments
Open

maxMint() violates EIP-4626 #553

c4-bot-2 opened this issue Apr 22, 2024 · 7 comments
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-501 grade-b Q-06 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_61_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")

Comments

@c4-bot-2
Copy link
Contributor

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);
}

Recommended Mitigation

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

@c4-bot-2 c4-bot-2 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Apr 22, 2024
c4-bot-2 added a commit that referenced this issue Apr 22, 2024
@c4-bot-11 c4-bot-11 added the 🤖_61_group AI based duplicate group recommendation label Apr 22, 2024
@c4-judge
Copy link
Contributor

Picodes marked the issue as primary issue

@dyedm1
Copy link

dyedm1 commented Apr 29, 2024

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).

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Apr 29, 2024
@c4-judge
Copy link
Contributor

Picodes marked the issue as satisfactory

@c4-judge
Copy link
Contributor

Picodes marked the issue as selected for report

@c4-judge c4-judge added the selected for report This submission will be included/highlighted in the audit report label Apr 29, 2024
@c4-judge
Copy link
Contributor

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

@c4-judge c4-judge added duplicate-501 and removed primary issue Highest quality submission among a set of duplicates selected for report This submission will be included/highlighted in the audit report labels Apr 29, 2024
@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels May 9, 2024
@c4-judge
Copy link
Contributor

c4-judge commented May 9, 2024

Picodes changed the severity to QA (Quality Assurance)

@c4-judge
Copy link
Contributor

Picodes marked the issue as grade-b

@C4-Staff C4-Staff reopened this May 13, 2024
@C4-Staff C4-Staff added the Q-06 label May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue duplicate-501 grade-b Q-06 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_61_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Projects
None yet
Development

No branches or pull requests

5 participants