Historischen EVM-State innerhalb unterstützter Fenster abfragen

Unterscheiden Sie authentifizierte State-Fenster, schlüssellosen Verlauf und Log-Spannen. Wählen Sie einen festen Block für eth_call und diagnostizieren Sie state_window-Fehler.

Historische eth_call-Aufrufe hängen vom State-Fenster der Chain ab, nicht von ihrem eth_getLogs-Blockbereichslimit. Prüfen Sie das State-Fenster, den Authentifizierungsmodus des Endpunkts und den Zielblock, bevor Sie einen früheren Contract-Wert auslesen.

Drei verschiedene historische Limits

Feld in GET /v1/chainsWas es steuertWas zu prüfen ist
state_window_blocksWie weit authentifizierte State-Leseoperationen wie eth_call, eth_getBalance, eth_getCode und eth_getStorageAt zurückreichen könnenBei Chain-Head H und deklariertem Fenster W liegt ein nummerierter Block, der älter als H − W ist, außerhalb des Fensters. Prüfen Sie auch methods.allow und methods.deny.
public.history_blocksHistorische Blockreferenzen über die schlüssellose public.urlNutzen Sie nur public.methods. Bei State-Leseoperationen gilt das kleinere aus öffentlichem Verlauf und deklariertem State-Fenster.
max_logs_block_rangeDie Anzahl der Blöcke in einer authentifizierten eth_getLogs-AnfrageZählen Sie toBlock − fromBlock + 1. Eine zulässige Spanne belegt nicht, dass alter Contract-State oder alte Logs verfügbar sind.

Diese Limits werden in Blöcken angegeben, nicht in Tagen. Ein null oder nicht deklariertes State-Fenster belegt keine Archiv-Abdeckung. Die schlüssellose Methodenverfügbarkeit ist von der authentifizierten Methodenverfügbarkeit getrennt: Eine Log-Spanne allein aktiviert kein öffentliches eth_getLogs.

State-Fenster pro Chain vergleichen

Die Tabelle zeigt veröffentlichte State-Fenster, den schlüssellosen Verlauf, Log-Spannen und deklarierte Data-API-Datensätze aus dem öffentlichen Snapshot. Für eine aktuelle Anfrage lesen Sie GET /v1/chains und GET /v1/status erneut aus.

Entwickler und KI-Agenten sollten Zustandsfenster und Log-Abfragespannen separat prüfen. Ein Null-Zustandsfenster garantiert keine Archiv-Abdeckung. Der öffentliche Verlauf gilt nur für die deklarierten öffentlichen Methoden.

ChainChain-SlugAuthentifiziertes Zustandsfenster: state_window_blocks (Blöcke)Schlüsselloser Verlauf: public.history_blocks (Blöcke)Authentifizierte Log-Abfragespanne: max_logs_block_range (Blöcke)Deklarierte Data-API-Datensätze
Arbitrum Onearb_mainnet6,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Basebase_mainnet10,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
BNB Smart Chainbsc_mainnet1001001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Ethereumeth_mainnet250,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Ethereum Sepoliaeth_sepoliaNicht deklariert1,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
HyperEVMhyperevm_mainnetNicht deklariert1,0001,000blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, freshness
Polygonpolygon_mainnet1261261,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Robinhood Chainrobinhood_mainnet9009001,000blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, dex_swaps, dex_prices, stocks, traces, freshness
Robinhood Chain Testnetrobinhood_testnet1,0231,0001,000Data API nicht verfügbar

GET /v1/chains · Stichprobe (UTC):

GET /v1/status · Stichprobe (UTC):

Block-Tag auswählen

Verwenden Sie latest für den aktuellen Wert. Für einen historischen Vergleich lesen Sie eth_blockNumber einmal aus und wandeln Sie eine gewählte Blocknummer in eine hexadezimale Größe wie 0x18efa2f um. Halten Sie diese Nummer für jeden Aufruf im Vergleich fest; wiederholte latest-Aufrufe können unterschiedliche Blöcke verwenden.

Bei State-Leseoperationen geben earliest, safe und finalized unter der State-Window-Richtlinie -32011 zurück. Wählen Sie stattdessen eine explizite Blocknummer innerhalb des deklarierten Fensters. Ein Block-Hash-Format ist kein Weg, um zusätzlichen Verlauf zu erhalten: Schlüssellose State-Leseoperationen weisen ihn ab, und eine authentifizierte Anfrage hängt weiterhin vom verfügbaren State ab.

