patternjavascriptTip
Reading ERC-20 token balance and decimals with ethers.js v6
Viewed 0 times
ethers.js v6.x
ERC-20balanceOfdecimalsformatUnitstoken balanceethers
Problem
Reading an ERC-20 token balance requires knowing the token's decimal precision to display a human-readable value.
Solution
Use a minimal ERC-20 ABI with balanceOf and decimals, create a Contract instance, then format with formatUnits.
import { Contract, formatUnits } from 'ethers';
const erc20Abi = ['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)'];
const token = new Contract(tokenAddress, erc20Abi, provider);
const [balance, decimals] = await Promise.all([token.balanceOf(userAddress), token.decimals()]);
console.log(formatUnits(balance, decimals));Why
ERC-20 tokens have variable decimal precision (commonly 18, but USDC uses 6). Always fetch decimals dynamically rather than hardcoding.
Gotchas
- Never hardcode 18 decimals — USDC is 6, WBTC is 8
- balanceOf returns raw uint256 in ethers v6 as a bigint
- formatUnits second argument accepts number or string, but bigint decimals must be converted
Code Snippets
Read ERC-20 balance with correct decimal formatting
import { Contract, formatUnits } from 'ethers';
const ERC20_ABI = [
'function balanceOf(address owner) view returns (uint256)',
'function decimals() view returns (uint8)',
'function symbol() view returns (string)',
];
async function getTokenBalance(tokenAddress, userAddress, provider) {
const token = new Contract(tokenAddress, ERC20_ABI, provider);
const [balance, decimals, symbol] = await Promise.all([
token.balanceOf(userAddress),
token.decimals(),
token.symbol(),
]);
return `${formatUnits(balance, decimals)} ${symbol}`;
}Context
Displaying a user's ERC-20 token balance in a dApp
Revisions (0)
No revisions yet.