Skip to content

Commit 5b1ae11

Browse files
feat: label eip checklist and add new cases
1 parent 7b0b6a8 commit 5b1ae11

File tree

2 files changed

+98
-17
lines changed

2 files changed

+98
-17
lines changed

tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
AuthorizationTuple,
1717
Block,
1818
BlockchainTestFiller,
19+
Bytecode,
1920
Environment,
2021
Hash,
2122
StateTestFiller,
@@ -201,6 +202,68 @@ def test_tx_gas_larger_than_block_gas_limit(
201202
blockchain_test(pre=pre, post={}, blocks=[block])
202203

203204

205+
@pytest.mark.parametrize(
206+
"exceed_gas_refund_limit",
207+
[
208+
pytest.param(True),
209+
pytest.param(False),
210+
],
211+
)
212+
@pytest.mark.valid_from("Osaka")
213+
def test_maximum_gas_refund(
214+
state_test: StateTestFiller,
215+
pre: Alloc,
216+
fork: Fork,
217+
exceed_gas_refund_limit: bool,
218+
):
219+
"""Test the maximum gas refund behavior according to EIP-3529."""
220+
gas_costs = fork.gas_costs()
221+
tx_gas_limit_cap = fork.transaction_gas_limit_cap()
222+
assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap"
223+
max_refund_quotient = fork.max_refund_quotient()
224+
225+
storage = Storage()
226+
227+
# Base Operation: SSTORE(slot, 0)
228+
iteration_cost = gas_costs.G_STORAGE_RESET + gas_costs.G_BASE + gas_costs.G_VERY_LOW
229+
gas_refund = gas_costs.R_STORAGE_CLEAR
230+
231+
# EIP-3529: Reduction in refunds
232+
storage_count = tx_gas_limit_cap // iteration_cost
233+
gas_used = storage_count * iteration_cost
234+
235+
maximum_gas_refund = gas_used // max_refund_quotient
236+
gas_refund_count = maximum_gas_refund // gas_refund
237+
238+
# Base case: operations that fit within the refund limit
239+
iteraction_count = min(storage_count, gas_refund_count + int(exceed_gas_refund_limit))
240+
241+
assert iteration_cost * iteraction_count <= tx_gas_limit_cap, (
242+
"Iteration cost exceeds tx gas limit cap"
243+
)
244+
245+
opcode = sum(
246+
(Op.SSTORE(storage.store_next(0), Op.PUSH0) for _ in range(iteraction_count)),
247+
Bytecode(),
248+
)
249+
assert len(opcode) <= fork.max_code_size(), "code size exceeds max code size"
250+
251+
contract = pre.deploy_contract(
252+
code=opcode,
253+
storage={Hash(i): Hash(1) for i in range(iteraction_count)},
254+
)
255+
256+
tx = Transaction(
257+
to=contract,
258+
sender=pre.fund_eoa(),
259+
gas_limit=tx_gas_limit_cap,
260+
)
261+
262+
post = {contract: Account(storage=storage)}
263+
264+
state_test(pre=pre, post=post, tx=tx)
265+
266+
204267
@pytest.fixture
205268
def total_cost_floor_per_token(fork: Fork):
206269
"""Total cost floor per token."""

tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import pytest
77

8+
from ethereum_test_checklists import EIPChecklist
89
from ethereum_test_forks import Fork
910
from ethereum_test_tools import (
1011
Account,
@@ -22,6 +23,10 @@
2223
REFERENCE_SPEC_VERSION = ref_spec_7825.version
2324

2425

26+
@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedBeforeFork()
27+
@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedBeforeFork()
28+
@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedAfterFork()
29+
@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedAfterFork()
2530
@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True)
2631
@pytest.mark.exception_test
2732
def test_transaction_gas_limit_cap_at_transition(
@@ -35,12 +40,11 @@ def test_transaction_gas_limit_cap_at_transition(
3540
Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are valid)
3641
At/after timestamp 15000: Gas limit cap of 2^24 is enforced
3742
"""
38-
sender = pre.fund_eoa()
3943
contract_address = pre.deploy_contract(
40-
code=Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1)) + Op.STOP,
44+
code=Op.SSTORE(Op.TIMESTAMP, Op.ADD(Op.SLOAD(0), 1)) + Op.STOP,
4145
)
4246

43-
pre_cap = fork.transaction_gas_limit_cap()
47+
pre_cap = fork.transaction_gas_limit_cap(timestamp=14_999)
4448
post_cap = fork.transaction_gas_limit_cap(timestamp=15_000)
4549
assert post_cap is not None, "Post cap should not be None"
4650

@@ -50,44 +54,57 @@ def test_transaction_gas_limit_cap_at_transition(
5054
"Post cap should be less than or equal to pre cap, test needs update"
5155
)
5256

53-
# Transaction with gas limit above the cap before transition
54-
high_gas_tx = Transaction(
57+
# Before fork activation
58+
high_gas_tx_before_fork = Transaction(
5559
ty=0, # Legacy transaction
5660
to=contract_address,
5761
gas_limit=pre_cap,
58-
data=b"",
59-
value=0,
60-
sender=sender,
62+
sender=pre.fund_eoa(),
63+
)
64+
65+
cap_tx_before_fork = Transaction(
66+
ty=0, # Legacy transaction
67+
to=contract_address,
68+
gas_limit=post_cap,
69+
sender=pre.fund_eoa(),
6170
)
6271

6372
post_cap_tx_error = TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM
6473

65-
# Transaction with gas limit at the cap
66-
cap_gas_tx = Transaction(
74+
# After fork activation
75+
high_gas_tx_after_fork = Transaction(
6776
ty=0, # Legacy transaction
6877
to=contract_address,
69-
gas_limit=post_cap + 1,
70-
data=b"",
71-
value=0,
72-
sender=sender,
78+
gas_limit=pre_cap,
79+
sender=pre.fund_eoa(),
7380
error=post_cap_tx_error,
7481
)
7582

83+
cap_tx_after_fork = Transaction(
84+
ty=0, # Legacy transaction
85+
to=contract_address,
86+
gas_limit=post_cap,
87+
sender=pre.fund_eoa(),
88+
)
89+
7690
blocks = []
7791

7892
# Before transition (timestamp < 15000): high gas transaction should succeed
7993
blocks.append(
8094
Block(
8195
timestamp=14_999,
82-
txs=[high_gas_tx],
96+
txs=[high_gas_tx_before_fork, cap_tx_before_fork],
8397
)
8498
)
8599

86100
# At transition (timestamp = 15000): high gas transaction should fail
87101
blocks.append(
88102
Block(
89103
timestamp=15_000,
90-
txs=[cap_gas_tx], # Only transaction at the cap succeeds
104+
txs=[
105+
cap_tx_after_fork,
106+
high_gas_tx_after_fork,
107+
],
91108
exception=post_cap_tx_error,
92109
)
93110
)
@@ -96,7 +113,8 @@ def test_transaction_gas_limit_cap_at_transition(
96113
post = {
97114
contract_address: Account(
98115
storage={
99-
0: 1, # Set by first transaction (before transition)
116+
14_999: 1, # Set by first transaction (before transition)
117+
15_000: 0, # Set by second transaction (at transition)
100118
}
101119
)
102120
}

0 commit comments

Comments
 (0)