Skip to content

Commit df6bc6b

Browse files
committed
oog
1 parent 24ded3e commit df6bc6b

File tree

4 files changed

+62
-22
lines changed

4 files changed

+62
-22
lines changed

src/ethereum_test_tools/vm/opcode.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def __new__(
6262
"""
6363
Creates a new opcode instance.
6464
"""
65-
if type(opcode_or_byte) is Opcode:
65+
if type(opcode_or_byte) is Opcode or type(opcode_or_byte) is Macro:
6666
# Required because Enum class calls the base class with the instantiated object as
6767
# parameter.
6868
return opcode_or_byte
@@ -73,7 +73,7 @@ def __new__(
7373
obj.min_stack_height = min_stack_height
7474
obj.data_portion_length = data_portion_length
7575
return obj
76-
assert False
76+
raise TypeError("Opcode constructor '__new__' didn't return an instance!")
7777

7878
def __call__(self, *args_t: Union[int, bytes, str, "Opcode", FixedSizeBytes]) -> bytes:
7979
"""
@@ -4582,8 +4582,8 @@ class Opcodes(Opcode, Enum):
45824582
Inputs
45834583
----
45844584
- value: value in wei to send to the new account
4585-
- offset: byte offset in the memory in bytes, the initialisation code for the new account
4586-
- size: byte size to copy (size of the initialisation code)
4585+
- offset: byte offset in the memory in bytes, the initialization code for the new account
4586+
- size: byte size to copy (size of the initialization code)
45874587
45884588
Outputs
45894589
----
@@ -4769,8 +4769,8 @@ class Opcodes(Opcode, Enum):
47694769
Inputs
47704770
----
47714771
- value: value in wei to send to the new account
4772-
- offset: byte offset in the memory in bytes, the initialisation code of the new account
4773-
- size: byte size to copy (size of the initialisation code)
4772+
- offset: byte offset in the memory in bytes, the initialization code of the new account
4773+
- size: byte size to copy (size of the initialization code)
47744774
- salt: 32-byte value used to create the new account at a deterministic address
47754775
47764776
Outputs
@@ -4928,6 +4928,9 @@ class Opcodes(Opcode, Enum):
49284928
49294929
Gas
49304930
----
4931-
4931+
This operation will result in gasprice = 19073514453125027
4932+
Add a little more and geth report gasprice = 30 with oog exception
4933+
Make it 0 - 1 and geth report gasprice > u64 error
4934+
49324935
Source: SHA3(0, 100000000000)
49334936
"""

tests/cancun/eip1153_tstore/test_tload_reentrancy.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@ def test_tload_reentrancy(
4040
"""
4141

4242
address_to = Address("A00000000000000000000000000000000000000A")
43+
tload_value = 44
44+
empty_value = 0
4345

4446
# Storages
4547
str_tload_in_subcall_result = 1
4648
str_tload_after_subcall_result = 2
4749
str_subcall_worked = 3
50+
str_code_worked = 4
4851

4952
# Function names
5053
do_load = 1
@@ -70,12 +73,13 @@ def make_call(call_type: Op) -> bytes:
7073
),
7174
Case(
7275
condition=Op.EQ(Op.CALLDATALOAD(0), do_reenter),
73-
action=Op.TSTORE(0, 44)
76+
action=Op.TSTORE(0, tload_value)
7477
+ Op.MSTORE(0, do_load)
7578
+ Op.MSTORE(32, 0xFF)
7679
+ Op.SSTORE(str_subcall_worked, make_call(call_type))
7780
+ Op.SSTORE(str_tload_in_subcall_result, Op.MLOAD(32))
78-
+ Op.SSTORE(str_tload_after_subcall_result, Op.TLOAD(0)),
81+
+ Op.SSTORE(str_tload_after_subcall_result, Op.TLOAD(0))
82+
+ Op.SSTORE(str_code_worked, 1),
7983
),
8084
],
8185
default_action=b"",
@@ -84,6 +88,7 @@ def make_call(call_type: Op) -> bytes:
8488
str_tload_in_subcall_result: 0xFF,
8589
str_tload_after_subcall_result: 0xFF,
8690
str_subcall_worked: 0xFF,
91+
str_code_worked: 0xFF,
8792
},
8893
),
8994
address_code: Account(
@@ -106,9 +111,10 @@ def make_call(call_type: Op) -> bytes:
106111
# if reentrancy
107112
post[address_to] = Account(
108113
storage={
114+
str_code_worked: 1,
109115
# if call OOG, we fail to obtain the result
110-
str_tload_in_subcall_result: 0xFF if call_return == Op.OOG else 44,
111-
str_tload_after_subcall_result: 44,
116+
str_tload_in_subcall_result: 0xFF if call_return == Op.OOG else tload_value,
117+
str_tload_after_subcall_result: tload_value,
112118
str_subcall_worked: (
113119
0 if call_return == Op.REVERT or call_return == Op.OOG else 1
114120
),
@@ -118,11 +124,16 @@ def make_call(call_type: Op) -> bytes:
118124
# if external call
119125
post[address_to] = Account(
120126
storage={
127+
str_code_worked: 1,
121128
str_tload_in_subcall_result: (
122129
0xFF # if call OOG, we fail to obtain the result
123130
if call_return == Op.OOG
124131
# else delegate and callcode are working in the same context so tload works
125-
else 44 if call_type == Op.DELEGATECALL or call_type == Op.CALLCODE else 0
132+
else (
133+
tload_value
134+
if call_type == Op.DELEGATECALL or call_type == Op.CALLCODE
135+
else empty_value
136+
)
126137
),
127138
# no subcall errors can change the tload result
128139
str_tload_after_subcall_result: 44,

tests/cancun/eip1153_tstore/test_tstore_reentrancy.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,27 @@ def test_tstore_reentrancy(
4747
(09_revertUndoesAllFiller.yml)
4848
Revert undoes all the transient storage writes to the same key from the failed call.
4949
50+
(11_tstoreDelegateCallFiller.yml)
51+
delegatecall manipulates transient storage in the context of the current address.
52+
53+
(13_tloadStaticCallFiller.yml)
54+
Transient storage cannot be manipulated in a static context, tstore reverts
55+
5056
(20_oogUndoesTransientStoreInCallFiller.yml)
5157
Out of gas undoes the transient storage writes from a call.
5258
"""
5359
address_to = Address("A00000000000000000000000000000000000000A")
60+
tload_value_set_before_call = 80
61+
tload_value_set_in_call = 90
5462

55-
# Storages
63+
# Storage cells
5664
str_tload_before_call = 0
5765
str_tload_in_subcall_result = 1
5866
str_tload_after_call = 2
5967
str_subcall_worked = 3
6068
str_tload_1_after_call = 4
69+
str_tstore_overwrite = 5
70+
str_code_worked = 6
6171

6272
# Function names
6373
do_tstore = 1
@@ -71,7 +81,7 @@ def make_call(call_type: Op) -> bytes:
7181

7282
subcall_code = (
7383
Op.TSTORE(0, 89)
74-
+ Op.TSTORE(0, 90)
84+
+ Op.TSTORE(0, tload_value_set_in_call)
7585
+ Op.TSTORE(1, 11)
7686
+ Op.TSTORE(1, 12)
7787
+ Op.MSTORE(0, Op.TLOAD(0))
@@ -90,14 +100,17 @@ def make_call(call_type: Op) -> bytes:
90100
),
91101
Case(
92102
condition=Op.EQ(Op.CALLDATALOAD(0), do_reenter),
93-
action=Op.TSTORE(0, 80)
103+
action=Op.TSTORE(0, tload_value_set_before_call)
94104
+ Op.SSTORE(str_tload_before_call, Op.TLOAD(0))
95105
+ Op.MSTORE(0, do_tstore)
96106
+ Op.MSTORE(32, 0xFF)
97107
+ Op.SSTORE(str_subcall_worked, make_call(call_type))
98108
+ Op.SSTORE(str_tload_in_subcall_result, Op.MLOAD(32))
99109
+ Op.SSTORE(str_tload_after_call, Op.TLOAD(0))
100-
+ Op.SSTORE(str_tload_1_after_call, Op.TLOAD(1)),
110+
+ Op.SSTORE(str_tload_1_after_call, Op.TLOAD(1))
111+
+ Op.TSTORE(0, 50)
112+
+ Op.SSTORE(str_tstore_overwrite, Op.TLOAD(0))
113+
+ Op.SSTORE(str_code_worked, 1),
101114
),
102115
],
103116
default_action=b"",
@@ -108,6 +121,8 @@ def make_call(call_type: Op) -> bytes:
108121
str_tload_after_call: 0xFF,
109122
str_subcall_worked: 0xFF,
110123
str_tload_1_after_call: 0xFF,
124+
str_tstore_overwrite: 0xFF,
125+
str_code_worked: 0xFF,
111126
},
112127
),
113128
address_code: Account(
@@ -140,16 +155,20 @@ def successful_delegate_or_callcode() -> bool:
140155
# if reentrancy
141156
post[address_to] = Account(
142157
storage={
143-
str_tload_before_call: 80,
158+
str_code_worked: 1,
159+
str_tload_before_call: tload_value_set_before_call,
144160
str_tload_in_subcall_result: (
145161
# we fail to obtain in call result if it fails
146162
0xFF
147163
if call_type == Op.STATICCALL or call_return == Op.OOG
148-
else 90
164+
else tload_value_set_in_call
149165
),
150166
# reentrant tstore overrides value in upper level
151-
str_tload_after_call: 80 if failing_calls() else 90,
167+
str_tload_after_call: (
168+
tload_value_set_before_call if failing_calls() else tload_value_set_in_call
169+
),
152170
str_tload_1_after_call: 0 if failing_calls() else 12,
171+
str_tstore_overwrite: 50,
153172
# tstore in static call not allowed
154173
str_subcall_worked: 0 if failing_calls() else 1,
155174
}
@@ -158,16 +177,22 @@ def successful_delegate_or_callcode() -> bool:
158177
post[address_to] = Account(
159178
# if external call
160179
storage={
161-
str_tload_before_call: 80,
180+
str_code_worked: 1,
181+
str_tload_before_call: tload_value_set_before_call,
162182
str_tload_in_subcall_result: (
163183
# we fail to obtain in call result if it fails
164184
0xFF
165185
if call_type == Op.STATICCALL or call_return == Op.OOG
166-
else 90
186+
else tload_value_set_in_call
167187
),
168188
# external tstore overrides value in upper level only in delegate and callcode
169-
str_tload_after_call: 90 if successful_delegate_or_callcode() else 80,
189+
str_tload_after_call: (
190+
tload_value_set_in_call
191+
if successful_delegate_or_callcode()
192+
else tload_value_set_before_call
193+
),
170194
str_tload_1_after_call: 12 if successful_delegate_or_callcode() else 0,
195+
str_tstore_overwrite: 50,
171196
# tstore in static call not allowed, reentrancy means external call here
172197
str_subcall_worked: 0 if failing_calls() else 1,
173198
}

whitelist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ div
381381
sdiv
382382
mod
383383
smod
384+
smlxl
384385
addmod
385386
mulmod
386387
exp

0 commit comments

Comments
 (0)