@@ -292,3 +292,90 @@ def test_modexp_entry_points(
292
292
gas_limit = tx_gas_limit ,
293
293
)
294
294
state_test (pre = pre , tx = tx , post = {})
295
+
296
+
297
+ def create_modexp_variable_gas_test_cases ():
298
+ """
299
+ Create test cases for ModExp variable gas cost testing.
300
+
301
+ Returns:
302
+ List of pytest.param objects for the test cases
303
+
304
+ """
305
+ # Test case definitions: (base, exponent, modulus, expected_result, test_id)
306
+ test_cases = [
307
+ ("" , "" , "" , "" , "Z0" ),
308
+ ("01" * 16 , "00" * 16 , "02" * 16 , "00" * 15 + "01" , "S0" ),
309
+ ("01" * 16 , "00" * 15 + "03" , "02" * 16 , "01" * 16 , "S1" ),
310
+ ("01" * 32 , "FF" * 32 , "02" * 32 , "01" * 32 , "S2" ),
311
+ ("01" * 16 , "00" * 40 , "02" * 16 , "00" * 15 + "01" , "S3" ),
312
+ ("01" * 16 , "00" * 39 + "01" , "02" * 16 , "01" * 16 , "S4" ),
313
+ ("01" * 24 , "00" , "02" * 8 , "00" * 7 + "01" , "S5" ),
314
+ ("01" * 8 , "01" , "02" * 24 , "00" * 16 + "01" * 8 , "S6" ),
315
+ ("01" * 40 , "00" * 16 , "02" * 40 , "00" * 39 + "01" , "L0" ),
316
+ ("01" * 40 , "FF" * 32 , "02" * 40 , "01" * 40 , "L1" ),
317
+ ("01" * 40 , "00" * 40 , "02" * 40 , "00" * 39 + "01" , "L2" ),
318
+ ("01" * 40 , "00" * 39 + "01" , "02" * 40 , "01" * 40 , "L3" ),
319
+ ("01" * 48 , "01" , "02" * 16 , "01" * 16 , "L4" ),
320
+ ("01" * 16 , "00" * 40 , "02" * 48 , "00" * 47 + "01" , "L5" ),
321
+ ]
322
+
323
+ # Gas calculation parameters:
324
+ #
325
+ # Please refer to EIP-7883 for details of each function in the gas calculation.
326
+ # Link: https://eips.ethereum.org/EIPS/eip-7883
327
+ #
328
+ # - calculate_multiplication_complexity:
329
+ # - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is Large (L)
330
+ # - Rel (Length Relation): base < modulus (<), base = modulus (=), base > modulus (>)
331
+ #
332
+ # - calculate_iteration_count
333
+ # - Iter (Iteration Case):
334
+ # - A: exp≤32 and exp=0
335
+ # - B: exp≤32 and exp≠0
336
+ # - C: exp>32 and low256=0
337
+ # - D: exp>32 and low256≠0
338
+ #
339
+ # - calculate_gas_cost
340
+ # - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500 (no clamping)
341
+
342
+ # Test case coverage table:
343
+ # ┌─────┬──────┬─────┬──────┬───────┬─────────┬─────────────────────────────────────────────┐
344
+ # │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │
345
+ # ├─────┼──────┼─────┼──────┼───────┼─────────┼─────────────────────────────────────────────┤
346
+ # │ Z0 │ - │ - │ - │ - │ 500 │ Zero case - empty inputs │
347
+ # │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exponent, clamped │
348
+ # │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │
349
+ # │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │
350
+ # │ S3 │ S │ = │ C │ False │ 2032 │ Small, equal, large exp+zero low256 │
351
+ # │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp+non-zero low256 │
352
+ # │ S5 │ S │ > │ A │ True │ 500 │ Small, base>mod, zero exp, clamped │
353
+ # │ S6 │ S │ < │ B │ True │ 500 │ Small, base<mod, small exp, clamped │
354
+ # │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │
355
+ # │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │
356
+ # │ L2 │ L │ = │ C │ False │ 6350 │ Large, equal, large exp+zero low256 │
357
+ # │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp+non-zero low256 │
358
+ # │ L4 │ L │ > │ B │ True │ 500 │ Large, base>mod, small exp, clamped │
359
+ # │ L5 │ L │ < │ C │ False │ 9144 │ Large, base<mod, large exp+zero low256 │
360
+ # └─────┴──────┴─────┴──────┴───────┴─────────┴─────────────────────────────────────────────┘
361
+
362
+ for base , exponent , modulus , expected_result , test_id in test_cases :
363
+ yield pytest .param (
364
+ ModExpInput (base = base , exponent = exponent , modulus = modulus ),
365
+ bytes .fromhex (expected_result ),
366
+ id = test_id ,
367
+ )
368
+
369
+
370
+ @pytest .mark .parametrize (
371
+ "modexp_input,modexp_expected" ,
372
+ create_modexp_variable_gas_test_cases (),
373
+ )
374
+ def test_modexp_variable_gas_cost (
375
+ state_test : StateTestFiller ,
376
+ pre : Alloc ,
377
+ tx : Transaction ,
378
+ post : Dict ,
379
+ ):
380
+ """Test ModExp variable gas cost."""
381
+ state_test (pre = pre , tx = tx , post = post )
0 commit comments