Liquidity Lu saysUniswap v3 concentrates liquidity to a price range [pLow, pHigh] — outside the range the position becomes 100% one token, inside it acts like a much larger v2 pool.
Uniswap v3's concentrated liquidity lets LPs pick a price range [pLow, pHigh]. Inside that range, their capital behaves like a much larger v2 pool — more depth per dollar. Outside the range, the position becomes 100% one token (the side prices are heading toward). The trade-off is constant rebalancing or accepting the auto-rebalance into the losing token.
The formulas: at price p inside the range, token amounts are x = L(1/√p − 1/√pHigh) and y = L(√p − √pLow). The demo computes the position composition at three prices: in-range, above-range, below-range.
Power-ups you unlock
LPs pick a price range [pLow, pHigh]
Inside range: capital acts like a deeper v2 pool
Above range: position becomes 100% the higher-priced token
Below range: position becomes 100% the lower-priced token
Composition: x = L(1/√p − 1/√pHigh), y = L(√p − √pLow)
The Sandwich Bot attacks — common mistakes
Picking a tight range and exiting it constantly (no fees, all token risk)
Forgetting auto-rebalance into the losing token at range edges
Treating v3 like v2 — they have different IL profiles
Ignoring the manual rebalancing cost when range shifts
Boss battleCompute the (x, y) composition of a v3 position with L=100 in [0.9, 1.1] at p = 0.8, 1.0, and 1.2.
Example code
<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
function v3Position(L, pLow, pHigh, p){
const sp = Math.sqrt(p), sl = Math.sqrt(pLow), sh = Math.sqrt(pHigh);
let x, y;
if(p <= pLow) { x = L * (1/sl - 1/sh); y = 0; }
else if(p >= pHigh) { x = 0; y = L * (sh - sl); }
else { x = L * (1/sp - 1/sh); y = L * (sp - sl); }
return { x, y, value: x*p + y };
}
const L = 100, pLow = 0.9, pHigh = 1.1;
const cases = [0.8, 1.0, 1.2];
const rows = cases.map(p => {
const r = v3Position(L, pLow, pHigh, p);
const where = p < pLow ? 'BELOW range' : p > pHigh ? 'ABOVE range' : 'IN range';
return ' p=' + p.toFixed(1) + ' x=' + r.x.toFixed(3) + ' y=' + r.y.toFixed(3) + ' value=' + r.value.toFixed(2) + ' [' + where + ']';
});
document.getElementById('o').textContent = [
'v3 position: L=' + L + ' in [' + pLow + ', ' + pHigh + ']',
...rows,
'',
'below range → 100% token X above range → 100% token Y'
].join('\n');
</script></body></html>