@@ -2255,3 +2255,65 @@ def test_worst_push(
2255
2255
post = {},
2256
2256
tx = tx ,
2257
2257
)
2258
+
2259
+
2260
+ @pytest .mark .parametrize (
2261
+ "opcode" ,
2262
+ [Op .RETURN , Op .REVERT ],
2263
+ )
2264
+ @pytest .mark .parametrize (
2265
+ "return_size, return_non_zero_data" ,
2266
+ [
2267
+ pytest .param (0 , False , id = "empty" ),
2268
+ pytest .param (1024 , True , id = "1KiB of non-zero data" ),
2269
+ pytest .param (1024 , False , id = "1KiB of zero data" ),
2270
+ pytest .param (1024 * 1024 , True , id = "1MiB of non-zero data" ),
2271
+ pytest .param (1024 * 1024 , False , id = "1MiB of zero data" ),
2272
+ ],
2273
+ )
2274
+ def test_worst_return_revert (
2275
+ state_test : StateTestFiller ,
2276
+ pre : Alloc ,
2277
+ fork : Fork ,
2278
+ opcode : Op ,
2279
+ return_size : int ,
2280
+ return_non_zero_data : bool ,
2281
+ ):
2282
+ """Test running a block with as many RETURN or REVERT as possible."""
2283
+ env = Environment ()
2284
+ max_code_size = fork .max_code_size ()
2285
+
2286
+ # Create the contract that will be called repeatedly.
2287
+ # The bytecode of the contract is:
2288
+ # ```
2289
+ # [CODECOPY(returned_size) -- Conditional if return_non_zero_data]
2290
+ # opcode(returned_size)
2291
+ # <Fill with INVALID opcodes up to the max contract size>
2292
+ # ```
2293
+ # Filling the contract up to the max size is a cheap way of leveraging CODECOPY to return
2294
+ # non-zero bytes if requested. Note that since this is a pre-deploy this cost isn't
2295
+ # relevant for the benchmark.
2296
+ mem_preparation = Op .CODECOPY (size = return_size ) if return_non_zero_data else Bytecode ()
2297
+ executable_code = mem_preparation + opcode (size = return_size )
2298
+ code = executable_code
2299
+ if return_non_zero_data :
2300
+ code += Op .INVALID * (max_code_size - len (executable_code ))
2301
+ target_contract_address = pre .deploy_contract (code = code )
2302
+
2303
+ calldata = Bytecode ()
2304
+ attack_block = Op .POP (Op .STATICCALL (address = target_contract_address ))
2305
+ code = code_loop_precompile_call (calldata , attack_block , fork )
2306
+ code_address = pre .deploy_contract (code = code )
2307
+
2308
+ tx = Transaction (
2309
+ to = code_address ,
2310
+ gas_limit = env .gas_limit ,
2311
+ sender = pre .fund_eoa (),
2312
+ )
2313
+
2314
+ state_test (
2315
+ env = env ,
2316
+ pre = pre ,
2317
+ post = {},
2318
+ tx = tx ,
2319
+ )
0 commit comments