@@ -185,21 +185,26 @@ def test_worst_address_state_warm(
185
185
)
186
186
187
187
188
- class StorageAction :
189
- """Enum for storage actions."""
188
+ class LoadAction :
189
+ """Enum for sload actions."""
190
190
191
191
READ = 1
192
- WRITE_SAME_VALUE = 2
193
- WRITE_NEW_VALUE = 3
192
+
193
+
194
+ class StoreAction :
195
+ """Enum for sstore actions."""
196
+
197
+ WRITE_SAME_VALUE = 1
198
+ WRITE_NEW_VALUE = 2
194
199
195
200
196
201
@pytest .mark .valid_from ("Cancun" )
197
202
@pytest .mark .parametrize (
198
203
"storage_action" ,
199
204
[
200
- pytest .param (StorageAction .READ , id = "SSLOAD" ),
201
- pytest .param (StorageAction .WRITE_SAME_VALUE , id = "SSTORE same value" ),
202
- pytest .param (StorageAction .WRITE_NEW_VALUE , id = "SSTORE new value" ),
205
+ pytest .param (LoadAction .READ , id = "SSLOAD" ),
206
+ pytest .param (StoreAction .WRITE_SAME_VALUE , id = "SSTORE same value" ),
207
+ pytest .param (StoreAction .WRITE_NEW_VALUE , id = "SSTORE new value" ),
203
208
],
204
209
)
205
210
@pytest .mark .parametrize (
@@ -214,7 +219,7 @@ def test_worst_storage_access_cold(
214
219
blockchain_test : BlockchainTestFiller ,
215
220
pre : Alloc ,
216
221
fork : Fork ,
217
- storage_action : StorageAction ,
222
+ storage_action : LoadAction | StoreAction ,
218
223
absent_slots : bool ,
219
224
):
220
225
"""Test running a block with as many cold storage slot accesses as possible."""
@@ -223,17 +228,17 @@ def test_worst_storage_access_cold(
223
228
attack_gas_limit = Environment ().gas_limit
224
229
225
230
cost = gas_costs .G_COLD_SLOAD # All accesses are always cold
226
- if storage_action == StorageAction .WRITE_NEW_VALUE :
231
+ if storage_action == StoreAction .WRITE_NEW_VALUE :
227
232
if not absent_slots :
228
233
cost += gas_costs .G_STORAGE_RESET
229
234
else :
230
235
cost += gas_costs .G_STORAGE_SET
231
- elif storage_action == StorageAction .WRITE_SAME_VALUE :
236
+ elif storage_action == StoreAction .WRITE_SAME_VALUE :
232
237
if absent_slots :
233
238
cost += gas_costs .G_STORAGE_SET
234
239
else :
235
240
cost += gas_costs .G_WARM_SLOAD
236
- elif storage_action == StorageAction .READ :
241
+ elif storage_action == LoadAction .READ :
237
242
cost += gas_costs .G_WARM_SLOAD
238
243
239
244
intrinsic_gas_cost_calc = fork .transaction_intrinsic_cost_calculator ()
@@ -242,30 +247,29 @@ def test_worst_storage_access_cold(
242
247
blocks = []
243
248
244
249
# Contract code
245
- execution_code_body = Bytecode ()
246
- if storage_action == StorageAction . WRITE_SAME_VALUE :
247
- # All the storage slots in the contract are initialized to their index.
248
- # That is, storage slot `i` is initialized to `i`.
249
- execution_code_body = Op . SSTORE ( Op . DUP1 , Op . DUP1 )
250
- elif storage_action == StorageAction . WRITE_NEW_VALUE :
251
- # The new value 2^256-1 is guaranteed to be different from the initial value .
252
- execution_code_body = Op . SSTORE ( Op . DUP2 , Op . NOT ( 0 ))
253
- elif storage_action == StorageAction . READ :
254
- execution_code_body = Op . POP ( Op . SLOAD ( Op . DUP1 ))
255
-
256
- execution_code = Op . PUSH4 ( num_target_slots ) + While (
257
- body = execution_code_body ,
258
- condition = Op . PUSH1 ( 1 ) + Op . SWAP1 + Op . SUB + Op . DUP1 + Op . ISZERO + Op . ISZERO ,
259
- )
250
+ execution_code = Bytecode ()
251
+
252
+ if isinstance ( storage_action , LoadAction ):
253
+ execution_code = sum ( Op . SLOAD ( i ) for i in reversed ( range ( num_target_slots )))
254
+ elif isinstance ( storage_action , StoreAction ):
255
+ if storage_action == StoreAction . WRITE_SAME_VALUE :
256
+ # All the storage slots in the contract are initialized to their index .
257
+ # That is, storage slot `i` is initialized to `i`.
258
+ execution_code += sum ( Op . SSTORE ( i , i ) for i in reversed ( range ( num_target_slots )))
259
+ elif storage_action == StoreAction . WRITE_NEW_VALUE :
260
+ # The new value 2^256-1 is guaranteed to be different from the initial value.
261
+ execution_code += sum (
262
+ Op . SSTORE ( i , Op . NOT ( 0 )) for i in reversed ( range ( num_target_slots ))
263
+ )
264
+
260
265
execution_code_address = pre .deploy_contract (code = execution_code )
261
266
262
267
# Contract creation
263
- slots_init = Bytecode ()
264
- if not absent_slots :
265
- slots_init = Op .PUSH4 (num_target_slots ) + While (
266
- body = Op .SSTORE (Op .DUP1 , Op .DUP1 ),
267
- condition = Op .PUSH1 (1 ) + Op .SWAP1 + Op .SUB + Op .DUP1 + Op .ISZERO + Op .ISZERO ,
268
- )
268
+ slots_init = (
269
+ Bytecode ()
270
+ if absent_slots
271
+ else sum (Op .SSTORE (i , i ) for i in reversed (range (num_target_slots )))
272
+ )
269
273
270
274
# To create the contract, we apply the slots_init code to initialize the storage slots
271
275
# (int the case of absent_slots=False) and then copy the execution code to the contract.
@@ -310,16 +314,17 @@ def test_worst_storage_access_cold(
310
314
@pytest .mark .parametrize (
311
315
"storage_action" ,
312
316
[
313
- pytest .param (StorageAction .READ , id = "SLOAD" ),
314
- pytest .param (StorageAction .WRITE_SAME_VALUE , id = "SSTORE same value" ),
315
- pytest .param (StorageAction .WRITE_NEW_VALUE , id = "SSTORE new value" ),
317
+ pytest .param (LoadAction .READ , id = "SLOAD" ),
318
+ pytest .param (StoreAction .WRITE_SAME_VALUE , id = "SSTORE same value" ),
319
+ pytest .param (StoreAction .WRITE_NEW_VALUE , id = "SSTORE new value" ),
316
320
],
317
321
)
318
322
@pytest .mark .slow ()
319
323
def test_worst_storage_access_warm (
320
324
blockchain_test : BlockchainTestFiller ,
321
325
pre : Alloc ,
322
- storage_action : StorageAction ,
326
+ storage_action : LoadAction | StoreAction ,
327
+ fork : Fork ,
323
328
):
324
329
"""Test running a block with as many warm storage slot accesses as possible."""
325
330
env = Environment (gas_limit = 100_000_000_000 )
@@ -332,16 +337,16 @@ def test_worst_storage_access_warm(
332
337
333
338
# Contract code
334
339
execution_code_body = Bytecode ()
335
- if storage_action == StorageAction .WRITE_SAME_VALUE :
340
+ if storage_action == StoreAction .WRITE_SAME_VALUE :
336
341
execution_code_body = Op .SSTORE (0 , Op .DUP1 )
337
- elif storage_action == StorageAction .WRITE_NEW_VALUE :
338
- execution_code_body = Op .PUSH1 ( 1 ) + Op . ADD + Op . SSTORE (0 , Op .DUP1 )
339
- elif storage_action == StorageAction .READ :
342
+ elif storage_action == StoreAction .WRITE_NEW_VALUE :
343
+ execution_code_body = Op .SSTORE (0 , Op .NOT ( 0 ) )
344
+ elif storage_action == LoadAction .READ :
340
345
execution_code_body = Op .POP (Op .SLOAD (0 ))
341
346
342
- execution_code = Op .PUSH1 (storage_slot_initial_value ) + While (
343
- body = execution_code_body ,
344
- )
347
+ calldata = Op .PUSH1 (storage_slot_initial_value )
348
+ execution_code = code_loop_precompile_call ( calldata , execution_code_body , fork )
349
+
345
350
execution_code_address = pre .deploy_contract (code = execution_code )
346
351
347
352
creation_code = (
0 commit comments