# Devchain

> Help users run a local Ethereum dev chain, write integration tests, fork networks, debug transactions, or replace Hardhat/Anvil with Nethereum DevChain (.NET). Use this skill when the user mentions local Ethereum node, dev chain, test chain, Hardhat replacement, Anvil replacement, in-process blockchain, snapshot/revert, debug_traceTransaction, account impersonation, or anything involving a local EVM for development and testing with C# or .NET.

- Skill: `nethereum/devchain` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nethereum/devchain`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nethereum/devchain/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: nethereum (https://skillmd.com/u/nethereum)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nethereum/devchain

---


# Nethereum DevChain

DevChain is a complete in-process Ethereum node for .NET. It runs the full EVM (up to Prague), mines blocks instantly, and needs no external dependencies — no Docker, no Geth, no Hardhat, no Anvil.

## When to Use This

- Running a local Ethereum node for development or testing
- Writing integration tests that need real EVM execution
- Replacing Hardhat or Anvil with a .NET-native solution
- Forking mainnet or L2s for local testing
- Debugging transaction execution at the opcode level
- Setting up Aspire-orchestrated dev environments

## Packages

```bash
dotnet add package Nethereum.DevChain          # Core in-process node
dotnet add package Nethereum.DevChain.Server   # HTTP JSON-RPC server
```

## Quick Start — In-Process Node

```csharp
using Nethereum.DevChain;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;

var account = new Account("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80");
var devChain = new DevChainNode();
await devChain.StartAsync(account);  // Pre-funds with 10,000 ETH

var web3 = devChain.CreateWeb3(account);  // In-process, no HTTP

// Standard Nethereum APIs work as-is
var receipt = await web3.Eth.GetEtherTransferService()
    .TransferEtherAndWaitForReceiptAsync("0x70997970C51812dc3A010C7d01b50e0d17dc79C8", 1.0m);

devChain.Dispose();
```

## Key Classes

| Class | Package | Purpose |
|-------|---------|---------|
| `DevChainNode` | Nethereum.DevChain | Main in-process node |
| `DevChainConfig` | Nethereum.DevChain | Chain configuration (ChainId, AutoMine, BlockGasLimit, etc.) |
| `DevChainServerConfig` | Nethereum.DevChain.Server | HTTP server configuration |
| `DevAccountManager` | Nethereum.DevChain.Server | HD wallet account management |
| `DevChainHostedService` | Nethereum.DevChain.Server | ASP.NET Core hosted service |

## Configuration

```csharp
var config = new DevChainConfig
{
    ChainId = 1337,              // Default: 1337 (Hardhat preset: 31337)
    BlockGasLimit = 30_000_000,
    AutoMine = true,             // Mine instantly on each tx
    InitialBalance = BigInteger.Parse("10000000000000000000000")  // 10,000 ETH
};

var devChain = new DevChainNode(config);
```

Presets: `DevChainConfig.Default` (1337), `DevChainConfig.Hardhat` (31337), `DevChainConfig.Anvil` (31337).

## Factory Methods

```csharp
// One-liner
var devChain = await DevChainNode.CreateAndStartAsync(account);

// In-memory (no SQLite)
var devChain = DevChainNode.CreateInMemory();

// Multiple accounts
var devChain = new DevChainNode();
await devChain.StartAsync(alice, bob);
var accounts = await devChain.GenerateAndFundAccountsAsync(10);
```

## Snapshot/Revert (Test Isolation)

```csharp
var snapshot = await devChain.TakeSnapshotAsync();
// ... transactions ...
await devChain.RevertToSnapshotAsync(snapshot);  // Undo all changes
```

## State Manipulation

```csharp
await devChain.SetBalanceAsync(address, Web3.Convert.ToWei(1_000_000));
await devChain.SetNonceAsync(address, 100);
await devChain.SetCodeAsync(address, bytecode);
await devChain.SetStorageAtAsync(address, slot, value);
```

Via RPC: `hardhat_setBalance`, `hardhat_setCode`, `hardhat_setNonce`, `hardhat_setStorageAt` (also `anvil_*` aliases).

## Forking

```csharp
var config = new DevChainConfig
{
    ForkUrl = "https://eth.llamarpc.com",
    ForkBlockNumber = 19000000
};
var devChain = new DevChainNode(config);
await devChain.StartAsync(account);
```

CLI: `nethereum-devchain -f https://eth.llamarpc.com --fork-block 19000000`

## Time Manipulation

```csharp
devChain.DevConfig.AddTimeOffset(3600);           // Advance 1 hour
devChain.DevConfig.SetNextBlockTimestamp(1700000000); // Exact timestamp
await devChain.MineBlockAsync();
```

## Debug Tracing

```csharp
using Nethereum.CoreChain.Tracing;

var traceConfig = new OpcodeTraceConfig
{
    DisableMemory = true,
    DisableStack = false,
    DisableStorage = false
};

var trace = await devChain.TraceTransactionAsync(txHash, traceConfig);
```

## HTTP Server (CLI)

```bash
nethereum-devchain                    # Defaults: port 8545, 10 accounts, auto-mine
nethereum-devchain -p 8546 -a 20     # Custom port and accounts
nethereum-devchain -f <url>          # Fork mode
nethereum-devchain --persist ./data  # Persistent storage
```

## Embedding HTTP Server in ASP.NET

```csharp
using Nethereum.DevChain.Server.Configuration;
using Nethereum.DevChain.Server.Hosting;
using Nethereum.DevChain.Server.Server;

var config = new DevChainServerConfig { ChainId = 31337, Storage = "memory" };
builder.Services.AddDevChainServer(config);
builder.Services.AddHostedService<DevChainHostedService>();
```

## Integration Test Pattern

```csharp
public class DevChainFixture : IAsyncLifetime
{
    public DevChainNode Node { get; private set; }
    public Account Alice { get; private set; }

    public async Task InitializeAsync()
    {
        Alice = new Account("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80");
        Node = new DevChainNode(new DevChainConfig { ChainId = 31337 });
        await Node.StartAsync(Alice);
    }

    public Task DisposeAsync() { Node?.Dispose(); return Task.CompletedTask; }
}

// In test class: snapshot before each test, revert after
public async Task InitializeAsync() => _snapshot = await _fixture.Node.TakeSnapshotAsync();
public async Task DisposeAsync() => await _fixture.Node.RevertToSnapshotAsync(_snapshot);
```

## Supported RPC Methods

Standard Ethereum (`eth_*`, `net_*`, `web3_*`), plus:
- **Dev**: `evm_mine`, `evm_snapshot`, `evm_revert`, `evm_increaseTime`, `evm_setNextBlockTimestamp`
- **Hardhat**: `hardhat_setBalance`, `hardhat_setCode`, `hardhat_setNonce`, `hardhat_setStorageAt`, `hardhat_impersonateAccount`, `hardhat_stopImpersonatingAccount`
- **Anvil aliases**: `anvil_setBalance`, `anvil_setCode`, `anvil_setNonce`, `anvil_setStorageAt`, `anvil_mine`, `anvil_snapshot`, `anvil_revert`
- **Debug**: `debug_traceTransaction`, `debug_traceCall`

## Hardhat/Anvil Migration

Same default mnemonic (`test test test test test test test test test test test junk`), same derivation path (`m/44'/60'/0'/0/{index}`), same RPC methods, same chain ID (31337 with Hardhat/Anvil presets). Existing test scripts work without changes.

For full documentation, see: https://docs.nethereum.com/docs/devchain/overview

