pallet_revive/vm/evm/instructions/
system.rs1use super::Context;
19use crate::{
20 address::AddressMapper,
21 vm::{evm::U256Converter, Ext, RuntimeCosts},
22 Config,
23};
24use core::ptr;
25use revm::{
26 interpreter::{
27 gas as revm_gas,
28 interpreter_types::{InputsTr, LegacyBytecode, MemoryTr, ReturnData, StackTr},
29 CallInput, InstructionResult, Interpreter,
30 },
31 primitives::{Address, B256, KECCAK_EMPTY, U256},
32};
33use sp_io::hashing::keccak_256;
34
35pub fn keccak256<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
41 popn_top!([offset], top, context.interpreter);
42 let len = as_usize_or_fail!(context.interpreter, top);
43 gas!(context.interpreter, RuntimeCosts::HashKeccak256(len as u32));
44 let hash = if len == 0 {
45 KECCAK_EMPTY
46 } else {
47 let from = as_usize_or_fail!(context.interpreter, offset);
48 resize_memory!(context.interpreter, from, len);
49 keccak_256(context.interpreter.memory.slice_len(from, len).as_ref()).into()
50 };
51 *top = hash.into();
52}
53
54pub fn address<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
58 gas!(context.interpreter, RuntimeCosts::Address);
59 let address: Address = context.interpreter.extend.address().0.into();
60 push!(context.interpreter, address.into_word().into());
61}
62
63pub fn caller<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
67 gas!(context.interpreter, RuntimeCosts::Caller);
68 match context.interpreter.extend.caller().account_id() {
69 Ok(account_id) => {
70 let address: Address = <E::T as Config>::AddressMapper::to_address(account_id).0.into();
71 push!(context.interpreter, address.into_word().into());
72 },
73 Err(_) => {
74 context
75 .interpreter
76 .halt(revm::interpreter::InstructionResult::FatalExternalError);
77 },
78 }
79}
80
81pub fn codesize<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
85 gas_legacy!(context.interpreter, revm_gas::BASE);
86 push!(context.interpreter, U256::from(context.interpreter.bytecode.bytecode_len()));
87}
88
89pub fn codecopy<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
93 popn!([memory_offset, code_offset, len], context.interpreter);
94 let len = as_usize_or_fail!(context.interpreter, len);
95 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
96 return;
97 };
98 let code_offset = as_usize_saturated!(code_offset);
99
100 context.interpreter.memory.set_data(
102 memory_offset,
103 code_offset,
104 len,
105 context.interpreter.bytecode.bytecode_slice(),
106 );
107}
108
109pub fn calldataload<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
113 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
114 popn_top!([], offset_ptr, context.interpreter);
116 let mut word = B256::ZERO;
117 let offset = as_usize_saturated!(offset_ptr);
118 let input = context.interpreter.input.input();
119 let input_len = input.len();
120 if offset < input_len {
121 let count = 32.min(input_len - offset);
122
123 match context.interpreter.input.input() {
128 CallInput::Bytes(bytes) => {
129 unsafe {
130 ptr::copy_nonoverlapping(bytes.as_ptr().add(offset), word.as_mut_ptr(), count)
131 };
132 },
133 CallInput::SharedBuffer(range) => {
134 let input_slice = context.interpreter.memory.global_slice(range.clone());
135 unsafe {
136 ptr::copy_nonoverlapping(
137 input_slice.as_ptr().add(offset),
138 word.as_mut_ptr(),
139 count,
140 )
141 };
142 },
143 }
144 }
145 *offset_ptr = word.into();
146}
147
148pub fn calldatasize<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
152 gas_legacy!(context.interpreter, revm_gas::BASE);
153 push!(context.interpreter, U256::from(context.interpreter.input.input().len()));
154}
155
156pub fn callvalue<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
160 gas!(context.interpreter, RuntimeCosts::ValueTransferred);
161 let call_value = context.interpreter.extend.value_transferred();
162 push!(context.interpreter, call_value.into_revm_u256());
163}
164
165pub fn calldatacopy<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
169 popn!([memory_offset, data_offset, len], context.interpreter);
170 let len = as_usize_or_fail!(context.interpreter, len);
171 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
172 return;
173 };
174
175 let data_offset = as_usize_saturated!(data_offset);
176 match context.interpreter.input.input() {
177 CallInput::Bytes(bytes) => {
178 context
179 .interpreter
180 .memory
181 .set_data(memory_offset, data_offset, len, bytes.as_ref());
182 },
183 CallInput::SharedBuffer(range) => {
184 context.interpreter.memory.set_data_from_global(
185 memory_offset,
186 data_offset,
187 len,
188 range.clone(),
189 );
190 },
191 }
192}
193
194pub fn returndatasize<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
196 gas_legacy!(context.interpreter, revm_gas::BASE);
197 push!(context.interpreter, U256::from(context.interpreter.return_data.buffer().len()));
198}
199
200pub fn returndatacopy<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
202 popn!([memory_offset, offset, len], context.interpreter);
203
204 let len = as_usize_or_fail!(context.interpreter, len);
205 let data_offset = as_usize_saturated!(offset);
206
207 let data_end = data_offset.saturating_add(len);
209 if data_end > context.interpreter.return_data.buffer().len() {
210 context.interpreter.halt(InstructionResult::OutOfOffset);
211 return;
212 }
213
214 let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else {
215 return;
216 };
217
218 context.interpreter.memory.set_data(
220 memory_offset,
221 data_offset,
222 len,
223 context.interpreter.return_data.buffer(),
224 );
225}
226
227pub fn gas<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
231 gas!(context.interpreter, RuntimeCosts::RefTimeLeft);
232 let gas = context.interpreter.extend.gas_meter().gas_left().ref_time();
235 push!(context.interpreter, U256::from(gas));
236}
237
238pub fn memory_resize<'a, E: Ext>(
242 interpreter: &mut Interpreter<crate::vm::evm::EVMInterpreter<'a, E>>,
243 memory_offset: U256,
244 len: usize,
245) -> Option<usize> {
246 gas!(interpreter, RuntimeCosts::CopyToContract(len as u32), None);
247 if len == 0 {
248 return None;
249 }
250 let memory_offset = as_usize_or_fail_ret!(interpreter, memory_offset, None);
251 resize_memory!(interpreter, memory_offset, len, None);
252
253 Some(memory_offset)
254}