Middle · Blockchain infrastructure

The endpoint is reachable but serves the wrong chain

The Go client connects successfully to an RPC URL. What must it verify before using balances or preparing transaction intent?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

EXAMPLE · FRAGMENT UNLESS A COMPLETE PROGRAM IS SHOWN

go
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"

	"github.com/ethereum/go-ethereum/ethclient"
)

func main() {
	// Local mock of eth_chainId; no public network or real wallet is used.
	node := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var q struct {
			ID     json.RawMessage `json:"id"`
			Method string          `json:"method"`
		}
		if err := json.NewDecoder(r.Body).Decode(&q); err != nil {
			http.Error(w, "bad request", 400)
			return
		}
		if q.Method != "eth_chainId" {
			http.Error(w, "unsupported", 400)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "id": q.ID, "result": "0x539"})
	}))
	defer node.Close()
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	client, err := ethclient.DialContext(ctx, node.URL)
	if err != nil {
		panic(err)
	}
	defer client.Close()
	chain, err := client.ChainID(ctx)
	if err != nil {
		panic(err)
	}
	fmt.Println(chain.String()) // 1337: the local mock chain
}
Reveal a strong answer
  1. An Ethereum RPC endpoint is an external dependency with latency, availability and trust limits. A successful TCP connection does not prove that the endpoint serves the intended chain or that every call will finish. Use typed clients, time-bounded operations and an expected chain ID configured by the application. Keep node credentials out of logs and never treat RPC data as authenticated business authority by default.

  2. Share an appropriately configured client for its intended lifetime, close it at the owning boundary and pass a fresh operation context to each RPC. Distinguish a transport timeout, JSON-RPC error, missing object and on-chain revert. Read related state at a consistent block/hash where required and report archive/pruning limitations rather than silently substituting latest state. The client calls a local HTTP test server and preserves the JSON-RPC request ID in its reply. The hex result becomes an exact big.Int value. Production code must compare that value with the configured expected chain, rather than accepting any reachable endpoint. A dial context does not become the deadline for every later operation.

  3. Providers can impose batch, rate and historical-range limits. Bound concurrency and response sizes, classify retryable reads and treat a transaction-send timeout as an unknown outcome. A single RPC provider is also a trust and availability assumption. Test wrong chain ID, unavailable history, malformed responses, cancellation and provider disagreement in a local or test-network environment.

Common trap

Quietly falling back to latest state can turn a reproducible historical query into a different operation.

Try it

Extend the local eth_chainId mock with wrong-chain and timeout responses, and compare dial and per-call context lifetimes.

Worked solution

Compare the reported chain ID with the configured expected identity and give every operation its own budget. A successful dial does not establish network identity or the deadline of subsequent calls. Classify transport, JSON-RPC, missing-data and chain execution outcomes separately. Use a consistent block/hash for related historical reads where required, handle provider pruning/rate limits explicitly and keep endpoint credentials out of logs.

Change the constraint

How would you handle a provider that cannot serve the requested historical block?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-28. Use documentation for your pinned runtime, driver and tool version.