12
12
from eth .utils .address import (
13
13
force_bytes_to_address ,
14
14
generate_contract_address ,
15
+ generate_safe_contract_address ,
15
16
)
16
17
from eth .utils .hexadecimal import (
17
18
encode_hex ,
@@ -100,44 +101,72 @@ def _selfdestruct(computation: BaseComputation, beneficiary: Address) -> None:
100
101
raise Halt ('SELFDESTRUCT' )
101
102
102
103
104
+ class CreateOpcodeStackData :
105
+
106
+ def __init__ (self ,
107
+ endowment : int ,
108
+ memory_start : int ,
109
+ memory_length : int ,
110
+ salt : int = None ) -> None :
111
+
112
+ self .endowment = endowment
113
+ self .memory_start = memory_start
114
+ self .memory_length = memory_length
115
+ self .salt = salt
116
+
117
+
103
118
class Create (Opcode ):
104
119
105
120
def max_child_gas_modifier (self , gas : int ) -> int :
106
121
return gas
107
122
108
- def __call__ (self , computation : BaseComputation ) -> None :
109
- computation .consume_gas (self .gas_cost , reason = self .mnemonic )
123
+ def generate_contract_address (self ,
124
+ stack_data : CreateOpcodeStackData ,
125
+ call_data : bytes ,
126
+ computation : BaseComputation ) -> Address :
110
127
111
- value , start_position , size = computation .stack_pop (
128
+ creation_nonce = computation .state .account_db .get_nonce (computation .msg .storage_address )
129
+ computation .state .account_db .increment_nonce (computation .msg .storage_address )
130
+
131
+ contract_address = generate_contract_address (
132
+ computation .msg .storage_address ,
133
+ creation_nonce ,
134
+ )
135
+
136
+ return contract_address
137
+
138
+ def get_stack_data (self , computation : BaseComputation ) -> CreateOpcodeStackData :
139
+ endowment , memory_start , memory_length = computation .stack_pop (
112
140
num_items = 3 ,
113
141
type_hint = constants .UINT256 ,
114
142
)
115
143
116
- computation .extend_memory (start_position , size )
144
+ return CreateOpcodeStackData (endowment , memory_start , memory_length )
145
+
146
+ def __call__ (self , computation : BaseComputation ) -> None :
147
+ computation .consume_gas (self .gas_cost , reason = self .mnemonic )
148
+
149
+ stack_data = self .get_stack_data (computation )
150
+
151
+ computation .extend_memory (stack_data .memory_start , stack_data .memory_length )
117
152
118
153
insufficient_funds = computation .state .account_db .get_balance (
119
154
computation .msg .storage_address
120
- ) < value
155
+ ) < stack_data . endowment
121
156
stack_too_deep = computation .msg .depth + 1 > constants .STACK_DEPTH_LIMIT
122
157
123
158
if insufficient_funds or stack_too_deep :
124
159
computation .stack_push (0 )
125
160
return
126
161
127
- call_data = computation .memory_read (start_position , size )
162
+ call_data = computation .memory_read (stack_data . memory_start , stack_data . memory_length )
128
163
129
164
create_msg_gas = self .max_child_gas_modifier (
130
165
computation .get_gas_remaining ()
131
166
)
132
- computation .consume_gas (create_msg_gas , reason = "CREATE" )
167
+ computation .consume_gas (create_msg_gas , reason = self . mnemonic )
133
168
134
- creation_nonce = computation .state .account_db .get_nonce (computation .msg .storage_address )
135
- computation .state .account_db .increment_nonce (computation .msg .storage_address )
136
-
137
- contract_address = generate_contract_address (
138
- computation .msg .storage_address ,
139
- creation_nonce ,
140
- )
169
+ contract_address = self .generate_contract_address (stack_data , call_data , computation )
141
170
142
171
is_collision = computation .state .account_db .account_has_code_or_nonce (contract_address )
143
172
@@ -152,7 +181,7 @@ def __call__(self, computation: BaseComputation) -> None:
152
181
child_msg = computation .prepare_child_message (
153
182
gas = create_msg_gas ,
154
183
to = constants .CREATE_CONTRACT_ADDRESS ,
155
- value = value ,
184
+ value = stack_data . endowment ,
156
185
data = b'' ,
157
186
code = call_data ,
158
187
create_address = contract_address ,
@@ -177,3 +206,26 @@ def __call__(self, computation: BaseComputation) -> None:
177
206
if computation .msg .is_static :
178
207
raise WriteProtection ("Cannot modify state while inside of a STATICCALL context" )
179
208
return super ().__call__ (computation )
209
+
210
+
211
+ class Create2 (CreateByzantium ):
212
+
213
+ def get_stack_data (self , computation : BaseComputation ) -> CreateOpcodeStackData :
214
+
215
+ endowment , memory_start , memory_length , salt = computation .stack_pop (
216
+ num_items = 4 ,
217
+ type_hint = constants .UINT256 ,
218
+ )
219
+
220
+ return CreateOpcodeStackData (endowment , memory_start , memory_length , salt )
221
+
222
+ def generate_contract_address (self ,
223
+ stack_data : CreateOpcodeStackData ,
224
+ call_data : bytes ,
225
+ computation : BaseComputation ) -> Address :
226
+
227
+ return generate_safe_contract_address (
228
+ computation .msg .storage_address ,
229
+ stack_data .salt ,
230
+ call_data
231
+ )
0 commit comments