Skip to content

Commit e3904fb

Browse files
committed
convert a few eip1153 json tests
1 parent 6d91ee9 commit e3904fb

File tree

3 files changed

+366
-0
lines changed

3 files changed

+366
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Ethereum Transient Storage EIP Tests
3+
https://eips.ethereum.org/EIPS/eip-1153
4+
"""
5+
6+
from typing import Dict, Union
7+
8+
import pytest
9+
10+
from ethereum_test_tools import (
11+
Account,
12+
Address,
13+
Environment,
14+
StateTestFiller,
15+
TestAddress,
16+
Transaction,
17+
)
18+
from ethereum_test_tools.vm.opcode import Opcodes as Op
19+
20+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
21+
REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0"
22+
23+
24+
@pytest.mark.valid_from("Cancun")
25+
def test_basic_tload(
26+
state_test: StateTestFiller,
27+
):
28+
"""
29+
Covered .json vectors:
30+
load arbitrary value is 0 at beginning of transaction (01_tloadBeginningTxnFiller.yml)
31+
tload from same slot after tstore returns correct value (02_tloadAfterTstoreFiller.yml)
32+
Loading any other slot after storing to a slot returns 0. (03_tloadAfterStoreIs0Filler.yml)
33+
tload costs 100 gas same as a warm sload (16_tloadGasFiller.yml)
34+
tload from same slot after store returns 0 (18_tloadAfterStoreFiller.yml)
35+
"""
36+
37+
address_to = Address("A00000000000000000000000000000000000000A")
38+
tload_at_transaction_begin_result = 1
39+
40+
tstore_value = 88
41+
tload_after_tstore_result = 2
42+
tload_after_tstore_result_second_time = 3
43+
tload_wrong_after_tstore_result = 4
44+
45+
# N OPNAME GAS_COST TOTAL_GAS REMAINING_GAS STACK
46+
# 28-1 MSTORE 2 20748 4958252 2:[4ba82f,0,]
47+
# MSTORE [0] = 4958255
48+
# 29-1 PUSH1 3 20754 4958246
49+
# 30-1 TLOAD 100 20757 4958243 1:[10,]
50+
# 31-1 GAS 2 20857 4958143 1:[2,]
51+
# 32-1 PUSH1 3 20859 4958141 2:[2,4ba7bd,]
52+
# 33-1 MSTORE 6 20862 4958138 3:[2,4ba7bd,20,]
53+
# MSTORE [32] = 4958141
54+
extra_opcode_gas = 11 # mstore(3), push1(3),gas(2),push1(3)
55+
56+
tload_nonzero_gas_price_result = 16
57+
tload_zero_gas_price_result = 1601
58+
59+
tload_from_sstore_result = 18
60+
61+
pre = {
62+
address_to: Account(
63+
balance=1000000000000000000,
64+
nonce=0,
65+
code=Op.JUMPDEST()
66+
# 01_tloadBeginningTxnFiller.yml
67+
+ Op.SSTORE(tload_at_transaction_begin_result, Op.TLOAD(0))
68+
# 02_tloadAfterTstoreFiller.yml
69+
+ Op.TSTORE(2, tstore_value)
70+
+ Op.SSTORE(tload_after_tstore_result, Op.TLOAD(2))
71+
+ Op.SSTORE(tload_after_tstore_result_second_time, Op.TLOAD(2))
72+
# 03_tloadAfterStoreIs0Filler.yml
73+
+ Op.TSTORE(3, tstore_value) + Op.SSTORE(tload_wrong_after_tstore_result, Op.TLOAD(0))
74+
# 16_tloadGasFiller.yml calculate tload gas
75+
+ Op.TSTORE(16, 2)
76+
+ Op.MSTORE(0, Op.GAS()) # hot load the memory
77+
+ Op.MSTORE(0, Op.GAS())
78+
+ Op.TLOAD(16)
79+
+ Op.MSTORE(32, Op.GAS())
80+
+ Op.SSTORE(tload_nonzero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32)))
81+
+ Op.SSTORE(tload_nonzero_gas_price_result, Op.SUB(Op.SLOAD(16), extra_opcode_gas))
82+
# from zero slot
83+
+ Op.MSTORE(0, Op.GAS())
84+
+ Op.TLOAD(5)
85+
+ Op.MSTORE(32, Op.GAS())
86+
+ Op.SSTORE(tload_zero_gas_price_result, Op.SUB(Op.MLOAD(0), Op.MLOAD(32)))
87+
+ Op.SSTORE(tload_zero_gas_price_result, Op.SUB(Op.SLOAD(1601), extra_opcode_gas))
88+
# 18_tloadAfterStoreFiller.yml
89+
+ Op.SSTORE(18, 22) + Op.SSTORE(tload_from_sstore_result, Op.TLOAD(18)),
90+
storage={
91+
tload_at_transaction_begin_result: 0xFF,
92+
tload_after_tstore_result: 0xFF,
93+
tload_after_tstore_result_second_time: 0xFF,
94+
tload_wrong_after_tstore_result: 0xFF,
95+
tload_nonzero_gas_price_result: 0xFF,
96+
tload_zero_gas_price_result: 0xFF,
97+
tload_from_sstore_result: 0xFF,
98+
},
99+
),
100+
TestAddress: Account(
101+
balance=7000000000000000000,
102+
nonce=0,
103+
code="0x",
104+
storage={},
105+
),
106+
}
107+
108+
post: Dict[Address, Union[Account, object]] = {}
109+
110+
post[address_to] = Account(
111+
storage={
112+
tload_at_transaction_begin_result: 0x00,
113+
tload_after_tstore_result: tstore_value,
114+
tload_after_tstore_result_second_time: tstore_value,
115+
tload_wrong_after_tstore_result: 0x00,
116+
tload_nonzero_gas_price_result: 100,
117+
tload_zero_gas_price_result: 100,
118+
tload_from_sstore_result: 0x00,
119+
}
120+
)
121+
122+
tx = Transaction(
123+
nonce=0,
124+
to=address_to,
125+
gas_price=10,
126+
data=b"",
127+
gas_limit=5000000,
128+
value=0,
129+
)
130+
131+
state_test(env=Environment(), pre=pre, post=post, tx=tx)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
Ethereum Transient Storage EIP Tests
3+
https://eips.ethereum.org/EIPS/eip-1153
4+
"""
5+
6+
from typing import Dict, Union
7+
8+
import pytest
9+
10+
from ethereum_test_tools import (
11+
Account,
12+
Address,
13+
Environment,
14+
StateTestFiller,
15+
TestAddress,
16+
Transaction,
17+
)
18+
from ethereum_test_tools.vm.opcode import Opcodes as Op
19+
20+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
21+
REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0"
22+
23+
24+
@pytest.mark.valid_from("Cancun")
25+
@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL])
26+
def test_tload_calls(state_test: StateTestFiller, call_type: Op):
27+
"""
28+
Covered .json vectors:
29+
Loading a slot after a call to another contract is 0. (04_tloadAfterCallFiller.yml)
30+
delegatecall reads transient storage in the context of the current address
31+
(12_tloadDelegateCallFiller.yml)
32+
"""
33+
34+
address_to = Address("A00000000000000000000000000000000000000A")
35+
address_call = Address("B00000000000000000000000000000000000000B")
36+
37+
# Variables
38+
var_a_tload_value = 0
39+
var_a_subcall_value = 32
40+
var_b_subcall_tload_value = 0
41+
var_b_subcall_updated_tload_value = 0
42+
43+
# Storages
44+
str_a_tload_after_subcall_result = 0
45+
str_a_subcall_result = 1
46+
str_b_subcall_tload_result = 2
47+
str_b_subcall_updated_tload_result = 3
48+
49+
pre = {
50+
address_to: Account(
51+
balance=1000000000000000000,
52+
nonce=0,
53+
code=Op.JUMPDEST()
54+
+ Op.TSTORE(0, 10)
55+
+ Op.MSTORE(var_a_subcall_value, call_type(Op.GAS(), address_call, 0, 0, 32, 0, 0))
56+
+ Op.MSTORE(var_a_tload_value, Op.TLOAD(0))
57+
+ Op.SSTORE(str_a_tload_after_subcall_result, Op.MLOAD(var_a_tload_value))
58+
+ Op.SSTORE(str_a_subcall_result, Op.MLOAD(var_a_subcall_value)),
59+
storage={
60+
str_a_subcall_result: 0xFF,
61+
str_a_tload_after_subcall_result: 0xFF,
62+
},
63+
),
64+
address_call: Account(
65+
balance=7000000000000000000,
66+
nonce=0,
67+
code=Op.JUMPDEST()
68+
+ Op.MSTORE(var_b_subcall_tload_value, Op.TLOAD(0))
69+
+ Op.SSTORE(str_b_subcall_tload_result, Op.MLOAD(var_b_subcall_tload_value))
70+
+ Op.TSTORE(0, 20)
71+
+ Op.MSTORE(var_b_subcall_updated_tload_value, Op.TLOAD(0))
72+
+ Op.SSTORE(
73+
str_b_subcall_updated_tload_result, Op.MLOAD(var_b_subcall_updated_tload_value)
74+
),
75+
storage={
76+
str_b_subcall_tload_result: 0xFF,
77+
str_b_subcall_updated_tload_result: 0xFF,
78+
},
79+
),
80+
TestAddress: Account(
81+
balance=7000000000000000000,
82+
nonce=0,
83+
code="0x",
84+
storage={},
85+
),
86+
}
87+
88+
post: Dict[Address, Union[Account, object]] = {}
89+
90+
post[address_to] = Account(
91+
storage={
92+
# other calls don't change context, there for tload updated in this account
93+
str_a_tload_after_subcall_result: 10 if call_type == Op.CALL else 20,
94+
str_a_subcall_result: 1,
95+
# since context unchanged the subcall works as if continued execution
96+
str_b_subcall_tload_result: 0 if call_type == Op.CALL else 10,
97+
str_b_subcall_updated_tload_result: 0 if call_type == Op.CALL else 20,
98+
}
99+
)
100+
101+
post[address_call] = Account(
102+
storage={
103+
str_b_subcall_tload_result: 0 if call_type == Op.CALL else 0xFF,
104+
str_b_subcall_updated_tload_result: 20 if call_type == Op.CALL else 0xFF,
105+
}
106+
)
107+
108+
tx = Transaction(
109+
nonce=0,
110+
to=address_to,
111+
gas_price=10,
112+
data=b"",
113+
gas_limit=5000000,
114+
value=0,
115+
)
116+
117+
state_test(env=Environment(), pre=pre, post=post, tx=tx)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""
2+
Ethereum Transient Storage EIP Tests
3+
https://eips.ethereum.org/EIPS/eip-1153
4+
"""
5+
6+
from typing import Dict, Union
7+
8+
import pytest
9+
10+
from ethereum_test_tools import (
11+
Account,
12+
Address,
13+
Case,
14+
Environment,
15+
Hash,
16+
StateTestFiller,
17+
Switch,
18+
TestAddress,
19+
Transaction,
20+
)
21+
from ethereum_test_tools.vm.opcode import Opcodes as Op
22+
23+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md"
24+
REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0"
25+
26+
27+
@pytest.mark.valid_from("Cancun")
28+
@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL])
29+
def test_tload_reentrancy(state_test: StateTestFiller, call_type: Op):
30+
"""
31+
Covered .json vectors:
32+
Reentrant calls access the same transient storage (05_tloadReentrancyFiller.yml)
33+
"""
34+
35+
address_to = Address("A00000000000000000000000000000000000000A")
36+
37+
# Variables
38+
var_tload = 0
39+
var_reentrancy_call_result = 32
40+
var_tload_after_do_load_reenter = 64
41+
42+
# Storages
43+
str_tload_in_reentrancy_result = 1
44+
str_tload_after_reentrancy_result = 2
45+
str_reentrancy_call_worked = 3
46+
47+
# Function names
48+
do_load = 1
49+
do_reenter = 2
50+
51+
def make_call(call_type: Op) -> bytes:
52+
if call_type == Op.DELEGATECALL:
53+
return call_type(Op.GAS(), Op.ADDRESS(), 0, 32, 0, 0)
54+
else:
55+
return call_type(Op.GAS(), Op.ADDRESS(), 0, 0, 32, 0, 0)
56+
57+
pre = {
58+
address_to: Account(
59+
balance=1000000000000000000,
60+
nonce=0,
61+
code=Switch(
62+
cases=[
63+
Case(
64+
condition=Op.EQ(Op.CALLDATALOAD(0), do_load),
65+
action=Op.MSTORE(var_tload, Op.TLOAD(0))
66+
+ Op.SSTORE(str_tload_in_reentrancy_result, Op.MLOAD(var_tload)),
67+
),
68+
Case(
69+
condition=Op.EQ(Op.CALLDATALOAD(0), do_reenter),
70+
action=Op.TSTORE(0, 44)
71+
+ Op.MSTORE(0, do_load)
72+
+ Op.MSTORE(var_reentrancy_call_result, make_call(call_type))
73+
+ Op.MSTORE(var_tload_after_do_load_reenter, Op.TLOAD(0))
74+
+ Op.SSTORE(
75+
str_tload_after_reentrancy_result,
76+
Op.MLOAD(var_tload_after_do_load_reenter),
77+
)
78+
+ Op.SSTORE(
79+
str_reentrancy_call_worked, Op.MLOAD(var_reentrancy_call_result)
80+
),
81+
),
82+
],
83+
default_action=b"",
84+
),
85+
storage={
86+
str_tload_in_reentrancy_result: 0xFF,
87+
str_tload_after_reentrancy_result: 0xFF,
88+
str_reentrancy_call_worked: 0xFF,
89+
},
90+
),
91+
TestAddress: Account(
92+
balance=7000000000000000000,
93+
nonce=0,
94+
code="0x",
95+
storage={},
96+
),
97+
}
98+
99+
post: Dict[Address, Union[Account, object]] = {}
100+
101+
post[address_to] = Account(
102+
storage={
103+
str_tload_in_reentrancy_result: 44,
104+
str_tload_after_reentrancy_result: 44,
105+
str_reentrancy_call_worked: 1,
106+
}
107+
)
108+
109+
tx = Transaction(
110+
nonce=0,
111+
to=address_to,
112+
gas_price=10,
113+
data=Hash(do_reenter),
114+
gas_limit=5000000,
115+
value=0,
116+
)
117+
118+
state_test(env=Environment(), pre=pre, post=post, tx=tx)

0 commit comments

Comments
 (0)