## Price can be manipulated prior to initialization, causing a DoS In `initialize`, we allow for the pool to have already been created and initialized: ```solidity pool = factory.getPool(token0, token1, fee); require(getState[pool].isInitialized == false, PoolAlreadyInitialized()); ... uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(isToken0 ? tickLower : tickUpper); // @audit if initialize reverts, we proceed try IUniswapV3Pool(pool).initialize(sqrtPriceX96) { } catch { } ``` This gives an attacker the ability to have arbitrarily set the starting price of the pool prior to initialization, e.g. by frontrunning. When we mint our positions, the `uniswapV3MintCallback` indicates the amount of tokens we need to transfer in to the pool. We assume that whichever non-zero `amountXOwed` param (prioritizing `amount0Owed` in case both are non-zero), corresponds to the `asset` token and is the correct amount to transfer in to mint the position: ```solidity function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external { CallbackData memory callbackData = abi.decode(data, (CallbackData)); address pool = factory.getPool(callbackData.asset, callbackData.numeraire, callbackData.fee); require(msg.sender == pool, OnlyPool()); // @audit we only ever transfer in the asset token ERC20(callbackData.asset).transferFrom(airlock, pool, amount0Owed == 0 ? amount1Owed : amount0Owed); } ``` An attacker can DoS here by manipulating the price such that the `numeraire` has to be transferred in to correctly mint the position, e.g. by setting the price above the starting price (denominated in the `asset` token). Since there's only logic to transfer in the `asset` token, this will lead to a revert. Safe mitigation for this kind of attack is quite difficult. One option is to do a zero value swap in case the current tick/price is incorrect, but an attacker can place single sided liquidity between the starting price and the actual pool price, preventing the swap from occurring.