mega-evme 1.7.0

MegaETH executable EVM
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# mega-evme run

A command-line tool for executing arbitrary EVM bytecode, similar to go-ethereum's `evm run` command. This tool provides a convenient way to test and debug EVM bytecode execution with full control over the execution environment.

## Table of Contents

- [Overview]#overview
- [Basic Usage]#basic-usage
- [Command Line Arguments]#command-line-arguments
- [Features]#features
  - [State Management]#state-management
  - [SALT Bucket Capacity Configuration]#salt-bucket-capacity-configuration
  - [Execution Tracing]#execution-tracing
  - [Benchmarking]#benchmarking
  - [Contract Creation]#contract-creation
  - [Block Environment Configuration]#block-environment-configuration
  - [Fork Selection]#fork-selection
- [State File Format]#state-file-format
- [Examples]#examples
- [Architecture]#architecture

## Overview

The `mega-evme run` command executes EVM bytecode in a controlled environment with configurable parameters. It supports:

- Arbitrary bytecode execution (call or create mode)
- State management (prestate loading and state dumping)
- SALT bucket capacity configuration
- Execution tracing with Geth-compatible output
- Performance benchmarking
- Full control over transaction and block environment

## Basic Usage

```bash
# Execute bytecode directly
mega-evme run 0x60016000526001601ff3

# Execute bytecode from file
mega-evme run --codefile contract.hex

# Execute with input data
mega-evme run 0x60016000526001601ff3 --input 0x1234567890

# Execute with custom gas limit
mega-evme run 0x60016000526001601ff3 --gas 5000000
```

## Command Line Arguments

### Code Input

- `CODE` (positional): EVM bytecode as hex string
- `--codefile <PATH>`: Path to file containing bytecode (use `-` for stdin)

### Transaction Configuration

- `--create`: Execute in create mode (deploy contract)
- `--gas <AMOUNT>`: Gas limit (default: 10000000)
- `--price <AMOUNT>`: Gas price in wei (default: 0)
- `--priorityfee <AMOUNT>`: EIP-1559 priority fee
- `--tx-type <TYPE>`: Transaction type (0=Legacy, 1=EIP-2930, 2=EIP-1559)
- `--value <AMOUNT>`: Value to send with transaction (default: 0)
- `--sender <ADDRESS>`: Transaction sender (default: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266)
- `--receiver <ADDRESS>`: Transaction receiver (default: 0x0000000000000000000000000000000000000000)

### Input Data

- `--input <HEX>`: Input data as hex string
- `--inputfile <PATH>`: Path to file containing input data

### State Management

- `--prestate <PATH>`: JSON file with initial state
- `--dump`: Dump final state after execution
- `--dump.output <PATH>`: Output file for state dump (prints to console if not specified)
- `--sender.balance <AMOUNT>`: Initial balance to allocate to sender account

### SALT Configuration

- `--bucket-capacity <ID:CAPACITY>`: Configure bucket capacity (can be specified multiple times)
  - Format: `bucket_id:capacity`
  - Example: `--bucket-capacity 123:1000000`

### Tracing

- `--tracer trace`: Enable Geth-compatible execution tracing
- `--trace.disable-memory`: Disable memory capture in traces
- `--trace.disable-stack`: Disable stack capture in traces
- `--trace.disable-storage`: Disable storage capture in traces
- `--trace.enable-return-data`: Enable return data capture in traces
- `--trace.output <PATH>`: Output file for trace data

### Debugging

- `--statdump`: Display stack and memory information
- `--bench`: Benchmark execution time

### Chain Configuration

- `--spec <SPEC>`: EVM spec (default: `Rex2`)
  - `MiniRex`: MegaETH MiniRex hardfork
  - `Rex`: MegaETH Rex hardfork
  - `Rex1`: MegaETH Rex1 hardfork
  - `Rex2`: MegaETH Rex2 hardfork
  - `Equivalence`: Optimism Isthmus compatibility mode
- `--chain-id <ID>`: Chain ID (default: 6342)

### Block Environment

- `--block.number <NUM>`: Block number (default: 1)
- `--block.coinbase <ADDRESS>`: Block beneficiary/coinbase address
- `--block.timestamp <TIMESTAMP>`: Block timestamp (default: 1)
- `--block.gaslimit <AMOUNT>`: Block gas limit (default: 30000000)
- `--block.basefee <AMOUNT>`: EIP-1559 base fee (default: 0)
- `--block.difficulty <AMOUNT>`: Block difficulty (default: 0)
- `--block.prevrandao <HASH>`: Previous randao value (post-merge)
- `--block.blobexcessgas <AMOUNT>`: EIP-4844 blob excess gas (default: 0)

## Features

### State Management

The tool supports loading initial state from JSON files and dumping final state after execution.

#### Loading Prestate

