|
| 1 | +"""Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork.""" |
| 2 | + |
| 3 | +import pytest |
| 4 | + |
| 5 | +from ethereum_test_forks import Fork |
| 6 | +from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction |
| 7 | +from ethereum_test_tools.vm.opcode import Opcodes as Op |
| 8 | + |
| 9 | +from .spec import Spec, ref_spec_7883 |
| 10 | + |
| 11 | +REFERENCE_SPEC_GIT_PATH = ref_spec_7883.git_path |
| 12 | +REFERENCE_SPEC_VERSION = ref_spec_7883.version |
| 13 | + |
| 14 | +pytestmark = pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) |
| 15 | + |
| 16 | + |
| 17 | +@pytest.mark.parametrize( |
| 18 | + "modexp_input,modexp_expected,gas_old,gas_new", |
| 19 | + [ |
| 20 | + pytest.param(Spec.modexp_input, Spec.modexp_expected, 200, 500), # Should be 1200 |
| 21 | + ], |
| 22 | +) |
| 23 | +def test_modexp_fork_transition( |
| 24 | + blockchain_test: BlockchainTestFiller, |
| 25 | + pre: Alloc, |
| 26 | + fork: Fork, |
| 27 | + gas_old: int, |
| 28 | + gas_new: int, |
| 29 | + tx_gas_limit: int, |
| 30 | +): |
| 31 | + """Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork.""" |
| 32 | + call_code = Op.CALL( |
| 33 | + address=Spec.MODEXP_ADDRESS, |
| 34 | + args_size=Op.CALLDATASIZE, |
| 35 | + ) |
| 36 | + |
| 37 | + gas_costs = fork.gas_costs() |
| 38 | + extra_gas = ( |
| 39 | + gas_costs.G_WARM_ACCOUNT_ACCESS |
| 40 | + + (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 2)) # type: ignore |
| 41 | + + (gas_costs.G_BASE * 3) |
| 42 | + ) |
| 43 | + code = ( |
| 44 | + Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE) |
| 45 | + + Op.GAS # [gas_start] |
| 46 | + + call_code # [gas_start, call_result] |
| 47 | + + Op.GAS # [gas_start, call_result, gas_end] |
| 48 | + + Op.SWAP1 # [gas_start, gas_end, call_result] |
| 49 | + + Op.POP # [gas_start, gas_end] |
| 50 | + + Op.PUSH2[extra_gas] # [gas_start, gas_end, extra_gas] |
| 51 | + + Op.ADD # [gas_start, gas_end + extra_gas] |
| 52 | + + Op.SWAP1 # [gas_end + extra_gas, gas_start] |
| 53 | + + Op.SUB # [gas_start - (gas_end + extra_gas)] |
| 54 | + + Op.TIMESTAMP # [gas_start - (gas_end + extra_gas), TIMESTAMP] |
| 55 | + + Op.SSTORE # [] |
| 56 | + ) |
| 57 | + |
| 58 | + senders = [pre.fund_eoa() for _ in range(3)] |
| 59 | + contracts = [pre.deploy_contract(code) for _ in range(3)] |
| 60 | + timestamps = [14_999, 15_000, 15_001] |
| 61 | + gas_values = [gas_old, gas_new, gas_new] |
| 62 | + |
| 63 | + blocks = [ |
| 64 | + Block( |
| 65 | + timestamp=ts, |
| 66 | + txs=[ |
| 67 | + Transaction( |
| 68 | + to=contract, |
| 69 | + sender=sender, |
| 70 | + gas_limit=tx_gas_limit, |
| 71 | + ) |
| 72 | + ], |
| 73 | + ) |
| 74 | + for ts, contract, sender in zip(timestamps, contracts, senders, strict=False) |
| 75 | + ] |
| 76 | + |
| 77 | + post = { |
| 78 | + contract: Account(storage={ts: gas}) |
| 79 | + for contract, ts, gas in zip(contracts, timestamps, gas_values, strict=False) |
| 80 | + } |
| 81 | + |
| 82 | + blockchain_test( |
| 83 | + pre=pre, |
| 84 | + blocks=blocks, |
| 85 | + post=post, |
| 86 | + ) |
0 commit comments