⚠️Blast API (blastapi.io) ends Oct 31. Migrate to Dwellir and skip Alchemy's expensive compute units.
Switch Today →
Skip to main content

eth_call

Executes a new message call immediately without creating a transaction on the blockchain. Used for reading smart contract state.

When to Use This Method

eth_call is essential for:

  • Reading Contract State - Query view/pure functions
  • Simulating Transactions - Test execution without gas costs
  • DeFi Integrations - Check prices, balances, allowances
  • Complex Queries - Execute multi-step contract logic

Parameters

  1. Transaction Object

    • from - (optional) Address executing the call
    • to - Contract address to call
    • gas - (optional) Gas limit for the call
    • gasPrice - (optional) Gas price in wei
    • value - (optional) Value to send in wei
    • data - Encoded function call data
  2. Block Parameter - QUANTITY|TAG

    • "latest" - Most recent block
    • "pending" - Pending state
    • Block number in hex
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"data": "0x70a08231000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f0beb"
},
"latest"
],
"id": 1
}

Returns

DATA - The return value of the executed contract function.

Implementation Examples

import { JsonRpcProvider, Contract, Interface } from 'ethers';

const provider = new JsonRpcProvider('https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc');

// ERC20 ABI for common functions
const ERC20_ABI = [
"function balanceOf(address owner) view returns (uint256)",
"function allowance(address owner, address spender) view returns (uint256)",
"function totalSupply() view returns (uint256)",
"function decimals() view returns (uint8)",
"function symbol() view returns (string)",
"function name() view returns (string)"
];

// Read ERC20 token balance
async function getTokenBalance(tokenAddress, walletAddress) {
const contract = new Contract(tokenAddress, ERC20_ABI, provider);
const balance = await contract.balanceOf(walletAddress);
const decimals = await contract.decimals();
const symbol = await contract.symbol();

return {
raw: balance.toString(),
formatted: (Number(balance) / Math.pow(10, decimals)).toFixed(4),
symbol: symbol
};
}

// Direct eth_call for custom encoding
async function directCall(to, data) {
const result = await provider.call({
to: to,
data: data
});

return result;
}

// Simulate transaction without sending
async function simulateTransaction(from, to, value, data) {
try {
const result = await provider.call({
from: from,
to: to,
value: value,
data: data,
gasLimit: 3000000 // High limit for simulation
});

return { success: true, result: result };
} catch (error) {
return { success: false, error: error.message };
}
}

Common Use Cases

1. DeFi Price Queries

// Trader Joe Pool Price Query (Avalanche native DEX)
async function getPoolPrice(poolAddress) {
const poolABI = [
"function getReserves() view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)",
"function token0() view returns (address)",
"function token1() view returns (address)"
];

const pool = new Contract(poolAddress, poolABI, provider);

const [reserves, token0, token1] = await Promise.all([
pool.getReserves(),
pool.token0(),
pool.token1()
]);

// Calculate price ratio
const price = Number(reserves.reserve1) / Number(reserves.reserve0);

return {
token0: token0,
token1: token1,
price: price,
reserve0: reserves.reserve0.toString(),
reserve1: reserves.reserve1.toString()
};
}

2. Multi-Contract Queries

// Batch multiple contract calls using Avalanche Multicall
async function multicall(calls) {
const multicallABI = [
"function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)"
];

const multicallAddress = "0xcA11bde05977b3631167028862bE2a173976CA11"; // Multicall3 on Avalanche
const multicall = new Contract(multicallAddress, multicallABI, provider);

const results = await multicall.aggregate(calls);
return results.returnData;
}

3. AVAX Balance and Token Queries

// Check both AVAX and token balances
async function getWalletBalances(walletAddress, tokenAddresses) {
// Get native AVAX balance
const avaxBalance = await provider.getBalance(walletAddress);

// Get token balances
const tokenBalances = [];
for (const tokenAddr of tokenAddresses) {
try {
const token = new Contract(tokenAddr, ERC20_ABI, provider);
const [balance, symbol, decimals] = await Promise.all([
token.balanceOf(walletAddress),
token.symbol(),
token.decimals()
]);

tokenBalances.push({
address: tokenAddr,
symbol: symbol,
balance: balance.toString(),
formatted: (Number(balance) / Math.pow(10, decimals)).toFixed(4)
});
} catch (error) {
console.error(`Error fetching token ${tokenAddr}:`, error);
}
}

return {
avax: {
balance: avaxBalance.toString(),
formatted: formatEther(avaxBalance)
},
tokens: tokenBalances
};
}

Error Handling

Error CodeDescriptionSolution
-32000Execution revertedCheck function requirements
-32602Invalid parametersVerify data encoding
-32015VM execution errorCheck contract logic
async function safeCall(to, data) {
try {
const result = await provider.call({ to, data });
return { success: true, data: result };
} catch (error) {
if (error.message.includes('revert')) {
// Try to decode revert reason
const reason = error.data?.replace('0x08c379a0', '');
if (reason) {
const decoded = ethers.utils.toUtf8String('0x' + reason.slice(8));
return { success: false, error: decoded };
}
}
return { success: false, error: error.message };
}
}

Need help? Contact our support team or check the Avalanche documentation.