ethereum.tangerine_whistle.vm.instructions.environment
Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Implementations of the EVM environment related instructions.
address
Pushes the address of the current executing account to the stack.
Parameters
evm : The current EVM frame.
def address(evm: Evm) -> None:
36 | """ |
---|---|
37 | Pushes the address of the current executing account to the stack. |
38 |
|
39 | Parameters |
40 | ---------- |
41 | evm : |
42 | The current EVM frame. |
43 |
|
44 | """ |
45 | # STACK |
46 | pass |
47 | |
48 | # GAS |
49 | charge_gas(evm, GAS_BASE) |
50 | |
51 | # OPERATION |
52 | push(evm.stack, U256.from_be_bytes(evm.message.current_target)) |
53 | |
54 | # PROGRAM COUNTER |
55 | evm.pc += Uint(1) |
balance
Pushes the balance of the given account onto the stack.
Parameters
evm : The current EVM frame.
def balance(evm: Evm) -> None:
59 | """ |
---|---|
60 | Pushes the balance of the given account onto the stack. |
61 |
|
62 | Parameters |
63 | ---------- |
64 | evm : |
65 | The current EVM frame. |
66 |
|
67 | """ |
68 | # STACK |
69 | address = to_address(pop(evm.stack)) |
70 | |
71 | # GAS |
72 | charge_gas(evm, GAS_BALANCE) |
73 | |
74 | # OPERATION |
75 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
76 | balance = get_account(evm.env.state, address).balance |
77 | |
78 | push(evm.stack, balance) |
79 | |
80 | # PROGRAM COUNTER |
81 | evm.pc += Uint(1) |
origin
Pushes the address of the original transaction sender to the stack. The origin address can only be an EOA.
Parameters
evm : The current EVM frame.
def origin(evm: Evm) -> None:
85 | """ |
---|---|
86 | Pushes the address of the original transaction sender to the stack. |
87 | The origin address can only be an EOA. |
88 |
|
89 | Parameters |
90 | ---------- |
91 | evm : |
92 | The current EVM frame. |
93 |
|
94 | """ |
95 | # STACK |
96 | pass |
97 | |
98 | # GAS |
99 | charge_gas(evm, GAS_BASE) |
100 | |
101 | # OPERATION |
102 | push(evm.stack, U256.from_be_bytes(evm.env.origin)) |
103 | |
104 | # PROGRAM COUNTER |
105 | evm.pc += Uint(1) |
caller
Pushes the address of the caller onto the stack.
Parameters
evm : The current EVM frame.
def caller(evm: Evm) -> None:
109 | """ |
---|---|
110 | Pushes the address of the caller onto the stack. |
111 |
|
112 | Parameters |
113 | ---------- |
114 | evm : |
115 | The current EVM frame. |
116 |
|
117 | """ |
118 | # STACK |
119 | pass |
120 | |
121 | # GAS |
122 | charge_gas(evm, GAS_BASE) |
123 | |
124 | # OPERATION |
125 | push(evm.stack, U256.from_be_bytes(evm.message.caller)) |
126 | |
127 | # PROGRAM COUNTER |
128 | evm.pc += Uint(1) |
callvalue
Push the value (in wei) sent with the call onto the stack.
Parameters
evm : The current EVM frame.
def callvalue(evm: Evm) -> None:
132 | """ |
---|---|
133 | Push the value (in wei) sent with the call onto the stack. |
134 |
|
135 | Parameters |
136 | ---------- |
137 | evm : |
138 | The current EVM frame. |
139 |
|
140 | """ |
141 | # STACK |
142 | pass |
143 | |
144 | # GAS |
145 | charge_gas(evm, GAS_BASE) |
146 | |
147 | # OPERATION |
148 | push(evm.stack, evm.message.value) |
149 | |
150 | # PROGRAM COUNTER |
151 | evm.pc += Uint(1) |
calldataload
Push a word (32 bytes) of the input data belonging to the current environment onto the stack.
Parameters
evm : The current EVM frame.
def calldataload(evm: Evm) -> None:
155 | """ |
---|---|
156 | Push a word (32 bytes) of the input data belonging to the current |
157 | environment onto the stack. |
158 |
|
159 | Parameters |
160 | ---------- |
161 | evm : |
162 | The current EVM frame. |
163 |
|
164 | """ |
165 | # STACK |
166 | start_index = pop(evm.stack) |
167 | |
168 | # GAS |
169 | charge_gas(evm, GAS_VERY_LOW) |
170 | |
171 | # OPERATION |
172 | value = buffer_read(evm.message.data, start_index, U256(32)) |
173 | |
174 | push(evm.stack, U256.from_be_bytes(value)) |
175 | |
176 | # PROGRAM COUNTER |
177 | evm.pc += Uint(1) |
calldatasize
Push the size of input data in current environment onto the stack.
Parameters
evm : The current EVM frame.
def calldatasize(evm: Evm) -> None:
181 | """ |
---|---|
182 | Push the size of input data in current environment onto the stack. |
183 |
|
184 | Parameters |
185 | ---------- |
186 | evm : |
187 | The current EVM frame. |
188 |
|
189 | """ |
190 | # STACK |
191 | pass |
192 | |
193 | # GAS |
194 | charge_gas(evm, GAS_BASE) |
195 | |
196 | # OPERATION |
197 | push(evm.stack, U256(len(evm.message.data))) |
198 | |
199 | # PROGRAM COUNTER |
200 | evm.pc += Uint(1) |
calldatacopy
Copy a portion of the input data in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
Parameters
evm : The current EVM frame.
def calldatacopy(evm: Evm) -> None:
204 | """ |
---|---|
205 | Copy a portion of the input data in current environment to memory. |
206 |
|
207 | This will also expand the memory, in case that the memory is insufficient |
208 | to store the data. |
209 |
|
210 | Parameters |
211 | ---------- |
212 | evm : |
213 | The current EVM frame. |
214 |
|
215 | """ |
216 | # STACK |
217 | memory_start_index = pop(evm.stack) |
218 | data_start_index = pop(evm.stack) |
219 | size = pop(evm.stack) |
220 | |
221 | # GAS |
222 | words = ceil32(Uint(size)) // Uint(32) |
223 | copy_gas_cost = GAS_COPY * words |
224 | extend_memory = calculate_gas_extend_memory( |
225 | evm.memory, [(memory_start_index, size)] |
226 | ) |
227 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
228 | |
229 | # OPERATION |
230 | evm.memory += b"\x00" * extend_memory.expand_by |
231 | value = buffer_read(evm.message.data, data_start_index, size) |
232 | memory_write(evm.memory, memory_start_index, value) |
233 | |
234 | # PROGRAM COUNTER |
235 | evm.pc += Uint(1) |
codesize
Push the size of code running in current environment onto the stack.
Parameters
evm : The current EVM frame.
def codesize(evm: Evm) -> None:
239 | """ |
---|---|
240 | Push the size of code running in current environment onto the stack. |
241 |
|
242 | Parameters |
243 | ---------- |
244 | evm : |
245 | The current EVM frame. |
246 |
|
247 | """ |
248 | # STACK |
249 | pass |
250 | |
251 | # GAS |
252 | charge_gas(evm, GAS_BASE) |
253 | |
254 | # OPERATION |
255 | push(evm.stack, U256(len(evm.code))) |
256 | |
257 | # PROGRAM COUNTER |
258 | evm.pc += Uint(1) |
codecopy
Copy a portion of the code in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
Parameters
evm : The current EVM frame.
def codecopy(evm: Evm) -> None:
262 | """ |
---|---|
263 | Copy a portion of the code in current environment to memory. |
264 |
|
265 | This will also expand the memory, in case that the memory is insufficient |
266 | to store the data. |
267 |
|
268 | Parameters |
269 | ---------- |
270 | evm : |
271 | The current EVM frame. |
272 |
|
273 | """ |
274 | # STACK |
275 | memory_start_index = pop(evm.stack) |
276 | code_start_index = pop(evm.stack) |
277 | size = pop(evm.stack) |
278 | |
279 | # GAS |
280 | words = ceil32(Uint(size)) // Uint(32) |
281 | copy_gas_cost = GAS_COPY * words |
282 | extend_memory = calculate_gas_extend_memory( |
283 | evm.memory, [(memory_start_index, size)] |
284 | ) |
285 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
286 | |
287 | # OPERATION |
288 | evm.memory += b"\x00" * extend_memory.expand_by |
289 | value = buffer_read(evm.code, code_start_index, size) |
290 | memory_write(evm.memory, memory_start_index, value) |
291 | |
292 | # PROGRAM COUNTER |
293 | evm.pc += Uint(1) |
gasprice
Push the gas price used in current environment onto the stack.
Parameters
evm : The current EVM frame.
def gasprice(evm: Evm) -> None:
297 | """ |
---|---|
298 | Push the gas price used in current environment onto the stack. |
299 |
|
300 | Parameters |
301 | ---------- |
302 | evm : |
303 | The current EVM frame. |
304 |
|
305 | """ |
306 | # STACK |
307 | pass |
308 | |
309 | # GAS |
310 | charge_gas(evm, GAS_BASE) |
311 | |
312 | # OPERATION |
313 | push(evm.stack, U256(evm.env.gas_price)) |
314 | |
315 | # PROGRAM COUNTER |
316 | evm.pc += Uint(1) |
extcodesize
Push the code size of a given account onto the stack.
Parameters
evm : The current EVM frame.
def extcodesize(evm: Evm) -> None:
320 | """ |
---|---|
321 | Push the code size of a given account onto the stack. |
322 |
|
323 | Parameters |
324 | ---------- |
325 | evm : |
326 | The current EVM frame. |
327 |
|
328 | """ |
329 | # STACK |
330 | address = to_address(pop(evm.stack)) |
331 | |
332 | # GAS |
333 | charge_gas(evm, GAS_EXTERNAL) |
334 | |
335 | # OPERATION |
336 | # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. |
337 | codesize = U256(len(get_account(evm.env.state, address).code)) |
338 | |
339 | push(evm.stack, codesize) |
340 | |
341 | # PROGRAM COUNTER |
342 | evm.pc += Uint(1) |
extcodecopy
Copy a portion of an account's code to memory.
Parameters
evm : The current EVM frame.
def extcodecopy(evm: Evm) -> None:
346 | """ |
---|---|
347 | Copy a portion of an account's code to memory. |
348 |
|
349 | Parameters |
350 | ---------- |
351 | evm : |
352 | The current EVM frame. |
353 |
|
354 | """ |
355 | # STACK |
356 | address = to_address(pop(evm.stack)) |
357 | memory_start_index = pop(evm.stack) |
358 | code_start_index = pop(evm.stack) |
359 | size = pop(evm.stack) |
360 | |
361 | # GAS |
362 | words = ceil32(Uint(size)) // Uint(32) |
363 | copy_gas_cost = GAS_COPY * words |
364 | extend_memory = calculate_gas_extend_memory( |
365 | evm.memory, [(memory_start_index, size)] |
366 | ) |
367 | charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) |
368 | |
369 | # OPERATION |
370 | evm.memory += b"\x00" * extend_memory.expand_by |
371 | code = get_account(evm.env.state, address).code |
372 | value = buffer_read(code, code_start_index, size) |
373 | memory_write(evm.memory, memory_start_index, value) |
374 | |
375 | # PROGRAM COUNTER |
376 | evm.pc += Uint(1) |