ワンクリックで
fix-nethtest
// Debug and fix failing Ethereum Foundation tests run with Nethermind.Test.Runner. Accepts test file paths as arguments. Runs the test, analyzes traces, identifies root causes in the EVM/spec/test harness, and proposes fixes.
// Debug and fix failing Ethereum Foundation tests run with Nethermind.Test.Runner. Accepts test file paths as arguments. Runs the test, analyzes traces, identifies root causes in the EVM/spec/test harness, and proposes fixes.
| name | fix-nethtest |
| description | Debug and fix failing Ethereum Foundation tests run with Nethermind.Test.Runner. Accepts test file paths as arguments. Runs the test, analyzes traces, identifies root causes in the EVM/spec/test harness, and proposes fixes. |
| allowed-tools | ["Bash","Read","Grep","Glob","Edit","Agent"] |
Diagnose and fix tests run with Nethermind.Test.Runner (nethtest). The test runner executes Ethereum Foundation state tests and blockchain tests against the Nethermind EVM.
Arguments: $ARGUMENTS — one or more test file paths.
Infer the test type from the JSON structure — do not require the user to specify it:
"blocks", "genesisBlockHeader", or "network" keys"transaction" and "post" keysA quick check: grep -l '"blocks"' <file> or grep -l '"transaction"' <file>.
# Build (only if needed)
dotnet build src/Nethermind/Nethermind.Test.Runner/Nethermind.Test.Runner.csproj -c release --verbosity quiet
# Run state test
dotnet run --project src/Nethermind/Nethermind.Test.Runner/Nethermind.Test.Runner.csproj -c release -- -t -i "<test-file>"
# Run blockchain test (add -b flag)
dotnet run --project src/Nethermind/Nethermind.Test.Runner/Nethermind.Test.Runner.csproj -c release -- -b -t -i "<test-file>"
Output structure:
{"pc":N,"op":N,"gas":"0x...","gasCost":"0x...","stack":[...],"depth":N,"opName":"...","error":"..."}{"output":"0x...","gasUsed":"0x...","time":N,"error":"..."}{"stateRoot":"0x..."}[{"name":"...","pass":bool,"fork":"...","stateRoot":"0x..."}]If pass is true, report success and stop. Otherwise proceed to Phase 2.
Read the test JSON file to understand:
post section key (e.g., "Osaka")authorizationList present)post.<fork>[0].hash (all-zeros = placeholder, not a real expected value)env (e.g., currentExcessBlobGas, currentBeaconRoot)Then classify the failure from the trace:
| Trace signal | Failure class | Likely cause area |
|---|---|---|
"error":"BadInstruction" on a known opcode | Opcode not available | Spec flag gate or instruction runtime guard |
"error":"BadInstruction" on unknown opcode | Unimplemented opcode | Missing opcode in EvmInstructions.cs |
"error":"OutOfGas" | Gas accounting | Gas cost calculation or intrinsic gas |
"error":"StackUnderflow" or "error":"StackOverflow" | Stack effect | Usually expected behavior of the bytecode, not a bug |
| No EVM error but wrong state root | State mismatch | Wrong storage writes, balance changes, or header field defaults |
"loadFailure" in result | Parse error | Unsupported JSON field or missing deserialization |
| Block validation fails (blockchain tests) | Header issue | Missing header fields or wrong defaults for fork |
This is the most common failure pattern for new forks. Follow these steps:
Identify the opcode from the trace entry where error is "BadInstruction":
op field = opcode byte valueopName field = human-readable nameCheck opcode registration in src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.cs:
lookup[(int)Instruction.<OPNAME>] = ...if (spec.<FlagName>) wrapping itCheck if the spec flag is true for the target fork:
src/Nethermind/Nethermind.Core/Specs/IReleaseSpecExtensions.cs or IReleaseSpec.cssrc/Nethermind/Nethermind.Specs/Forks/Apply(ReleaseSpec spec) to set its flags; the chain is replayed from rootIf the opcode IS registered but still fails — the instruction implementation has a runtime guard. Check the instruction handler in src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.*.cs:
if (!context.Header.SomeField.HasValue) goto BadInstruction;Check the test harness header construction:
src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs — look at the BlockHeader initializer (around line 115-138)src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.csis Cancun, is Prague) instead of spec flag checks (IsEip4844Enabled, IsEip7702Enabled) — type checks only match the exact class, not subclasses or later forksExcessBlobGas, RequestsHash, BlockAccessListHash)Check if expected hash is all-zeros — this is a placeholder test. The test was generated but the expected root hasn't been filled in. Report this to the user; it's not a code bug.
Check conditional defaults in header construction — a missing header field (e.g., null ExcessBlobGas) can change how the EVM executes even without causing BadInstruction.
Analyze the trace for unexpected behavior:
Check fork spec configuration:
Apply() methodconfig.blobSchedule)Check blob schedule override — test JSON may have a config.blobSchedule section with per-fork overrides for target, max, and baseFeeUpdateFraction. Verify these are applied via OverridableReleaseSpec in JsonToEthereumTest.LoadSpec().
BlockAccessListHash)genesisUsesTargetFork logic in BlockchainTestBase.cs)Ethereum.Test.Base/JsonToEthereumTest.cs and the JSON model classesSpecNameParser.cs for unsupported fork names| Purpose | Path (relative to src/Nethermind/) |
|---|---|
| Test runner CLI | Nethermind.Test.Runner/Program.cs |
| State test execution + header | Ethereum.Test.Base/GeneralTestBase.cs |
| Blockchain test execution | Ethereum.Test.Base/BlockchainTestBase.cs |
| Test JSON parsing | Ethereum.Test.Base/JsonToEthereumTest.cs |
| Opcode registration + spec gates | Nethermind.Evm/Instructions/EvmInstructions.cs |
| Instruction implementations | Nethermind.Evm/Instructions/EvmInstructions.*.cs |
| Spec flag extensions | Nethermind.Core/Specs/IReleaseSpecExtensions.cs |
| Fork definitions | Nethermind.Specs/Forks/*.cs |
| Fork name parser | Nethermind.Specs/SpecNameParser.cs |
| EVM exception types | Nethermind.Evm/EvmException.cs |
| Block execution context | Nethermind.Evm/BlockExecutionContext.cs |
RLP deserialization — incorrect RLP decoding can either accept malformed data (missing validation, wrong type expectations) or reject valid data (overly strict length checks, wrong sequence handling). For blockchain tests, blocks arrive as RLP — check Nethermind.Serialization.Rlp/ decoders for the relevant types. Common issues: not handling optional fields added by new EIPs, wrong list vs single-item decoding, incorrect length prefix validation.
Gas accounting — wrong gas costs for opcodes, missing gas charges for memory expansion, incorrect intrinsic gas calculation for new transaction types, or wrong refund logic. Compare against the EIP specification. Check GasCostOf.cs for static costs, instruction handlers for dynamic costs, and IntrinsicGasCalculator for transaction-level gas.
State root mismatch — execution completes without EVM errors but produces the wrong state root. Causes include: incorrect storage writes (wrong slot or value), wrong balance updates (fee burning, coinbase rewards, value transfer edge cases), missing or extra account touches that affect empty-account cleanup (EIP-158), or wrong nonce increments.
Missing header field default — new EIPs add nullable fields to BlockHeader. The test harness must default them for forks that enable them when the test JSON doesn't provide them (e.g., ExcessBlobGas = 0 for EIP-4844+ forks).
Instruction runtime guard — an opcode can be registered in the lookup table but still fail if its implementation checks a header field that wasn't set (e.g., BLOBBASEFEE checks ExcessBlobGas.HasValue).
Validation errors — missing validation that should reject invalid data (e.g., not checking transaction type constraints, accepting out-of-range values) or overly strict validation that rejects valid inputs (e.g., rejecting new transaction fields not yet accounted for, wrong bounds on EIP-introduced parameters). For blockchain tests, check block and transaction validators. For state tests, check TransactionProcessor validation and BlockValidator.
Missing blob schedule override — test JSON config.blobSchedule overrides blob parameters per fork. If JsonToEthereumTest.LoadSpec() doesn't handle the fork name, parameters revert to defaults.
Build a diag Docker image, run gas-benchmarks repricing workflow, and analyze results including dotTrace XML reports. Use when asked to "run benchmarks", "trigger gas benchmarks", "benchmark this branch", "profile block processing", or "analyze benchmark run". Supports analyze-only mode for CI integration.
Audit C#/.NET code for resource leaks, IDisposable misuse, CTS lifecycle bugs, unbounded growth, handle exhaustion, and dispose race conditions. Use when asked to "audit for leaks", "check for resource leaks", "find dispose issues", "review for memory leaks", or when reviewing a PR that touches resource management, disposal, CancellationTokenSource, ArrayPool, event subscriptions, or async coordination patterns.
Deep code review for an Ethereum execution client. Checks consensus correctness, security, robustness, performance, DI patterns, breaking changes, and observability. Use when asked to "review", "check this PR", "look for bugs", "audit", or "review my changes".