1
1
"""Benchmark code generator classes for creating optimized bytecode patterns."""
2
2
3
+ from ethereum_test_base_types import Address
3
4
from ethereum_test_forks import Fork
4
5
from ethereum_test_specs .benchmark import BenchmarkCodeGenerator
5
6
from ethereum_test_types import Alloc , Transaction
10
11
class JumpLoopGenerator (BenchmarkCodeGenerator ):
11
12
"""Generates bytecode that loops execution using JUMP operations."""
12
13
13
- def deploy_contracts (self , pre : Alloc , fork : Fork ) -> None :
14
+ def deploy_contracts (self , pre : Alloc , fork : Fork ) -> Address :
14
15
"""Deploy the looping contract."""
15
16
# Benchmark Test Structure:
16
17
# setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length)
17
- code = self .generate_repeated_code (self .attack_block , self .setup , fork )
18
+ code = self .generate_repeated_code (self .attack_block , self .setup , self . cleanup , fork )
18
19
self ._contract_address = pre .deploy_contract (code = code )
20
+ return self ._contract_address
19
21
20
22
def generate_transaction (self , pre : Alloc , gas_limit : int , fork : Fork ) -> Transaction :
21
23
"""Generate transaction that executes the looping contract."""
22
24
if not hasattr (self , "_contract_address" ):
23
- raise ValueError ( " deploy_contracts must be called before generate_transaction" )
25
+ self . deploy_contracts ( pre , fork )
24
26
25
27
return Transaction (
26
28
to = self ._contract_address ,
@@ -32,7 +34,7 @@ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transa
32
34
class ExtCallGenerator (BenchmarkCodeGenerator ):
33
35
"""Generates bytecode that fills the contract to maximum allowed code size."""
34
36
35
- def deploy_contracts (self , pre : Alloc , fork : Fork ) -> None :
37
+ def deploy_contracts (self , pre : Alloc , fork : Fork ) -> Address :
36
38
"""Deploy both target and caller contracts."""
37
39
# Benchmark Test Structure:
38
40
# There are two contracts:
@@ -45,21 +47,22 @@ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None:
45
47
46
48
# Deploy target contract that contains the actual attack block
47
49
self ._target_contract_address = pre .deploy_contract (
48
- code = self .attack_block * max_iterations
50
+ code = self .setup + self . attack_block * max_iterations
49
51
)
50
52
51
53
# Create caller contract that repeatedly calls the target contract
52
54
# attack = POP(STATICCALL(GAS, target_contract_address, 0, 0, 0, 0))
53
55
# setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length)
54
56
code_sequence = Op .POP (Op .STATICCALL (Op .GAS , self ._target_contract_address , 0 , 0 , 0 , 0 ))
55
57
56
- caller_code = self .generate_repeated_code (code_sequence , Bytecode (), fork )
58
+ caller_code = self .generate_repeated_code (code_sequence , Bytecode (), self . cleanup , fork )
57
59
self ._contract_address = pre .deploy_contract (code = caller_code )
60
+ return self ._contract_address
58
61
59
62
def generate_transaction (self , pre : Alloc , gas_limit : int , fork : Fork ) -> Transaction :
60
63
"""Generate transaction that executes the caller contract."""
61
64
if not hasattr (self , "_contract_address" ):
62
- raise ValueError ( " deploy_contracts must be called before generate_transaction" )
65
+ self . deploy_contracts ( pre , fork )
63
66
64
67
return Transaction (
65
68
to = self ._contract_address ,
0 commit comments