revm_interpreter/instructions/
data.rs1use crate::{
2 gas::{cost_per_word, BASE, DATA_LOAD_GAS, VERYLOW},
3 interpreter_types::{
4 EofData, Immediates, InterpreterTypes, Jumps, MemoryTr, RuntimeFlag, StackTr,
5 },
6};
7use primitives::{B256, U256};
8
9use crate::InstructionContext;
10
11pub fn data_load<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
12 require_eof!(context.interpreter);
13 gas!(context.interpreter, DATA_LOAD_GAS);
14 popn_top!([], offset, context.interpreter);
15
16 let offset_usize = as_usize_saturated!(offset);
17
18 let slice = context.interpreter.bytecode.data_slice(offset_usize, 32);
19
20 let mut word = [0u8; 32];
21 word[..slice.len()].copy_from_slice(slice);
22
23 *offset = U256::from_be_bytes(word);
24}
25
26pub fn data_loadn<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
27 require_eof!(context.interpreter);
28 gas!(context.interpreter, VERYLOW);
29 let offset = context.interpreter.bytecode.read_u16() as usize;
30
31 let slice = context.interpreter.bytecode.data_slice(offset, 32);
32
33 let mut word = [0u8; 32];
34 word[..slice.len()].copy_from_slice(slice);
35
36 push!(context.interpreter, B256::new(word).into());
37
38 context.interpreter.bytecode.relative_jump(2);
40}
41
42pub fn data_size<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
43 require_eof!(context.interpreter);
44 gas!(context.interpreter, BASE);
45
46 push!(
47 context.interpreter,
48 U256::from(context.interpreter.bytecode.data_size())
49 );
50}
51
52pub fn data_copy<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
53 require_eof!(context.interpreter);
54 gas!(context.interpreter, VERYLOW);
55 popn!([mem_offset, offset, size], context.interpreter);
56
57 let size = as_usize_or_fail!(context.interpreter, size);
59 if size == 0 {
61 return;
62 }
63 let mem_offset = as_usize_or_fail!(context.interpreter, mem_offset);
65 resize_memory!(context.interpreter, mem_offset, size);
66
67 gas_or_fail!(context.interpreter, cost_per_word(size, VERYLOW));
68
69 let offset = as_usize_saturated!(offset);
70 let data = context.interpreter.bytecode.data();
71
72 context
74 .interpreter
75 .memory
76 .set_data(mem_offset, offset, size, data);
77}
78
79#[cfg(test)]
80mod test {
81 use bytecode::{Bytecode, Eof};
82 use primitives::{b256, bytes, Bytes};
83 use std::sync::Arc;
84
85 use super::*;
86 use crate::{instruction_table, Interpreter};
87 use bytecode::opcode::{DATACOPY, DATALOAD, DATALOADN, DATASIZE};
88
89 fn dummy_eof(code_bytes: Bytes) -> Bytecode {
90 let bytes = bytes!("ef00010100040200010001ff00000000800000fe");
91 let mut eof = Eof::decode(bytes).unwrap();
92
93 eof.body.data_section =
94 bytes!("000000000000000000000000000000000000000000000000000000000000000102030405");
95 eof.header.data_size = eof.body.data_section.len() as u16;
96
97 eof.header.code_sizes[0] = code_bytes.len() as u16;
98 eof.body.code_section[0] = code_bytes.len();
99 eof.body.code = code_bytes;
100 Bytecode::Eof(Arc::new(eof))
101 }
102
103 #[test]
104 fn dataload_dataloadn() {
105 let table = instruction_table();
106
107 let eof = dummy_eof(Bytes::from([
108 DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN,
109 0x00, 36, DATASIZE,
110 ]));
111
112 let mut interpreter = Interpreter::default().with_bytecode(eof);
113 interpreter.runtime_flag.is_eof = true;
114
115 let _ = interpreter.stack.push(U256::from(0));
117 interpreter.step_dummy(&table);
118 assert_eq!(interpreter.stack.data(), &vec![U256::from(0x01)]);
119 interpreter.stack.pop().unwrap();
120
121 interpreter.step_dummy(&table);
123 assert_eq!(interpreter.stack.data(), &vec![U256::from(0x01)]);
124 interpreter.stack.pop().unwrap();
125
126 let _ = interpreter.stack.push(U256::from(35));
128 interpreter.step_dummy(&table);
129
130 assert_eq!(
131 interpreter.stack.data(),
132 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
133 );
134 interpreter.stack.pop().unwrap();
135
136 interpreter.step_dummy(&table);
138 assert_eq!(
139 interpreter.stack.data(),
140 &vec![b256!("0500000000000000000000000000000000000000000000000000000000000000").into()]
141 );
142 interpreter.stack.pop().unwrap();
143
144 let _ = interpreter.stack.push(U256::from(36));
146 interpreter.step_dummy(&table);
147 assert_eq!(interpreter.stack.data(), &vec![U256::ZERO]);
148 interpreter.stack.pop().unwrap();
149
150 interpreter.step_dummy(&table);
152 assert_eq!(interpreter.stack.data(), &vec![U256::ZERO]);
153 interpreter.stack.pop().unwrap();
154
155 interpreter.step_dummy(&table);
157 assert_eq!(interpreter.stack.data(), &vec![U256::from(36)]);
158 }
159
160 #[test]
161 fn data_copy() {
162 let table = instruction_table();
163 let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY]));
164
165 let mut interpreter = Interpreter::default().with_bytecode(eof);
166 interpreter.runtime_flag.is_eof = true;
167
168 let _ = interpreter.stack.push(U256::from(32));
171 let _ = interpreter.stack.push(U256::from(0));
172 let _ = interpreter.stack.push(U256::from(0));
173
174 interpreter.step_dummy(&table);
175 assert_eq!(
176 *interpreter.memory.context_memory(),
177 bytes!("0000000000000000000000000000000000000000000000000000000000000001")
178 );
179
180 let _ = interpreter.stack.push(U256::from(2));
183 let _ = interpreter.stack.push(U256::from(35));
184 let _ = interpreter.stack.push(U256::from(1));
185 interpreter.step_dummy(&table);
186 assert_eq!(
187 *interpreter.memory.context_memory(),
188 bytes!("0005000000000000000000000000000000000000000000000000000000000001")
189 );
190
191 let _ = interpreter.stack.push(U256::from(2));
194 let _ = interpreter.stack.push(U256::from(37));
195 let _ = interpreter.stack.push(U256::from(1));
196 interpreter.step_dummy(&table);
197 assert_eq!(
198 *interpreter.memory.context_memory(),
199 bytes!("0000000000000000000000000000000000000000000000000000000000000001")
200 );
201
202 let _ = interpreter.stack.push(U256::from(0));
205 let _ = interpreter.stack.push(U256::from(37));
206 let _ = interpreter.stack.push(U256::from(1));
207 interpreter.step_dummy(&table);
208 assert_eq!(
209 *interpreter.memory.context_memory(),
210 bytes!("0000000000000000000000000000000000000000000000000000000000000001")
211 );
212 }
213}