2727 Bytecode ,
2828 CodeGasMeasure ,
2929 Fork ,
30+ Hash ,
3031 Header ,
3132 Initcode ,
3233 Op ,
@@ -395,14 +396,15 @@ def test_create_tx_gas_boundary(
395396 [
396397 pytest .param ("insufficient_balance" , id = "insufficient_balance" ),
397398 pytest .param ("nonce_overflow" , id = "nonce_overflow" ),
399+ pytest .param (None , id = "no_error" ),
398400 ],
399401)
400402def test_aborted_create_does_not_warm_address (
401403 state_test : StateTestFiller ,
402404 pre : Alloc ,
403405 fork : Fork ,
404406 create_opcode : Op ,
405- abort_mode : str ,
407+ abort_mode : str | None ,
406408) -> None :
407409 """
408410 Verify a silently-aborted CREATE does not warm the target address.
@@ -413,67 +415,59 @@ def test_aborted_create_does_not_warm_address(
413415 ``BALANCE`` of that address is therefore charged the full
414416 ``COLD_ACCOUNT_ACCESS`` (3,000), not ``WARM_ACCESS`` (100).
415417 """
416- gas_costs = fork .gas_costs ()
417-
418418 init_code = Op .STOP
419419 init_code_bytes = bytes (init_code )
420- init_code_len = len (init_code_bytes )
420+ init_code_len = len (init_code )
421421
422- value = 1 if abort_mode == "insufficient_balance" else 0
423- create_call = (
424- Op .CREATE2 (value = value , offset = 0 , size = init_code_len , salt = 0 )
425- if create_opcode == Op .CREATE2
426- else Op .CREATE (value = value , offset = 0 , size = init_code_len )
422+ create_value = 1
423+ create_call = create_opcode (
424+ value = create_value , offset = 0 , size = init_code_len
427425 )
428426
429427 # After the aborted CREATE, measure the BALANCE access of the
430- # would-be address (passed via calldata). The CREATE runs before the
431- # measured region; the BALANCE leaves one stack item (the balance),
432- # and the overhead subtracts BALANCE's own cold cost so the stored
433- # value is exactly the account-access cost.
434- balance_code = Op .BALANCE (Op .CALLDATALOAD (0 ))
435- overhead = balance_code .gas_cost (fork ) - Op .BALANCE (
436- address_warm = False
437- ).gas_cost (fork )
438- measure = CodeGasMeasure (
439- code = balance_code ,
440- overhead_cost = overhead ,
441- extra_stack_items = 1 ,
442- )
428+ # would-be address (passed via calldata).
429+ # The address should only be warm when the CREATE/CREATE2 opcode
430+ # successfully reached initcode execution stage.
431+ address_warm = abort_mode is None
432+ balance_code = Op .BALANCE (Op .CALLDATALOAD (0 ), address_warm = address_warm )
433+ measure = CodeGasMeasure (code = balance_code , extra_stack_items = 1 )
443434
444435 setup = Op .MSTORE (
445436 0 ,
446437 int .from_bytes (init_code_bytes , "big" ) << (256 - 8 * init_code_len ),
447438 )
448439 factory_code = setup + Op .POP (create_call ) + measure
449440
450- if abort_mode == "nonce_overflow" :
451- factory = pre .deploy_contract (code = factory_code , nonce = 2 ** 64 - 1 )
452- else :
453- # Zero balance so the value=1 endowment cannot be satisfied.
454- factory = pre .deploy_contract (code = factory_code , balance = 0 )
455-
456- if create_opcode == Op .CREATE2 :
457- from execution_testing import compute_create2_address
441+ factory_nonce = 2 ** 64 - 1 if abort_mode == "nonce_overflow" else 1
442+ factory_balance = create_value
443+ if abort_mode == "insufficient_balance" :
444+ factory_balance -= 1
445+ factory = pre .deploy_contract (
446+ code = factory_code , nonce = factory_nonce , balance = factory_balance
447+ )
458448
459- target_address = compute_create2_address (
460- address = factory , salt = 0 , initcode = init_code_bytes
461- )
462- else :
463- target_address = compute_create_address (address = factory , nonce = 1 )
449+ target_address = compute_create_address (
450+ address = factory ,
451+ salt = 0 ,
452+ initcode = init_code_bytes ,
453+ nonce = factory_nonce ,
454+ opcode = create_opcode ,
455+ )
464456
465457 tx = Transaction (
466458 to = factory ,
467- # Left-pad the 20-byte address to a 32-byte calldata word so
468- # CALLDATALOAD(0) reads it in the low 20 bytes.
469- data = b"\x00 " * 12 + bytes (target_address ),
470- gas_limit = 1_000_000 ,
459+ data = Hash (target_address , left_padding = True ),
471460 sender = pre .fund_eoa (),
472461 )
473462
474- # The BALANCE must be cold: the aborted CREATE never warmed the
475- # would-be address.
476- post = {factory : Account (storage = {0 : gas_costs .COLD_ACCOUNT_ACCESS })}
463+ # The BALANCE must be cold: in case of error, the aborted CREATE never
464+ # warmed the would-be address.
465+ post = {
466+ factory : Account (storage = {0 : balance_code .gas_cost (fork )}),
467+ target_address : Account (nonce = 1 )
468+ if abort_mode is None
469+ else Account .NONEXISTENT ,
470+ }
477471 state_test (pre = pre , post = post , tx = tx )
478472
479473
0 commit comments