Omniscia Steer Protocol Audit
LiquidityManagerHelper Manual Review Findings
LiquidityManagerHelper Manual Review Findings
LMH-01M: Inexistent Validation of Oracle Observation Cardinality
| Type | Severity | Location |
|---|---|---|
| Standard Conformity | ![]() | LiquidityManagerHelper.sol:L59 |
Description:
The LiquidityManagerHelper::uniV4Volatility function does not validate that the integrated Oracle hook has a proper cardinality configured.
Impact:
A proper cardinality configuration varies per asset and is usually attached to the volatility of the asset (i.e. volatile assets should have higher cardinalities to ensure longer sample periods).
In reality, a proper alleviation would involve an initialization of some sort in the system per pool that ensures it is set to a specific cardinality based on the underlying asset's presumed volatility level.
Example:
41/// @notice Checks if the current tick is within allowed volatility range from TWAP42/// @param poolKey The pool key containing hook address for TWAP data43/// @param currentTick The current tick from the pool44/// @param twapInterval The time interval for TWAP calculation45/// @param maxTickChange Maximum allowed tick deviation from TWAP46function uniV4Volatility(PoolKey calldata poolKey, int24 currentTick, uint32 twapInterval, int24 maxTickChange)47 external48 view49 override50{51 uint32[] memory secondsAgos = new uint32[](2);52 secondsAgos[0] = twapInterval; // Δt53 secondsAgos[1] = 0; // now54
55 // Get the Oracle Hook from poolKey.hooks56 IOracleHook oracleHook = IOracleHook(address(poolKey.hooks));57
58 // Call observe on the Oracle Hook to get tickCumulatives59 (int48[] memory tickCumulatives,) = oracleHook.observe(poolKey, secondsAgos);60
61 // Calculate TWAP tick from tick cumulatives62 int24 twapTick = int24((tickCumulatives[1] - tickCumulatives[0]) / int32(twapInterval));63
64 // Check that the current tick is within the allowed range from the TWAP tick65 require(66 currentTick <= twapTick + maxTickChange && currentTick >= twapTick - maxTickChange,67 "V" // "volatility" revert reason kept unchanged68 );69}Recommendation:
We advise the code to mandate a minimum cardinality target, preventing pools with few observations from being considered as supported by the system.
Alleviation (121dc0b1329a48555f90bb92e58a95e8ff8a7c79):
The Steer Protocol team evaluated this exhibit and opted to acknowledge it due to the nuisances involved in being able to properly validate the cardinality of each unique asset.
LMH-02M: Improper Utilization of Checked Arithmetic
| Type | Severity | Location |
|---|---|---|
| Logical Fault | ![]() | LiquidityManagerHelper.sol: • I-1: L220 • I-2: L221 |
Description:
The referenced calculations are meant to mimic the mechanisms of Uniswap V4 that calculate the fees due for a particular position.
The Steer Protocol team implementation will employ checked arithmetic when calculating the fee growth which is incorrect and can result in a severe Denial-of-Service for the vault due to underflows when the AMM pool is in its early stages.
Impact:
Certain pool configurations and trading activities can result in the fee growth being close to the maximum permitted and underflowing, resulting in an erroneous transaction revert in the current implementation.
Example:
219// delta = growth since last time the position was touched220vars.fees0 = FullMath.mulDiv(vars.feeGrowth0Inside - vars.feeGrowth0Last, vars.liquidity, FixedPoint128.Q128);221vars.fees1 = FullMath.mulDiv(vars.feeGrowth1Inside - vars.feeGrowth1Last, vars.liquidity, FixedPoint128.Q128);Recommendation:
We advise the relevant operations to be wrapped in an unchecked code block, ensuring that they are calculated in line with their original implementation.
Alleviation (121dc0b1329a48555f90bb92e58a95e8ff8a7c79):
An unchecked code block has been properly introduced for the referenced operations, alleviating this exhibit in full.
LMH-03M: Inexistent Rounding of TWAP
| Type | Severity | Location |
|---|---|---|
| Mathematical Operations | ![]() | LiquidityManagerHelper.sol:L62 |
Description:
The TWAP observation implemented through the V4 oracle hook is meant to mimic the Uniswap V3 approach and should thus round toward negative infinity as well.
Impact:
The current TWAP tick calculation mechanism will round toward zero which contradicts the expected behaviour of the system for negative values.
Example:
46function uniV4Volatility(PoolKey calldata poolKey, int24 currentTick, uint32 twapInterval, int24 maxTickChange)47 external48 view49 override50{51 uint32[] memory secondsAgos = new uint32[](2);52 secondsAgos[0] = twapInterval; // Δt53 secondsAgos[1] = 0; // now54
55 // Get the Oracle Hook from poolKey.hooks56 IOracleHook oracleHook = IOracleHook(address(poolKey.hooks));57
58 // Call observe on the Oracle Hook to get tickCumulatives59 (int48[] memory tickCumulatives,) = oracleHook.observe(poolKey, secondsAgos);60
61 // Calculate TWAP tick from tick cumulatives62 int24 twapTick = int24((tickCumulatives[1] - tickCumulatives[0]) / int32(twapInterval));63
64 // Check that the current tick is within the allowed range from the TWAP tick65 require(66 currentTick <= twapTick + maxTickChange && currentTick >= twapTick - maxTickChange,67 "V" // "volatility" revert reason kept unchanged68 );69}Recommendation:
We advise the same behaviour to be implemented hear as well, ensuring that the observed tick is correct for negative values.
Alleviation (121dc0b1329a48555f90bb92e58a95e8ff8a7c79):
The code was updated to properly round toward negative infinity, alleviating this exhibit.

