The Constant Product Formula

The foundational building block of AMMs in DeFi.

Brief history

Before the introduction of the Logarithmic Market Scoring Rule (LMSR) by economist Robin Hanson, most prediction markets worked using a Continuous Double Auction (CDA). In a CDA, the trading platform uses a limit order book, which has the following flaws for a prediction market:

  1. Illiquidity: For niche markets (e.g., “Will a specific software project release a new version by 2028?”), the price a buyer is willing to bid can sit far below the price a seller is asking, making fair trades hard to complete.
  2. Thin markets: Small trades causing massive price spikes and distorting the market’s data.

LMSRs solved this by automatically setting prices using a mathematical formula based on how many shares of each outcome have been bought, and initial funding from the market’s creator to guarantee winners get paid. This way, the market does not need to match you with a trader and solves the problem of illiquidity. The world was now given the concept of an automated market maker (AMM) using mathematics.

Now, when it comes to decentralized exchanges, limit order books also present major flaws. On a traditional exchange, market makers post and cancel thousands of orders per second at almost no cost. However, on Ethereum, each order, cancellation, and update is a paid transaction, and blocks (in the year 2017–2018) arrive only every ~15 seconds.

In 2016, Vitalik presented a solution for this issue on Reddit, proposing that decentralized exchanges could work like LMSR-style prediction markets. That idea was later refined, with the help of others such as Martin Köppelmann from Gnosis, into the x * y = k market maker formula.

How the formula works

The key question that needed to be solved was as follows: How can a pool change its price automatically as tokens are bought?

Assume a pool has two tokens: token A = x, and token B = y. Let’s determine how much x we must pay to receive a specific amount of y.

Firstly, we know that we must use a product formula. As y is taken, a proportional amount of x needs to be added. Simple supply and demand economics. That gives us the intuition behind the formula x * y = k, where k must remain constant.

Now, imagine Bob creates an ETH / USDC pool, priced at 2,500 USDC / ETH. Bob deposits 10,000 USDC and 4 ETH. This gives us (x = 4) * (y = 10,000) = 40,000 = k.

Suppose Alice decides to swap 1 ETH for USDC. To determine the amount of USDC Alice receives, we need to solve for y_new: x_new * y_new = 40,000, where x_new = 5. y_new = 40,000 / 5 = 8,000 USDC. Therefore, the pool must have at least 8,000 USDC to maintain k, so Alice receives 10,000 − 8,000 = 2,000 USDC.

But wait, isn’t ETH trading at 2,500 USDC and Alice received only 2,000 USDC? This is because the pool liquidity in this example is thin relative to Alice’s trade, so it causes a larger price impact. If Alice traded at a pool where x = 4,000 ETH and y = 10,000,000 USDC, then she would be able to trade her 1 ETH at about the market price of 2,500 USDC.

This concept of price impact is important because it limits the amount of trades that can occur in the pool, thus preventing the pool from being drained at stale prices. If ETH rises to 3,000 USDC elsewhere, traders will not be able to buy all of Bob’s ETH at the outdated price. The price must adjust due to the impact of each trade.

Now that we understand the formula, we can implement the price calculation function used for swaps. Let’s create a function that determines how much of the output token Alice will receive given an input of either token of the pool.

We have the formula x * y = k. Let a = Alice’s input and b = Alice’s output. After Alice’s trade, the formula will give us (x + a)(y - b) = k. Our goal for this function is to solve for b (the amount of output). Before I break down the algebra, take a moment to try it for yourself:

Try it

Rearrange (x + a)(y − b) = k to find Alice’s output, b. Which expression is correct?

We know k = x * y. Therefore we can use substitution to derive (x + a)(y - b) = x * y. Solving for b, we now have b = y - (x*y)/(x+a).

Remember common denominators? We can use that to further simplify this formula. Since y = y(x+a) / (x+a), we can insert that into our formula to derive b = [y(x+a) - (x*y)] / (x+a) = (xy + ay - xy) / (x + a) = ay / (x + a). Our simplified formula is b = ay / (x + a).

The following function demonstrates calculating the output of a swap given an input:

