If you’re learning how Automated Market Makers (AMMs) like Uniswap work, one thing can feel weird at first:
Why do we use the old k when calculating swap outputs?
At a glance, it feels more “correct” to recompute k after adding tokens but doing that completely breaks the swap logic.
Let’s walk through why the invariant must stay constant, step by step, with real numbers and Solidity-style math.
The Core Idea: What Does x * y = k Actually Mean?
In a constant product AMM:
x * y = k
- x = reserve of token A
- y = reserve of token B
- k = a constant
The key invariant is simple:
During a swap, k must remain constant
This doesn’t mean reserves don’t change, they do.
It means the product of the reserves stays the same.
That’s the entire pricing mechanism.
Initial State
Let’s start with a simple pool:
reserveA = 1000
reserveB = 1000
Compute k:
k = reserveA * reserveB = 1_000_000;
This k defines the curve the pool must stay on.
A User Swaps Token A for Token B
The user swaps:
amountAIn = 100
Step 1: Use the current invariant
uint256 k = reserveA * reserveB; // 1,000,000
This is the only valid k for this swap.
Step 2: Add the incoming tokens
uint256 newReserveA = reserveA + amountAIn;
// newReserveA = 1100
At this point:
We know the new A reserve
We don’t know the new B reserve yet
Step 3: Solve for the new B reserve
To preserve the invariant:
newReserveA * newReserveB = k
So:
uint256 newReserveB = k / newReserveA;
// newReserveB ≈ 909.09
Step 4: Calculate what the user receives
amountBOut = reserveB - newReserveB;
// ≈ 1000 - 909.09 = 90.91
*The user receives ~90.91 token B
*The pool stays on the same curve
Verifying the Invariant
1100 * 909.09 ≈ 1,000,000
- The invariant holds.
The Common Mistake: Recomputing k
A lot of people instinctively try this instead:
uint256 newK = newReserveA * reserveB; // 1100 * 1000 = 1,100,000
uint256 newReserveB = newK / newReserveA; // = 1000
Then:
amountBOut = reserveB - newReserveB;
// = 0
The user gets nothing.
Why? Because this logic moves the pool to a new curve, instead of keeping it on the original one. That violates the fundamental invariant.
The Real Swap Equation;
The actual AMM equation during a swap is:
(reserveA + amountIn) * (reserveB - amountOut)
= reserveA * reserveB
Solving for amountOut:
amountOut =
reserveB -
(reserveA * reserveB) / (reserveA + amountIn)
Which is exactly what Uniswap-style contracts implement.
No magic. Just algebra.
Why the Old k Must Be Used
Here’s the intuition that finally makes it click:
- k represents the curve
- A swap moves the pool along the same curve
- Adding liquidity creates a new curve
- Swaps do not
If you recalculate k during a swap:
You’re no longer moving along the curve. You’re jumping to a different curve, and pricing instantly breaks.
Mental Model That Helps;
- Think of k as a rail track.
- Liquidity providers lay down new tracks (new k)
- Traders move along the existing track
- You never redraw the track mid-swap
Takeaway
- k is not recomputed during swaps
- The invariant defines the pricing curve
- Swaps must start and end on the same curve
- Using a “new k” destroys the AMM logic
If this ever feels counterintuitive again, just remember:
Swaps move the pool along the curve — they don’t redraw it.

Top comments (0)