You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/writing_tests/writing_a_new_test.md
+57-8Lines changed: 57 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -146,17 +146,66 @@ which allows checking for an exact `gas_used` value.
146
146
147
147
## Writing code for the accounts in the test
148
148
149
-
Account bytecode can be embedded in the test accounts by adding it to the `code`
150
-
field of the `account` object, or the `data` field of the `tx` object if the
151
-
bytecode is meant to be treated as init code or call data.
149
+
Account bytecode can be "deployed" in a test's pre-state using the `pre` pytest fixture. The @ethereum/execution-spec-tests Python [`Opcodes`][ethereum_test_vm.Opcodes] minilang can be used to help write the bytecode in a readable form.
152
150
153
-
The code can be in either of the following formats:
151
+
### Using the Python Opcode Minilang
154
152
155
-
-`bytes` object, representing the raw opcodes in binary format.
156
-
-`str`, representing an hexadecimal format of the opcodes.
157
-
-`Code` compilable object.
153
+
EVM bytecode for tests should be written using the Python-based minilang provided by the [`Opcodes`][ethereum_test_vm.Opcodes] class. This allows you to construct bytecode using symbolic opcodes as Python objects.
158
154
159
-
`Code` objects can be concatenated together by using the `+` operator.
155
+
#### Example: Simple Addition Contract
156
+
157
+
```python
158
+
from ethereum_test_vm.opcode import Opcodes
159
+
160
+
code = (
161
+
Opcodes.PUSH1(0x02)
162
+
+ Opcodes.PUSH1(0x03)
163
+
+ Opcodes.ADD()
164
+
+ Opcodes.PUSH1(0x00)
165
+
+ Opcodes.SSTORE()
166
+
+ Opcodes.STOP()
167
+
)
168
+
169
+
# within a test function, using the "pre" fixture
170
+
contract_address = pre.deploy_contract(code=code)
171
+
```
172
+
173
+
You add this contract to the test's pre-state using the `pre` fixture or assign this `code` to the `code` field of an account in your test's `post` state. See the [state test tutorial](./tutorials/state_transition.md) for more help.
174
+
175
+
For a full list of available opcodes and their usage, see [`Opcodes`][ethereum_test_vm.Opcodes].
176
+
177
+
#### Higher-Level Constructs
178
+
179
+
For more complex control flow, you can use constructs like [`Switch`][ethereum_test_tools.code.generators.Switch] and [`Case`][ethereum_test_tools.code.generators.Case] from the `ethereum_test_tools.code.generators` module:
180
+
181
+
```python
182
+
from ethereum_test_tools.code.generators import Switch, Case
The `ethereum_test_tools.code.generators` module also defines other high-level constructs like [`While`][ethereum_test_tools.code.generators.While] and [`Conditional`][ethereum_test_tools.code.generators.Conditional].
195
+
196
+
#### Converting Bytecode to Minilang
197
+
198
+
If you have EVM bytecode (as hex or binary), you can use the [`evm_bytes` CLI tool](../library/cli/evm_bytes.md) to convert it to the EEST Python opcode minilang automatically, for example:
199
+
200
+
```console
201
+
uv run evm_bytes hex-string 0x604260005260206000F3
As of [PR #1779](https://github.com/ethereum/execution-spec-tests/pull/1779), the use of Yul source in Python test cases is forbidden. All new tests must use the Python opcode minilang as shown above.
0 commit comments