Reading Contract State at a Past Block Using Wagmi
Source: Dev.to
The Core Idea
Ethereum (and EVM chains in general) allow you to query contract state as it existed at any historical block. If a contract method is view or pure, you can read it at a past block without any special indexing infrastructure. Wagmi exposes this directly through the blockNumber parameter.
The Scenario: Chainlink Price at a Past Time
Chainlink price feeds expose methods like latestRoundData(). If you already know the round ID, you can query it directly, but sometimes you only know the timestamp. A reliable approach is to convert the timestamp you care about into a block number and then read the contract at that block.
import { readContract } from '@wagmi/core';
import { parseAbi } from 'viem';
const aggregatorAbi = parseAbi([
'function latestRoundData() view returns (uint80,int256,uint256,uint256,uint80)'
]);
const priceFeedAddress = '0x...';
const blockNumber = 18_500_000n; // block corresponding to the desired timestamp
const data = await readContract({
address: priceFeedAddress,
abi: aggregatorAbi,
functionName: 'latestRoundData',
blockNumber,
});
Wagmi asks the RPC node: “Pretend the chain is at block 18,500,000. What does this function return?” The result is exactly what the Chainlink contract would have returned at that block, not the current value.
Why This Works
Ethereum nodes store historical state. When you specify a blockNumber, the node executes the call against that historical snapshot—no subgraph or external indexer required, just deterministic blockchain state.
Mapping Time to Block
You usually know a timestamp rather than a block number. Typical approaches to obtain the corresponding block:
- Binary search blocks by timestamp using
eth_getBlockByNumber. - Helper API (e.g., a block‑explorer service) once, then cache the mapping.
- Archive node for full accuracy.
Once you have the block number, Wagmi handles the rest.
Frontend Example with React
If you’re using Wagmi hooks in a React app:
import { useReadContract } from 'wagmi';
const { data } = useReadContract({
address: priceFeedAddress,
abi: aggregatorAbi,
functionName: 'latestRoundData',
blockNumber: 18_500_000n,
});
Use Cases
- Historical price charts
- Auditing past contract states
- Any feature that requires on‑chain data from a specific point in time
Important Caveats
- RPC support: Not all RPC providers expose historical state; an archive node is often required.
- Performance: Queries to old blocks can be slower than current‑state calls.
Final Thoughts
Wagmi doesn’t heavily advertise this feature, but once you realize you can read contract state at any point in time, many problems become simpler. Leveraging blockNumber lets you retrieve accurate on‑chain data from the past without relying on off‑chain snapshots or indexers.