1use crate::{
2 gas,
3 interpreter::Interpreter,
4 interpreter_types::{
5 InputsTr, InterpreterTypes, LegacyBytecode, MemoryTr, ReturnData, RuntimeFlag, StackTr,
6 },
7 CallInput, InstructionResult,
8};
9use core::ptr;
10use primitives::{B256, KECCAK_EMPTY, U256};
11
12use crate::InstructionContext;
13
14pub fn keccak256<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
15 popn_top!([offset], top, context.interpreter);
16 let len = as_usize_or_fail!(context.interpreter, top);
17 gas_or_fail!(context.interpreter, gas::keccak256_cost(len));
18 let hash = if len == 0 {
19 KECCAK_EMPTY
20 } else {
21 let from = as_usize_or_fail!(context.interpreter, offset);
22 resize_memory!(context.interpreter, from, len);
23 primitives::keccak256(context.interpreter.memory.slice_len(from, len).as_ref())
24 };
25 *top = hash.into();
26}
27
28pub fn address<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
29 gas!(context.interpreter, gas::BASE);
30 push!(
31 context.interpreter,
32 context
33 .interpreter
34 .input
35 .target_address()
36 .into_word()
37 .into()
38 );
39}
40
41pub fn caller<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
42 gas!(context.interpreter, gas::BASE);
43 push!(
44 context.interpreter,
45 context
46 .interpreter
47 .input
48 .caller_address()
49 .into_word()
50 .into()
51 );
52}
53
54pub fn codesize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
55 gas!(context.interpreter, gas::BASE);
56 push!(
57 context.interpreter,
58 U256::from(context.interpreter.bytecode.bytecode_len())
59 );
60}
61
62pub fn codecopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
63 popn!([memory_offset, code_offset, len], context.interpreter);
64 let len = as_usize_or_fail!(context.interpreter, len);
65 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
66 return;
67 };
68 let code_offset = as_usize_saturated!(code_offset);
69
70 context.interpreter.memory.set_data(
72 memory_offset,
73 code_offset,
74 len,
75 context.interpreter.bytecode.bytecode_slice(),
76 );
77}
78
79pub fn calldataload<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
80 gas!(context.interpreter, gas::VERYLOW);
81 popn_top!([], offset_ptr, context.interpreter);
83 let mut word = B256::ZERO;
84 let offset = as_usize_saturated!(offset_ptr);
85 let input = context.interpreter.input.input();
86 let input_len = input.len();
87 if offset < input_len {
88 let count = 32.min(input_len - offset);
89
90 match context.interpreter.input.input() {
95 CallInput::Bytes(bytes) => {
96 unsafe {
97 ptr::copy_nonoverlapping(bytes.as_ptr().add(offset), word.as_mut_ptr(), count)
98 };
99 }
100 CallInput::SharedBuffer(range) => {
101 let input_slice = context.interpreter.memory.global_slice(range.clone());
102 unsafe {
103 ptr::copy_nonoverlapping(
104 input_slice.as_ptr().add(offset),
105 word.as_mut_ptr(),
106 count,
107 )
108 };
109 }
110 }
111 }
112 *offset_ptr = word.into();
113}
114
115pub fn calldatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
116 gas!(context.interpreter, gas::BASE);
117 push!(
118 context.interpreter,
119 U256::from(context.interpreter.input.input().len())
120 );
121}
122
123pub fn callvalue<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
124 gas!(context.interpreter, gas::BASE);
125 push!(context.interpreter, context.interpreter.input.call_value());
126}
127
128pub fn calldatacopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
129 popn!([memory_offset, data_offset, len], context.interpreter);
130 let len = as_usize_or_fail!(context.interpreter, len);
131 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
132 return;
133 };
134
135 let data_offset = as_usize_saturated!(data_offset);
136 match context.interpreter.input.input() {
137 CallInput::Bytes(bytes) => {
138 context
139 .interpreter
140 .memory
141 .set_data(memory_offset, data_offset, len, bytes.as_ref());
142 }
143 CallInput::SharedBuffer(range) => {
144 context.interpreter.memory.set_data_from_global(
145 memory_offset,
146 data_offset,
147 len,
148 range.clone(),
149 );
150 }
151 }
152}
153
154pub fn returndatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
156 check!(context.interpreter, BYZANTIUM);
157 gas!(context.interpreter, gas::BASE);
158 push!(
159 context.interpreter,
160 U256::from(context.interpreter.return_data.buffer().len())
161 );
162}
163
164pub fn returndatacopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
166 check!(context.interpreter, BYZANTIUM);
167 popn!([memory_offset, offset, len], context.interpreter);
168
169 let len = as_usize_or_fail!(context.interpreter, len);
170 let data_offset = as_usize_saturated!(offset);
171
172 let data_end = data_offset.saturating_add(len);
175 if data_end > context.interpreter.return_data.buffer().len()
176 && !context.interpreter.runtime_flag.is_eof()
177 {
178 context.interpreter.halt(InstructionResult::OutOfOffset);
179 return;
180 }
181
182 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
183 return;
184 };
185
186 context.interpreter.memory.set_data(
188 memory_offset,
189 data_offset,
190 len,
191 context.interpreter.return_data.buffer(),
192 );
193}
194
195pub fn returndataload<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
197 require_eof!(context.interpreter);
198 gas!(context.interpreter, gas::VERYLOW);
199 popn_top!([], offset, context.interpreter);
200 let offset_usize = as_usize_saturated!(offset);
201
202 let mut output = [0u8; 32];
203 if let Some(available) = context
204 .interpreter
205 .return_data
206 .buffer()
207 .len()
208 .checked_sub(offset_usize)
209 {
210 let copy_len = available.min(32);
211 output[..copy_len].copy_from_slice(
212 &context.interpreter.return_data.buffer()[offset_usize..offset_usize + copy_len],
213 );
214 }
215
216 *offset = B256::from(output).into();
217}
218
219pub fn gas<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
220 gas!(context.interpreter, gas::BASE);
221 push!(
222 context.interpreter,
223 U256::from(context.interpreter.gas.remaining())
224 );
225}
226
227pub fn memory_resize(
229 interpreter: &mut Interpreter<impl InterpreterTypes>,
230 memory_offset: U256,
231 len: usize,
232) -> Option<usize> {
233 gas_or_fail!(interpreter, gas::copy_cost_verylow(len), None);
235 if len == 0 {
236 return None;
237 }
238 let memory_offset = as_usize_or_fail_ret!(interpreter, memory_offset, None);
239 resize_memory!(interpreter, memory_offset, len, None);
240
241 Some(memory_offset)
242}
243
244#[cfg(test)]
245mod test {
246 use super::*;
247 use crate::{instruction_table, interpreter_types::LoopControl};
248 use bytecode::{opcode::RETURNDATACOPY, opcode::RETURNDATALOAD, Bytecode};
249 use primitives::{bytes, Bytes};
250
251 #[test]
252 fn returndataload() {
253 let bytecode = Bytecode::new_raw(Bytes::from(&[
254 RETURNDATALOAD,
255 RETURNDATALOAD,
256 RETURNDATALOAD,
257 RETURNDATALOAD,
258 ]));
259 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
260
261 let table = instruction_table();
262 interpreter.runtime_flag.is_eof = true;
263
264 let _ = interpreter.stack.push(U256::from(0));
265 interpreter.return_data.set_buffer(bytes!(
266 "000000000000000400000000000000030000000000000002000000000000000100"
267 ));
268
269 interpreter.step_dummy(&table);
270 assert_eq!(
271 interpreter.stack.data(),
272 &vec![U256::from_limbs([0x01, 0x02, 0x03, 0x04])]
273 );
274
275 let _ = interpreter.stack.pop();
276 let _ = interpreter.stack.push(U256::from(1));
277
278 interpreter.step_dummy(&table);
279 assert!(interpreter.bytecode.is_not_end());
280 assert_eq!(
281 interpreter.stack.data(),
282 &vec![U256::from_limbs([0x0100, 0x0200, 0x0300, 0x0400])]
283 );
284
285 let _ = interpreter.stack.pop();
286 let _ = interpreter.stack.push(U256::from(32));
287 interpreter.step_dummy(&table);
288 assert!(interpreter.bytecode.is_not_end());
289 assert_eq!(
290 interpreter.stack.data(),
291 &vec![U256::from_limbs([0x00, 0x00, 0x00, 0x00])]
292 );
293
294 let _ = interpreter.stack.pop();
296 let _ = interpreter
297 .stack
298 .push(U256::from(interpreter.return_data.buffer().len()));
299 interpreter.step_dummy(&table);
300 assert!(interpreter.bytecode.is_not_end());
301 assert_eq!(
302 interpreter.stack.data(),
303 &vec![U256::from_limbs([0x00, 0x00, 0x00, 0x00])]
304 );
305 }
306
307 #[test]
308 fn returndatacopy() {
309 let bytecode = Bytecode::new_raw(Bytes::from(&[
310 RETURNDATACOPY,
311 RETURNDATACOPY,
312 RETURNDATACOPY,
313 RETURNDATACOPY,
314 RETURNDATACOPY,
315 RETURNDATACOPY,
316 ]));
317 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
318
319 let table = instruction_table();
320 interpreter.runtime_flag.is_eof = true;
321
322 interpreter.return_data.set_buffer(bytes!(
323 "000000000000000400000000000000030000000000000002000000000000000100"
324 ));
325 interpreter.memory.resize(256);
326
327 let _ = interpreter.stack.push(U256::from(32));
329 let _ = interpreter.stack.push(U256::from(0));
330 let _ = interpreter.stack.push(U256::from(0));
331
332 interpreter.step_dummy(&table);
333 assert!(interpreter.bytecode.is_not_end());
334 assert_eq!(
335 *interpreter.memory.slice(0..32),
336 interpreter.return_data.buffer()[0..32]
337 );
338
339 let _ = interpreter.stack.push(U256::from(64));
341 let _ = interpreter.stack.push(U256::from(16));
342 let _ = interpreter.stack.push(U256::from(64));
343 interpreter.step_dummy(&table);
344 assert!(interpreter.bytecode.is_not_end());
345 assert_eq!(
346 *interpreter.memory.slice(64..80),
347 interpreter.return_data.buffer()[16..32]
348 );
349 assert_eq!(*interpreter.memory.slice(80..128), [0u8; 48]);
350
351 let _ = interpreter.stack.push(U256::from(32));
353 let _ = interpreter.stack.push(U256::from(96));
354 let _ = interpreter.stack.push(U256::from(128));
355 interpreter.step_dummy(&table);
356 assert!(interpreter.bytecode.is_not_end());
357 assert_eq!(*interpreter.memory.slice(128..160), [0u8; 32]);
358
359 let _ = interpreter.stack.push(U256::from(32));
361 let _ = interpreter.stack.push(U256::MAX);
362 let _ = interpreter.stack.push(U256::from(0));
363 interpreter.step_dummy(&table);
364 assert!(interpreter.bytecode.is_not_end());
365 assert_eq!(*interpreter.memory.slice(0..32), [0u8; 32]);
366
367 let _ = interpreter.stack.push(U256::from(32));
369 let _ = interpreter
370 .stack
371 .push(U256::from(interpreter.return_data.buffer().len() - 32));
372 let _ = interpreter.stack.push(U256::from(0));
373 interpreter.step_dummy(&table);
374 assert!(interpreter.bytecode.is_not_end());
375 assert_eq!(
376 *interpreter.memory.slice(0..32),
377 interpreter.return_data.buffer()[interpreter.return_data.buffer().len() - 32..]
378 );
379
380 let _ = interpreter.stack.push(U256::from(32));
382 let _ = interpreter
383 .stack
384 .push(U256::from(interpreter.return_data.buffer().len()));
385 let _ = interpreter.stack.push(U256::from(0));
386 interpreter.step_dummy(&table);
387 assert!(interpreter.bytecode.is_not_end());
388 assert_eq!(*interpreter.memory.slice(0..32), [0u8; 32]);
389 }
390}