If you've ever swapped tokens on Uniswap or PancakeSwap,
you've used a liquidity pool. But what's actually happening
under the hood?
This post gives you a solid mental model as a developer —
no heavy math, just the concepts you need to build on top of DeFi.
The Core Problem
Traditional exchanges use an order book — buyers and sellers
post orders, the exchange matches them.
On-chain this is painful:
- Every order is a transaction (gas costs)
- Thin markets mean no liquidity for small tokens
- Slow block times create front-running opportunities
Liquidity pools solve this by removing the need for a
counterparty entirely.
What is a Liquidity Pool?
A liquidity pool is a smart contract holding two tokens
in reserve. Instead of matching a buyer with a seller,
you trade directly against the contract.
The price is determined automatically based on the ratio
of tokens in the pool. No order book. No matching engine.
Just a contract and a formula.
This model is called an Automated Market Maker (AMM).
Liquidity Providers
Anyone can deposit tokens into a pool and become a
Liquidity Provider (LP).
You deposit equal value of both tokens. In return:
- You receive LP tokens representing your pool share
- You earn a cut of every swap fee (typically 0.3%)
- You can withdraw anytime by burning your LP tokens
The more trading volume the pool sees, the more LPs earn.
The Key Risk — Impermanent Loss
This is the most important concept for anyone building
with or investing in liquidity pools.
When token prices shift significantly after you deposit,
the pool auto-rebalances. You end up with more of the
token that dropped and less of the one that rose.
When you withdraw, you may have less value than if
you had simply held the tokens in your wallet.
That gap is impermanent loss.
It's called "impermanent" because if prices return to
original levels, the loss disappears. But if you withdraw
while prices are different — it's a realized loss.
Fee revenue can offset this — but for highly volatile
pairs, IL can outweigh what you earn.
Reading a Pool with ethers.js
Every Uniswap V2 pool exposes a getReserves() function.
Here's how to read live pool data:
import { ethers } from "ethers";
const PAIR_ABI = [
"function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)",
];
const provider = new ethers.JsonRpcProvider(
"https://mainnet.infura.io/v3/YOUR_KEY"
);
// ETH/USDC pair — Uniswap V2
const PAIR = "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc";
const pool = new ethers.Contract(PAIR, PAIR_ABI, provider);
async function getPrice() {
const [reserve0, reserve1] = await pool.getReserves();
const usdc = Number(reserve0) / 1e6; // USDC = 6 decimals
const eth = Number(reserve1) / 1e18; // ETH = 18 decimals
console.log(`ETH price: $${(usdc / eth).toFixed(2)}`);
}
getPrice();
That's it — you're reading live on-chain price data
directly from the pool contract.
V2 vs V3 — What Changed
Uniswap V3 introduced concentrated liquidity —
instead of spreading liquidity across all possible prices,
LPs choose a specific price range to provide liquidity in.
The tradeoff:
- Much more capital efficient within the range
- Stops earning fees if price moves outside the range
- Requires active management vs V2's set-and-forget
V3 positions are also NFTs — because each position
is unique (different price ranges), they can't be
fungible tokens like V2 LP tokens.
Key Terms Cheatsheet
| Term | What it means |
|---|---|
| AMM | Smart contract that prices assets automatically |
| LP | Someone who deposits tokens to earn fees |
| LP Token | Your receipt/share of the pool |
| Impermanent Loss | Value difference vs just holding |
| Concentrated Liquidity | V3 feature — LPs pick a price range |
| Slippage | Price difference between quote and execution |
What's Next
Next part: Building a real-time pool price monitor
with ethers.js — watching reserve changes live and
calculating price impact before a swap.
If anything here is unclear or wrong, drop it in
the comments. Always prefer a correction over bad
mental models spreading.
Top comments (0)