eth_getLogs - Arc RPC Method
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.
Returns an array of all logs matching a given filter object on Arc.
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_getLogs method serves these key scenarios for payment platforms, stablecoin issuers, exchange and treasury teams, and Solidity developers building on Arc:
- Index smart contract events - Track transfers, swaps, and approvals emitted by any contract on Arc for use in indexed databases
- Monitor DeFi protocol activity - Watch for liquidity changes, price updates, and position events in real time across crossborder settlement, merchant payments, institutional clearing, and USDC-denominated financial applications
- Build analytics pipelines - Extract on-chain event data for dashboards, reporting, and trend analysis on Arc
- Track token holder activity - Monitor whale movements and large transfers to detect significant market activity
Common Use Cases
1. Monitor ERC20 Transfer Events
Track all transfer events for a specific token contract within a defined block range. The Transfer event signature hash filters for exactly this event type, and you can optionally filter by sender or recipient address using indexed topics.
import { JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const tokenAddress = '0x3600000000000000000000000000000000000000';
const transferTopic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
async function getRecentTransfers(fromBlock, toBlock) {
const logs = await provider.getLogs({
address: tokenAddress,
fromBlock: fromBlock,
toBlock: toBlock,
topics: [transferTopic]
});
const transfers = logs.map(log => ({
from: '0x' + log.topics[1].slice(26),
to: '0x' + log.topics[2].slice(26),
amount: BigInt(log.data).toString(),
txHash: log.transactionHash
}));
console.log(`Found ${transfers.length} transfers`);
return transfers;
}
const recentTransfers = await getRecentTransfers('latest', 'latest');2. Track DEX Swap Events
Capture swap events from a DEX to analyze trading volume, price impact, and liquidity flow. Each swap emits event parameters that include the amounts and addresses involved - ideal for building price feeds and volume aggregators.
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const SWAP_TOPIC = '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822';
const pairAddress = '0x3600000000000000000000000000000000000000';
async function getRecentSwaps(fromBlock, toBlock) {
const logs = await provider.getLogs({
address: pairAddress,
fromBlock: fromBlock,
toBlock: toBlock,
topics: [SWAP_TOPIC]
});
return logs.map(log => ({
sender: '0x' + log.topics[1].slice(26),
to: '0x' + log.topics[2].slice(26),
amount0In: BigInt('0x' + log.data.slice(2, 66)).toString(),
amount1In: BigInt('0x' + log.data.slice(66, 130)).toString(),
amount0Out: BigInt('0x' + log.data.slice(130, 194)).toString(),
amount1Out: BigInt('0x' + log.data.slice(194, 258)).toString(),
txHash: log.transactionHash
}));
}
const swaps = await getRecentSwaps('latest', 'latest');
console.log(`Found ${swaps.length} swaps`);3. Multi-Contract Event Aggregation
Query events from multiple contracts simultaneously by passing an array of addresses. This is useful for cross-protocol analytics - aggregating lending, borrowing, and liquidation events from multiple DeFi protocols in a single query on Arc.
const provider = new JsonRpcProvider('https://api-arc-mainnet.n.dwellir.com/YOUR_API_KEY');
const contracts = [
'0xContractA...',
'0xContractB...',
'0xContractC...'
];
const EVENT_TOPIC = '0x...';
async function aggregateEvents(fromBlock, toBlock) {
const logs = await provider.getLogs({
address: contracts,
fromBlock: fromBlock,
toBlock: toBlock,
topics: [EVENT_TOPIC]
});
const grouped = {};
for (const log of logs) {
const contract = log.address;
if (!grouped[contract]) grouped[contract] = [];
grouped[contract].push(log);
}
for (const [contract, events] of Object.entries(grouped)) {
console.log(`${contract}: ${events.length} events`);
}
return grouped;
}
aggregateEvents('0x100000', '0x1000c7');Block-range limits
Each request can cover up to 500 blocks on Developer or 10,000 on Growth, Scale, and Enterprise by default.
Free and Starter do not include eth_getLogs.
Both endpoint blocks count: toBlock - fromBlock + 1. Address and topic filters do not increase this allowance.
Individual networks may enforce lower limits.
Supply block bounds or a blockHash. Do not combine a non-null hash with non-null bounds.
Missing or null bounds default to latest. Equal tags request one block.
Numeric ranges ending at latest or pending use the observed endpoint head plus a 6-block margin for validation.
Use explicit numeric bounds for exact pagination. Mixed ranges involving safe or finalized are rejected.
The earliest tag means block zero.
Range errors return HTTP 200 with a JSON-RPC error body.
Oversized ranges use code -32005, invalid bounds use -32602, and an unavailable endpoint head uses -32000.
WebSocket uses the same JSON-RPC codes.
The same range validation applies to eth_newFilter.
A rejected log query rejects its entire batch before any member executes.
See request examples and pagination guidance.
Best Practices
- Split historical ranges into chunks within your plan limit, using smaller chunks if Arc enforces a lower limit.
- Use topic filters for efficient log filtering: the node filters at the storage level before returning results
- For high-volume monitoring, use
eth_newFilterwith polling instead of repeatedly callingeth_getLogs - Store the last processed block number for incremental indexing rather than re-scanning the full chain
- Budget for the split: each chunk is a separate request billed as one response at the standard 1 credit, so a wide backfill costs proportionally more on a plan with a smaller limit
- For long backfills on Arc, follow the
eth_getLogslimits guide to size windows from the error messages instead of guessing
Native USDC Transfer logs on Arc
On a standard EVM chain a plain native send emits no log. Arc implements EIP-7708, so native USDC movement emits a standard ERC-20 Transfer log from a system address. That covers plain sends, contract endowments, self-destruct transfers, and precompile-backed operations.
That means USDC activity reaches you from two emitters with different precision:
| Source | Emitter address | Decimals |
|---|---|---|
| Native USDC (system, EIP-7708) | 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE | 18 |
ERC-20 USDC (NativeFiatToken) | 0x3600000000000000000000000000000000000000 | 6 |
Both use the standard Transfer topic0 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, so filtering on topic0 alone is not enough. Filter on the emitter address as well. An ERC-20 transfer() call produces a log from both emitters for the same movement; counting both double-counts the transfer. A plain native send produces only the system log.
Gas deductions and block rewards are not emitted as Transfer events. Derive gas cost from the receipt (gasUsed × effectiveGasPrice) and attribute block rewards via block.miner.
See Arc's USDC system events reference for the full event catalogue.
Code Examples
Error Handling
| Error Code | Message | Description |
|---|---|---|
| -32005 | Plan block-range limit exceeded, or a stricter native limit | Reduce the range within your plan and network limits |
| -32602 | Invalid params | Invalid filter parameters |
| -32000 | Endpoint head unavailable | Retry shortly or use explicit numeric bounds |
Related Methods
eth_newFilter- Create a filter for logseth_getFilterChanges- Poll filter for new logs
eth_call
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.
eth_newFilter
Create an event log filter on Arc. Essential for event monitoring, contract activity tracking, and DeFi event streaming for crossborder settlement, merchant payments, institutional clearing, and USDC-denominated financial applications.