> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phylax.systems/llms.txt
> Use this file to discover all available pages before exploring further.

# Constant Product

> Assert that a constant product is maintained in an AMM pool

## When to Use This Pattern

Ensures the constant product (k = x \* y) is maintained in AMM pools, preventing unauthorized manipulation of pool reserves and potential flash loan attacks. Critical for Uniswap V2-style AMMs, DEX aggregators, lending protocols using AMM price oracles, and yield farming protocols providing liquidity.

The constant product formula is fundamental to many AMM designs - any deviation could indicate a serious security issue or potential exploit.

## What This Pattern Checks

Monitors the product of reserves (k) in AMM pools to ensure it remains constant after transactions using:

* `_preTx()` / `_postTx()` with Reshiram snapshot reads: Compare reserve product before and after transaction
* `ph.loadStateAt()`: Load reserve slots before and after the transaction
* Direct validation that k = reserve0 \* reserve1 remains unchanged

The assertion verifies both initial/final states and detects potential manipulations during transaction execution.

For more information about cheatcodes, see the [Cheatcodes Documentation](/credible/cheatcodes-reference).

## Assertion Pattern

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {Assertion} from "credible-std/Assertion.sol";
import {AssertionSpec} from "credible-std/SpecRecorder.sol";
import {PhEvm} from "credible-std/PhEvm.sol";

contract ConstantProductAssertion is Assertion {
    bytes32 internal constant RESERVE0_SLOT = bytes32(uint256(0));
    bytes32 internal constant RESERVE1_SLOT = bytes32(uint256(1));

    constructor() {
        registerAssertionSpec(AssertionSpec.Reshiram);
    }

    function triggers() external view override {
        registerTxEndTrigger(this.assertionConstantProduct.selector);
    }

    /// @notice Checks that the pool's stored reserve product is not reduced by the transaction.
    function assertionConstantProduct() external view {
        address pool = ph.getAssertionAdopter();
        PhEvm.ForkId memory preFork = _preTx();
        PhEvm.ForkId memory postFork = _postTx();

        uint256 reserve0Pre = uint256(ph.loadStateAt(pool, RESERVE0_SLOT, preFork));
        uint256 reserve1Pre = uint256(ph.loadStateAt(pool, RESERVE1_SLOT, preFork));
        uint256 reserve0Post = uint256(ph.loadStateAt(pool, RESERVE0_SLOT, postFork));
        uint256 reserve1Post = uint256(ph.loadStateAt(pool, RESERVE1_SLOT, postFork));

        require(reserve0Post * reserve1Post >= reserve0Pre * reserve1Pre, "Constant product invariant reduced");
    }
}
```

<Note>Full examples and mock protocol code are available in [credible-std](https://github.com/phylaxsystems/credible-std/tree/master/examples/assertions-book).</Note>

## Related Patterns

* [Fee Calculations](/assertions-book/assertions/ass14-fee-calculations)
* [ERC20 Cumulative Outflow Breaker](/assertions-book/assertions/ass20-erc20-drain)
* [Panic State Validation](/assertions-book/assertions/ass17-panic-state-validation)
* [ERC20 Cumulative Inflow Breaker](/assertions-book/assertions/ass22-erc20-inflow-breaker)
