5
5
6
6
import pytest
7
7
8
- from ethereum_test_tools import Account , Alloc , Environment , StateTestFiller , Transaction
8
+ from ethereum_test_tools import Alloc , Environment , StateTestFiller
9
9
from ethereum_test_tools .eof .v1 import Container
10
10
from ethereum_test_tools .vm .opcode import Opcodes as Op
11
- from ethereum_test_types .eof .v1 import Section
12
- from ethereum_test_types .types import EOA
13
- from ethereum_test_vm import Bytecode , EVMCodeType
14
11
15
12
from .. import EOF_FORK_NAME
13
+ from ..gas_test import gas_test
16
14
from . import REFERENCE_SPEC_GIT_PATH , REFERENCE_SPEC_VERSION
17
- from .helpers import (
18
- slot_cold_gas ,
19
- slot_oog_call_result ,
20
- slot_sanity_call_result ,
21
- slot_warm_gas ,
22
- value_call_legacy_abort ,
23
- value_call_legacy_success ,
24
- )
25
15
26
16
REFERENCE_SPEC_GIT_PATH = REFERENCE_SPEC_GIT_PATH
27
17
REFERENCE_SPEC_VERSION = REFERENCE_SPEC_VERSION
@@ -47,126 +37,6 @@ def state_env() -> Environment:
47
37
return Environment ()
48
38
49
39
50
- def gas_test (
51
- state_test : StateTestFiller ,
52
- env : Environment ,
53
- pre : Alloc ,
54
- setup_code : Bytecode ,
55
- subject_code : Bytecode ,
56
- tear_down_code : Bytecode ,
57
- cold_gas : int ,
58
- warm_gas : int | None = None ,
59
- subject_subcontainer : Container | None = None ,
60
- sender : EOA | None = None ,
61
- subject_balance : int = 0 ,
62
- oog_difference : int = 1 ,
63
- ):
64
- """
65
- Creates a State Test to check the gas cost of a sequence of EOF code.
66
-
67
- `setup_code` and `tear_down_code` are called multiple times during the test, and MUST NOT have
68
- any side-effects which persist across message calls, and in particular, any effects on the gas
69
- usage of `subject_code`.
70
- """
71
- if cold_gas <= 0 :
72
- raise ValueError (f"Target gas allocations (cold_gas) must be > 0, got { cold_gas } " )
73
- if warm_gas is None :
74
- warm_gas = cold_gas
75
-
76
- if not sender :
77
- sender = pre .fund_eoa ()
78
-
79
- address_baseline = pre .deploy_contract (Container .Code (setup_code + tear_down_code ))
80
- code_subject = setup_code + subject_code + tear_down_code
81
- address_subject = pre .deploy_contract (
82
- Container .Code (code_subject )
83
- if not subject_subcontainer
84
- else Container (
85
- sections = [
86
- Section .Code (code_subject ),
87
- Section .Container (subject_subcontainer ),
88
- ]
89
- ),
90
- balance = subject_balance ,
91
- )
92
- # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every gas run
93
- gas_single_gas_run = 2 * 2 + 2 + WARM_ACCOUNT_ACCESS_GAS + 6 * 3
94
- address_legacy_harness = pre .deploy_contract (
95
- code = (
96
- # warm subject and baseline without executing
97
- (Op .BALANCE (address_subject ) + Op .POP + Op .BALANCE (address_baseline ) + Op .POP )
98
- # Baseline gas run
99
- + (
100
- Op .GAS
101
- + Op .CALL (address = address_baseline , gas = Op .GAS )
102
- + Op .POP
103
- + Op .GAS
104
- + Op .SWAP1
105
- + Op .SUB
106
- )
107
- # cold gas run
108
- + (
109
- Op .GAS
110
- + Op .CALL (address = address_subject , gas = Op .GAS )
111
- + Op .POP
112
- + Op .GAS
113
- + Op .SWAP1
114
- + Op .SUB
115
- )
116
- # warm gas run
117
- + (
118
- Op .GAS
119
- + Op .CALL (address = address_subject , gas = Op .GAS )
120
- + Op .POP
121
- + Op .GAS
122
- + Op .SWAP1
123
- + Op .SUB
124
- )
125
- # Store warm gas: DUP3 is the gas of the baseline gas run
126
- + (Op .DUP3 + Op .SWAP1 + Op .SUB + Op .PUSH2 (slot_warm_gas ) + Op .SSTORE )
127
- # store cold gas: DUP2 is the gas of the baseline gas run
128
- + (Op .DUP2 + Op .SWAP1 + Op .SUB + Op .PUSH2 (slot_cold_gas ) + Op .SSTORE )
129
- # oog gas run:
130
- # - DUP7 is the gas of the baseline gas run, after other CALL args were pushed
131
- # - subtract the gas charged by the harness
132
- # - add warm gas charged by the subject
133
- # - subtract `oog_difference` to cause OOG exception (1 by default)
134
- + Op .SSTORE (
135
- slot_oog_call_result ,
136
- Op .CALL (
137
- gas = Op .ADD (warm_gas - gas_single_gas_run - oog_difference , Op .DUP7 ),
138
- address = address_subject ,
139
- ),
140
- )
141
- # sanity gas run: not subtracting 1 to see if enough gas makes the call succeed
142
- + Op .SSTORE (
143
- slot_sanity_call_result ,
144
- Op .CALL (
145
- gas = Op .ADD (warm_gas - gas_single_gas_run , Op .DUP7 ),
146
- address = address_subject ,
147
- ),
148
- )
149
- + Op .STOP
150
- ),
151
- evm_code_type = EVMCodeType .LEGACY , # Needs to be legacy to use GAS opcode
152
- )
153
-
154
- post = {
155
- address_legacy_harness : Account (
156
- storage = {
157
- slot_warm_gas : warm_gas ,
158
- slot_cold_gas : cold_gas ,
159
- slot_oog_call_result : value_call_legacy_abort ,
160
- slot_sanity_call_result : value_call_legacy_success ,
161
- },
162
- ),
163
- }
164
-
165
- tx = Transaction (to = address_legacy_harness , gas_limit = env .gas_limit , sender = sender )
166
-
167
- state_test (env = env , pre = pre , tx = tx , post = post )
168
-
169
-
170
40
@pytest .mark .parametrize (
171
41
["opcode" , "pre_setup" , "cold_gas" , "warm_gas" , "new_account" ],
172
42
[
0 commit comments