Uniswap v4 slippage & price impact, and why the v3 formula breaks and how to get real data via API
Uniswap v4 moved every pool into a single PoolManager and opened them up to hooks. The constant-product math that used to estimate slippage no longer maps to a single market. Here's why, and how to read real per-pool slippage and price impact straight from the chain.
PoolId, the way the protocol actually partitions state. Bitquery's DEXPoolSlippages API does exactly that, in real time, across every EVM chain.01 · The breakWhy v3 slippage math stops working on v4
For years, estimating slippage on Uniswap was a solved problem. A pair like WETH/USDC mapped to a single pool contract (v2) or a handful of fee-tier pools (v3). You pulled the reserves or the tick liquidity for that contract address, applied the constant-product or concentrated-liquidity formula, and out came a price-impact curve. Every aggregator, bot, and analytics dashboard leaned on that one-to-one relationship: one pair → one contract → one curve.
Uniswap v4 dissolved that relationship. There is no longer a pool contract to point at, and "the WETH/USDC pool" is no longer a single thing. If your slippage logic still assumes it is, it now returns a blended number that doesn't describe any market you can actually trade against.
02 · The causeSingleton + hooks: one contract, many pools
Two design changes in v4 are responsible.
The singleton. In v2 and v3, each pool was its own deployed contract. In v4, almost all pool state lives inside one PoolManager contract at 0x000000000004444c5dc75cB358380D2e3dE08A90 on Ethereum mainnet. The protocol does not deploy a contract per pair. Instead, each logical pool is a row of state keyed by a deterministic identifier: the PoolId.
Hooks. PoolId is derived from the pool's static configuration: the two currencies, the fee tier, the tick spacing, and crucially the hooks contract. Hooks are v4's extension point: custom code invoked around swaps and liquidity changes that can apply dynamic fees or otherwise alter execution. Two pools with the same two tokens and the same fee still produce different PoolIds and separate liquidity curves if their hooks differ.
PoolId returns the depth of the single market you route through.03 · The distinction
Price impact vs slippage: what you're actually measuring
These two terms get used interchangeably and shouldn't be:
- Price impact is the price movement your own trade causes against the pool's liquidity. A $100k swap into a thin pool moves the price more than the same swap into a deep one. It's a deterministic function of trade size and pool depth.
- Slippage is the gap between the price you expected when you submitted and the price you got at execution. It includes price impact plus anything that changed between quote and fill.
On v4, both depend on reading the right pool. A dynamic-fee hook can change the effective cost of the same swap from one block to the next, so a static formula over merged liquidity mis-estimates both numbers. You want the depth and price table of one PoolId, refreshed as the pool changes.
04 · The fix
Reading real per-pool slippage with DEXPoolSlippages
Bitquery indexes DEX pool state into a DEXPools cube, exposed through two schema entries: DEXPoolEvents (swaps, mints, burns) and DEXPoolSlippages (slippage and price-impact tables). The slippage stream simulates swaps through the pool's initialized ticks and returns, per pool:
MaxAmountInis the largest amount you can swap in at a given toleranceMinAmountOutis the guaranteed minimum output at that levelPriceis the average execution price for that trade sizeSlippageBasisPointsis the tolerance the row is computed for- both swap directions,
AtoBandBtoA
Every row carries Pool.PoolId, so you isolate one v4 market instead of blending all of them. Run this query in the Bitquery IDE.
query LatestSlippageForOneV4Pool {
EVM(network: eth) {
DEXPoolSlippages(
where: {
Price: {
Pool: {
PoolId: {
is: "0xdce6394339af00981949f5f3baf27e3610c76326a700af57e4b3e3ae4977f78d"
}
}
Dex: { ProtocolName: { is: "uniswap_v4" } }
}
}
orderBy: { descending: Block_Time }
limit: { count: 10 }
) {
Price {
AtoB {
Price
MinAmountOut
MaxAmountIn
}
BtoA {
Price
MinAmountOut
MaxAmountIn
}
Pool {
PoolId
CurrencyA {
Symbol
SmartContract
}
CurrencyB {
Symbol
SmartContract
}
}
Dex {
ProtocolName
ProtocolVersion
}
SlippageBasisPoints
}
Block {
Time
Number
}
}
}
}
Swap the PoolId for the market you route through and you get its real price-impact table, not an average of every ETH/USDC configuration sharing the manager address.
05 · In practice
Slippage scales with trade size. Read the whole curve.
The reason per-pool accuracy matters: each slippage tolerance maps to a different maximum trade size, and price impact is non-linear. Pulling DEXPoolSlippages for this exact ETH/USDC v4 pool at block 25,350,531 (mid price ≈ 1,694 USDC/ETH) gives the real ladder for selling ETH into USDC:
SlippageBasisPoints level from DEXPoolSlippages for PoolId 0xdce6394339af00981949f5f3baf27e3610c76326a700af57e4b3e3ae4977f78d. value is the MinAmountOut in USDC (the guaranteed proceeds); the average execution price drifts further below the 1,694 mid as the order grows. Loosening tolerance from 0.1% to 10% unlocks roughly 90× more size, and the reverse direction (USDC→ETH) comes back on the same row via BtoA. Read it per PoolId and you size orders against real depth instead of guessing a tolerance.06 · LiveStream slippage as the pool changes
Because hooks and liquidity events move the curve, a static snapshot ages fast. The same cube streams in real time. Subscribe once and every swap or ModifyLiquidity event refreshes the slippage table across all Uniswap v4 pools. Open this subscription in the Bitquery IDE.
subscription RealtimeSlippage {
EVM(network: eth) {
DEXPoolSlippages(
where: { Price: { Dex: { ProtocolName: { is: "uniswap_v4" } } } }
) {
Price {
AtoB {
Price
MinAmountOut
MaxAmountIn
}
BtoA {
Price
MinAmountOut
MaxAmountIn
}
Pool {
PoolId
SmartContract
}
Dex {
ProtocolName
ProtocolFamily
ProtocolVersion
}
SlippageBasisPoints
}
Block {
Time
Number
}
}
}
}
The same data is available over Kafka streams for high-throughput pipelines, and across EVM chains. Change network to base, bsc, arbitrum, matic, and the rest.
07 · Read backwardThe full picture, end to end
PoolId returns the real per-pool slippage of the single market you trade.08 · Who needs this
Where accurate v4 slippage actually pays off
PoolId-level price tables are the answer, consumed in real time at volume.One API for real per-pool v4 slippage
The DEXPoolSlippages cube simulates swaps through each pool's ticks and returns MaxAmountIn, MinAmountOut, and average execution price at every tolerance level. Each row is keyed by PoolId so v4's singleton never blends markets. Access it over GraphQL query, real-time subscription, and Kafka, across every major EVM chain.
09 · Start hereDocs & queries
PoolId: docs.bitquery.io/docs/blockchain/Ethereum/dextrades/uniswap-v4-liquidity-api.Get real Uniswap v4 slippage, per pool, in real time
Stop estimating v4 slippage from a formula that assumes one pool per pair. Read the real price-impact table for the exact PoolId you route through, over query, subscription, or Kafka, across every EVM chain.
Legal disclaimer
This article is provided for informational and educational purposes only. Code samples reflect Bitquery's GraphQL schema as of the date indicated and may change; consult the linked documentation for the current API.
Numeric examples of slippage and price impact (trade-size curves, execution prices, percentage figures) are illustrative and intended to explain how price impact scales with trade size against pool depth. They are not quotes, financial advice, or a guarantee of execution at any price. Always read live data for the specific PoolId you intend to trade.
References to Uniswap v4 architecture (PoolManager address, PoolId derivation, hooks) describe the protocol's public design. 'Uniswap' and other product names are the property of their respective owners; this content is independent and not affiliated with or endorsed by Uniswap Labs.