@@ -1128,7 +1128,9 @@ def test_create_silent_failure_refunds_state_gas(
11281128 """
11291129 gas_limit_cap = fork .transaction_gas_limit_cap ()
11301130 assert gas_limit_cap is not None
1131+ gas_costs = fork .gas_costs ()
11311132 sstore_state_gas = fork .sstore_state_gas ()
1133+ intrinsic_cost = fork .transaction_intrinsic_cost_calculator ()()
11321134
11331135 mstore_value , size = init_code_at_high_bytes (Op .STOP )
11341136 value = 1 if failure_mode == "insufficient_balance" else 0
@@ -1150,7 +1152,17 @@ def test_create_silent_failure_refunds_state_gas(
11501152 sender = pre .fund_eoa (),
11511153 )
11521154
1153- expected = sstore_state_gas
1155+ # CREATE's GAS_NEW_ACCOUNT is refunded (silent failure, no child
1156+ # spawned). SSTORE's state portion is tracked separately in
1157+ # tx_state.
1158+ tx_regular = (
1159+ intrinsic_cost
1160+ + factory_code .gas_cost (fork )
1161+ - gas_costs .GAS_NEW_ACCOUNT
1162+ - sstore_state_gas
1163+ )
1164+ tx_state = sstore_state_gas
1165+ expected = max (tx_regular , tx_state )
11541166 blockchain_test (
11551167 pre = pre ,
11561168 blocks = [Block (txs = [tx ], header_verify = Header (gas_used = expected ))],
@@ -1186,7 +1198,9 @@ def test_create_child_revert_refunds_state_gas(
11861198 """
11871199 gas_limit_cap = fork .transaction_gas_limit_cap ()
11881200 assert gas_limit_cap is not None
1201+ gas_costs = fork .gas_costs ()
11891202 sstore_state_gas = fork .sstore_state_gas ()
1203+ intrinsic_cost = fork .transaction_intrinsic_cost_calculator ()()
11901204
11911205 init_code = Op .REVERT (0 , 0 )
11921206 mstore_value , size = init_code_at_high_bytes (init_code )
@@ -1198,13 +1212,12 @@ def test_create_child_revert_refunds_state_gas(
11981212 )
11991213
12001214 storage = Storage ()
1201- factory = pre .deploy_contract (
1202- code = (
1203- Op .MSTORE (0 , mstore_value )
1204- + Op .POP (create_call )
1205- + Op .SSTORE (storage .store_next (1 , "reservoir_ok" ), 1 )
1206- ),
1215+ factory_code = (
1216+ Op .MSTORE (0 , mstore_value )
1217+ + Op .POP (create_call )
1218+ + Op .SSTORE (storage .store_next (1 , "reservoir_ok" ), 1 )
12071219 )
1220+ factory = pre .deploy_contract (code = factory_code )
12081221
12091222 gas_limit = (
12101223 gas_limit_cap
@@ -1217,7 +1230,19 @@ def test_create_child_revert_refunds_state_gas(
12171230 sender = pre .fund_eoa (),
12181231 )
12191232
1220- expected = sstore_state_gas
1233+ # CREATE's GAS_NEW_ACCOUNT is refunded on child REVERT. SSTORE's
1234+ # state portion is tracked separately. Child REVERT regular
1235+ # (init_code execution) is propagated via
1236+ # incorporate_child_on_error.
1237+ tx_regular = (
1238+ intrinsic_cost
1239+ + factory_code .gas_cost (fork )
1240+ - gas_costs .GAS_NEW_ACCOUNT
1241+ - sstore_state_gas
1242+ + init_code .gas_cost (fork )
1243+ )
1244+ tx_state = sstore_state_gas
1245+ expected = max (tx_regular , tx_state )
12211246 blockchain_test (
12221247 pre = pre ,
12231248 blocks = [Block (txs = [tx ], header_verify = Header (gas_used = expected ))],
@@ -1246,13 +1271,17 @@ def test_create_child_halt_refunds_state_gas(
12461271
12471272 Exceptional halts (invalid opcode, EIP-3541 invalid prefix)
12481273 consume all forwarded gas as `regular_gas_used`, so block
1249- accounting cannot strictly discriminate via header gas. The
1250- probe SSTORE confirms the reservoir holds the refunded
1251- `GAS_NEW_ACCOUNT` for state-gas-dependent operations.
1274+ accounting cannot strictly discriminate via header gas. Tight
1275+ gas tuning via a caller wrapper leaves the factory with just
1276+ enough `gas_left` to pay the probe SSTORE's regular portion
1277+ but not enough to spill the state portion, so the probe SSTORE
1278+ can only succeed via the refunded reservoir.
12521279 """
12531280 gas_limit_cap = fork .transaction_gas_limit_cap ()
12541281 assert gas_limit_cap is not None
1282+ gas_costs = fork .gas_costs ()
12551283 sstore_state_gas = fork .sstore_state_gas ()
1284+ new_account_state_gas = gas_costs .GAS_NEW_ACCOUNT
12561285
12571286 init_code : Op | Bytecode
12581287 if failure_mode == "initcode_halt" :
@@ -1278,9 +1307,27 @@ def test_create_child_halt_refunds_state_gas(
12781307 ),
12791308 )
12801309
1310+ # Tight gas tuning: child halt consumes all forwarded gas as
1311+ # regular_gas_used. Factory retains
1312+ # ~(forwarded - pre_sstore_regular) / 64 after CREATE. Target
1313+ # the discrimination window `(probe_regular,
1314+ # probe_regular + sstore_state_gas)` so the probe SSTORE
1315+ # regular fits but state gas spillover from `gas_left` under
1316+ # the old behavior OOGs.
1317+ pre_sstore_code = Op .MSTORE (0 , mstore_value ) + Op .POP (create_call )
1318+ pre_sstore_regular = pre_sstore_code .gas_cost (fork ) - new_account_state_gas
1319+ probe_code = Op .SSTORE (0 , 1 )
1320+ probe_regular = probe_code .gas_cost (fork ) - sstore_state_gas
1321+ target_gas_left = probe_regular + sstore_state_gas // 2
1322+ forwarded_gas = target_gas_left * 64 + pre_sstore_regular
1323+ # Reservoir sized for CREATE charge only — SSTORE must pull
1324+ # from the refunded reservoir, not from spill.
1325+ caller = pre .deploy_contract (
1326+ code = Op .CALL (gas = forwarded_gas , address = factory )
1327+ )
12811328 tx = Transaction (
1282- to = factory ,
1283- gas_limit = gas_limit_cap + sstore_state_gas ,
1329+ to = caller ,
1330+ gas_limit = gas_limit_cap + new_account_state_gas ,
12841331 sender = pre .fund_eoa (),
12851332 )
12861333
0 commit comments