# Interroger l'état historique de l'EVM dans les fenêtres prises en charge

> Source: https://docs.blockvectra.com/fr/guides/evm-historical-state/

`eth_call` historique dépend de la fenêtre d'état de la chaîne, et non de sa limite de plage de blocs `eth_getLogs`. Vérifiez la fenêtre d'état, le mode d'authentification de l'endpoint et le bloc cible avant de lire une valeur de contrat antérieure.

## Trois limites d'historique différentes

| Champ dans [GET /v1/chains](https://api.blockvectra.com/v1/chains) | Ce qu'il contrôle                                                                                                                                        | Ce qu'il faut vérifier                                                                                                                                                     |
| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state_window_blocks`                                              | Jusqu'où dans le passé les lectures d'état authentifiées telles que `eth_call`, `eth_getBalance`, `eth_getCode` et `eth_getStorageAt` peuvent interroger | Avec la tête `H` et la fenêtre déclarée `W`, un bloc numéroté antérieur à `H − W` se trouve en dehors de la fenêtre. Vérifiez également `methods.allow` et `methods.deny`. |
| `public.history_blocks`                                            | Références de blocs historiques via le `public.url` sans clé                                                                                             | Utilisez uniquement `public.methods`. Pour les lectures d'état, la plus petite valeur entre l'historique public et la fenêtre d'état déclarée s'applique.                  |
| `max_logs_block_range`                                             | Le nombre de blocs dans une seule requête `eth_getLogs` authentifiée                                                                                     | Comptez `toBlock − fromBlock + 1`. Une plage autorisée n'établit pas que l'état ancien du contrat ou les logs sont disponibles.                                            |

Ces limites sont exprimées en blocs, et non en jours. Une fenêtre d'état `null` ou non déclarée n'établit pas une couverture d'archive. La disponibilité des méthodes sans clé est distincte de celle des méthodes authentifiées : une plage de logs à elle seule n'active pas `eth_getLogs` en accès public.

## Comparer les fenêtres d'état par chaîne

Le tableau affiche les fenêtres d'état publiées, l'historique sans clé, les plages de logs et les jeux de données Data API déclarés à partir de l'instantané public. Pour une requête immédiate, lisez à nouveau [GET /v1/chains](https://api.blockvectra.com/v1/chains) et [GET /v1/status](https://api.blockvectra.com/v1/status).

Les développeurs et les agents IA doivent vérifier séparément les fenêtres d'état et les plages de requêtes de logs. Une fenêtre d'état null n'établit pas une couverture d'archive complète. L'historique public s'applique uniquement aux méthodes publiques déclarées.

| Chaîne | Slug de chaîne | Fenêtre d'état authentifiée : state_window_blocks (blocs) | Historique sans clé : public.history_blocks (blocs) | Plage de requêtes de logs authentifiée : max_logs_block_range (blocs) | Jeux de données Data API déclarés |
| --- | --- | --- | --- | --- | --- |
| Arbitrum One | `arb_mainnet` | 6,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Base | `base_mainnet` | 10,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| BNB Smart Chain | `bsc_mainnet` | 100 | 100 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Ethereum | `eth_mainnet` | 250,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Ethereum Sepolia | `eth_sepolia` | Non déclaré | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| HyperEVM | `hyperevm_mainnet` | Non déclaré | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, freshness |
| Polygon | `polygon_mainnet` | 126 | 126 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Robinhood Chain | `robinhood_mainnet` | 900 | 900 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, dex_swaps, dex_prices, stocks, traces, freshness |
| Robinhood Chain Testnet | `robinhood_testnet` | 1,023 | 1,000 | 1,000 | Data API indisponible |

[GET /v1/chains](https://api.blockvectra.com/v1/chains) · Échantillonné (UTC): 2026-10-09

[GET /v1/status](https://api.blockvectra.com/v1/status) · Échantillonné (UTC): 2026-10-09

## Choisir un tag de bloc

Utilisez `latest` pour la valeur actuelle. Pour une comparaison historique, lisez `eth_blockNumber` une fois et convertissez le numéro de bloc choisi en une quantité hexadécimale telle que `0x18efa2f`. Conservez ce numéro fixe pour chaque appel de la comparaison ; des appels `latest` répétés peuvent utiliser des blocs différents.

Pour les lectures d'état, `earliest`, `safe` et `finalized` renvoient `-32011` selon la politique de fenêtre d'état. Choisissez plutôt un numéro de bloc explicite dans la fenêtre déclarée. L'utilisation d'un hash de bloc n'est pas un moyen d'obtenir un historique supplémentaire : les lectures d'état sans clé la rejettent, et une requête authentifiée dépend toujours de l'état disponible.

Un numéro de bloc peut faire référence à un bloc différent après une réorganisation. Enregistrez le hash du bloc avec `eth_getBlockByNumber` si vous devez identifier le bloc du résultat. Un numéro dans la fenêtre nécessite également une chaîne synchronisée et un contrat existant à cette hauteur.

## Lecture de contrat à bloc fixe

Sur Ethereum, le WETH à l'adresse `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` expose `decimals()` avec le sélecteur `0x313ce567`. Un appel sans clé échantillonné le 2026-10-08 (UTC) au bloc `0x18efa2f` a renvoyé HTTP 200 avec ce résultat :

Requête vers le `public.url` de la chaîne :

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

Réponse :

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

L'entier encodé en ABI est 18. Le résultat est une valeur de décimales, et non un solde, et n'établit pas la disponibilité à d'autres hauteurs. Ce bloc fixe sortira d'une fenêtre bornée au fil du temps ; utilisez un bloc récent lors de l'exécution ultérieure de l'exemple suivant.

Enregistrez l'exemple sous le nom `historical-state.mjs` et exécutez `node historical-state.mjs` avec Node.js 24 ou une version ultérieure et votre variable d'environnement `BLOCKVECTRA_API_KEY` définie. Il utilise l'endpoint authentifié, conserve le même contrat et calldata, et compare `latest`, un bloc récent fixe et un bloc en dehors de la fenêtre authentifiée publiée. Chaque sortie comprend le statut HTTP réel et le corps JSON-RPC ; un statut HTTP 200 peut toujours contenir une erreur. Il s'arrête en cas de réponse inattendue au lieu de la traiter comme une lecture réussie.

```js
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');
  }
}
```

La réponse enregistrée ci-dessus utilise `public.url` ; le script utilise une clé API. Pour effectuer une lecture sans clé, prenez l'URL directement depuis `public.url`, omettez la clé et choisissez un bloc situé dans `public.history_blocks` ainsi que dans la fenêtre d'état. Changer de mode d'authentification peut modifier l'historique autorisé, même pour le même contrat et calldata.

## Diagnostiquer une erreur de fenêtre d'état dépassée

Sur le même endpoint sans clé, un appel échantillonné le 2026-10-08 (UTC) en changeant uniquement le bloc cible en `0x18ef650` (et l'ID de requête) a renvoyé HTTP 200 avec `error.code: -32011`, `error.data.reason: state_window` et `error.data.retryable: false`. Son message était `block reference is outside the public history window`. Il s'agit d'un échec lié à l'historique public ; l'endpoint authentifié possède sa propre fenêtre d'état.

Utilisez ces champs issus de l'[entrée d'erreur state\_window](https://docs.blockvectra.com/fr/errors/#state_window) pour reconnaître l'échec plutôt que de vous fier à un numéro de fenêtre particulier dans le message :

| Champ                  | Valeur documentée ou signification                                                                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Statut HTTP            | `200` ; inspectez l'`error` JSON-RPC même lorsque la requête HTTP réussit                                                                                                       |
| `error.code`           | `-32011`                                                                                                                                                                        |
| `error.message`        | Les erreurs de fenêtre d'état authentifiée décrivent le nombre de blocs pris en charge les plus récents ; les erreurs d'historique public peuvent utiliser un message différent |
| `error.data.reason`    | `state_window`                                                                                                                                                                  |
| `error.data.docs_url`  | Lien vers l'explication de `state_window` dans le catalogue des erreurs                                                                                                         |
| `error.data.retryable` | `false` : envoyer la même requête ultérieurement ne restaure pas l'état plus ancien                                                                                             |

Choisissez un bloc numéroté plus récent ou utilisez `latest` si la tâche nécessite la valeur actuelle. Réduire une plage `eth_getLogs` ne permet pas de récupérer l'état historique de `eth_call`. D'autres motifs associés à `-32011` nécessitent des actions différentes : [range\_not\_indexed](https://docs.blockvectra.com/fr/errors/#range_not_indexed) exige une plage couverte ; [history\_not\_ready](https://docs.blockvectra.com/fr/errors/#history_not_ready) permet de réessayer après le rattrapage de l'indexation. Inspectez `error.data.reason`, et pas seulement le code numérique.

L'état sous-jacent peut également être indisponible avec `-32000`, ou l'historique des blocs élagué avec `4444` ; consultez le [catalogue des erreurs](https://docs.blockvectra.com/fr/errors/). Ne réessayez pas un bloc ancien sans modification et ne supposez pas qu'une fenêtre déclarée plus grande garantit chaque réponse.

## Choisir la requête suivante

Pour une liste de contrôle complète de la charge de travail et des auto-tests, commencez par [Comment choisir un fournisseur RPC](https://docs.blockvectra.com/fr/guides/choose-rpc-provider/).

Lors du choix d'un fournisseur pour des lectures de contrats répétées, [comparez les budgets quotidiens et de cycle pour les lectures EVM](https://docs.blockvectra.com/fr/guides/infura-alternative/). Vérifiez d'abord les blocs historiques requis, puis planifiez la répartition quotidienne et le débit de la tâche ; respecter un budget de crédits n'établit pas la couverture de l'état.

Lors de la comparaison de fournisseurs pour des lectures historiques, confirmez d'abord que les deux peuvent servir le bloc cible. La [comparaison des dépassements de requête complète](https://docs.blockvectra.com/fr/guides/chainstack-alternative/) compare les prix des RU supplémentaires avec les coûts basés sur les méthodes, sépare le quota inclus de l'utilisation excédentaire et explique les classes de facturation complète et d'archive.

Pour les blocs, transactions, transferts ou autres jeux de données indexés plus anciens, consultez les jeux de données Data API déclarés dans le tableau et la [référence de la Data API](https://docs.blockvectra.com/fr/api/data/). Les enregistrements indexés ne fournissent pas d'exécution arbitraire de contrat historique et n'impliquent pas que chaque chaîne dispose de soldes historiques.

* [Référence de la méthode eth\_call](https://docs.blockvectra.com/fr/api/json-rpc/methods/eth_call/) pour les paramètres d'appel et l'encodage de retour.
* [Plage de blocs eth\_getLogs et requêtes découpées](https://docs.blockvectra.com/fr/guides/getlogs-block-range/) pour l'historique des logs d'événements.
* [Configuration RPC personnalisée pour portefeuille](https://docs.blockvectra.com/fr/guides/wallet-custom-rpc/) pour les connexions de portefeuille et les clés dédiées.
* [Chaînes prises en charge](https://docs.blockvectra.com/fr/chains/) pour la disponibilité réseau et [tarification en CU](https://docs.blockvectra.com/fr/guides/reading-cu-pricing/) pour le coût des méthodes.
