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