// Calculate the output for a specified input.
function getInputPrice(
    uint256 inputAmount, // amount Alice decides to swap (a value)
    uint256 inputReserve, // current ETH reserves (x value)
    uint256 outputReserve // current USDC reserves (y value)
) internal pure returns (uint256) {
    require(inputReserve > 0 && outputReserve > 0); // only accept swaps for non-zero reserves

    // Account for the 0.3% fee.
    uint256 inputAmountWithFee = inputAmount * 997; // apply the input fee

    uint256 numerator = inputAmountWithFee * outputReserve; // a * y
    uint256 denominator = inputReserve * 1000 + inputAmountWithFee; // (x + a)

    // Integer division rounds down.
    return numerator / denominator; // a * y / (x + a)
}

Note that we apply the * (997/1000) so that 99.7% of the input is used to calculate the output, thus extracting a 0.3% fee for LPs.

Tip

In Solidity, it is important to always multiply before dividing, where safe, to avoid precision loss.

Deposits and withdrawals

The key for swaps is that k must remain constant. However, deposits increase k, since x and y both increase. Therefore, we must focus on maintaining the current price of the pool, which is the ratio of y/x.

Recall Bob’s pool has x = 4 ETH and y = 10,000 USDC, with the price at y/x = 2,500 USDC/ETH. To maintain the ratio y/x, we need (y + b)/(x + a) = y/x, where a and b represent Alice’s ETH and USDC deposit respectively. Solving for b, we can simplify this formula using algebra:

(y + b)/(x + a) = y/x
=> (y + b)x = y(x+a)
=> yx + bx = yx + ya
=> b = ay/x

Using the above formula, we can determine how much of tokenB Alice must deposit to maintain the price ratio, given her deposit of a specific amount of tokenA:

tokenBRequired = tokenADeposited * tokenBReserve / tokenAReserve + 1;
sharesMinted = tokenADeposited * totalShares / tokenAReserve;

Warning

The +1 is necessary here. As Solidity rounds down integer division to the nearest whole number, this can allow users to give less tokenB than required, allowing them to extract from LPs.

During withdrawals, Alice receives tokenA and tokenB in proportion to her shares burned. The same share fraction burned is applied to both tokens, thus maintaining the current price:

tokenAReturned = sharesBurned * tokenAReserve / totalShares;
tokenBReturned = sharesBurned * tokenBReserve / totalShares;

Warning

Slippage protection: As transactions sit in the mempool before execution, the amount of tokens transferred or received can be vastly different than expected. A classic example of this is sandwich attacks.

To avoid this, users must be able to specify the min and max tokens they are willing to transfer/receive for each deposit, withdrawal, and swap transaction.

Right place, right time

In 2017, Hayden Adams, a mechanical engineer who was just laid off from his job, began applying the constant product formula into a prototype. Learning from Vitalik’s posts and implementing the ideas we described above, he created Uniswap v1, which launched in 2018.

Other major projects followed:

  • Curve (2019–2020): combined constant-sum and constant-product formulas for stablecoins.
  • Balancer (2020): generalized it to pools with more than two tokens and custom weights.

As of October 2026, Uniswap is one of the most successful DeFi protocols, and has processed more than $4.7 trillion in trades since its launch.

Conclusion

The best ideas are often built on other great ideas, with many great minds participating to further improve them. The idea of the constant product formula was derived from exceptional minds already achieving something similar, in this case the concept of the LMSR by Robin Hanson. Inspired by this, Vitalik urged others to implement a similar idea for DeFi. This was later done by Hayden Adams, who achieved one of the most successful projects today, called Uniswap.

The constant product formula continues to serve as the basis for most AMMs in the DeFi landscape, allowing trades without needing to match a buyer and seller, with each trade automatically adjusting the price in the pool.

Test your knowledge

Ready to apply what you’ve learned? Test your understanding with the questions below.

Two pools have the same token ratio, but one holds 1,000 times more liquidity. Why does the same trade receive better execution in the larger pool?

How does the swap calculation account for the 0.3% fee?

Someone adds both tokens in the pool’s existing ratio. What happens, ignoring rounding?

Why does a proportional liquidity withdrawal preserve the pool’s price ratio, ignoring rounding?

Why is it required to add one smallest token unit when calculating the token deposit?

Alice burns a fixed number of LP shares. Why might she still need minimum withdrawal amounts?

Discover more from CrypticDefense Audits

Subscribe now to keep reading and get access to the full archive.

Continue reading