Eine Blocknummer kann sich nach einer Reorganisation auf einen anderen Block beziehen. Erfassen Sie den Block-Hash mit eth_getBlockByNumber, wenn Sie den Block des Ergebnisses eindeutig identifizieren müssen. Eine Nummer innerhalb des Fensters setzt zudem eine synchronisierte Chain und einen existierenden Contract auf dieser Höhe voraus.

Contract-Leseoperation bei festem Block

Auf Ethereum stellt WETH unter 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 die Methode decimals() mit dem Selektor 0x313ce567 bereit. Ein schlüsselloser Aufruf, der am 2026-10-08 (UTC) bei Block 0x18efa2f als Stichprobe ausgeführt wurde, gab HTTP 200 mit diesem Ergebnis zurück:

Anfrage an die public.url der Chain:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "eth_call",
  "params": [
    { "to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "data": "0x313ce567" },
    "0x18efa2f"
  ]
}

Antwort:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "0x0000000000000000000000000000000000000000000000000000000000000012"
}

Die ABI-codierte Ganzzahl ist 18. Das Ergebnis ist ein decimals-Wert, kein Kontostand, und belegt keine Verfügbarkeit auf anderen Höhen. Dieser feste Block fällt mit der Zeit aus einem begrenzten Fenster heraus; verwenden Sie einen aktuellen Block, wenn Sie das folgende Beispiel später ausführen.

Speichern Sie das Beispiel als historical-state.mjs und führen Sie node historical-state.mjs mit Node.js 24 oder höher und gesetzter Umgebungsvariable BLOCKVECTRA_API_KEY aus. Es nutzt den authentifizierten Endpunkt, behält denselben Contract und dieselben Calldata bei und vergleicht latest, einen festen aktuellen Block und einen Block außerhalb des veröffentlichten authentifizierten Fensters. Jede Ausgabe enthält den tatsächlichen HTTP-Status und den JSON-RPC-Body; ein HTTP 200 kann dennoch einen Fehler enthalten. Bei einer unerwarteten Antwort bricht es ab, anstatt diese als erfolgreiche Leseoperation zu behandeln.

const key = process.env.BLOCKVECTRA_API_KEY;
if (!key) throw new Error('Set BLOCKVECTRA_API_KEY');
const chainsUrl = 'https://api.blockvectra.com/v1/chains';
const catalogResponse = await fetch(chainsUrl, { signal: AbortSignal.timeout(15_000) });
if (!catalogResponse.ok) throw new Error(`Chains HTTP ${catalogResponse.status}`);
const catalog = await catalogResponse.json();
const chain = catalog.chains.find(item => item.chain === 'eth_mainnet');
const matches = (method, pattern) => pattern.endsWith('*')
  ? method.startsWith(pattern.slice(0, -1)) : method === pattern;
