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/tutorials/state_transition.md
+21-67Lines changed: 21 additions & 67 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# State Transition Tests
2
2
3
-
This tutorial teaches you to create a state transition execution specification test. These tests verify that a starting pre-state will reach a specified post-state after executing a single transaction. Note: This tutorial is partly outdated because it still uses Yul code, today we instead only use our Python opcode language.
3
+
This tutorial teaches you to create a state transition execution specification test. These tests verify that a starting pre-state will reach a specified post-state after executing a single transaction.
4
4
5
5
## Pre-requisites
6
6
@@ -9,27 +9,12 @@ Before proceeding with this tutorial, it is assumed that you have prior knowledg
9
9
- Repository set-up, see [installation](../../getting_started/installation.md).and run an execution specification test as outlined in the .
10
10
- Able to run `fill`, see [Getting Started: Filling Tests](../../filling_tests/getting_started.md).
11
11
- Understand how to read a [static state transition test](https://ethereum-tests.readthedocs.io/en/latest/state-transition-tutorial.html#the-source-code).
12
-
- Know the basics of [Yul](https://docs.soliditylang.org/en/latest/yul.html), which is an EVM assembly language.
12
+
- Know the basics of the [EVM](https://www.evm.codes/).
13
13
- Familiarity with [Python](https://docs.python.org/3/tutorial/).
14
14
15
-
## Example Tests
15
+
## Example Test
16
16
17
-
The most effective method of learning how to write tests is to study a couple of straightforward examples. In this tutorial we will go over the [Yul](https://github.com/ethereum/execution-spec-tests/blob/main/tests/homestead/yul/test_yul_example.py#L19) state test.
18
-
19
-
### Yul Test
20
-
21
-
You can find the source code for the Yul test in `tests/homestead/yul/test_yul_example.py`.
22
-
It is the spec test equivalent of this [static test](https://github.com/ethereum/tests/blob/develop/src/GeneralStateTestsFiller/stExample/yulExampleFiller.yml).
23
-
24
-
Lets examine each section.
25
-
26
-
```python
27
-
"""
28
-
Test Yul Source Code Examples
29
-
"""
30
-
```
31
-
32
-
In Python, multi-line strings are denoted using `"""`. As a convention, a file's purpose is often described in the opening string of the file.
17
+
The most effective method of learning how to write tests is to study a straightforward example. In this tutorial we will go over a simple state test that adds two numbers and stores them in the storage.
33
18
34
19
```python
35
20
from ethereum_test_forks import Fork, Frontier, Homestead
@@ -39,7 +24,6 @@ from ethereum_test_tools import (
39
24
Environment,
40
25
StateTestFiller,
41
26
Transaction,
42
-
YulCompiler,
43
27
)
44
28
```
45
29
@@ -57,19 +41,19 @@ In this case, the decorator is a custom [pytest fixture](https://docs.pytest.org
57
41
To fill this test for all the specified forks, we can specify pytest's `-k` flag that [filters test cases by keyword expression](https://docs.pytest.org/en/latest/how-to/usage.html#specifying-tests-selecting-tests):
58
42
59
43
```console
60
-
fill -k test_yul
44
+
fill -k test_example
61
45
```
62
46
63
47
and to fill it for a specific fork range, we can provide the `--from` and `--until` command-line arguments:
Test that adds two numbers and stores the result in storage at key 0.
73
57
"""
74
58
```
75
59
@@ -93,7 +77,7 @@ In most tests the defaults are good enough.
93
77
94
78
For more information, [see the static test documentation](../../running_tests/test_formats/state_test.md).
95
79
96
-
####Pre State
80
+
### Pre State
97
81
98
82
For every test we need to define the pre-state requirements, so we are certain of what is on the "blockchain" before the transaction is executed.
99
83
It can be used as a [dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries), which is the Python term for an associative array, but the appropriate way to populate it is by using the methods `fund_eoa`, `deploy_contract` or `fund_address` from the `Alloc` object.
@@ -102,23 +86,18 @@ In this example we are using the `deploy_contract` method to deploy a contract t
102
86
103
87
```python
104
88
contract_address = pre.deploy_contract(
105
-
code=yul(
106
-
"""
107
-
{
108
-
function f(a, b) -> c {
109
-
c := add(a, b)
110
-
}
111
-
112
-
sstore(0, f(1, 2))
113
-
return(0, 32)
114
-
}
115
-
"""
116
-
),
89
+
code= Op.PUSH1(0)
90
+
+ Op.PUSH1(2)
91
+
+ Op.PUSH1(1)
92
+
+ Op.ADD
93
+
+ Op.SSTORE
94
+
+ Op.STOP
95
+
,
117
96
balance=0x0BA1A9CE0BA1A9CE,
118
97
)
119
98
```
120
99
121
-
Specifically we deploy a contract with yul code that adds two numbers and stores the result in storage.
100
+
Specifically we deploy a contract with EVM bytecode that adds two numbers and stores the result in storage.
122
101
123
102
```python
124
103
balance=0x0BA1A9CE0BA1A9CE,
@@ -134,38 +113,13 @@ As return value of the `deploy_contract` method we get the address where the con
134
113
135
114
```python
136
115
storage={
137
-
0x00: 0x00,
116
+
0x00: 0x03,
138
117
},
139
118
```
140
119
141
120
We could also specify a starting storage for the contract, which is done by adding a `storage` parameter to the `deploy_contract` method.
142
121
143
-
```python
144
-
code=yul(
145
-
```
146
-
147
-
Here we define the [Yul](https://docs.soliditylang.org/en/v0.8.17/yul.html) code for the contract. It is defined as a multi-line string and starts and ends with curly braces (`{ <yul> }`).
148
-
149
-
When running the test filler `fill`, the solidity compiler `solc` will automatically translate the Yul to EVM opcode at runtime.
150
-
151
-
!!! note
152
-
Currently Yul and direct EVM opcode are supported in execution spec tests.
153
-
154
-
```python
155
-
"""
156
-
{
157
-
function f(a, b) -> c {
158
-
c := add(a, b)
159
-
}
160
-
sstore(0, f(1, 2))
161
-
return(0, 32)
162
-
}
163
-
"""
164
-
```
165
-
166
-
Within this example test Yul code we have a function definition, and inside it we are using the Yul `add` instruction. When compiled with`solc` it translates the instruction directly to the `ADD` opcode. For further Yul instructions [see here](https://docs.soliditylang.org/en/latest/yul.html#evm-dialect). Notice that function is utilized with the Yul `sstore` instruction, which stores the result of `add(1, 2)` to the storage address `0x00`.
167
-
168
-
Generally for execution spec tests the `sstore` instruction acts as a high-level assertion method to check pre to post-state changes. The test filler achieves this by verifying that the correct value is held within post-state storage, hence we can validate that the Yul code has run successfully.
122
+
Generally for execution spec tests the `sstore` instruction acts as a high-level assertion method to check pre to post-state changes. The test filler achieves this by verifying that the correct value is held within post-state storage, hence we can validate that the code has run successfully.
169
123
170
124
```python
171
125
sender= pre.fund_eoa(amount=0x0BA1A9CE0BA1A9CE)
@@ -223,15 +177,15 @@ For more information, [see the static test documentation](../../running_tests/te
223
177
224
178
This is the post-state which is equivalent to [`expect`](https://ethereum-tests.readthedocs.io/en/latest/test_filler/state_filler.html#expect) in static tests, but without the indexes. It is similar to the pre-state, except that we do not need to specify everything, only those accounts and fields we wish to test.
225
179
226
-
In this case, we look at the storage of the contract we called and add to it what we expect to see. In this example storage cell `0x00` should be `0x03`asin the pre-state we essentially stored the result of the Yul instruction `add(1, 2)`.
180
+
In this case, we look at the storage of the contract we called and add to it what we expect to see. In this example storage cell `0x00` should be `0x03`asin the pre-state we essentially stored the result of the instruction `add(1, 2)`.
227
181
228
182
#### State Test
229
183
230
184
```python
231
185
state_test(env=env, pre=pre, post=post, tx=tx)
232
186
```
233
187
234
-
This line calls the wrapper to the `StateTest`object that provides all the objects required (for example, the fork parameter) in order to fill the test, generate the test fixtures and write them to file (by default, `./fixtures/<blockchain,state>_tests/example/yul_example/test_yul.json`).
188
+
This line calls the wrapper to the `StateTest`object that provides all the objects required (for example, the fork parameter) in order to fill the test, generate the test fixtures and write them to file (by default, `./fixtures/<blockchain,state>_tests/example/test_example.json`).
0 commit comments