get_price_impact
Estimate price impact for trades on Base DEX pools using the constant product formula to calculate how trade size affects token prices.
Instructions
Estimate price impact for a given trade size using constant product formula
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| token_address | Yes | Token contract address on Base | |
| trade_size_eth | Yes | Trade size in ETH (e.g. '0.1') |
Implementation Reference
- src/index.ts:726-813 (handler)The "get_price_impact" tool handler, which calculates the estimated price impact of a trade based on pool reserves (V2/Aerodrome) or liquidity (V3).
server.tool( "get_price_impact", "Estimate price impact for a given trade size using constant product formula", { token_address: z.string().describe("Token contract address on Base"), trade_size_eth: z.string().describe("Trade size in ETH (e.g. '0.1')"), }, async ({ token_address, trade_size_eth }) => { try { const quoteAddress = WETH; const tradeEth = parseFloat(trade_size_eth); if (isNaN(tradeEth) || tradeEth <= 0) { return { content: [{ type: "text" as const, text: "Invalid trade size. Must be a positive number." }] }; } const [tokenDecimals, quoteDecimals, tokenSymbol] = await Promise.all([ getTokenDecimals(token_address), getTokenDecimals(quoteAddress), getTokenSymbol(token_address), ]); const pools = await findAllPools(token_address, quoteAddress); if (pools.length === 0) { return { content: [{ type: "text" as const, text: `No DEX pools found for ${token_address} on Base.` }] }; } const impacts = pools.map((pool) => { const spotPrice = calculatePrice(pool, tokenDecimals, quoteDecimals); if (pool.sqrtPriceX96 !== undefined) { // V3 — rough estimate using liquidity const liq = Number(pool.liquidity ?? 0n); if (liq === 0) { return { dex: pool.dex, pool: pool.address, spotPrice: formatEth(spotPrice), impact: "N/A (no liquidity)" }; } // Approximate: impact ~ tradeSize / (2 * liquidity_in_eth_terms) // This is a rough estimate for V3 const roughImpact = (tradeEth / (liq / 1e18)) * 100; return { dex: pool.dex, pool: pool.address, spotPrice: formatEth(spotPrice), estimatedImpact: Math.min(roughImpact, 100).toFixed(4) + "%", note: "V3 impact is approximate (depends on tick range)", }; } // V2/Aerodrome — constant product formula // Buy: tokensOut = reserveToken - k / (reserveETH + tradeETH) const ethReserve = pool.tokenIsToken0 ? Number(ethers.formatUnits(pool.reserve1, quoteDecimals)) : Number(ethers.formatUnits(pool.reserve0, quoteDecimals)); const tokenReserve = pool.tokenIsToken0 ? Number(ethers.formatUnits(pool.reserve0, tokenDecimals)) : Number(ethers.formatUnits(pool.reserve1, tokenDecimals)); if (ethReserve <= 0 || tokenReserve <= 0) { return { dex: pool.dex, pool: pool.address, spotPrice: formatEth(spotPrice), impact: "N/A (empty pool)" }; } const k = ethReserve * tokenReserve; const newEthReserve = ethReserve + tradeEth; const newTokenReserve = k / newEthReserve; const tokensOut = tokenReserve - newTokenReserve; const effectivePrice = tradeEth / tokensOut; const priceImpact = ((effectivePrice - spotPrice) / spotPrice) * 100; return { dex: pool.dex, pool: pool.address, spotPrice: formatEth(spotPrice), effectivePrice: formatEth(effectivePrice), tokensReceived: tokensOut.toFixed(4), priceImpact: priceImpact.toFixed(4) + "%", ethReserve: formatEth(ethReserve), }; }); return { content: [{ type: "text" as const, text: JSON.stringify({ token: token_address, symbol: tokenSymbol, tradeSizeETH: trade_size_eth, pools: impacts, }, null, 2), }],