```bash
# Load initial state from JSON file
mega-evme run 0x60016000526001601ff3 --prestate initial_state.json
```

The prestate file should contain account information in Ethereum JSON format (see [State File Format](#state-file-format)).

#### Dumping State

```bash
# Dump state to console
mega-evme run 0x60016000526001601ff3 --dump

# Save state to file
mega-evme run 0x60016000526001601ff3 --dump --dump.output final_state.json
```

#### Setting Sender Balance

By default, the sender account has zero balance. You can allocate balance explicitly:

```bash
# Allocate 1 ETH to sender
mega-evme run 0x60016000526001601ff3 --sender.balance 1000000000000000000
```

**Note**: Balance is only allocated when `--sender.balance` is specified. This gives you explicit control over account balances.

#### Round-Trip State Management

You can dump state, modify it, and reload it:

```bash
# 1. Execute and dump state
mega-evme run contract.hex --dump --dump.output state1.json

# 2. Modify state1.json as needed

# 3. Execute with modified state
mega-evme run next_contract.hex --prestate state1.json --dump --dump.output state2.json
```

### SALT Bucket Capacity Configuration

Configure SALT bucket capacities for testing storage gas costs:

```bash
# Configure single bucket
mega-evme run contract.hex --bucket-capacity 123:1000000

# Configure multiple buckets
mega-evme run contract.hex \
  --bucket-capacity 123:1000000 \
  --bucket-capacity 456:2000000 \
  --bucket-capacity 789:500000
```

The bucket capacity configuration uses the format `bucket_id:capacity` where:
- `bucket_id`: 32-bit bucket identifier
- `capacity`: Current capacity in bytes

This affects gas costs for storage operations in MiniRex hardfork.

### Execution Tracing

Enable Geth-compatible execution tracing to see opcode-level execution:

```bash
# Basic tracing
mega-evme run 0x60016000526001601ff3 --tracer trace

# Optimized tracing (disable memory and stack)
mega-evme run contract.hex \
  --tracer trace \
  --trace.disable-memory \
  --trace.disable-stack

# Save trace to file
mega-evme run contract.hex --tracer trace --trace.output trace.json
```

Trace output includes:
- Gas costs per operation
- Stack state (unless disabled)
- Memory state (unless disabled)
- Storage changes (unless disabled)
- Return data (if enabled)

### Benchmarking

Measure execution time:

```bash
mega-evme run contract.hex --bench
```

Output includes:
- Total execution time
- Gas used
- Execution result

### Contract Creation

Deploy contracts using create mode:

```bash
# Deploy contract (code is init code)
mega-evme run --create 0x6080604052...

# Deploy with constructor arguments
mega-evme run --create 0x6080604052... --input 0x0000000000000000000000001234...
```

In create mode:
- The bytecode is treated as init code
- Input data is appended to init code
- Returns the deployed contract address

### Block Environment Configuration

Configure block parameters for testing:

```bash
mega-evme run contract.hex \
  --block.number 1000 \
  --block.timestamp 1234567890 \
  --block.coinbase 0x1111111111111111111111111111111111111111 \
  --block.gaslimit 50000000 \
  --block.basefee 1000000000
```

This is useful for:
- Testing time-dependent contracts
- Simulating specific block conditions
- Testing EIP-1559 base fee mechanics

### Spec Selection

Choose between different EVM specifications:

```bash
# Use MiniRex spec
mega-evme run contract.hex --spec MiniRex

# Use Optimism Isthmus compatibility
mega-evme run contract.hex --spec Equivalence
```

Differences:
- **MiniRex**: Includes SALT dynamic gas costs, LOG cost increases, large contract support
- **Equivalence**: Optimism Isthmus compatibility, parallel execution support

## State File Format

State files use JSON format with Ethereum quantity encoding:

```json
{
  "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": {
    "balance": "0xde0b6b3a7640000",
    "nonce": "0x1",
    "code": "0x60806040...",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "storage": {
      "0x0": "0x2a",
      "0x1": "0x64"
    }
  },
  "0x0000000000000000000000000000000000100001": {
    "balance": "0x0",
    "nonce": "0x0",
    "code": "0x",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "storage": {}
  }
}
```

### Field Descriptions

- **balance**: Account balance in wei (quantity format: 0x-prefixed hex without leading zeros)
- **nonce**: Transaction nonce (quantity format)
- **code**: Contract bytecode (hex string with 0x prefix)
- **codeHash**: Keccak256 hash of the code (hex string with 0x prefix, always 32 bytes)
- **storage**: Key-value map of storage slots (both keys and values use quantity format)

### Format Notes

- Uses Ethereum "quantity" format: `0x` prefix with no leading zeros (except `0x0` for zero)
- Empty code is represented as `"0x"`
- Empty storage is represented as `{}`
- All addresses are checksummed (though case-insensitive during parsing)

## Examples

### Example 1: Simple Execution

Execute bytecode that returns value 1:

```bash
mega-evme run 0x60016000526001601ff3
# Output: 0x01
```

Bytecode breakdown:
- `60 01`: PUSH1 0x01
- `60 00`: PUSH1 0x00
- `52`: MSTORE (store 0x01 at memory position 0)
- `60 01`: PUSH1 0x01
- `60 1f`: PUSH1 0x1f (31 bytes offset)
- `f3`: RETURN (return 1 byte starting at position 31)

### Example 2: State Persistence

Create initial state, execute, and verify:

```bash
# Create initial state file
cat > state.json << 'EOF'
{
  "0x1000000000000000000000000000000000000001": {
    "balance": "0x1000000",
    "nonce": "0x0",
    "code": "0x",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "storage": {}
  }
}
EOF

# Execute with prestate
mega-evme run 0x60016000526001601ff3 --prestate state.json --dump
```

### Example 3: Contract Deployment

Deploy a simple storage contract:

```bash
# Init code that deploys runtime code
mega-evme run --create 0x600a600c600039600a6000f3602a60005260206000f3 --dump
```

### Example 4: Testing with Tracing

Debug contract execution with full traces:

```bash
mega-evme run contract.hex \
  --tracer trace \
  --trace.enable-return-data \
  --trace.output trace.json \
  --gas 10000000
```

### Example 5: SALT Bucket Testing

Test storage operations with bucket capacity limits:

```bash
# Set up account with code
cat > contract_state.json << 'EOF'
{
  "0x0000000000000000000000000000000000000001": {
    "balance": "0x0",
    "nonce": "0x0",
    "code": "0x60aa60005560bb60015560cc600255",
    "codeHash": "0xabcd...",
    "storage": {}
  }
}
EOF

# Execute with bucket capacity limits
mega-evme run 0x00 \
  --receiver 0x0000000000000000000000000000000000000001 \
  --prestate contract_state.json \
  --bucket-capacity 1:1000 \
  --bucket-capacity 2:2000 \
  --dump
```

### Example 6: Benchmarking Gas Costs

Compare gas usage between implementations:

```bash
# Benchmark first version
mega-evme run contract_v1.hex --bench

# Benchmark optimized version
mega-evme run contract_v2.hex --bench
```

## Architecture

### Module Structure

```
run/
├── mod.rs          # Module exports and utility functions
│                   # - load_code() / load_input(): Input loading
│                   # - parse_bucket_capacity(): Bucket config parsing
│                   # - StateDump: State serialization struct
│                   # - AccountState: Account data struct
└── cmd.rs          # Command implementation
                    # - Cmd: CLI argument struct
                    # - RunResult: Execution result struct
                    # - Main execution logic
```

### Key Components

#### `Cmd` Struct

Defines all CLI arguments using `clap`:
- Transaction configuration (gas, value, sender, etc.)
- State management (prestate, dump)
- Tracing options
- Block environment
- Fork selection
- SALT configuration

#### `StateDump` / `AccountState`

Handles state serialization/deserialization:
- **StateDump**: Root struct containing accounts map
- **AccountState**: Individual account data (balance, nonce, code, storage)
- Uses `alloy_serde` for proper Ethereum quantity format
- Implements `from_evm_state()` for conversion from REVM state

#### Execution Flow

1. **Input Loading**: Load bytecode and input data
2. **State Setup**: Create initial state (prestate + code + sender balance)
3. **Environment Configuration**: Setup cfg, block, tx, and external envs
4. **Execution**: Run transaction with optional tracing
5. **Output**: Print results, traces, and state dumps

### Dependencies

- **revm**: Core EVM execution engine
- **alloy-primitives**: Ethereum types (Address, U256, Bytes, B256)
- **alloy-serde**: Proper Ethereum serialization
- **revm-inspectors**: Execution tracing
- **clap**: CLI argument parsing
- **serde_json**: JSON serialization

### Design Decisions

1. **Explicit Balance Allocation**: Only allocate sender balance when `--sender.balance` is specified. This prevents implicit behavior and gives users full control.

2. **Built-in Serialization**: Use `alloy-primitives`' built-in serde implementations instead of custom serialization. This ensures compatibility with Ethereum tooling and reduces maintenance burden.

3. **Structured State**: Use `StateDump` and `AccountState` structs instead of manual JSON manipulation. This provides type safety and better error messages.

4. **Separation of Concerns**: Keep CLI parsing (`Cmd`), execution logic, and state management separate for better testability and maintainability.

5. **Flexible Output**: Support both console and file output for traces and state dumps, making it suitable for both interactive and automated use.

## See Also

- [Project Architecture]../../../../ARCH.md
- [Main README]../../../../README.md
- [Main README]../../../../README.md