The slot0 of a Uniswap V3 pool, which contains the current price (sqrtPriceX96Existing), can be easily manipulated.
This means that the sqrtPriceX96Existing fetched may frequently differ from the params.initialPoolPriceX96 provided by the caller of initProject().
Due to the manipulability of slot0, the function _initUniV3PoolIfNecessary() may revert almost every time if the existing pool's price has changed from the initial price provided.
This makes it difficult to initialize projects reliably.
Vulnerability Details
During project initialization via initProject(), the uniV3PoolAddress is fetched by calling _initUniV3PoolIfNecessary() with params.initialPoolPriceX96 supplied by the caller.
The function _initUniV3PoolIfNecessary() checks if the Uniswap V3 pool already exists. If it does, it verifies that the existing pool's initial price (sqrtPriceX96Existing) matches the supplied params.initialPoolPriceX96. If there is a mismatch, the function reverts with an error.
However, due to the manipulability of slot0, the function _initUniV3PoolIfNecessary() may revert almost every time if the existing pool's price has changed from the initial price provided.
Tools Used
Manual Review
Recommended mitigation steps
Remove the requirement that sqrtPriceX96Existing must match params.initialPoolPriceX96.
This will prevent the function from reverting due to minor price differences caused by market fluctuations.
Implement a tolerance range for price validation.
Allow a small percentage deviation between sqrtPriceX96Existing and params.initialPoolPriceX96. This accommodates minor price changes while still ensuring the pool is initialized at a reasonable price.
Lines of code
https://github.com/code-423n4/2024-06-vultisig/blob/cb72b1e9053c02a58d874ff376359a83dc3f0742/src/ILOManager.sol#L119
Vulnerability details
Impact
The
slot0
of a Uniswap V3 pool, which contains the current price (sqrtPriceX96Existing
), can be easily manipulated. This means that thesqrtPriceX96Existing
fetched may frequently differ from theparams.initialPoolPriceX96
provided by the caller ofinitProject()
.Due to the manipulability of
slot0
, the function_initUniV3PoolIfNecessary()
may revert almost every time if the existing pool's price has changed from the initial price provided. This makes it difficult to initialize projects reliably.Vulnerability Details
During project initialization via initProject(), the
uniV3PoolAddress
is fetched by calling_initUniV3PoolIfNecessary()
withparams.initialPoolPriceX96
supplied by the caller.The function _initUniV3PoolIfNecessary() checks if the Uniswap V3 pool already exists. If it does, it verifies that the existing pool's initial price (
sqrtPriceX96Existing
) matches the suppliedparams.initialPoolPriceX96
. If there is a mismatch, the function reverts with an error.However, due to the manipulability of
slot0
, the function_initUniV3PoolIfNecessary()
may revert almost every time if the existing pool's price has changed from the initial price provided.Tools Used
Manual Review
Recommended mitigation steps
sqrtPriceX96Existing
must matchparams.initialPoolPriceX96
.This will prevent the function from reverting due to minor price differences caused by market fluctuations.
Allow a small percentage deviation between
sqrtPriceX96Existing
andparams.initialPoolPriceX96
. This accommodates minor price changes while still ensuring the pool is initialized at a reasonable price.Assessed type
Uniswap