24
24
REFERENCE_SPEC_GIT_PATH = "TODO"
25
25
REFERENCE_SPEC_VERSION = "TODO"
26
26
27
- MAX_CONTRACT_SIZE = 24 * 1024
28
- GAS_LIMIT = 36_000_000 # TODO: Parametrize using the (yet to be implemented) block gas limit
27
+ MAX_CONTRACT_SIZE = 24 * 1024 # TODO: This could be a fork property
28
+ BLOCK_GAS_LIMIT = 36_000_000 # TODO: Parametrize using the (yet to be implemented) block gas limit
29
+ # OPCODE_GAS_LIMIT = BLOCK_GAS_LIMIT # TODO: Reduced in order to run the test in a reasonable time
30
+ OPCODE_GAS_LIMIT = 100_000
29
31
30
32
XOR_TABLE_SIZE = 256
31
33
XOR_TABLE = [Hash (i ).sha256 () for i in range (XOR_TABLE_SIZE )]
37
39
"opcode" ,
38
40
[
39
41
Op .EXTCODESIZE ,
40
- Op .EXTCODEHASH ,
41
42
],
42
43
)
43
44
@pytest .mark .valid_from ("Cancun" )
@@ -59,7 +60,7 @@ def test_worst_bytecode_single_opcode(
59
60
The test is performed in the last block of the test, and the entire block gas limit is
60
61
consumed by repeated opcode executions.
61
62
"""
62
- env = Environment (gas_limit = GAS_LIMIT )
63
+ env = Environment (gas_limit = BLOCK_GAS_LIMIT )
63
64
64
65
# The initcode will take its address as a starting point to the input to the keccak
65
66
# hash function.
@@ -112,25 +113,21 @@ def test_worst_bytecode_single_opcode(
112
113
)
113
114
factory_caller_address = pre .deploy_contract (code = factory_caller_code )
114
115
115
- # TODO: The correct way to calculate this is to use the gas costs and the transaction
116
- # intrinsic cost calculator, but this is generating approx 13,822 calls, and deploying this
117
- # many different contracts requires 1,974 blocks.
118
- # gas_costs = fork.gas_costs()
119
- # intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
120
- # max_number_of_contract_calls = (GAS_LIMIT - intrinsic_gas_cost_calc()) // (
121
- # gas_costs.G_VERY_LOW + gas_costs.G_BASE + gas_costs.G_COLD_ACCOUNT_ACCESS
122
- # )
123
- max_number_of_contract_calls = 10
116
+ gas_costs = fork .gas_costs ()
117
+ intrinsic_gas_cost_calc = fork .transaction_intrinsic_cost_calculator ()
118
+ max_number_of_contract_calls = (OPCODE_GAS_LIMIT - intrinsic_gas_cost_calc ()) // (
119
+ gas_costs .G_VERY_LOW + gas_costs .G_BASE + gas_costs .G_COLD_ACCOUNT_ACCESS
120
+ )
124
121
total_contracts_to_deploy = max_number_of_contract_calls
125
122
approximate_gas_per_deployment = 4_970_000 # Obtained from evm tracing
126
- contracts_deployed_per_tx = GAS_LIMIT // approximate_gas_per_deployment
123
+ contracts_deployed_per_tx = BLOCK_GAS_LIMIT // approximate_gas_per_deployment
127
124
128
125
deploy_txs = []
129
126
130
127
def generate_deploy_tx (contracts_to_deploy : int ):
131
128
return Transaction (
132
129
to = factory_caller_address ,
133
- gas_limit = GAS_LIMIT ,
130
+ gas_limit = BLOCK_GAS_LIMIT ,
134
131
gas_price = 10 ** 9 , # Bump required due to the amount of full blocks
135
132
data = Hash (contracts_deployed_per_tx ),
136
133
sender = pre .fund_eoa (),
@@ -154,11 +151,19 @@ def generate_deploy_tx(contracts_to_deploy: int):
154
151
post [deployed_contract_address ] = Account (nonce = 1 )
155
152
deployed_contract_addresses .append (deployed_contract_address )
156
153
157
- opcode_code = sum (opcode (address = address ) for address in deployed_contract_addresses ) + Op .STOP
154
+ opcode_code = (
155
+ sum (Op .POP (opcode (address = address )) for address in deployed_contract_addresses ) + Op .STOP
156
+ )
157
+ if len (opcode_code ) > MAX_CONTRACT_SIZE :
158
+ # TODO: A workaround could be to split the opcode code into multiple contracts
159
+ # and call them in sequence.
160
+ raise ValueError (
161
+ f"Code size { len (opcode_code )} exceeds maximum code size { MAX_CONTRACT_SIZE } "
162
+ )
158
163
opcode_address = pre .deploy_contract (code = opcode_code )
159
164
opcode_tx = Transaction (
160
165
to = opcode_address ,
161
- gas_limit = GAS_LIMIT ,
166
+ gas_limit = OPCODE_GAS_LIMIT ,
162
167
gas_price = 10 ** 9 , # Bump required due to the amount of full blocks
163
168
sender = pre .fund_eoa (),
164
169
)
0 commit comments