## Summary
- rename the FRAME alias for `pallet_evm` from `Evm` to `EVM` across the
mainnet, stagenet, and testnet runtimes
- adjust benchmarks, configuration modules, genesis builders, and
runtime tests to rely on the new alias
- keep precompile genesis setup and proxy/precompile tests aligned with
the updated names
## Context
Frontier’s `StorageOverrideHandler` (see
`fc_storage::StorageQuerier::account_code`) reads contract bytecode from
`pallet_evm::AccountCodes` using the constant `PALLET_EVM = b"EVM"` to
build the storage key:
`twox_128("EVM") ++ twox_128("AccountCodes") ++ …`
Our runtimes exported `pallet_evm` as `Evm`, so substrate stored
bytecode under the *camel-cased* prefix (`twox_128("Evm")`). Every call
that ultimately hits the storage override—including `eth_getCode`,
`eth_call`, and state queries during replay—therefore failed to locate
code for *any* account (deployed contracts and precompiles alike).
Renaming the alias to `EVM` realigns the storage prefix with Frontier’s
expectations so the override layers can pull bytecode correctly.
## Testing
- `cargo check -p datahaven-node`
- `cargo build --release -p datahaven-node`
- `eth_getCode 0x0000000000000000000000000000000000000802` → returns
`0x60006000fd`
## Storage Migration
Renaming a pallet alias changes the storage prefix for all pallet data.
Without migration, existing EVM data (smart contracts, account codes,
storage) would become inaccessible.
**Migration details:**
- **Type**: Multi-Block Migration (MBM)
- **Storage migrated**: `AccountCodes`, `AccountCodesMetadata`,
`AccountStorages`
- **Migration ID**: `datahaven-evm-mbm` (version 0 → 1)
**Testing the migration:**
```bash
# Build runtime with try-runtime
cargo build --release --features try-runtime -p
datahaven-stagenet-runtime
# Test against stagenet
try-runtime \
--runtime
./target/release/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.wasm
\
on-runtime-upgrade \
--blocktime 6000 \
--checks all \
--disable-spec-version-check \
live --uri wss://dh-validator-0.datahaven-kt.xyz
```
Test results from stagenet:
- ✅ Migration completes in 1 block
- ✅ PoV size: ~5.3 KB
- ✅ Weight consumption: <0.1% of block capacity
- ✅ All 39 keys successfully migrated
## ⚠️ Breaking Changes ⚠️
If you are manually computing storage keys for the EVM pallet (e.g., directly querying chain state), you must update your code to use the new storage prefix:
- Old prefix: twox128("Evm") = 0x8b90cb...
- New prefix: twox128("EVM") = 0x6a5e91...
All EVM-facing interfaces remain unchanged.
|
||
|---|---|---|
| .. | ||
| .cargo | ||
| benchmarking | ||
| node | ||
| pallets | ||
| precompiles | ||
| primitives | ||
| runtime | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| rust-toolchain.toml | ||
DataHaven Operator (Substrate Node) 🫎
The DataHaven operator is a Substrate-based blockchain node that serves as an EigenLayer AVS operator. It combines Substrate's modular framework with EVM compatibility (via Frontier) and cross-chain capabilities (via Snowbridge).
Overview
Built on the polkadot-sdk-solochain-template, this node implements:
- EVM Compatibility: Full Ethereum compatibility via Frontier pallets
- EigenLayer Integration: Operator registration and management via AVS contracts
- External Validators: Dynamic validator set controlled by EigenLayer registry
- Cross-chain Communication: Token and message passing via Snowbridge
- Rewards System: Performance-based validator rewards from Ethereum
Project Structure
operator/
├── node/ # Node implementation
│ ├── src/
│ │ ├── chain_spec.rs # Chain specification & genesis config
│ │ ├── cli.rs # CLI interface
│ │ ├── command.rs # Command handlers
│ │ ├── rpc.rs # RPC configuration
│ │ └── service.rs # Node service setup
├── pallets/ # Custom pallets
│ ├── external-validators/ # EigenLayer validator set management
│ ├── native-transfer/ # Cross-chain token transfers
│ └── rewards/ # Validator rewards distribution
├── runtime/ # Runtime configurations
│ ├── mainnet/ # Mainnet runtime
│ ├── stagenet/ # Stagenet runtime
│ └── testnet/ # Testnet runtime (with fast-runtime feature)
└── scripts/ # Utility scripts
└── run-benchmarks.sh # Runtime benchmarking automation
Prerequisites
- Rust (latest stable)
- Substrate dependencies
- Zig (macOS only, for cross-compilation)
Building
Development Build (Fast Runtime)
For local development with faster block times:
cargo build --release --features fast-runtime
This enables 3-second block times instead of the production 12-second blocks.
Production Build
For production or stagenet deployments:
cargo build --release
Running Tests
# Run all tests
cargo test
# Run tests for specific pallet
cargo test -p pallet-external-validators
# Run with output
cargo test -- --nocapture
Code Quality
# Format code
cargo fmt
# Lint with clippy
cargo clippy --all-targets --all-features
Benchmarking
DataHaven uses runtime benchmarking to generate accurate weight calculations for all pallets. The benchmarking process is automated using frame-omni-bencher.
Requirements
- Latest Rust stable version
frame-omni-bencher: Install withcargo install frame-omni-bencher --profile=production
Running Benchmarks
Execute from the operator directory:
# Benchmark all pallets for testnet runtime (default)
./scripts/run-benchmarks.sh
# Benchmark specific runtime
./scripts/run-benchmarks.sh mainnet
# Custom steps and repetitions
./scripts/run-benchmarks.sh testnet 100 50
The script will:
- Discover all available pallets
- Build runtime WASM with
runtime-benchmarksfeature - Generate weight files in
runtime/{runtime}/src/weights/ - Provide summary of results
Parameters:
runtime: Runtime to benchmark (testnet, stagenet, mainnet). Default: testnetsteps: Number of steps. Default: 50repeat: Number of repetitions. Default: 20
Zombienet Testing
Zombienet provides local multi-validator network testing.
Setup
-
Install Zombienet:
# Download binary from releases # Or install via npm npm install -g @zombienet/cli -
Spawn local network with four validators:
zombienet -p native spawn test/config/zombie-datahaven-local.toml
This launches a local solochain with BABE consensus for testing validator coordination.
Docker Image
Build local Docker image for testing:
cd ../test
bun build:docker:operator
This creates datahavenxyz/datahaven:local using optimized caching:
- sccache: Rust build caching
- cargo-chef: Dependency layer caching
- BuildKit cache mounts: External cache restoration
Type Generation
After runtime changes, regenerate Polkadot-API TypeScript types:
cd ../test
bun generate:types # Production runtime
bun generate:types:fast # Fast runtime (development)
Integration Testing
For full network integration tests with Ethereum, Snowbridge, and contracts:
cd ../test
bun cli launch # Interactive launcher
bun test:e2e # Run E2E test suite
See the test directory for comprehensive testing documentation.
Custom Pallets
External Validators
Manages the dynamic validator set based on EigenLayer operator registry. Syncs validator changes from Ethereum to the Substrate consensus layer.
Location: pallets/external-validators/
Native Transfer
Handles cross-chain token transfers between Ethereum and DataHaven via Snowbridge messaging.
Location: pallets/native-transfer/
Rewards
Distributes performance-based rewards to validators, processing reward messages from the Ethereum RewardsRegistry contract.
Location: pallets/rewards/
Each pallet includes its own tests and benchmarks. See pallet-specific README files for details.