home / skills / openclaw / skills / uniswap-pool-analysis

uniswap-pool-analysis skill

/skills/wpank/uniswap-pool-analysis

This skill analyzes Uniswap pool data such as liquidity distribution, fee tiers, and TVL to answer on-chain pool metrics.

npx playbooks add skill openclaw/skills --skill uniswap-pool-analysis

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
2.6 KB
---
name: uniswap-pool-analysis
description: Analyze Uniswap pool data including liquidity distribution, fee tiers, tick ranges, and TVL. Use when the user asks about pool metrics, liquidity analysis, or wants to query on-chain pool state.
---

# Uniswap Pool Analysis

## Overview

This skill covers querying and analyzing Uniswap v3/v4 pool state on-chain using viem.

## Key Concepts

- **sqrtPriceX96**: Encoded price format used by Uniswap v3/v4. Convert with `price = (sqrtPriceX96 / 2^96)^2`
- **Ticks**: Discrete price points defining liquidity ranges. Tick spacing depends on fee tier.
- **Liquidity**: The `L` value representing active liquidity at the current tick.

## Fee Tiers (v3)

| Fee (bps)   | Tick Spacing | Typical Use      |
| ----------- | ------------ | ---------------- |
| 1 (0.01%)   | 1            | Stablecoin pairs |
| 5 (0.05%)   | 10           | Correlated pairs |
| 30 (0.30%)  | 60           | Standard pairs   |
| 100 (1.00%) | 200          | Exotic pairs     |

## Querying Pool State

Use the Uniswap v3 Pool ABI to read on-chain state:

```typescript
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";

const client = createPublicClient({
  chain: mainnet,
  transport: http(process.env.ETHEREUM_RPC_URL),
});

// Read slot0 for current price and tick
const [
  sqrtPriceX96,
  tick,
  observationIndex,
  observationCardinality,
  observationCardinalityNext,
  feeProtocol,
  unlocked,
] = await client.readContract({
  address: poolAddress,
  abi: poolAbi,
  functionName: "slot0",
});

// Read liquidity
const liquidity = await client.readContract({
  address: poolAddress,
  abi: poolAbi,
  functionName: "liquidity",
});
```

## Price Conversion

```typescript
function sqrtPriceX96ToPrice(
  sqrtPriceX96: bigint,
  decimals0: number,
  decimals1: number,
): number {
  const price = Number(sqrtPriceX96) / 2 ** 96;
  return (price * price * 10 ** decimals0) / 10 ** decimals1;
}

function tickToPrice(
  tick: number,
  decimals0: number,
  decimals1: number,
): number {
  return (1.0001 ** tick * 10 ** decimals0) / 10 ** decimals1;
}
```

## Liquidity Distribution

To analyze liquidity distribution across ticks:

1. Query `tickBitmap` to find initialized ticks
2. For each initialized tick, read `ticks(tickIndex)` to get `liquidityNet`
3. Walk from `MIN_TICK` to `MAX_TICK`, accumulating net liquidity changes
4. Plot cumulative liquidity vs price for the distribution

## Multi-chain Support

Always accept a `chainId` parameter. Use the shared chain config from `packages/common/` to resolve:

- RPC URL
- Pool factory address
- Quoter address
- Subgraph endpoint (if available)

Overview

This skill analyzes Uniswap v3/v4 pool state to surface liquidity distribution, fee tiers, tick ranges, current price, and TVL. It queries on-chain pool storage and converts encoded values into human-friendly metrics for liquidity and price analysis. Use it to inspect pool health, concentration, and active ranges across chains.

How this skill works

The skill reads pool state via a JSON-RPC client (viem) to fetch slot0, liquidity, tick bitmaps, and individual tick entries. It converts sqrtPriceX96 and tick values into standard price units, accumulates liquidityNet across initialized ticks, and builds a cumulative liquidity vs price distribution. It accepts a chainId to resolve RPC, factory, and quoter addresses for multi-chain support.

When to use it

  • You want current pool price, tick, and active liquidity on-chain rather than relying on subgraphs.
  • Assessing liquidity concentration and where most liquidity sits across tick ranges.
  • Comparing fee tier implications and tick spacing for a given pool.
  • Calculating TVL and per-token reserves from on-chain state.
  • Auditing pool initialization, unexpected tick activity, or low liquidity windows.

Best practices

  • Always pass chainId and correct pool address to avoid querying wrong network.
  • Rate-limit RPC calls and batch reads where possible; reading ticks can be expensive.
  • Read tickBitmap first to locate initialized ticks before fetching individual ticks.
  • Convert sqrtPriceX96 with decimal normalization to get accurate price between tokens.
  • Validate fee tier and tick spacing to interpret tick indexes correctly.

Example use cases

  • Generate a cumulative liquidity vs price chart to visualize concentration and ranges.
  • Compute TVL and token reserves using slot0 price and on-chain liquidity value.
  • Detect whether liquidity is narrowly concentrated around current price (risk of slippage).
  • Compare two pools’ liquidity distribution to choose where to route swaps.
  • Verify a pool’s initialized tick set after liquidity migration or provision.

FAQ

How do I convert sqrtPriceX96 to a human price?

Convert sqrtPriceX96 to a decimal by dividing by 2**96, square the result, and adjust for token decimals: price = (sqrtPriceX96/2**96)^2 * 10^decimals0 / 10^decimals1.

How can I find which ticks are initialized efficiently?

Read tickBitmap words to find nonzero slots and iterate only those bit positions, then call ticks(tickIndex) for initialized ticks instead of scanning the full range.