or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assembly.mddisassembly.mdfork-management.mdindex.mdinstruction-analysis.md

fork-management.mddocs/

0

# Fork Management

1

2

Comprehensive support for all Ethereum hard forks with proper opcode evolution, gas cost updates, and utilities for fork selection and block number conversion. PyEVMAsm accurately handles the historical development of the EVM instruction set across all major Ethereum upgrades.

3

4

## Capabilities

5

6

### Fork Constants and Configuration

7

8

Default fork configuration and comprehensive fork support information.

9

10

```python { .api }

11

DEFAULT_FORK: str # Current default fork name ("istanbul")

12

```

13

14

**Usage Examples:**

15

16

```python

17

from pyevmasm import DEFAULT_FORK

18

19

print(f"Default fork: {DEFAULT_FORK}") # istanbul

20

21

# Supported forks can be accessed via instruction_tables.keys()

22

from pyevmasm import instruction_tables

23

supported_forks = tuple(instruction_tables.keys())

24

print(f"Supported forks: {supported_forks}")

25

# ('frontier', 'homestead', 'tangerine_whistle', 'spurious_dragon',

26

# 'byzantium', 'constantinople', 'petersburg', 'serenity', 'istanbul')

27

28

# Check if a fork is supported

29

fork_name = "byzantium"

30

if fork_name in instruction_tables:

31

print(f"{fork_name} is supported")

32

```

33

34

### Instruction Tables

35

36

Fork-specific instruction lookup tables providing accurate opcode definitions for each Ethereum hard fork.

37

38

```python { .api }

39

instruction_tables: dict # Mapping of fork names to InstructionTable instances

40

41

# Individual fork instruction tables

42

frontier_instruction_table: InstructionTable

43

homestead_instruction_table: InstructionTable

44

tangerine_whistle_instruction_table: InstructionTable

45

spurious_dragon_instruction_table: InstructionTable

46

byzantium_instruction_table: InstructionTable

47

constantinople_instruction_table: InstructionTable

48

serenity_instruction_table: InstructionTable

49

istanbul_instruction_table: InstructionTable

50

```

51

52

**Usage Examples:**

53

54

```python

55

from pyevmasm import instruction_tables

56

57

# Access fork-specific instruction table

58

byzantium_table = instruction_tables["byzantium"]

59

frontier_table = instruction_tables["frontier"]

60

61

# Look up instructions by opcode

62

returndatasize = byzantium_table[0x3d] # RETURNDATASIZE

63

print(f"Byzantium 0x3d: {returndatasize.name}") # RETURNDATASIZE

64

65

# Same opcode in frontier (before RETURNDATASIZE existed)

66

try:

67

frontier_returndatasize = frontier_table[0x3d]

68

print(f"Frontier 0x3d: {frontier_returndatasize.name}") # INVALID

69

except KeyError:

70

print("0x3d not defined in frontier")

71

72

# Look up by mnemonic

73

push1 = byzantium_table["PUSH1"]

74

print(f"PUSH1 opcode: 0x{push1.opcode:02x}") # 0x60

75

```

76

77

### InstructionTable Class

78

79

Fork-specific instruction lookup and iteration capabilities.

80

81

```python { .api }

82

class InstructionTable:

83

"""

84

EVM Instruction factory providing fork-specific instruction definitions.

85

Implements an immutable, iterable instruction lookup table indexed by

86

both mnemonic and opcode.

87

"""

88

89

def __getitem__(self, key) -> Instruction:

90

"""

91

Get instruction by opcode (int) or mnemonic (str).

92

93

Parameters:

94

- key (int | str): Opcode value (0x00-0xFF) or mnemonic name

95

96

Returns:

97

Instruction: New Instruction instance for the specified opcode/mnemonic

98

99

Raises:

100

KeyError: If opcode/mnemonic not found in this fork

101

"""

102

103

def get(self, key, default=None) -> Instruction:

104

"""

105

Get instruction with default fallback.

106

107

Parameters:

108

- key (int | str): Opcode value or mnemonic name

109

- default: Default value if key not found

110

111

Returns:

112

Instruction | default: Instruction instance or default value

113

"""

114

115

def __contains__(self, key) -> bool:

116

"""Check if opcode or mnemonic exists in this fork."""

117

118

def __iter__(self):

119

"""Iterate over all instructions in opcode order."""

120

121

def keys(self):

122

"""Get sorted list of all opcodes in this fork."""

123

```

124

125

**Usage Examples:**

126

127

```python

128

from pyevmasm import instruction_tables

129

130

# Get instruction table for specific fork

131

istanbul_table = instruction_tables["istanbul"]

132

133

# Multiple ways to access instructions

134

push1_by_opcode = istanbul_table[0x60] # By opcode

135

push1_by_name = istanbul_table["PUSH1"] # By mnemonic

136

print(f"Same instruction: {push1_by_opcode.name == push1_by_name.name}") # True

137

138

# Safe access with default

139

unknown = istanbul_table.get(0xff, None) # SELFDESTRUCT or None depending on context

140

valid_instr = istanbul_table.get("ADD") # Returns ADD instruction

141

142

# Check existence

143

has_returndatasize = "RETURNDATASIZE" in istanbul_table # True

144

has_returndatasize_frontier = "RETURNDATASIZE" in instruction_tables["frontier"] # False

145

146

# Iterate all instructions

147

for instruction in istanbul_table:

148

if instruction.is_arithmetic:

149

print(f"Arithmetic: {instruction.name}")

150

151

# Get all opcodes

152

all_opcodes = istanbul_table.keys()

153

print(f"Total opcodes in Istanbul: {len(all_opcodes)}")

154

```

