Use Case
In Automated Market Makers (AMMs), particularly those using concentrated liquidity models like Uniswap V3, the price is represented by ticks. A tick is a discrete unit of measurement for the price of an asset, and maintaining proper tick boundaries is critical for protocol security.
This assertion is particularly important for:
- Preventing price manipulation through tick boundary violations
- Ensuring trades execute at valid price points
- Maintaining protocol invariants around price representation
- Detecting potential exploits that could manipulate tick boundaries
For example, if an attacker could push the price outside the valid tick range, they could potentially:
- Execute trades at invalid prices
- Manipulate liquidity positions
- Cause protocol calculations to fail
Applicable Protocols
- AMMs using concentrated liquidity models (e.g., Uniswap V3, PancakeSwap V3)
- Protocols that rely on tick-based price calculations
- DeFi protocols that interact with tick-based AMMs
- Cross-chain bridges that use tick-based price feeds
Explanation
The assertion implements a focused approach to verify tick integrity:
-
Tick Range Validation:
- Verifies that ticks stay within global bounds (-887272 to 887272)
- Prevents tick manipulation outside valid ranges
- Ensures the AMM’s mathematical model remains valid
-
Tick Spacing Alignment:
- Ensures ticks align with the pool’s tick spacing
- Maintains proper concentrated liquidity calculations
- Prevents position management errors
The assertion uses the following cheatcodes and functions:
ph.forkPreState()
: Captures the initial tick state
ph.forkPostState()
: Captures the final tick state
registerStorageChangeTrigger()
: Monitors changes to tick-related storage slots
This focused approach ensures:
- Ticks remain within protocol-defined bounds
- Tick spacing rules are enforced
- Core AMM functionality remains secure
For more information about cheatcodes, see the Cheatcodes Documentation.
Code Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {Assertion} from "credible-std/Assertion.sol";
import {PhEvm} from "credible-std/PhEvm.sol";
// Uniswap v3 pool style interface
interface IUniswapV3Pool {
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
function tickSpacing() external view returns (int24);
}
contract PriceWithinTicksAssertion is Assertion {
IUniswapV3Pool public pool;
// Uniswap V3 tick bounds
int24 constant MIN_TICK = -887272;
int24 constant MAX_TICK = 887272;
constructor(IUniswapV3Pool pool_) {
pool = pool_;
}
function triggers() external view override {
// Register trigger for changes to the tick storage slot
// Assumes tick is stored in slot0 of the pool contract
registerStorageChangeTrigger(this.priceWithinTicks.selector, bytes32(uint256(0)));
}
// Check that the price is within the tick bounds and that the tick is divisible by the tick spacing
function priceWithinTicks() external {
// Get pre-swap state
ph.forkPreState();
(, int24 preTick,,,,,) = pool.slot0();
// Get post-swap state
ph.forkPostState();
(, int24 postTick,,,,,) = pool.slot0();
int24 spacing = pool.tickSpacing();
// Check 1: Tick must be within global bounds
require(postTick >= MIN_TICK && postTick <= MAX_TICK, "Tick outside global bounds");
// Check 2: Tick must be divisible by tickSpacing
require(postTick % spacing == 0, "Tick not aligned with spacing");
}
}
Note: This code example is maintained in the Phylax Assertion Examples Repository. For a full examples with mock protocol code and tests please refer to the repository.
Testing
To test this assertion:
- Deploy a mock Uniswap V3 pool contract
- Create test scenarios that:
- Execute trades within valid tick ranges
- Attempt trades that would push ticks outside bounds
- Test tick spacing alignment
Assertion Best Practices
- Combine this assertion with other AMM-related assertions like Fee Calculations
- Consider protocol-specific parameters for:
- Tick spacing requirements
- Global tick bounds (if different from Uniswap V3)
Responses are generated using AI and may contain mistakes.