Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
Network & Protocol Guides11 min read

Best Crypto Liquidity Pools: A Reproducible Evaluation Framework

Learn how to identify and compare the best crypto liquidity pools using a repeatable, data-driven framework that accounts for yield, risk, and on-chain mechanics.

TL;DR

There is no universally "best" crypto liquidity pool; the right pool depends on your risk tolerance, capital size, and time horizon. This article provides a reproducible framework for evaluating pools: you will learn to pull on-chain data, calculate real yield net of impermanent loss, assess TVL quality, and screen for smart contract risk. Rather than a static list, you get a methodology you can rerun as market conditions change. The final section shows how to automate the data collection using RPC endpoints and a simple script.

Why a Static List of Best Pools Fails

Searching for the "best crypto liquidity pools" typically returns listicles that rank pools by advertised APY. These lists are misleading for three reasons: APY figures often include temporary token emissions that collapse, they ignore impermanent loss (IL), and they rarely account for the liquidity depth needed to exit without slippage. A pool showing 200% APY may have $50k TVL and a 15% exit slippage for a $10k position.

A more reliable approach is to treat pool selection as a quantitative screening problem. You define your constraints (capital size, acceptable IL, chain preference, smart contract risk tolerance), then measure each candidate pool against those constraints using on-chain data. The "best" pool is the one that survives your filters with the highest risk-adjusted return.

This guide focuses on the methodology and the tooling to execute it. For concrete RPC endpoint recommendations to power your data collection, see the RPC endpoints guide and the multi-chain RPC endpoints guide.

  • Advertised APY is not net yield; subtract IL and emission decay.
  • TVL alone does not indicate safety; check holder concentration and lock status.
  • Exit liquidity matters more than entry yield for positions above $5k.

Prerequisites and Assumptions

To follow the procedures in this article you need: a working RPC endpoint for the chain you are analyzing (Ethereum, Arbitrum, Base, Solana, etc.), basic familiarity with JavaScript or Python, and access to a block explorer or indexer API for historical data. You do not need a paid data provider; most of the metrics can be derived from standard JSON-RPC calls and public subgraph endpoints.

The examples assume an EVM-compatible chain and use ethers.js v6. For Solana-based pools, the same logic applies but the RPC methods differ (getAccountInfo, getTokenAccountsByOwner). If you are unsure which RPC provider to use for a given network, the OnFinality networks page lists supported chains, and the API service provides managed endpoints.

All code uses placeholders: replace RPC_URL with your endpoint and POOL_ADDRESS with the pool contract address you are evaluating. Never hardcode private keys in scripts; use environment variables.

The Mental Model: Four Dimensions of Pool Quality

Every liquidity pool can be scored on four dimensions. First, real yield: the fee revenue plus sustainable emissions minus impermanent loss, annualized. Second, depth: the TVL and its distribution across price ranges, which determines slippage for your position size. Third, safety: smart contract audit status, admin key privileges, and oracle dependencies. Fourth, liquidity of your LP token: whether you can exit the pool without a lock-up or a secondary market discount.

A pool that scores well on yield but poorly on depth and safety is a yield trap. A pool with deep liquidity and low yield may be appropriate for stablecoin pairs where capital preservation is the goal. The framework lets you weight these dimensions according to your own risk profile rather than accepting a generic ranking.

For a deeper explanation of how automated market makers (AMMs) set prices and how IL arises, see the blockchain node hosting guide which covers the infrastructure layer that supports these protocols.

Step 1: Pull Pool Reserves and Compute Depth

The first measurement is pool depth. For a constant-product AMM (Uniswap v2 style), you can read reserves directly from the pair contract. For concentrated liquidity pools (Uniswap v3, Algebra), you need to query the current tick and liquidity. The following JavaScript snippet reads reserves from a v2-style pair and calculates the USD value of each side using a price feed you supply.

Run this against several candidate pools to build a comparison table. The output gives you reserve0, reserve1, and total TVL in USD. A pool with TVL below your position size multiplied by 20 is likely to suffer unacceptable slippage on exit.

const { ethers } = require('ethers');

const RPC_URL = process.env.RPC_URL;
const POOL_ADDRESS = '0x...'; // pair contract
const provider = new ethers.JsonRpcProvider(RPC_URL);

const ABI = [
  'function getReserves() view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)',
  'function token0() view returns (address)',
  'function token1() view returns (address)'
];

async function poolDepth() {
  const pair = new ethers.Contract(POOL_ADDRESS, ABI, provider);
  const [r0, r1] = await pair.getReserves();
  const t0 = await pair.token0();
  const t1 = await pair.token1();
  console.log({ token0: t0, reserve0: r0.toString(), token1: t1, reserve1: r1.toString() });
  // Multiply reserves by token prices (from an oracle or DEX quote) to get USD TVL.
}

poolDepth().catch(console.error);

Step 2: Calculate Impermanent Loss for Your Holding Period

Impermanent loss is the difference between holding the two tokens and providing them to the pool. For a constant-product pool, IL as a function of price ratio k is: IL = 2*sqrt(k)/(1+k) - 1. This formula assumes no fees. To get net yield, add the fee APR and subtract the IL realized over your intended holding period.

The Python function below computes IL for a range of price ratios. Use it to stress-test a pool: if a 2x price move produces 5.7% IL, and the pool's fee APR is 8%, your net return over a year (assuming the price move happens once) is roughly 2.3% before emissions. This is the number that matters, not the headline APY.

