How to Retrieve Uniswap V2 Pool Addresses and Token Prices

·

Obtaining Pool Addresses

To retrieve a Uniswap V2 pool address (e.g., FTM/WETH on Ethereum Mainnet), use the factory contract's getPair function with the token contract addresses. Below is a JavaScript implementation using Ethers.js:

const { ethers } = require("hardhat");
const factoryAddress = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"; // Uniswap factory address
const weth = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const ftm = "0x4e15361fd6b4bb609fa63c81a2be19d873717870";

const factoryABI = [
  "function getPair(address tokenA, address tokenB) external view returns (address pair)"
];

async function main() {
  const factoryContract = new ethers.Contract(factoryAddress, factoryABI, ethers.provider);
  const ftm_weth = await factoryContract.getPair(ftm, weth);
  console.log("FTM/WETH Pool Address: %s", ftm_weth);
}
main().catch(console.error);

Example Output:
FTM/WETH Pool Address: 0x1ffC57cAda109985aD896a69FbCEBD565dB4290e

👉 Track live pool metrics on DexScreener


Calculating Token Prices

Method 1: Using Reserves

After obtaining the pool address, query reserves with getReserves() to calculate the price ratio:

const v2PairABI = ["function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)"];

async function getPrice() {
  const ftmWethPairContract = new ethers.Contract(ftm_weth_address, v2PairABI, ethers.provider);
  const [reserve0, reserve1] = await ftmWethPairContract.getReserves();
  const price = new Big(reserve1).div(new Big(reserve0)).toString();
  console.log("FTM/WETH Price:", price);
}

Key Notes:

Example Output:
FTM/WETH Price: 0.00027843670259855536


Method 2: Using Router Quotes

Alternative method with price impact consideration:

const routerAddress = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const routerABI = ["function getAmountsIn(uint amountOut, address[] memory path) external view returns (uint[] memory amounts)"];

async function getRouterPrice() {
  const routerContract = new ethers.Contract(routerAddress, routerABI, ethers.provider);
  const amountOut = ethers.parseUnits('1', 18);
  const price = await routerContract.getAmountsIn(amountOut, [weth, ftm]);
  console.log("FTM/WETH Price (Router):", ethers.formatUnits(price[0], 18));
}

Key Differences:

👉 Compare liquidity across DEXs


FAQ

Q: Why are prices from reserves and router different?
A: Router quotes include swap fees, while reserve ratios reflect raw pool balances.

Q: How do I handle tokens with different decimals?
A: Always normalize amounts using ethers.parseUnits() with the correct decimal places.

Q: Can I retrieve historical prices?
A: Yes, by querying reserves at specific block heights using archival nodes.

Q: What's the gas cost for these queries?
A: All methods shown are view functions—no gas fees required.


Optimization Tips

  1. Batch Requests: Fetch multiple pairs in single calls using Multicall contracts
  2. Caching: Store frequently-accessed pool addresses locally
  3. Error Handling: Verify contract existence before queries with eth_getCode

For advanced analytics, consider subgraph queries or third-party APIs like 👉 OKX DEX aggregator.