Skip to content

feat(tests): EIP-1153: Convert tests from ethereum/tests #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions converted-ethereum-tests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
([#440](https://github.com/ethereum/execution-spec-tests/pull/440))
GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/03_tloadAfterStoreIs0.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/04_tloadAfterCall.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/05_tloadReentrancy.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/06_tstoreInReentrancyCall.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/07_tloadAfterReentrancyStore.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/08_revertUndoesTransientStore.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/09_revertUndoesAll.json

GeneralStateTests/Cancun/stEIP1153-transientStorage/11_tstoreDelegateCall.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/12_tloadDelegateCall.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/13_tloadStaticCall.json

GeneralStateTests/Cancun/stEIP1153-transientStorage/16_tloadGas.json
GeneralStateTests/Cancun/stEIP1153-transientStorage/18_tloadAfterStore.json

GeneralStateTests/Cancun/stEIP1153-transientStorage/20_oogUndoesTransientStoreInCall.json
3 changes: 1 addition & 2 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Test fixtures for use by clients are available for each release on the [Github r
- 🐞 Fix typos in self-destruct collision test from erroneous pytest parametrization ([#608](https://github.com/ethereum/execution-spec-tests/pull/608)).
- ✨ Add tests for [EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540) ([#634](https://github.com/ethereum/execution-spec-tests/pull/634)).
- 🔀 Update EIP-7002 tests to match spec changes in [ethereum/execution-apis#549](https://github.com/ethereum/execution-apis/pull/549) ([#600](https://github.com/ethereum/execution-spec-tests/pull/600))
- ✨ Convert a few eip1153 tests from ethereum/tests repo into .py ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)).

### 🛠️ Framework

Expand All @@ -47,7 +48,6 @@ Test fixtures for use by clients are available for each release on the [Github r
- ✨ Enable loading of [ethereum/tests/BlockchainTests](https://github.com/ethereum/tests/tree/develop/BlockchainTests) ([#596](https://github.com/ethereum/execution-spec-tests/pull/596)).
- 🔀 Refactor `gentest` to use `ethereum_test_tools.rpc.rpc` by adding to `get_transaction_by_hash`, `debug_trace_call` to `EthRPC` ([#568](https://github.com/ethereum/execution-spec-tests/pull/568)).
- ✨ Write a properties file to the output directory and enable direct generation of a fixture tarball from `fill` via `--output=fixtures.tgz`([#627](https://github.com/ethereum/execution-spec-tests/pull/627)).
- ✨ Some opcodes now support keyword arguments for their parameters ([#648](https://github.com/ethereum/execution-spec-tests/pull/648))

### 🔧 EVM Tools

Expand All @@ -68,7 +68,6 @@ Test fixtures for use by clients are available for each release on the [Github r

- Cancun is now the latest deployed fork, and the development fork is now Prague ([#489](https://github.com/ethereum/execution-spec-tests/pull/489)).
- Stable fixtures artifact `fixtures.tar.gz` has been renamed to `fixtures_stable.tar.gz` ([#573](https://github.com/ethereum/execution-spec-tests/pull/573))
- EOF fixtures now contain an `containerKind` optional field that specifies whether the container should be interpreted as a runtime container (default when the field is missing) or initcode container, with string `RUNTIME` or `INITCODE` respectively ([#651](https://github.com/ethereum/execution-spec-tests/pull/651))

## 🔜 [v2.1.1](https://github.com/ethereum/execution-spec-tests/releases/tag/v2.1.1) - 2024-03-09

Expand Down
1 change: 1 addition & 0 deletions src/ethereum_test_tools/vm/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ def __new__(
return macro_or_bytes
else:
instance = super().__new__(cls, macro_or_bytes)
instance.unchecked_stack = True
return instance


Expand Down
284 changes: 284 additions & 0 deletions tests/cancun/eip1153_tstore/test_basic_tload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
"""
Ethereum Transient Storage EIP Tests
https://eips.ethereum.org/EIPS/eip-1153
"""

from typing import Dict, Union

import pytest

from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .spec import Spec, ref_spec_1153

REFERENCE_SPEC_GIT_PATH = ref_spec_1153.git_path
REFERENCE_SPEC_VERSION = ref_spec_1153.version


@pytest.mark.valid_from("Cancun")
def test_basic_tload_transaction_begin(
state_test: StateTestFiller,
pre: Alloc,
):
"""
Ported .json vectors:

(01_tloadBeginningTxnFiller.yml)
load arbitrary value is 0 at beginning of transaction
"""
slot_tload_at_transaction_begin_result = 1
slot_code_worked = 2

address_to = pre.deploy_contract(
code=Op.JUMPDEST()
# 01 test
+ Op.SSTORE(slot_tload_at_transaction_begin_result, Op.TLOAD(0))
+ Op.SSTORE(slot_code_worked, 1),
storage={
slot_tload_at_transaction_begin_result: 0xFF,
},
)

post = {
address_to: Account(
storage={
slot_tload_at_transaction_begin_result: 0x00,
slot_code_worked: 0x01,
}
)
}

tx = Transaction(
sender=pre.fund_eoa(7_000_000_000_000_000_000),
to=address_to,
gas_price=10,
data=b"",
gas_limit=5000000,
value=0,
)

state_test(env=Environment(), pre=pre, post=post, tx=tx)


@pytest.mark.valid_from("Cancun")
def test_basic_tload_works(
state_test: StateTestFiller,
pre: Alloc,
):
"""
Ported .json vectors:

(02_tloadAfterTstoreFiller.yml)
tload from same slot after tstore returns correct value
"""
tstore_value = 88

slot_tload_after_tstore_result = 0
slot_tload_after_tstore_result_second_time = 1
slot_code_worked = 2

address_to = pre.deploy_contract(
code=Op.JUMPDEST()
# 02 test
+ Op.TSTORE(2, tstore_value)
+ Op.SSTORE(slot_tload_after_tstore_result, Op.TLOAD(2))
+ Op.SSTORE(slot_tload_after_tstore_result_second_time, Op.TLOAD(2))
+ Op.SSTORE(slot_code_worked, 1),
storage={
slot_tload_after_tstore_result: 0xFF,
slot_tload_after_tstore_result_second_time: 0xFF,
},
)

post = {
address_to: Account(
storage={
slot_tload_after_tstore_result: tstore_value,
slot_tload_after_tstore_result_second_time: tstore_value,
slot_code_worked: 0x01,
}
)
}

tx = Transaction(
sender=pre.fund_eoa(7_000_000_000_000_000_000),
to=address_to,
gas_price=10,
data=b"",
gas_limit=5000000,
value=0,
)

state_test(env=Environment(), pre=pre, post=post, tx=tx)


@pytest.mark.valid_from("Cancun")
def test_basic_tload_other_after_tstore(
state_test: StateTestFiller,
pre: Alloc,
):
"""
Ported .json vectors:

(03_tloadAfterStoreIs0Filler.yml)
Loading any other slot after storing to a slot returns 0.
"""
tstore_value = 88

slot_tload_untouched_slot_after_tstore_result = 1
slot_code_worked = 2

address_to = pre.deploy_contract(
code=Op.JUMPDEST()
# 03 test
+ Op.TSTORE(3, tstore_value)
+ Op.SSTORE(slot_tload_untouched_slot_after_tstore_result, Op.TLOAD(0))
+ Op.SSTORE(slot_code_worked, 1),
storage={
slot_tload_untouched_slot_after_tstore_result: 0xFF,
},
)

post = {
address_to: Account(
storage={
slot_tload_untouched_slot_after_tstore_result: 0x00,
slot_code_worked: 0x01,
}
)
}

tx = Transaction(
sender=pre.fund_eoa(7_000_000_000_000_000_000),
to=address_to,
gas_price=10,
data=b"",
gas_limit=5000000,
value=0,
)

state_test(env=Environment(), pre=pre, post=post, tx=tx)


@pytest.mark.valid_from("Cancun")
def test_basic_tload_gasprice(
state_test: StateTestFiller,
pre: Alloc,
):
"""
Ported .json vectors:

(16_tloadGasFiller.yml)
tload costs 100 gas same as a warm sload
"""
slot_tload_nonzero_gas_price_result = 1
slot_tload_zero_gas_price_result = 2
slot_code_worked = 3

"""
N OPNAME GAS_COST TOTAL_GAS REMAINING_GAS STACK
28-1 MSTORE 2 20748 4958252 2:[4ba82f,0,]
MSTORE [0] = 4958255
29-1 PUSH1 3 20754 4958246
30-1 TLOAD 100 20757 4958243 1:[10,]
31-1 GAS 2 20857 4958143 1:[2,]
32-1 PUSH1 3 20859 4958141 2:[2,4ba7bd,]
33-1 MSTORE 6 20862 4958138 3:[2,4ba7bd,20,]
MSTORE [32] = 4958141
"""
extra_opcode_gas = 11 # mstore(3), push1(3),gas(2),push1(3)

address_to = pre.deploy_contract(
code=Op.JUMPDEST()
# 16 test
+ Op.TSTORE(16, 2)
+ Op.MSTORE(0, Op.GAS()) # hot load the memory to make the extra_opcode_gas be 11
+ Op.MSTORE(0, Op.GAS())
+ Op.TLOAD(16)
+ Op.MSTORE(32, Op.GAS())
+ Op.SSTORE(slot_tload_nonzero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32)))
+ Op.SSTORE(
slot_tload_nonzero_gas_price_result,
Op.SUB(Op.SLOAD(slot_tload_nonzero_gas_price_result), extra_opcode_gas),
)
+ Op.MSTORE(0, Op.GAS())
+ Op.TLOAD(5) # tload slot at 5 is 0
+ Op.MSTORE(32, Op.GAS())
+ Op.SSTORE(slot_tload_zero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32)))
+ Op.SSTORE(
slot_tload_zero_gas_price_result,
Op.SUB(Op.SLOAD(slot_tload_zero_gas_price_result), extra_opcode_gas),
)
+ Op.SSTORE(slot_code_worked, 1),
storage={
slot_tload_nonzero_gas_price_result: 0xFF,
slot_tload_zero_gas_price_result: 0xFF,
},
)

post = {
address_to: Account(
storage={
slot_tload_nonzero_gas_price_result: Spec.TLOAD_GAS_COST,
slot_tload_zero_gas_price_result: Spec.TLOAD_GAS_COST,
slot_code_worked: 0x01,
}
)
}

tx = Transaction(
sender=pre.fund_eoa(7_000_000_000_000_000_000),
to=address_to,
gas_price=10,
data=b"",
gas_limit=5000000,
value=0,
)

state_test(env=Environment(), pre=pre, post=post, tx=tx)


@pytest.mark.valid_from("Cancun")
def test_basic_tload_after_store(
state_test: StateTestFiller,
pre: Alloc,
):
"""
Ported .json vectors:

(18_tloadAfterStoreFiller.yml)
tload from same slot after store returns 0
"""
slot_tload_from_sstore_result = 1
slot_code_worked = 2

address_to = pre.deploy_contract(
code=Op.JUMPDEST()
# 18 test
+ Op.SSTORE(slot_tload_from_sstore_result, 22)
+ Op.SSTORE(slot_tload_from_sstore_result, Op.TLOAD(slot_tload_from_sstore_result))
+ Op.SSTORE(slot_code_worked, 1),
storage={
slot_tload_from_sstore_result: 0xFF,
},
)

post: Dict[Address, Union[Account, object]] = {}
post[address_to] = Account(
storage={
slot_tload_from_sstore_result: 0x00,
slot_code_worked: 0x01,
}
)

tx = Transaction(
sender=pre.fund_eoa(7_000_000_000_000_000_000),
to=address_to,
gas_price=10,
data=b"",
gas_limit=5000000,
value=0,
)

state_test(env=Environment(), pre=pre, post=post, tx=tx)
Loading
Loading