155

156

### Block Number to Fork Conversion

157

158

Utility function to determine the appropriate fork for a given Ethereum block number.

159

160

```python { .api }

161

def block_to_fork(block_number: int) -> str:

162

"""

163

Convert Ethereum block number to appropriate fork name.

164

165

Parameters:

166

- block_number (int): Ethereum block number

167

168

Returns:

169

str: Fork name appropriate for the given block number

170

171

Example:

172

>>> block_to_fork(0)

173

'frontier'

174

>>> block_to_fork(4370000)

175

'byzantium'

176

>>> block_to_fork(7280000)

177

'petersburg'

178

"""

179

```

180

181

**Usage Examples:**

182

183

```python

184

from pyevmasm import block_to_fork

185

186

# Historical block analysis

187

print(f"Block 0: {block_to_fork(0)}") # frontier

188

print(f"Block 1150000: {block_to_fork(1150000)}") # homestead

189

print(f"Block 4370000: {block_to_fork(4370000)}") # byzantium

190

print(f"Block 7280000: {block_to_fork(7280000)}") # petersburg

191

print(f"Recent block: {block_to_fork(15000000)}") # petersburg (latest)

192

193

# Use in analysis

194

def analyze_transaction_bytecode(bytecode, block_number):

195

fork = block_to_fork(block_number)

196

return disassemble_hex(bytecode, fork=fork)

197

```

198

199

## Fork Evolution and Differences

200

201

### Frontier (Block 0)

202

- Original EVM instruction set

203

- Basic arithmetic, comparison, bitwise, and system operations

204

- All core opcodes: STOP, ADD, MUL, PUSH, POP, MLOAD, SSTORE, CALL, etc.

205

206

### Homestead (Block 1,150,000)

207

- Added DELEGATECALL (0xf4)

208

- Enhanced contract creation security

209

210

### Tangerine Whistle (Block 2,463,000)

211

- Gas cost increases for several opcodes

212

- EXTCODESIZE, EXTCODECOPY, BALANCE, SLOAD, CALL operations became more expensive

213

- SELFDESTRUCT gas cost increased

214

215

### Spurious Dragon (Block 2,675,000)

216

- No new opcodes

217

- Additional gas cost and state tree adjustments

218

219

### Byzantium (Block 4,370,000)

220

- Added RETURNDATASIZE (0x3d), RETURNDATACOPY (0x3e)

221

- Added STATICCALL (0xfa) for state-reading calls

222

- Added REVERT (0xfd) for better error handling

223

224

### Constantinople/Petersburg (Block 7,280,000)

225

- Added shift operations: SHL (0x1b), SHR (0x1c), SAR (0x1d)

226

- Added EXTCODEHASH (0x3f) for code hash retrieval

227

- Added CREATE2 (0xf5) for deterministic contract addresses

228

229

### Istanbul (Latest Default)

230

- Updated gas costs for BALANCE, EXTCODEHASH, SLOAD

231

- Added CHAINID (0x46) and SELFBALANCE (0x47)

232

233

**Fork Compatibility Examples:**

234

235

```python

236

from pyevmasm import assemble_hex, disassemble_one

237

238

# Instructions available in different forks

239

def test_fork_compatibility():

240

# This works in all forks

241

basic_code = assemble_hex("PUSH1 0x01\nADD", fork="frontier")

242

243

# DELEGATECALL introduced in homestead

244

try:

245

homestead_code = assemble_hex("DELEGATECALL", fork="homestead") # Works

246

frontier_code = assemble_hex("DELEGATECALL", fork="frontier") # Fails

247

except AssembleError:

248

print("DELEGATECALL not available in frontier")

249

250

# RETURNDATASIZE introduced in byzantium

251

byzantium_instr = disassemble_one(b'\x3d', fork="byzantium") # RETURNDATASIZE

252

frontier_instr = disassemble_one(b'\x3d', fork="frontier") # INVALID

253

254

# Gas costs change between forks

255

balance_frontier = disassemble_one(b'\x31', fork="frontier") # fee: 20

256

balance_istanbul = disassemble_one(b'\x31', fork="istanbul") # fee: 700

257

258

print(f"BALANCE gas: frontier={balance_frontier.fee}, istanbul={balance_istanbul.fee}")

259

260

# Choose appropriate fork for analysis

261

def analyze_historical_transaction(bytecode, block_number):

262

fork = block_to_fork(block_number)

263

instructions = list(disassemble_all(bytecode, fork=fork))

264

265

# Analysis with correct historical opcodes

266

for instr in instructions:

267

if instr.name == "INVALID":

268

print(f"Invalid opcode 0x{instr.opcode:02x} at block {block_number} (fork: {fork})")

269

```

270

271

## Best Practices

272

273

### Fork Selection

274

- Use `DEFAULT_FORK` for current/modern bytecode analysis

275

- Use `block_to_fork()` for historical transaction analysis

276

- Specify explicit fork when analyzing specific deployment contexts

277

- Test compatibility when working with cross-fork smart contracts

278

279

### Instruction Table Caching

280

- Instruction tables are pre-computed and immutable

281

- Safe to cache table references for performance

282

- Each table lookup creates new Instruction instances

283

284

### Version-Aware Analysis

285

```python

286

from pyevmasm import instruction_tables, block_to_fork

287

288

def version_aware_analysis(bytecode, context_block=None):

289

if context_block:

290

fork = block_to_fork(context_block)

291

else:

292

fork = DEFAULT_FORK

293

294

table = instruction_tables[fork]

295

# Proceed with fork-appropriate analysis

296

return disassemble_all(bytecode, fork=fork)

297

```