Pour les développeurs / JSON-RPC

Écarts avec Ethereum

Pickle a la forme d'Ethereum, pas son équivalence. Voici la liste complète des endroits où un client standard recevra une réponse qu'il n'attendait pas, classée par le temps que chacun coûte à découvrir à la dure.

Les raisons de revert sont indécodables

error.data n'est jamais renseigné

A revert arrives as message text - "execution reverted: 0x<returndata>" - and error.data is absent.

Libraries decode custom errors and revert strings out of error.data, so on this chain they cannot. ethers and viem will both surface the raw message instead of a decoded error. If you need the reason, parse the hex out of the message yourself and decode it against your own ABI.

S'il vous faut la raison, les données de retour sont dans le texte du message et vous pouvez les décoder vous-même :

javascript
try {
  await client.readContract({ /* … */ });
} catch (err) {
  // "execution reverted: 0x08c379a0…"
  const hex = String(err.message).match(/0x[0-9a-fA-F]+/)?.[0];
  // Decode that hex against your own ABI's errors, or against Error(string).
}

Il n'y a pas d'état historique

eth_getBalance, eth_getTransactionCount, eth_getCode et eth_getStorageAt analysent l'adresse puis lisent le dernier instantané publié. Le paramètre de bloc est accepté et ignoré en silence - une demande de solde au bloc 100 n'échoue pas, elle répond avec le solde actuel.

eth_call et eth_estimateGas font de même, et ignorent en plus le gas, le gasPrice et le nonce que vous leur envoyez : la simulation tourne toujours à la limite de gas par bloc de 30 000 000 contre l'état le plus récent.

Celui-ci échoue en silence, et c'est pourquoi il est deuxième

Tout motif de type archive - lire un solde historique, rejouer l'état à un bloc passé, calculer un instantané - rend ici des réponses assurées, plausibles et fausses plutôt qu'une erreur. Lisez depuis l'explorateur pour tout ce qui est historique.

Les étiquettes de bloc s'effondrent

latest, pending, safe et finalized se résolvent toutes vers la même chose : la pointe conservée. Et earliest se résout vers le plus ancien bloc conservé, pas le bloc 0 - il avance donc à mesure que la fenêtre glisse.

Les objets EIP-1898 sont acceptés : { blockNumber } ou { blockHash }, un hash étant résolu par l'index et répondant null quand il n'est plus conservé. Tout le reste donne -32602 "block tag".

Un client qui distingue safe de finalized pour décider quand se fier à un résultat ne reçoit aucun signal de cette chaîne. La finalité est ici le règlement L1 et n'est pas du tout visible à travers ces étiquettes.

Racines et blooms sont à zéro

Sur les blocs comme sur les reçus, stateRoot, transactionsRoot et receiptsRoot valent zéro, et logsBloom est 512 caractères zéro.

Deux conséquences. Un client qui vérifie les racines ne peut rien vérifier ici. Et un client qui pré-filtre par bloom avant d'aller chercher des logs ne trouvera rien - filtrez avec eth_getLogs, qui lit un vrai index.

Les en-têtes sont par ailleurs correctement au format Cancun, mixHash, withdrawalsRoot, blobGasUsed, excessBlobGas et parentBeaconBlockRoot compris. mixHash est porteur plutôt que décoratif : sans lui, tout client fondé sur revm, forge script inclus, rejette l'en-tête avec prevrandao not set avant même de simuler.

Champs de reçu et de transaction

  • type vaut toujours "0x0", quelle que soit l'enveloppe que vous avez réellement envoyée, et une transaction rapporte un unique gasPrice plat - ni maxFeePerGas, ni maxPriorityFeePerGas, ni accessList ne reviennent. Les transactions typées sont acceptées à l'entrée ; c'est la forme de la réponse qui ne reflète simplement pas le type.
  • cumulativeGasUsed est le gasUsed propre de la transaction, pas un cumul courant pour le bloc. En faire la somme sur un bloc ne compte rien deux fois mais ne vous apprend rien non plus.
  • blockHash et blockNumber valent null entre l'exécution et le scellement EVM. Un reçu existe dans cette fenêtre, donc « le reçu n'est pas null » n'est pas le même test que « inclus dans un bloc ».
  • Une transaction porte des extras non standard - raw, miniBlockNumber, miniBlockHash - et un reçu porte les deux derniers. Ils sont utiles et ils ne sont pas portables.
  • eth_getBlockByNumber avec fullTransactions: true peut renvoyer un tableau mixte : des objets pour les transactions dont les reçus sont encore indexés, de simples chaînes de hash pour celles déjà évincées.
  • eth_getBlockReceipts omet en silence les reçus évincés, donc le tableau peut être plus court que la liste des transactions du bloc.

logIndex est par transaction

logIndex est énuméré sur les logs de son propre reçu, pas sur le bloc. Deux logs d'un même bloc peuvent tous deux avoir logIndex 0.

Si vous indexez un magasin d'événements sur (blockNumber, logIndex) - la clé primaire composite habituelle d'un indexeur - vous aurez des collisions. Incluez transactionHash.

Pending n'est pas un mempool

Il n'y a pas de mempool public où être pending. Un hash n'atteint eth_newPendingTransactionFilter et l'abonnement newPendingTransactions qu'après que la transaction a été exécutée et indexée.

C'est donc un flux de transactions exécutées sous un nom trompeur. Vous ne pouvez pas guetter les transactions entrantes avant qu'elles n'atterrissent, et il n'y a rien à devancer à travers cette interface.

Les méthodes qui répondent par des constantes

Deux méthodes ont l'air de fonctionner et renvoient des valeurs qui ne sont pas des mesures. Les deux sont signalées dans la référence, et les deux sont plus dangereuses qu'une méthode qui échoue :

  • eth_feeHistory ne lit que blockCount, ignore entièrement newestBlock et rewardPercentiles, et renvoie baseFeePerGas comme 0x1 répété avec gasUsedRatio comme 0.0 répété.
  • eth_createAccessList renvoie { accessList: [], gasUsed: "0x0" } sans regarder ni les paramètres ni l'état.

Un troisième groupe répond honnêtement mais à vide, parce que les concepts ne s'appliquent pas : eth_accounts est toujours vide, eth_mining faux, eth_hashrate zéro, et les quatre méthodes d'oncles renvoient zéro ou null sans valider leurs paramètres.

Les espaces de noms qui n'existent pas

rpc_modules annonce eth, net, web3 et pickle. Absents et non implémentés : debug, trace, txpool et admin. Il n'y a donc pas de debug_traceTransaction - pour les traces d'appels, utilisez l'explorateur, qui les a.

Les méthodes de signature sont enregistrées et refusent délibérément : eth_sendTransaction, eth_sign, eth_signTransaction, personal_sign et eth_coinbase répondent toutes -32601. Le nœud ne détient aucune clé d'utilisateur - signez localement et utilisez eth_sendRawTransaction.