in Lines #115 to #117 we initialize the pool with the preferred Price
but the problem here arises that non Empty UniSwap Pools are still open for people to use and swap "meaning that its user controlled" POC will be provided
whenever a malicious user manipulate the price of the uniswap pool all ILOPool launched will be useless due to the following
as we see in line #189 we retrieve the Price from slot0 then strictly check the equivalence with project configuration at Line #192 which will lead to all Pools not being initialized
foundry POC that shows that empty Pools are actually manipulatable
contract UniswapV3PoolSwapTest is Test {
UniswapV3Pool public pool;
TestERC20 public tokenA;
TestERC20 public tokenB;
uint24 public constant FEE_AMOUNT = 3000; // 0.3%
int24 public constant TICK_SPACING = 60;
int24 public constant INITIAL_TICK = 0;
function setUp() public {
tokenA = new TestERC20("Token A", "TKNA", 18);
tokenB = new TestERC20("Token B", "TKNB", 18);
pool = new UniswapV3Pool(
address(tokenA),
address(tokenB),
FEE_AMOUNT,
TICK_SPACING
);
// Initialize the pool with a specific sqrtPriceX96
int24 initialTick = INITIAL_TICK;
uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(initialTick);
pool.initialize(sqrtPriceX96);
}
function testSwapWithoutLiquidity() public {
uint256 amountIn = 10 * 1e18; // 10 Token A
// Get the initial slot0 values
(uint160 initialSqrtPriceX96, int24 initialTick, , , , , ) = pool.slot0();
// Swap Token A for Token B
vm.startPrank(address(this));
tokenA.mint(address(this), amountIn);
tokenA.approve(address(pool), amountIn);
pool.swap(address(this), false, amountIn, 0, TickMath.MAX_SQRT_RATIO);
vm.stopPrank();
// Get the updated slot0 values
(uint160 newSqrtPriceX96, int24 newTick, , , , , ) = pool.slot0();
// Check if the swap affected the price (sqrtPriceX96)
assertnEq(newSqrtPriceX96, initialSqrtPriceX96);
assertnEq(newTick, initialTick);
}
}
Lines of code
https://github.com/code-423n4/2024-06-vultisig/blob/cb72b1e9053c02a58d874ff376359a83dc3f0742/src/ILOManager.sol#L187-L198
Vulnerability details
Impact
a malicious user can grief Pool creation permanently corrupting the project launch
Proof of Concept
the problem starts in the following function
which as we see in Line #61 calls
_initUniV3PoolIfNecessary
passinginitialPoolPriceX96
as parameter herein Lines #115 to #117 we
initialize
the pool with the preferred Price but the problem here arises that non Empty UniSwap Pools are still open for people to use and swap "meaning that its user controlled"POC will be provided
whenever a malicious user manipulate the price of theuniswap pool
allILOPool
launched will be useless due to the followingas we see in line #189 we retrieve the Price from
slot0
then strictly check the equivalence with project configuration at Line #192 which will lead to all Pools not being initializedfoundry POC that shows that empty Pools are actually manipulatable
Tools Used
manual review and foundry
Recommended Mitigation Steps
consider using TWAP oracle
Assessed type
Uniswap