revm_interpreter/instructions/
system.rs1use 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>) {
18 popn_top!([offset], top, context.interpreter);
19 let len = as_usize_or_fail!(context.interpreter, top);
20 gas_or_fail!(context.interpreter, gas::keccak256_cost(len));
21 let hash = if len == 0 {
22 KECCAK_EMPTY
23 } else {
24 let from = as_usize_or_fail!(context.interpreter, offset);
25 resize_memory!(context.interpreter, from, len);
26 primitives::keccak256(context.interpreter.memory.slice_len(from, len).as_ref())
27 };
28 *top = hash.into();
29}
30
31pub fn address<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
35 push!(
37 context.interpreter,
38 context
39 .interpreter
40 .input
41 .target_address()
42 .into_word()
43 .into()
44 );
45}
46
47pub fn caller<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
51 push!(
53 context.interpreter,
54 context
55 .interpreter
56 .input
57 .caller_address()
58 .into_word()
59 .into()
60 );
61}
62
63pub fn codesize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
67 push!(
69 context.interpreter,
70 U256::from(context.interpreter.bytecode.bytecode_len())
71 );
72}
73
74pub fn codecopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
78 popn!([memory_offset, code_offset, len], context.interpreter);
79 let len = as_usize_or_fail!(context.interpreter, len);
80 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
81 return;
82 };
83 let code_offset = as_usize_saturated!(code_offset);
84
85 context.interpreter.memory.set_data(
87 memory_offset,
88 code_offset,
89 len,
90 context.interpreter.bytecode.bytecode_slice(),
91 );
92}
93
94pub fn calldataload<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
98 popn_top!([], offset_ptr, context.interpreter);
100 let mut word = B256::ZERO;
101 let offset = as_usize_saturated!(offset_ptr);
102 let input = context.interpreter.input.input();
103 let input_len = input.len();
104 if offset < input_len {
105 let count = 32.min(input_len - offset);
106
107 match context.interpreter.input.input() {
112 CallInput::Bytes(bytes) => {
113 unsafe {
114 ptr::copy_nonoverlapping(bytes.as_ptr().add(offset), word.as_mut_ptr(), count)
115 };
116 }
117 CallInput::SharedBuffer(range) => {
118 let input_slice = context.interpreter.memory.global_slice(range.clone());
119 unsafe {
120 ptr::copy_nonoverlapping(
121 input_slice.as_ptr().add(offset),
122 word.as_mut_ptr(),
123 count,
124 )
125 };
126 }
127 }
128 }
129 *offset_ptr = word.into();
130}
131
132pub fn calldatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
136 push!(
138 context.interpreter,
139 U256::from(context.interpreter.input.input().len())
140 );
141}
142
143pub fn callvalue<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
147 push!(context.interpreter, context.interpreter.input.call_value());
149}
150
151pub fn calldatacopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
155 popn!([memory_offset, data_offset, len], context.interpreter);
156 let len = as_usize_or_fail!(context.interpreter, len);
157 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
158 return;
159 };
160
161 let data_offset = as_usize_saturated!(data_offset);
162 match context.interpreter.input.input() {
163 CallInput::Bytes(bytes) => {
164 context
165 .interpreter
166 .memory
167 .set_data(memory_offset, data_offset, len, bytes.as_ref());
168 }
169 CallInput::SharedBuffer(range) => {
170 context.interpreter.memory.set_data_from_global(
171 memory_offset,
172 data_offset,
173 len,
174 range.clone(),
175 );
176 }
177 }
178}
179
180pub fn returndatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
182 check!(context.interpreter, BYZANTIUM);
183 push!(
185 context.interpreter,
186 U256::from(context.interpreter.return_data.buffer().len())
187 );
188}
189
190pub fn returndatacopy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
192 check!(context.interpreter, BYZANTIUM);
193 popn!([memory_offset, offset, len], context.interpreter);
194
195 let len = as_usize_or_fail!(context.interpreter, len);
196 let data_offset = as_usize_saturated!(offset);
197
198 let data_end = data_offset.saturating_add(len);
200 if data_end > context.interpreter.return_data.buffer().len() {
201 context.interpreter.halt(InstructionResult::OutOfOffset);
202 return;
203 }
204
205 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
206 return;
207 };
208
209 context.interpreter.memory.set_data(
211 memory_offset,
212 data_offset,
213 len,
214 context.interpreter.return_data.buffer(),
215 );
216}
217
218pub fn gas<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
222 push!(
224 context.interpreter,
225 U256::from(context.interpreter.gas.remaining())
226 );
227}
228
229pub fn memory_resize(
233 interpreter: &mut Interpreter<impl InterpreterTypes>,
234 memory_offset: U256,
235 len: usize,
236) -> Option<usize> {
237 gas_or_fail!(interpreter, gas::copy_cost_verylow(len), None);
239 if len == 0 {
240 return None;
241 }
242 let memory_offset = as_usize_or_fail_ret!(interpreter, memory_offset, None);
243 resize_memory!(interpreter, memory_offset, len, None);
244
245 Some(memory_offset)
246}