<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maria Kalala</title>
    <description>The latest articles on DEV Community by Maria Kalala (@mariakalala).</description>
    <link>https://dev.to/mariakalala</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1909241%2F20f17bec-47c4-4e34-8813-b911febb7e4b.jpg</url>
      <title>DEV Community: Maria Kalala</title>
      <link>https://dev.to/mariakalala</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariakalala"/>
    <language>en</language>
    <item>
      <title>Understanding the Constant Product Formula in AMMs (Without Getting Tricked by k)</title>
      <dc:creator>Maria Kalala</dc:creator>
      <pubDate>Tue, 23 Dec 2025 10:43:30 +0000</pubDate>
      <link>https://dev.to/mariakalala/understanding-the-constant-product-formula-in-amms-without-getting-tricked-by-k-4ehd</link>
      <guid>https://dev.to/mariakalala/understanding-the-constant-product-formula-in-amms-without-getting-tricked-by-k-4ehd</guid>
      <description>&lt;p&gt;If you’re learning how Automated Market Makers (AMMs) like Uniswap work, one thing can feel weird at first:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do we use the old k when calculating swap outputs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At a glance, it feels more “correct” to recompute k after adding tokens but doing that completely breaks the swap logic.&lt;/p&gt;

&lt;p&gt;Let’s walk through why the invariant must stay constant, step by step, with real numbers and Solidity-style math.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea: What Does &lt;code&gt;x * y = k&lt;/code&gt; Actually Mean?
&lt;/h2&gt;

&lt;p&gt;In a constant product AMM:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x * y = k&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x = reserve of token A&lt;/li&gt;
&lt;li&gt;y = reserve of token B&lt;/li&gt;
&lt;li&gt;k = a constant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key invariant is simple:&lt;br&gt;
During a swap, k must remain constant&lt;/p&gt;

&lt;p&gt;This doesn’t mean reserves don’t change, they do.&lt;br&gt;
It means the product of the reserves stays the same.&lt;br&gt;
That’s the entire pricing mechanism.&lt;/p&gt;
&lt;h2&gt;
  
  
  Initial State
&lt;/h2&gt;

&lt;p&gt;Let’s start with a simple pool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reserveA = 1000
reserveB = 1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compute k:&lt;br&gt;
&lt;code&gt;k = reserveA * reserveB = 1_000_000;&lt;/code&gt;&lt;br&gt;
This k defines the curve the pool must stay on.&lt;/p&gt;

&lt;p&gt;A User Swaps Token A for Token B&lt;br&gt;
The user swaps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amountAIn = 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Use the current invariant
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;uint256 k = reserveA * reserveB; // 1,000,000&lt;/code&gt;&lt;br&gt;
This is the only valid k for this swap.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Add the incoming tokens
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 newReserveA = reserveA + amountAIn;
// newReserveA = 1100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At this point:&lt;br&gt;
We know the new A reserve&lt;br&gt;
We don’t know the new B reserve yet&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Solve for the new B reserve
&lt;/h3&gt;

&lt;p&gt;To preserve the invariant:&lt;br&gt;
&lt;code&gt;newReserveA * newReserveB = k&lt;/code&gt;&lt;br&gt;
So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 newReserveB = k / newReserveA;
// newReserveB ≈ 909.09
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Calculate what the user receives
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amountBOut = reserveB - newReserveB;
// ≈ 1000 - 909.09 = 90.91
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*The user receives ~90.91 token B&lt;br&gt;
*The pool stays on the same curve&lt;/p&gt;

&lt;p&gt;Verifying the Invariant&lt;br&gt;
&lt;code&gt;1100 * 909.09 ≈ 1,000,000&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The invariant holds.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Common Mistake: Recomputing k
&lt;/h2&gt;

&lt;p&gt;A lot of people instinctively try this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256 newK = newReserveA * reserveB; // 1100 * 1000 = 1,100,000
uint256 newReserveB = newK / newReserveA; // = 1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amountBOut = reserveB - newReserveB;
// = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user gets nothing.&lt;/p&gt;

&lt;p&gt;Why? Because this logic moves the pool to a new curve, instead of keeping it on the original one. That violates the fundamental invariant.&lt;/p&gt;

&lt;p&gt;The Real Swap Equation;&lt;/p&gt;

&lt;p&gt;The actual AMM equation during a swap is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(reserveA + amountIn) * (reserveB - amountOut)
  = reserveA * reserveB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solving for amountOut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amountOut =
reserveB -
(reserveA * reserveB) / (reserveA + amountIn)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is exactly what Uniswap-style contracts implement.&lt;br&gt;
No magic. Just algebra.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the Old k Must Be Used
&lt;/h3&gt;

&lt;p&gt;Here’s the intuition that finally makes it click:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;k represents the curve&lt;/li&gt;
&lt;li&gt;A swap moves the pool along the same curve&lt;/li&gt;
&lt;li&gt;Adding liquidity creates a new curve&lt;/li&gt;
&lt;li&gt;Swaps do not&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you recalculate k during a swap:&lt;br&gt;
You’re no longer moving along the curve. You’re jumping to a different curve, and pricing instantly breaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mental Model That Helps;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Think of k as a rail track.&lt;/li&gt;
&lt;li&gt;Liquidity providers lay down new tracks (new k)&lt;/li&gt;
&lt;li&gt;Traders move along the existing track&lt;/li&gt;
&lt;li&gt;You never redraw the track mid-swap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Takeaway&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;k is not recomputed during swaps&lt;/li&gt;
&lt;li&gt;The invariant defines the pricing curve&lt;/li&gt;
&lt;li&gt;Swaps must start and end on the same curve&lt;/li&gt;
&lt;li&gt;Using a “new k” destroys the AMM logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this ever feels counterintuitive again, just remember:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swaps move the pool along the curve — they don’t redraw it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf7lyitnn0kdcfh4fu9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf7lyitnn0kdcfh4fu9a.png" alt="Constant Product Curve for AMMs" width="794" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>smartcontract</category>
      <category>defi</category>
    </item>
  </channel>
</rss>
