|
5 | 5 | import pytest
|
6 | 6 |
|
7 | 7 | from ethereum_test_forks import Fork, Osaka
|
8 |
| -from ethereum_test_tools import Account, Address, Alloc, Bytes, Storage, Transaction, keccak256 |
| 8 | +from ethereum_test_tools import ( |
| 9 | + Account, |
| 10 | + Address, |
| 11 | + Alloc, |
| 12 | + Bytes, |
| 13 | + Environment, |
| 14 | + Storage, |
| 15 | + Transaction, |
| 16 | + keccak256, |
| 17 | +) |
9 | 18 | from ethereum_test_tools.vm.opcode import Opcodes as Op
|
10 | 19 |
|
11 | 20 | from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput
|
@@ -40,12 +49,50 @@ def call_contract_post_storage() -> Storage:
|
40 | 49 |
|
41 | 50 |
|
42 | 51 | @pytest.fixture
|
43 |
| -def call_succeeds() -> bool: |
| 52 | +def total_tx_gas_needed( |
| 53 | + fork: Fork, modexp_expected: bytes, modexp_input: ModExpInput, precompile_gas: int |
| 54 | +) -> int: |
| 55 | + """Calculate total tx gas needed for the transaction.""" |
| 56 | + intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() |
| 57 | + memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() |
| 58 | + sstore_gas = fork.gas_costs().G_STORAGE_SET * (len(modexp_expected) // 32) |
| 59 | + extra_gas = 100_000 |
| 60 | + |
| 61 | + return ( |
| 62 | + extra_gas |
| 63 | + + intrinsic_gas_cost_calculator(calldata=bytes(modexp_input)) |
| 64 | + + memory_expansion_gas_calculator(new_bytes=len(bytes(modexp_input))) |
| 65 | + + precompile_gas |
| 66 | + + sstore_gas |
| 67 | + ) |
| 68 | + |
| 69 | + |
| 70 | +@pytest.fixture |
| 71 | +def exceeds_tx_gas_cap(total_tx_gas_needed: int, fork: Fork, env: Environment) -> bool: |
| 72 | + """Determine if total gas requirements exceed transaction gas cap.""" |
| 73 | + tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit |
| 74 | + return total_tx_gas_needed > tx_gas_limit_cap |
| 75 | + |
| 76 | + |
| 77 | +@pytest.fixture |
| 78 | +def expected_tx_cap_fail() -> bool: |
| 79 | + """Whether this test is expected to fail due to transaction gas cap.""" |
| 80 | + return False |
| 81 | + |
| 82 | + |
| 83 | +@pytest.fixture |
| 84 | +def call_succeeds(exceeds_tx_gas_cap: bool, expected_tx_cap_fail: bool) -> bool: |
44 | 85 | """
|
45 |
| - By default, depending on the expected output, we can deduce if the call is expected to succeed |
46 |
| - or fail. |
| 86 | + Determine whether the ModExp precompile call should succeed or fail. |
| 87 | + By default, depending on the expected output, we assume it succeeds. |
| 88 | + Under EIP-7825, transactions requiring more gas than the cap should fail only if unexpected. |
47 | 89 | """
|
48 |
| - return True |
| 90 | + if exceeds_tx_gas_cap and not expected_tx_cap_fail: |
| 91 | + pytest.fail( |
| 92 | + "Test unexpectedly exceeds tx gas cap. " |
| 93 | + "Either mark with `expected_tx_cap_fail=True` or adjust inputs." |
| 94 | + ) |
| 95 | + return not exceeds_tx_gas_cap |
49 | 96 |
|
50 | 97 |
|
51 | 98 | @pytest.fixture
|
@@ -111,7 +158,7 @@ def gas_measure_contract(
|
111 | 158 | Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE)
|
112 | 159 | + Op.SSTORE(call_contract_post_storage.store_next(call_succeeds), call_result_measurement)
|
113 | 160 | + Op.SSTORE(
|
114 |
| - call_contract_post_storage.store_next(len(modexp_expected)), |
| 161 | + call_contract_post_storage.store_next(len(modexp_expected) if call_succeeds else 0), |
115 | 162 | Op.RETURNDATASIZE(),
|
116 | 163 | )
|
117 | 164 | )
|
@@ -174,28 +221,10 @@ def tx(
|
174 | 221 |
|
175 | 222 |
|
176 | 223 | @pytest.fixture
|
177 |
| -def tx_gas_limit( |
178 |
| - fork: Fork, modexp_expected: bytes, modexp_input: ModExpInput, precompile_gas: int |
179 |
| -) -> int: |
| 224 | +def tx_gas_limit(total_tx_gas_needed: int, fork: Fork, env: Environment) -> int: |
180 | 225 | """Transaction gas limit used for the test (Can be overridden in the test)."""
|
181 |
| - intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() |
182 |
| - memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() |
183 |
| - sstore_gas = fork.gas_costs().G_STORAGE_SET * (len(modexp_expected) // 32) |
184 |
| - extra_gas = 100_000 |
185 |
| - |
186 |
| - total_gas = ( |
187 |
| - extra_gas |
188 |
| - + intrinsic_gas_cost_calculator(calldata=bytes(modexp_input)) |
189 |
| - + memory_expansion_gas_calculator(new_bytes=len(bytes(modexp_input))) |
190 |
| - + precompile_gas |
191 |
| - + sstore_gas |
192 |
| - ) |
193 |
| - |
194 |
| - tx_gas_limit_cap = fork.transaction_gas_limit_cap() |
195 |
| - |
196 |
| - if tx_gas_limit_cap is not None: |
197 |
| - return min(tx_gas_limit_cap, total_gas) |
198 |
| - return total_gas |
| 226 | + tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit |
| 227 | + return min(tx_gas_limit_cap, total_tx_gas_needed) |
199 | 228 |
|
200 | 229 |
|
201 | 230 | @pytest.fixture
|
|
0 commit comments