On-Chain Trading Slippage: Root Cause Analysis and Algorithmic Mitigation
On-Chain Trading Slippage: Root Cause Analysis and Algorithmic Mitigation
Slippage on DEXes is not random — it's a mathematical consequence of how Automated Market Makers work. Understanding the math lets you minimize it algorithmically.
What Causes Slippage?
On a constant-product AMM (like Uniswap V2), the pool maintains:
x * y = k
Where x = reserve of token A, y = reserve of token B, and k = constant.
When you buy token B by adding token A:
- The pool's token B reserve decreases
- Each subsequent unit of B costs more A
- This price impact IS slippage
Calculating Expected Slippage
def calculate_slippage_v2(
reserve_in: float,
reserve_out: float,
amount_in: float,
fee_bps: int = 30, # 0.3% for Uniswap V2
) -> dict:
"""Calculate slippage for a constant-product AMM swap."""
# Spot price (no impact)
spot_price = reserve_out / reserve_in
# Apply fee
amount_in_after_fee = amount_in * (10000 - fee_bps) / 10000
# Actual output (constant product formula)
amount_out = (
reserve_out * amount_in_after_fee
/ (reserve_in + amount_in_after_fee)
)
# Effective price
effective_price = amount_out / amount_in
# Slippage
slippage_pct = (1 - effective_price / spot_price) * 100
# Price impact (without fee)
price_impact = (
1 - (reserve_out - amount_out) * reserve_in
/ (reserve_out * (reserve_in + amount_in))
) * 100
return {
'spot_price': spot_price,
'effective_price': effective_price,
'amount_out': amount_out,
'slippage_pct': round(slippage_pct, 4),
'price_impact_pct': round(price_impact, 4),
'fee_pct': fee_bps / 100,
}
# Example: Swap $10,000 USDC for ETH in a $10M pool
result = calculate_slippage_v2(
reserve_in=5_000_000, # 5M USDC
reserve_out=1_500, # 1500 ETH
amount_in=10_000, # $10,000 swap
)
print(f"Slippage: {result['slippage_pct']}%")
print(f"Amount out: {result['amount_out']:.4f} ETH")
Mitigation Strategies
1. Order Splitting (TWAP)
async def twap_swap(
total_amount: float,
num_chunks: int = 10,
interval_seconds: int = 15,
) -> list:
"""Time-Weighted Average Price execution."""
chunk_size = total_amount / num_chunks
results = []
for i in range(num_chunks):
result = await execute_swap(chunk_size)
results.append(result)
if i < num_chunks - 1:
await asyncio.sleep(interval_seconds)
avg_price = sum(
r['effective_price'] for r in results
) / len(results)
print(f"TWAP avg price: {avg_price:.4f}")
return results
2. Multi-Route Splitting
def find_optimal_route_split(
pools: list,
total_amount: float,
) -> list:
"""Split order across multiple pools to minimize total slippage."""
from scipy.optimize import minimize
def total_slippage(splits):
total = 0
for i, pool in enumerate(pools):
if splits[i] <= 0:
continue
result = calculate_slippage_v2(
pool['reserve_in'],
pool['reserve_out'],
splits[i],
)
total += result['slippage_pct'] * splits[i]
return total
n = len(pools)
result = minimize(
total_slippage,
x0=[total_amount / n] * n,
constraints={'type': 'eq',
'fun': lambda x: sum(x) - total_amount},
bounds=[(0, total_amount)] * n,
)
return [
{'pool': pools[i]['name'], 'amount': result.x[i]}
for i in range(n)
if result.x[i] > 0.01
]
Slippage by Trade Size
| Trade Size (vs Pool) | Expected Slippage | Strategy |
|---|---|---|
| < 0.1% of pool | < 0.05% | Direct swap |
| 0.1% - 1% of pool | 0.05% - 0.5% | Consider splitting |
| 1% - 5% of pool | 0.5% - 5% | Must split / multi-route |
| > 5% of pool | > 5% | OTC or staged execution |
Understanding and minimizing slippage is essential for any strategy trading on-chain. ClawDUX's strategy verification engine measures actual slippage during backtesting to provide buyers with realistic performance expectations.
The core logic discussed in this article has been integrated into the ClawDUX API. Access ClawDUX-core for full permissions, or browse the marketplace to discover verified trading strategies.