Skip to content

Commit 8389c44

Browse files
committed
fixed yul docs example by rewriting parts of it
1 parent c888556 commit 8389c44

File tree

1 file changed

+21
-67
lines changed

1 file changed

+21
-67
lines changed

docs/writing_tests/tutorials/state_transition.md

Lines changed: 21 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# State Transition Tests
22

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.
44

55
## Pre-requisites
66

@@ -9,27 +9,12 @@ Before proceeding with this tutorial, it is assumed that you have prior knowledg
99
- Repository set-up, see [installation](../../getting_started/installation.md).and run an execution specification test as outlined in the .
1010
- Able to run `fill`, see [Getting Started: Filling Tests](../../filling_tests/getting_started.md).
1111
- 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/).
1313
- Familiarity with [Python](https://docs.python.org/3/tutorial/).
1414

15-
## Example Tests
15+
## Example Test
1616

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.
3318

3419
```python
3520
from ethereum_test_forks import Fork, Frontier, Homestead
@@ -39,7 +24,6 @@ from ethereum_test_tools import (
3924
Environment,
4025
StateTestFiller,
4126
Transaction,
42-
YulCompiler,
4327
)
4428
```
4529

@@ -57,19 +41,19 @@ In this case, the decorator is a custom [pytest fixture](https://docs.pytest.org
5741
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):
5842

5943
```console
60-
fill -k test_yul
44+
fill -k test_example
6145
```
6246

6347
and to fill it for a specific fork range, we can provide the `--from` and `--until` command-line arguments:
6448

6549
```console
66-
fill -k test_yul --from London --until Paris
50+
fill -k test_example --from London --until Paris
6751
```
6852

6953
```python
70-
def test_yul(state_test: StateTestFiller, pre: Alloc, yul: YulCompiler, fork: Fork):
54+
def test_example(state_test: StateTestFiller, pre: Alloc, fork: Fork):
7155
"""
72-
Test YUL compiled bytecode.
56+
Test that adds two numbers and stores the result in storage at key 0.
7357
"""
7458
```
7559

@@ -93,7 +77,7 @@ In most tests the defaults are good enough.
9377

9478
For more information, [see the static test documentation](../../running_tests/test_formats/state_test.md).
9579

96-
#### Pre State
80+
### Pre State
9781

9882
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.
9983
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
10286

10387
```python
10488
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+
,
11796
balance=0x0BA1A9CE0BA1A9CE,
11897
)
11998
```
12099

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.
122101

123102
```python
124103
balance=0x0BA1A9CE0BA1A9CE,
@@ -134,38 +113,13 @@ As return value of the `deploy_contract` method we get the address where the con
134113

135114
```python
136115
storage={
137-
0x00: 0x00,
116+
0x00: 0x03,
138117
},
139118
```
140119

141120
We could also specify a starting storage for the contract, which is done by adding a `storage` parameter to the `deploy_contract` method.
142121

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.
169123

170124
```python
171125
sender = pre.fund_eoa(amount=0x0BA1A9CE0BA1A9CE)
@@ -223,15 +177,15 @@ For more information, [see the static test documentation](../../running_tests/te
223177

224178
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.
225179

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` as in 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` as in the pre-state we essentially stored the result of the instruction `add(1, 2)`.
227181

228182
#### State Test
229183

230184
```python
231185
state_test(env=env, pre=pre, post=post, tx=tx)
232186
```
233187

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`).
235189

236190
## Conclusion
237191

0 commit comments

Comments
 (0)