For stablecoin pairs, k stays near 1 and IL is negligible; the dominant risk is depeg. For volatile pairs, IL can exceed fee income. Always compute both.

import math

def impermanent_loss(k):
    """k = price ratio (new price / initial price). Returns IL as a negative fraction."""
    return 2 * math.sqrt(k) / (1 + k) - 1

for k in [0.5, 0.8, 1.0, 1.25, 2.0, 4.0]:
    print(f"price ratio {k:.2f} -> IL {impermanent_loss(k)*100:.2f}%")

Step 3: Screen for Smart Contract and Admin Risk

Yield is meaningless if the contract is upgradeable by a single key or the pool relies on a manipulable oracle. Before depositing, check three things: whether the pool contract is behind a proxy with an admin, whether the admin is a multisig or timelock, and whether the protocol has been audited by a reputable firm. You can verify proxy status by reading the EIP-1967 implementation slot.

The following curl command queries the implementation slot for a proxy contract. If the slot returns a non-zero address, the contract is upgradeable and you must identify who controls upgrades. A zero address indicates a non-upgradeable contract, which reduces admin risk (though not bugs).

Also check the pool's token holder distribution. A pool where one address holds 80% of LP tokens is effectively controlled by that address; a rug pull or large withdrawal can drain liquidity. Use a block explorer's holder tab or query Transfer events to compute concentration.

curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc":"2.0",
    "method":"eth_getStorageAt",
    "params":["0xPOOL_ADDRESS","0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc","latest"],
    "id":1
  }'

Step 4: Build a Comparison Table from Measured Data

Once you have depth, IL, and safety flags for each candidate, assemble them into a table. Do not fill in numbers from memory or from a listicle; every cell should come from a query you ran or a source you can cite. The table below is a template; replace the placeholder rows with your own measurements.

PoolChainTVL (USD)Fee APREmission APRIL (2x move)UpgradeableAuditNet Score
POOL_AEthereummeasuredmeasuredmeasuredcomputedyes/noyes/nocomputed
POOL_BArbitrummeasuredmeasuredmeasuredcomputedyes/noyes/nocomputed
POOL_CBasemeasuredmeasuredmeasuredcomputedyes/noyes/nocomputed

Net Score can be a simple weighted sum: 0.4 * (fee APR - IL) + 0.3 * log(TVL) + 0.2 * safety_flag + 0.1 * exit_liquidity_flag. Adjust weights to your risk tolerance. The point is to make the trade-offs explicit rather than hiding them behind a single APY number.

For performance and reliability of the RPC layer that feeds this table, see the performance and optimization category and consider a dedicated node if you are querying many pools frequently.

Expected Verification Results

After running the scripts, you should have: (1) a JSON object per pool with reserve0, reserve1, and token addresses; (2) an IL curve for each volatile pair; (3) a proxy status flag from the storage slot query; and (4) a completed comparison table. If any query returns null or reverts, the pool address or ABI is likely wrong, or the RPC endpoint does not support the method.

Verify your depth calculation against a public dashboard for one pool. If your TVL differs by more than 5%, check your token price source and decimal handling. A common error is using raw reserve values without adjusting for token decimals (USDC has 6, WETH has 18).

Troubleshooting Common Measurement Errors

If getReserves reverts, the pool may be a v3-style contract that does not expose that function; use slot0 and liquidity instead. If the RPC returns a rate-limit error, reduce request frequency or switch to a provider with higher throughput; the pricing page explains plan limits. If your IL calculation produces positive numbers, you have inverted the ratio; k should be new price divided by initial price.

If the proxy slot query returns 0x000...000, the contract is not a standard EIP-1967 proxy, but it may still be upgradeable via a custom pattern. Check the contract source on a block explorer before concluding it is immutable. If holder concentration data is unavailable, query Transfer events from the pool's LP token contract and aggregate balances manually.

  • Revert on getReserves: pool is likely v3 or a non-standard AMM.
  • Rate limit: batch requests or use a dedicated endpoint.
  • IL sign error: ensure k = new/initial, not initial/new.
  • TVL mismatch: check token decimals and price timestamp.

Limitations and Trade-offs

This framework measures what is observable on-chain at a point in time. It does not predict future emissions changes, governance votes that alter fee splits, or black swan events. Emissions APY in particular can change weekly; rerun the measurement before each deposit. The safety score is a heuristic, not a guarantee; audits reduce but do not eliminate risk.

Concentrated liquidity pools require a different depth calculation because liquidity is distributed across ticks. The reserve-based method in Step 1 will understate depth for v3 pools. For those, query the liquidity net at each initialized tick or use a subgraph that exposes tick data. The IL formula also differs for concentrated positions; use the range-specific formula from the protocol documentation.

Finally, this guide does not recommend specific pools. The "best" pool for a stablecoin holder differs from the best pool for a degen farmer. The framework gives you the tools to decide; the decision remains yours.

Next Steps: Automate and Monitor

Once you have a working comparison table, automate the data collection on a schedule. A cron job that runs the depth and IL scripts every hour and writes results to a database lets you track how yield and depth change over time. Alert when a pool's TVL drops below your exit threshold or when the admin key changes.

For production monitoring, use a reliable RPC endpoint with sufficient rate limits. The OnFinality API service provides managed access to multiple chains, and the networks page lists supported networks. If you are running high-frequency queries across many pools, a dedicated node reduces latency and avoids shared rate limits. For endpoint selection guidance, the RPC Assistant covers concrete provider choices; this article covers the methodology that those endpoints support.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started