K-Invariant
The core invariant of Uniswap V2 and other constant-product AMMs: `reserve0 * reserve1 >= k` after every swap. Its enforcement is what prevents attackers from draining the pool by trading at off-curve prices.
The K-invariant is the central correctness property enforced by Uniswap V2 and every constant-product AMM descended from it. It says: after any swap, the product of the pool's two token reserves must be greater than or equal to what it was before the swap, adjusted for the protocol fee.
In formula form:
1reserve0_after * reserve1_after >= reserve0_before * reserve1_before
Expressed as code inside Uniswap V2's swap() function:
1uint balance0Adjusted = balance0 * 1000 - amount0In * 3;2uint balance1Adjusted = balance1 * 1000 - amount1In * 3;3require(4 balance0Adjusted * balance1Adjusted >=5 uint(_reserve0) * _reserve1 * (1000**2),6 'UniswapV2: K'7);
The * 3 and * 1000 coefficients are how Uniswap V2 bakes in the 0.3% fee. The left side deducts the fee from the input amount before squaring; the right side scales up by 1000^2 to keep units consistent. The actual geometric meaning: the pool's state must not fall off the constant-product curve, except in the protocol's favor (due to fees).
Why It Matters
If the K-invariant were not enforced, the pool could be drained trivially. Consider: a malicious caller could pass huge amount0Out and tiny amount1In, receive the tokens, and leave the pool with less value than it started with. The K check is the single line that prevents this.
This is why the K-invariant check is the most tested function in any Uniswap V2 implementation. The Zealynx Academy Uniswap V2 module has dedicated test cases for:
- Swap preserves K after normal trades
- K strictly grows over time due to fees
- Flash swaps must restore K by end of callback
- Rounding always favors the protocol, never the trader
- Fee-on-transfer tokens do not break K
If your implementation passes all of these, you understand the invariant. If not, the test failure tells you exactly which case broke.
Common Pitfalls
The K check is subtle. Specific ways builders get it wrong:
Using reserves instead of balances on the left side. The post-swap reserves are what you are about to write. The balances are what actually sit in the contract right now. If a flash-swap callback returned tokens, the balance reflects that; the reserve does not. Check against balance.
Forgetting the fee scaling on the right. The left side is scaled by * 1000 because we deduct 3 per 1000. The right side must be scaled by * (1000**2) — that is the ** 2 matching the two multiplications on the left. Miss the exponent and the check becomes either trivially passing or trivially failing.
Using subtraction instead of the invariant check. A simpler-looking check like require(k_after >= k_before) without fee scaling is not equivalent. With fees, the left side must be higher than the right by exactly the fee amount; naive equality or greater-than-or-equal on unadjusted reserves breaks the math.
Overflow in the multiplication. balance0Adjusted * balance1Adjusted can exceed uint256 if both values are large. V2 uses uint112 for reserves partly to cap this; a fork that expands to uint256 must handle the multiplication overflow carefully, often by using mulDiv helper logic.
The K-Invariant as Security Foundation
Every bug that drained a Uniswap V2 fork came back, in one way or another, to a failure of the K-invariant to hold under some edge case. Fee-on-transfer tokens that silently reduce balances. Rebasing tokens that change balances without transfers. Callback reentrancy that moves tokens between checks. Rounding in the wrong direction.
Understanding the K-invariant — what it enforces, how it is computed, and what can break it — is the security foundation for working with any constant-product AMM. It is the single most important concept from building Uniswap V2.
Articles Using This Term
Learn more about K-Invariant in these articles:
Related Terms
Constant Product Formula
The mathematical formula (x · y = k) that governs automated market makers, maintaining a constant product of token reserves.
Automated Market Maker (AMM)
A decentralized exchange protocol that uses mathematical formulas to price assets instead of order books.
Uniswap V2
The second version of the Uniswap AMM protocol, released in 2020. A minimal constant-product automated market maker composed of a Factory, Pair contracts, a Router, and a Library. The most-forked DeFi contract ever shipped.
Flash Swap
A Uniswap V2 feature where the Pair contract sends output tokens to the recipient before checking the K-invariant, letting the recipient use them temporarily as long as they return sufficient tokens in the same transaction.
Need expert guidance on K-Invariant?
Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.
Get a Quote

