Ejecutable local con Anvil
Depurar JSON-RPC con cast
Hacer llamadas JSON-RPC con Cast y clasificar cada error en su capa: transporte, JSON-RPC o EVM.
- Duración
- 20–35 min
- Nivel
- Base práctica Ethereum
- Pasos
- 3
- Versión
- 3.29.0-alpha.1
Modelo mental
Un error de "RPC" puede venir de tres lugares distintos: no llegaste al nodo, el nodo no entendió la petición, o la EVM ejecutó y revirtió. Cada capa pide un arreglo diferente.
- 1Preflight
- 2Anvil
- 3Lecturas
- 4Errores por capa
- 5Reporte
Antes de empezar
- Foundry instalado: anvil y cast en el PATH (https://getfoundry.sh).
- Node.js 20 o superior para el preflight.
- Puerto local 8545 libre.
Pasos
Paso 1Preflight y Anvil
Asegurar que las herramientas existen y que el RPC es local.
Preflight node tools/labs/ethereum-rpc-cast-debugging/preflight.mjsTerminal A: Anvil anvil --host 127.0.0.1 --port 8545 --chain-id 31337Comprueba
- — El JSON del preflight muestra available: true para anvil y cast, rpcSafe: true y port8545Free: true.
- — Anvil queda escuchando en 127.0.0.1:8545.
Evidencia esperada
JSON del preflight.
Paso 2Lecturas básicas
Ver la respuesta cruda de un método JSON-RPC, no solo la versión formateada.
Terminal B export RPC_URL="http://127.0.0.1:8545" cast chain-id --rpc-url $RPC_URL cast block-number --rpc-url $RPC_URL cast rpc eth_getBlockByNumber latest false --rpc-url $RPC_URL cast rpc eth_chainId --rpc-url $RPC_URLComprueba
- — chain-id devuelve 31337 y eth_chainId devuelve "0x7a69", el mismo número en hexadecimal.
- — eth_getBlockByNumber devuelve un JSON con hash, parentHash, stateRoot y transactionsRoot.
Evidencia esperada
Salida de las cuatro llamadas.
Paso 3Provocar un error por capa
Aprender a leer el mensaje y asignar la responsabilidad correcta.
Transporte cast block-number --rpc-url http://127.0.0.1:8546JSON-RPC cast rpc eth_foo --rpc-url $RPC_URLEVM cast rpc eth_call '{"data":"0x60006000fd"}' latest --rpc-url $RPC_URLComprueba
- — Transporte: "Connection refused (os error 111)"; nunca llegó al nodo.
- — JSON-RPC: "error code -32601: Method not found"; el nodo respondió pero no conoce el método.
- — EVM: "error code 3: execution reverted"; el código 0x60006000fd (PUSH1 0, PUSH1 0, REVERT) se ejecutó y revirtió.
Evidencia esperada
Tabla con endpoint, método, parámetros, error y capa responsable para cada caso.
El código del laboratorio
Estos son los archivos que ejecutan los pasos, tal como están en el repositorio .
# Ethereum RPC + Cast debugging
Version: `2.0.44-alpha.1`
## Boundary
Use only `http://127.0.0.1:8545` with an ephemeral Anvil instance. Never paste a personal private key or public RPC credential.
## Start
```powershell
node tools/labs/ethereum-rpc-cast-debugging/preflight.mjs
anvil --host 127.0.0.1 --port 8545 --chain-id 31337
```
In a second terminal:
```powershell
$env:RPC_URL="http://127.0.0.1:8545"
cast chain-id --rpc-url $env:RPC_URL
cast block-number --rpc-url $env:RPC_URL
cast rpc eth_getBlockByNumber latest false --rpc-url $env:RPC_URL
```
Bash equivalent:
```bash
export RPC_URL="http://127.0.0.1:8545"
cast chain-id --rpc-url $RPC_URL
cast block-number --rpc-url $RPC_URL
cast rpc eth_getBlockByNumber latest false --rpc-url $RPC_URL
```
Then provoke one failure per layer:
```bash
cast block-number --rpc-url http://127.0.0.1:8546 # transport: Connection refused
cast rpc eth_foo --rpc-url $RPC_URL # JSON-RPC: -32601 Method not found
cast rpc eth_call '{"data":"0x60006000fd"}' latest --rpc-url $RPC_URL # EVM: code 3 execution reverted
```
Record endpoint, method, parameters, result or error, and the layer responsible: transport, JSON-RPC, or EVM.
## Cleanup
Stop Anvil with `Ctrl+C` and remove `RPC_URL` from the environment (`unset RPC_URL` in Bash).import { spawnSync } from 'node:child_process';
import net from 'node:net';
const commands = ['anvil', 'cast'];
const versions = Object.fromEntries(
commands.map((command) => {
const result = spawnSync(command, ['--version'], { encoding: 'utf8' });
return [command, { available: result.status === 0, version: (result.stdout || result.stderr || result.error?.message || '').trim().split('\n')[0] }];
})
);
const rpcUrl = process.env.RPC_URL ?? '';
const rpcSafe = !rpcUrl || /^https?:\/\/(127\.0\.0\.1|localhost)(:\d+)?\/?$/i.test(rpcUrl);
const portFree = await new Promise((resolve) => {
const server = net.createServer();
server.once('error', () => resolve(false));
server.listen(8545, '127.0.0.1', () => server.close(() => resolve(true)));
});
const report = { versions, rpcUrl: rpcUrl || '(unset)', rpcSafe, port8545Free: portFree };
console.log(JSON.stringify(report, null, 2));
if (commands.some((command) => !versions[command].available) || !rpcSafe) process.exit(1);Criterios de aceptación
- Las lecturas responden con chainId 31337.
- Cada uno de los tres errores queda asignado a la capa correcta.
- Anvil quedó detenido y RPC_URL eliminado.
Limpieza
unset RPC_URLAnvil: Ctrl+C en la terminal A.
Si algo falla
| Síntoma | Causa | Qué hacer |
|---|---|---|
| El preflight termina con código 1 y rpcSafe: false | RPC_URL apunta a un host que no es 127.0.0.1 ni localhost. | Ejecuta unset RPC_URL o apúntalo a http://127.0.0.1:8545. |
| port8545Free: false | Ya hay un Anvil corriendo. | Es válido si es tu Anvil; si no, ciérralo antes de empezar. |
| El caso de transporte no falla | Hay otro servicio escuchando en 8546. | Usa otro puerto cerrado para el ejemplo. |