if (!chain?.jsonrpc || !['eth_call', 'eth_blockNumber'].every(method =>
  chain.methods?.allow?.some(pattern => matches(method, pattern)) &&
  !chain.methods?.deny?.some(pattern => matches(method, pattern)))) {
  throw new Error('Required methods are unavailable');
}
const window = chain.state_window_blocks;
if (!Number.isSafeInteger(window) || window < 10) {
  throw new Error('This example needs a declared state window of at least 10 blocks');
}
const rpcUrl = new URL('./eth_mainnet', chainsUrl).href;
let id = 0;
async function rpc(method, params) {
  const response = await fetch(rpcUrl, {
    method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15_000),
    headers: { 'Content-Type': 'application/json', 'x-api-key': key },
    body: JSON.stringify({ jsonrpc: '2.0', id: ++id, method, params }),
  });
  return { http: response.status, body: await response.json() };
}
const headResponse = await rpc('eth_blockNumber', []);
if (headResponse.http !== 200 || headResponse.body.error ||
    !/^0x[0-9a-f]+$/i.test(headResponse.body.result ?? '')) {
  throw new Error(`Cannot read head: ${JSON.stringify(headResponse)}`);
}
const head = BigInt(headResponse.body.result);
if (head <= BigInt(window)) throw new Error('Head is too low for an out-of-window block');
const hex = value => `0x${value.toString(16)}`;
const fixedBlock = hex(head - 10n);
const outsideBlock = hex(head - BigInt(window) - 1n);
const call = { to: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', data: '0x313ce567' };
for (const block of ['latest', fixedBlock, outsideBlock]) {
  const reply = await rpc('eth_call', [call, block]);
  console.log(JSON.stringify({ head: hex(head), block, ...reply }));
  if (block === outsideBlock) {
    if (reply.http !== 200 || reply.body.error?.code !== -32011 ||
        reply.body.error?.data?.reason !== 'state_window') {
      throw new Error('Expected state_window; inspect the actual response above');
    }
  } else if (reply.http !== 200 || reply.body.error ||
      reply.body.result !== '0x0000000000000000000000000000000000000000000000000000000000000012') {
    throw new Error('Expected the WETH decimals result; inspect the actual response above');
  }
}

Die oben aufgezeichnete Antwort verwendet public.url; das Skript verwendet einen API key. Um eine schlüssellose Leseoperation durchzuführen, übernehmen Sie die URL direkt aus public.url, lassen Sie den Key weg und wählen Sie einen Block sowohl innerhalb von public.history_blocks als auch innerhalb des State-Fensters. Eine Änderung der Authentifizierung kann den zulässigen Verlauf verändern, selbst für denselben Contract und dieselben Calldata.

Fehler außerhalb des Fensters diagnostizieren

Auf demselben schlüssellosen Endpunkt ergab ein am 2026-10-08 (UTC) als Stichprobe ausgeführter Aufruf, bei dem lediglich der Zielblock auf 0x18ef650 (und die Anfrage-ID) geändert wurde, HTTP 200 mit error.code: -32011, error.data.reason: state_window und error.data.retryable: false. Die Nachricht lautete block reference is outside the public history window. Dies ist ein Fehler des öffentlichen Verlaufs; der authentifizierte Endpunkt hat sein eigenes State-Fenster.

Verwenden Sie diese Felder aus dem state_window-Fehlereintrag, um den Fehler zu erkennen, anstatt sich auf eine bestimmte Fensternummer in der Nachricht zu verlassen:

FeldDokumentierter Wert oder Bedeutung
HTTP-Status200; prüfen Sie den JSON-RPC-error auch bei erfolgreichem HTTP-Status
error.code-32011
error.messageAuthentifizierte State-Window-Fehler beschreiben die Anzahl der zuletzt unterstützten Blöcke; Fehler des öffentlichen Verlaufs können eine andere Nachricht verwenden
error.data.reasonstate_window
error.data.docs_urlLink zur state_window-Erklärung im Fehlerkatalog
error.data.retryablefalse: Ein erneutes Senden derselben Anfrage zu einem späteren Zeitpunkt stellt keinen älteren State wieder her

Wählen Sie einen neueren nummerierten Block oder nutzen Sie latest, wenn die Aufgabe den aktuellen Wert benötigt. Das Verringern einer eth_getLogs-Spanne stellt keinen historischen eth_call-State wieder her. Andere Gründe für -32011 erfordern unterschiedliche Maßnahmen: range_not_indexed erfordert einen abgedeckten Bereich; history_not_ready erlaubt Wiederholungsversuche, nachdem die Indexierung aufholt. Prüfen Sie error.data.reason, nicht nur den numerischen Code.

Zugrunde liegender State kann auch mit -32000 nicht verfügbar sein oder bereinigter (pruned) Blockverlauf mit 4444; siehe den Fehlerkatalog. Wiederholen Sie eine Anfrage für einen alten Block nicht unverändert und gehen Sie nicht davon aus, dass ein größeres deklariertes Fenster jede Antwort garantiert.

Nächste Abfrage auswählen

Eine vollständige Workload-Checkliste und Selbsttests finden Sie unter Auswahl eines RPC-Providers.

Wenn Sie einen Provider für wiederholte Contract-Leseoperationen auswählen, vergleichen Sie Tages- und Zyklusbudgets für EVM-Leseoperationen. Prüfen Sie zuerst die erforderlichen historischen Blöcke und planen Sie anschließend die tägliche Verteilung und den Durchsatz der Aufgabe; das Einpassen in ein Guthabenbudget garantiert keine State-Abdeckung.

Bestätigen Sie beim Vergleich von Providern für historische Leseoperationen zunächst, dass beide den Zielblock bedienen können. Der Vergleich von Mehraufwand für vollständige Anfragen vergleicht zusätzliche RU-Preise mit methodenbasierten Kosten, trennt enthaltene Kontingente von zusätzlicher Nutzung und erläutert Full- versus Archive-Abrechnungsklassen.

Für frühere indexierte Blöcke, Transaktionen, Transfers oder andere Datensätze prüfen Sie die in der Tabelle deklarierten Data-API-Datensätze und die Data-API-Referenz. Indexierte Datensätze bieten keine beliebige historische Contract-Ausführung und bedeuten nicht, dass jede Chain über historische Kontostände verfügt.

Zuletzt aktualisiert:

Auf dieser Seite