Pre-fork testing: What to check before activating a hard fork
Hard forks are the highest-risk events in blockchain infrastructure. The chain’s consensus rules change at a specific block, and every node must be running compatible software. But even when you’ve upgraded to the right client version, the RPC behavior your applications depend on may have changed in subtle ways.
Before the fork: Preparation
1. Identify affected RPC methods
Every EIP in a hard fork potentially changes RPC behavior. Start by mapping EIPs to methods:
| EIP category | Affected methods |
|---|---|
| Gas repricing | eth_estimateGas, eth_gasPrice, eth_maxPriorityFeePerGas |
| New transaction types | eth_sendRawTransaction, eth_getTransactionByHash, eth_getTransactionReceipt |
| New opcodes | debug_traceTransaction, debug_traceCall |
| State changes | eth_getBalance, eth_getStorageAt, eth_call |
| Receipt/log changes | eth_getTransactionReceipt, eth_getLogs |
| Block structure | eth_getBlockByNumber, eth_getBlockByHash |
Not every fork touches every category, but gas repricing and new transaction types are common across most forks.
2. Baseline your current behavior
Before upgrading anything, record the RPC responses for your critical methods on your current client version. This gives you a reference point to diff against after the upgrade.
What to baseline:
- Method responses for a representative set of block numbers and transaction hashes
- Gas estimates for your most common transaction patterns
- Error responses for known edge cases (zero-value calls, out-of-gas scenarios)
- Trace outputs if you run analytics or debugging infrastructure
3. Upgrade to the fork-ready client version
Most client teams release fork-ready versions weeks before activation. Upgrade early to catch build and configuration issues before the deadline.
Key checks after upgrading:
- Node syncs to chain head without errors
- Peer count is stable
- No unexpected warnings in logs about deprecated flags or changed defaults
4. Test on a testnet first
If the fork has already activated on a testnet (Sepolia, Hoodi), test there before mainnet. Run your full test suite against the testnet node and compare responses across the fork boundary.
Pay attention to:
- Blocks just before and after the fork activation
- Transactions that use the new features (new tx types, new opcodes)
- Historical queries for pre-fork blocks (these should be unchanged)
After the fork: Verification
5. Validate receipt and block fields
Hard forks frequently add new fields to receipts and blocks. Check that:
- Your parsers handle new fields gracefully (don’t fail on unknown keys)
- Expected fields are still present and in the same format
- New fields contain valid data (not null or zero when they should have values)
Common gotchas:
blobGasUsedandblobGasPriceappearing in post-EIP-4844 receiptswithdrawalsarray in post-Shanghai blocksparentBeaconBlockRootin post-Dencun blocks
6. Check gas estimation accuracy
Gas repricing EIPs change the cost of operations, which directly affects eth_estimateGas results. Verify that:
- Estimates for your common transactions are within expected bounds
- The delta from pre-fork estimates matches what the EIP predicts
- Edge cases (contract deployments, large calldata) don’t produce unexpectedly high estimates
7. Verify trace compatibility
If you use debug_traceTransaction or debug_traceCall, verify that:
- Trace output structure hasn’t changed
- New opcodes appear correctly in traces
- Gas costs in traces reflect the new pricing
Trace output changes are one of the most commonly missed regressions because they rarely have formal specifications.
8. Test cross-client consistency
If you run multiple client implementations (geth + nethermind, for example), verify that they agree on:
- Block hashes at and after the fork
- Transaction receipts for the same transactions
- Gas estimates for identical calls
- Error responses for the same invalid inputs
Different clients implement the same EIPs independently, and subtle disagreements are common in the first few days after a fork.
9. Monitor production after activation
Even with thorough testing, some issues only appear under real traffic patterns. After the fork activates:
- Watch gas estimation accuracy for the first 100 blocks
- Monitor error rates on RPC methods
- Check that websocket subscriptions (
newHeads,logs) are working - Verify that pending transaction behavior is correct
Automating the checklist
Running this checklist manually is feasible for one fork, but it doesn’t scale. Each mainnet fork comes with testnets activating weeks earlier, client pre-releases to test, and multiple environments to verify.
OnchainProbe automates this entire workflow. Define your test suites once. Gas estimation, receipt validation, cross-client comparison. Then run them on schedule or triggered by your CI pipeline. When a fork activates, you get clear verdicts with exact field-level diffs showing what changed.
Fork readiness becomes a continuous process.