Skip to content

Commit 05feea2

Browse files
feat: add fork transition test
1 parent aa1f360 commit 05feea2

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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

Comments
 (0)