revm_interpreter/instructions/
system.rs1use crate::{
2 interpreter::Interpreter,
3 interpreter_types::{
4 InputsTr, InterpreterTypes, LegacyBytecode, MemoryTr, ReturnData, RuntimeFlag, StackTr,
5 },
6 CallInput, InstructionResult,
7};
8use context_interface::{cfg::GasParams, Host};
9use core::ptr;
10use primitives::{B256, KECCAK_EMPTY, U256};
11
12use crate::InstructionContext;
13
14pub fn keccak256<WIRE: InterpreterTypes, H: Host + ?Sized>(
18 context: InstructionContext<'_, H, WIRE>,
19) {
20 popn_top!([offset], top, context.interpreter);
21 let len = as_usize_or_fail!(context.interpreter, top);
22 gas!(
23 context.interpreter,
24 context.host.gas_params().keccak256_cost(len)
25 );
26 let hash = if len == 0 {
27 KECCAK_EMPTY
28 } else {
29 let from = as_usize_or_fail!(context.interpreter, offset);
30 resize_memory!(context.interpreter, context.host.gas_params(), from, len);
31 primitives::keccak256(context.interpreter.memory.slice_len(from, len).as_ref())
32 };
33 *top = hash.into();
34}
35
36pub fn address<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
40 push!(
41 context.interpreter,
42 context
43 .interpreter
44 .input
45 .target_address()
46 .into_word()
47 .into()
48 );
49}
50
51pub fn caller<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
55 push!(
56 context.interpreter,
57 context
58 .interpreter
59 .input
60 .caller_address()
61 .into_word()
62 .into()
63 );
64}
65
66pub fn codesize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
70 push!(
71 context.interpreter,
72 U256::from(context.interpreter.bytecode.bytecode_len())
73 );
74}
75
76pub fn codecopy<WIRE: InterpreterTypes, H: Host + ?Sized>(
80 context: InstructionContext<'_, H, WIRE>,
81) {
82 popn!([memory_offset, code_offset, len], context.interpreter);
83 let len = as_usize_or_fail!(context.interpreter, len);
84 let Some(memory_offset) = copy_cost_and_memory_resize(
85 context.interpreter,
86 context.host.gas_params(),
87 memory_offset,
88 len,
89 ) else {
90 return;
91 };
92 let code_offset = as_usize_saturated!(code_offset);
93
94 context.interpreter.memory.set_data(
96 memory_offset,
97 code_offset,
98 len,
99 context.interpreter.bytecode.bytecode_slice(),
100 );
101}
102
103pub fn calldataload<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
107 popn_top!([], offset_ptr, context.interpreter);
108 let mut word = B256::ZERO;
109 let offset = as_usize_saturated!(offset_ptr);
110 let input = context.interpreter.input.input();
111 let input_len = input.len();
112 if offset < input_len {
113 let count = 32.min(input_len - offset);
114
115 match context.interpreter.input.input() {
120 CallInput::Bytes(bytes) => {
121 unsafe {
122 ptr::copy_nonoverlapping(bytes.as_ptr().add(offset), word.as_mut_ptr(), count)
123 };
124 }
125 CallInput::SharedBuffer(range) => {
126 let input_slice = context.interpreter.memory.global_slice(range.clone());
127 unsafe {
128 ptr::copy_nonoverlapping(
129 input_slice.as_ptr().add(offset),
130 word.as_mut_ptr(),
131 count,
132 )
133 };
134 }
135 }
136 }
137 *offset_ptr = word.into();
138}
139
140pub fn calldatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
144 push!(
145 context.interpreter,
146 U256::from(context.interpreter.input.input().len())
147 );
148}
149
150pub fn callvalue<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
154 push!(context.interpreter, context.interpreter.input.call_value());
155}
156
157pub fn calldatacopy<WIRE: InterpreterTypes, H: Host + ?Sized>(
161 context: InstructionContext<'_, H, WIRE>,
162) {
163 popn!([memory_offset, data_offset, len], context.interpreter);
164 let len = as_usize_or_fail!(context.interpreter, len);
165 let Some(memory_offset) = copy_cost_and_memory_resize(
166 context.interpreter,
167 context.host.gas_params(),
168 memory_offset,
169 len,
170 ) else {
171 return;
172 };
173
174 let data_offset = as_usize_saturated!(data_offset);
175 match context.interpreter.input.input() {
176 CallInput::Bytes(bytes) => {
177 context
178 .interpreter
179 .memory
180 .set_data(memory_offset, data_offset, len, bytes.as_ref());
181 }
182 CallInput::SharedBuffer(range) => {
183 context.interpreter.memory.set_data_from_global(
184 memory_offset,
185 data_offset,
186 len,
187 range.clone(),
188 );
189 }
190 }
191}
192
193pub fn returndatasize<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
195 check!(context.interpreter, BYZANTIUM);
196 push!(
197 context.interpreter,
198 U256::from(context.interpreter.return_data.buffer().len())
199 );
200}
201
202pub fn returndatacopy<WIRE: InterpreterTypes, H: Host + ?Sized>(
204 context: InstructionContext<'_, H, WIRE>,
205) {
206 check!(context.interpreter, BYZANTIUM);
207 popn!([memory_offset, offset, len], context.interpreter);
208
209 let len = as_usize_or_fail!(context.interpreter, len);
210 let data_offset = as_usize_saturated!(offset);
211
212 let data_end = data_offset.saturating_add(len);
214 if data_end > context.interpreter.return_data.buffer().len() {
215 context.interpreter.halt(InstructionResult::OutOfOffset);
216 return;
217 }
218
219 let Some(memory_offset) = copy_cost_and_memory_resize(
220 context.interpreter,
221 context.host.gas_params(),
222 memory_offset,
223 len,
224 ) else {
225 return;
226 };
227
228 context.interpreter.memory.set_data(
230 memory_offset,
231 data_offset,
232 len,
233 context.interpreter.return_data.buffer(),
234 );
235}
236
237pub fn gas<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
241 push!(
242 context.interpreter,
243 U256::from(context.interpreter.gas.remaining())
244 );
245}
246
247pub fn copy_cost_and_memory_resize(
251 interpreter: &mut Interpreter<impl InterpreterTypes>,
252 gas_params: &GasParams,
253 memory_offset: U256,
254 len: usize,
255) -> Option<usize> {
256 gas!(interpreter, gas_params.copy_cost(len), None);
258 if len == 0 {
259 return None;
260 }
261 let memory_offset = as_usize_or_fail_ret!(interpreter, memory_offset, None);
262 resize_memory!(interpreter, gas_params, memory_offset, len, None);
263
264 Some(memory_offset)
265}