eth_call - Arc RPC Method
Execute smart contract calls without creating transactions on Arc. Essential for reading contract state for crossborder settlement, merchant payments, institutional clearing, and USDC-denominated financial applications.
Executes a new message call immediately without creating a transaction on Arc. Used for reading smart contract state.
Why Arc? Build on Circle's stablecoin-native Layer 1 where USDC is the gas token and BFT consensus gives sub-second deterministic finality with USDC as the native gas token, sub-second irreversible finality, an EWMA-smoothed fee market with a 20 Gwei floor, and EIP-7708 Transfer logs for native value movement.
When to Use This Method
The eth_call method serves these key scenarios for payment platforms, stablecoin issuers, exchange and treasury teams, and Solidity developers building on Arc:
- Read smart contract state - Execute view and pure functions to query token balances, DeFi positions, and protocol data without spending gas
- Simulate transactions - Test contract interactions before submitting them on-chain, avoiding failed transactions and wasted gas costs
- Multi-call aggregator queries - Batch multiple read calls into a single request using multicall contracts, reducing API overhead on Arc
- MEV and arbitrage analysis - Simulate transaction bundles to evaluate profitable opportunities before execution on crossborder settlement, merchant payments, institutional clearing, and USDC-denominated financial applications
Common Use Cases
1. Read ERC20 Token Balance
Query an ERC20 token contract to retrieve the balance for a specific wallet address using the balanceOf(address) function selector encoded as calldata. The selector is derived from the first 4 bytes of keccak256("balanceOf(address)"), followed by the 32-byte zero-padded address argument.
import { JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const tokenAddress = '0x3600000000000000000000000000000000000000';
const walletAddress = '0x3600000000000000000000000000000000000000';
const balanceSelector = '0x70a08231' + walletAddress.slice(2).padStart(64, '0');
async function getTokenBalance() {
const result = await provider.call({
to: tokenAddress,
data: balanceSelector
});
console.log('Balance (raw):', BigInt(result).toString());
return result;
}
getTokenBalance();2. Query DeFi Protocol State
Read protocol reserves, price oracles, or user positions from DeFi contracts on Arc. Each protocol exposes view functions that let you inspect pool state without modifying it - ideal for building analytics dashboards and trading bots.
import { JsonRpcProvider, Interface } from 'ethers';
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const poolAbi = [
'function getReserves() view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestamp)'
];
const poolInterface = new Interface(poolAbi);
const poolAddress = '0x3600000000000000000000000000000000000000';
async function getPoolReserves() {
const data = poolInterface.encodeFunctionData('getReserves');
const result = await provider.call({ to: poolAddress, data });
const decoded = poolInterface.decodeFunctionResult('getReserves', result);
console.log('Reserve 0:', decoded[0].toString());
console.log('Reserve 1:', decoded[1].toString());
return decoded;
}
getPoolReserves();3. Simulate a Swap Before Execution
Before committing a token swap, call the router contract's quote function to calculate the expected output. This lets you validate slippage tolerance and compare rates across DEXes without risking gas on a failed trade.
import { JsonRpcProvider, Interface, parseEther } from 'ethers';
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const routerAddress = '0x3600000000000000000000000000000000000000';
const routerAbi = [
'function getAmountsOut(uint amountIn, address[] calldata path) view returns (uint[] amounts)'
];
const routerInterface = new Interface(routerAbi);
async function simulateSwap(amountIn, tokenIn, tokenOut) {
const data = routerInterface.encodeFunctionData('getAmountsOut', [
parseEther(amountIn),
[tokenIn, tokenOut]
]);
const result = await provider.call({ to: routerAddress, data });
const decoded = routerInterface.decodeFunctionResult('getAmountsOut', result);
console.log('Expected output:', decoded[0][1].toString());
return decoded[0][1];
}
simulateSwap('1.0', '0xTokenA...', '0xTokenB...');Best Practices
- Use
latestfor current-state reads andpendingfor pre-confirmation simulation on Arc - Encode function selectors correctly: take the first 4 bytes of the keccak256 hash of the function signature
- Handle revert errors gracefully by parsing the revert reason from the error response data
- For batch reads, use multicall contracts to combine multiple
eth_callrequests into a single RPC call eth_calldoes not consume gas, making it ideal for unlimited read queries on Arc
USDC balances on Arc
Arc's native token is USDC, not ETH, and the same balance is exposed through two interfaces with different precision:
| Interface | Where you read it | Decimals |
|---|---|---|
| Native | eth_getBalance, msg.value, address.balance | 18 |
| ERC-20 | balanceOf on 0x3600000000000000000000000000000000000000 | 6 |
Divide the native value by 1012 to display it as USDC. These are not two assets and there is no WETH-style wrapper, so never add the two values together or pair them against each other in pool math.
Credit and record balances from the 18-decimal native value. The ERC-20 view truncates sub-USDC fractions, so crediting from balanceOf records less than was actually transferred. A balanceOf of 0 does not mean the account is empty: a residual native balance below 1012 wei truncates to zero in the 6-decimal view.
See Arc's stablecoin native model for the full two-interface table.
Code Examples
Error Handling
| Error Code | Message | Description |
|---|---|---|
| -32000 | Execution reverted | Contract function reverted |
| -32602 | Invalid parameters | Invalid data encoding |
| -32015 | VM execution error | Contract logic error |
Related Methods
eth_estimateGas- Estimate gas for transactioneth_sendRawTransaction- Send actual transaction
eth_feeHistory
Get historical gas fee data on Arc including base fees and priority fee percentiles. Essential for gas price prediction, fee estimation UIs, and network congestion monitoring.
eth_getLogs
Query event logs on Arc. Essential for indexing crossborder settlement, merchant payments, institutional clearing, and USDC-denominated financial applications on Circle's stablecoin-native Layer 1 where USDC is the gas token and BFT consensus gives sub-second deterministic finality.