Constant Product
Assert that a constant product is maintained in an AMM pool
Use Case
Check if the constant product (k = x * y) is maintained in an AMM pool. This is a critical security parameter for Automated Market Maker (AMM) protocols as it ensures:
- Prevention of unauthorized manipulation of pool reserves
- Detection of potential flash loan attacks that could drain the pool
- Verification that trades maintain the expected mathematical relationship between assets
- Protection against arithmetic overflow/underflow vulnerabilities in reserve calculations
The constant product formula (k = x * y) is fundamental to many AMM designs, particularly those following the Uniswap V2 model. Any deviation from this invariant could indicate a serious security issue or potential exploit.
Applicable Protocols
- Uniswap V2-style AMMs that use the x * y = k formula
- DEX aggregators that interact with constant product pools
- Lending protocols that use AMM pools as price oracles
- Yield farming protocols that provide liquidity to AMM pools
These protocols rely heavily on the constant product invariant for:
- Price discovery and trading
- Liquidity provision calculations
- Fee calculations
- Oracle price feeds
Explanation
The assertion monitors the product of reserves (k) in an AMM pool to ensure it remains constant after transactions:
- Pre-state verification: Captures the initial state of pool reserves
- Post-state verification: Checks the final state after transactions
- Constant product validation: Ensures k = reserve0 * reserve1 remains unchanged
The assertion uses the following cheatcodes:
forkPreState()
: Creates a fork of the state before the transaction to capture initial reservesforkPostState()
: Creates a fork of the state after the transaction to verify final reservesgetStateChanges()
: Monitors reserve changes throughout the transaction callstack to detect potential manipulations
The implementation performs two checks:
- A direct comparison between pre-state and post-state constant product values
- Verification that the final product equals the initial product
This approach ensures that:
- The constant product invariant is maintained throughout the transaction
- No unauthorized manipulation of reserves occurs
- The mathematical relationship between assets is preserved
Note that as mentioned in the code comments, an ideal solution would allow for checking the invariant at any point during the transaction’s execution, not just at the beginning and end.
For more information about cheatcodes, see the Cheatcodes Documentation.
Code Example
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 an AMM pool with the constant product formula
- Set up the assertion contract with the pool address
- Test various scenarios:
- Normal trades that maintain the constant product
- Edge cases with very small/large numbers
- Attempted manipulations that should be caught
- Flash loan attacks that try to drain the pool
Assertion Best Practices
- Consider combining this assertion with Fee Calculations for comprehensive AMM security
- Use precise arithmetic checks to prevent rounding errors from triggering false positives
- Monitor both reserve slots to catch any unauthorized modifications
- Add detailed error messages to help with debugging when assertions fail