1use crate::{
19 exec::ExecError,
20 vec,
21 vm::{BytecodeType, ExecResult, Ext},
22 AccountIdOf, Code, CodeInfo, Config, ContractBlob, DispatchError, Error, ExecReturnValue, H256,
23 LOG_TARGET, U256,
24};
25use alloc::{boxed::Box, vec::Vec};
26use core::cmp::min;
27use instructions::instruction_table;
28use pallet_revive_uapi::ReturnFlags;
29use revm::{
30 bytecode::Bytecode,
31 context::CreateScheme,
32 interpreter::{
33 host::DummyHost,
34 interpreter::{ExtBytecode, ReturnDataImpl, RuntimeFlags},
35 interpreter_action::InterpreterAction,
36 interpreter_types::{InputsTr, MemoryTr, ReturnData},
37 CallInput, CallInputs, CallScheme, CreateInputs, FrameInput, Gas, InstructionResult,
38 Interpreter, InterpreterResult, InterpreterTypes, SharedMemory, Stack,
39 },
40 primitives::{self, hardfork::SpecId, Address, Bytes},
41};
42use sp_core::H160;
43use sp_runtime::Weight;
44
45mod instructions;
46
47pub(crate) const DIFFICULTY: u64 = 2500000000000000_u64;
54
55pub(crate) const BASE_FEE: U256 = U256::zero();
59
60impl<T: Config> ContractBlob<T> {
61 pub fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError> {
63 if code.len() > revm::primitives::eip3860::MAX_INITCODE_SIZE {
64 return Err(<Error<T>>::BlobTooLarge.into());
65 }
66
67 if code.first() == Some(&0xEF) {
69 return Err(<Error<T>>::CodeRejected.into());
70 }
71
72 let code_len = code.len() as u32;
73 let code_info = CodeInfo {
74 owner,
75 deposit: Default::default(),
76 refcount: 0,
77 code_len,
78 code_type: BytecodeType::Evm,
79 behaviour_version: Default::default(),
80 };
81
82 Bytecode::new_raw_checked(Bytes::from(code.to_vec())).map_err(|err| {
83 log::debug!(target: LOG_TARGET, "failed to create evm bytecode from init code: {err:?}" );
84 <Error<T>>::CodeRejected
85 })?;
86
87 let code_hash = H256::default();
89 Ok(ContractBlob { code, code_info, code_hash })
90 }
91
92 pub fn from_evm_runtime_code(
94 code: Vec<u8>,
95 owner: AccountIdOf<T>,
96 ) -> Result<Self, DispatchError> {
97 if code.len() > revm::primitives::eip170::MAX_CODE_SIZE {
98 return Err(<Error<T>>::BlobTooLarge.into());
99 }
100
101 let code_len = code.len() as u32;
102 let deposit = super::calculate_code_deposit::<T>(code_len);
103
104 let code_info = CodeInfo {
105 owner,
106 deposit,
107 refcount: 0,
108 code_len,
109 code_type: BytecodeType::Evm,
110 behaviour_version: Default::default(),
111 };
112
113 Bytecode::new_raw_checked(Bytes::from(code.to_vec())).map_err(|err| {
114 log::debug!(target: LOG_TARGET, "failed to create evm bytecode from code: {err:?}" );
115 <Error<T>>::CodeRejected
116 })?;
117
118 let code_hash = H256(sp_io::hashing::keccak_256(&code));
119 Ok(ContractBlob { code, code_info, code_hash })
120 }
121}
122
123pub fn call<'a, E: Ext>(bytecode: Bytecode, ext: &'a mut E, inputs: EVMInputs) -> ExecResult {
125 let mut interpreter: Interpreter<EVMInterpreter<'a, E>> = Interpreter {
126 gas: Gas::default(),
127 bytecode: ExtBytecode::new(bytecode),
128 stack: Stack::new(),
129 return_data: Default::default(),
130 memory: SharedMemory::new(),
131 input: inputs,
132 runtime_flag: RuntimeFlags { is_static: false, spec_id: SpecId::default() },
133 extend: ext,
134 };
135
136 let table = instruction_table::<'a, E>();
137 let result = run(&mut interpreter, &table);
138
139 instruction_result_into_exec_error::<E>(result.result)
140 .map(Err)
141 .unwrap_or_else(|| {
142 Ok(ExecReturnValue {
143 flags: if result.is_revert() { ReturnFlags::REVERT } else { ReturnFlags::empty() },
144 data: result.output.to_vec(),
145 })
146 })
147}
148
149fn run<'a, E: Ext>(
151 interpreter: &mut Interpreter<EVMInterpreter<'a, E>>,
152 table: &revm::interpreter::InstructionTable<EVMInterpreter<'a, E>, DummyHost>,
153) -> InterpreterResult {
154 let host = &mut DummyHost {};
155 loop {
156 let action = interpreter.run_plain(table, host);
157 match action {
158 InterpreterAction::Return(result) => {
159 log::trace!(target: LOG_TARGET, "Evm return {:?}", result);
160 debug_assert!(
161 result.gas.limit() == 0 &&
162 result.gas.remaining() == 0 &&
163 result.gas.refunded() == 0,
164 "Interpreter gas state should remain unchanged; found: {:?}",
165 result.gas,
166 );
167 return result;
168 },
169 InterpreterAction::NewFrame(frame_input) => match frame_input {
170 FrameInput::Call(call_input) => run_call(interpreter, call_input),
171 FrameInput::Create(create_input) => run_create(interpreter, create_input),
172 FrameInput::Empty => unreachable!(),
173 },
174 }
175 }
176}
177
178fn run_call<'a, E: Ext>(
179 interpreter: &mut Interpreter<EVMInterpreter<'a, E>>,
180 call_input: Box<CallInputs>,
181) {
182 let callee: H160 = if call_input.scheme.is_delegate_call() {
183 call_input.bytecode_address.0 .0.into()
184 } else {
185 call_input.target_address.0 .0.into()
186 };
187
188 let input = match &call_input.input {
189 CallInput::Bytes(bytes) => bytes.to_vec(),
190 CallInput::SharedBuffer(range) => interpreter.memory.global_slice(range.clone()).to_vec(),
192 };
193 let call_result = match call_input.scheme {
194 CallScheme::Call | CallScheme::StaticCall => interpreter.extend.call(
195 Weight::from_parts(call_input.gas_limit, u64::MAX),
196 U256::MAX,
197 &callee,
198 U256::from_revm_u256(&call_input.call_value()),
199 input,
200 true,
201 call_input.is_static,
202 ),
203 CallScheme::CallCode => {
204 unreachable!()
205 },
206 CallScheme::DelegateCall => interpreter.extend.delegate_call(
207 Weight::from_parts(call_input.gas_limit, u64::MAX),
208 U256::MAX,
209 callee,
210 input,
211 ),
212 };
213
214 let return_value = interpreter.extend.last_frame_output();
215 let return_data: Bytes = return_value.data.clone().into();
216
217 let mem_length = call_input.return_memory_offset.len();
218 let mem_start = call_input.return_memory_offset.start;
219 let returned_len = return_data.len();
220 let target_len = min(mem_length, returned_len);
221 interpreter.return_data.set_buffer(return_data);
223
224 match call_result {
225 Ok(()) => {
226 interpreter
229 .memory
230 .set(mem_start, &interpreter.return_data.buffer()[..target_len]);
231 let _ =
232 interpreter.stack.push(primitives::U256::from(!return_value.did_revert() as u8));
233 },
234 Err(err) => {
235 let _ = interpreter.stack.push(primitives::U256::ZERO);
236 if let Some(reason) = exec_error_into_halt_reason::<E>(err) {
237 interpreter.halt(reason);
238 }
239 },
240 }
241}
242
243fn run_create<'a, E: Ext>(
244 interpreter: &mut Interpreter<EVMInterpreter<'a, E>>,
245 create_input: Box<CreateInputs>,
246) {
247 let value = U256::from_revm_u256(&create_input.value);
248
249 let salt = match create_input.scheme {
250 CreateScheme::Create => None,
251 CreateScheme::Create2 { salt } => Some(salt.to_le_bytes()),
252 CreateScheme::Custom { .. } => unreachable!("custom create schemes are not supported"),
253 };
254
255 let call_result = interpreter.extend.instantiate(
256 Weight::from_parts(create_input.gas_limit, u64::MAX),
257 U256::MAX,
258 Code::Upload(create_input.init_code.to_vec()),
259 value,
260 vec![],
261 salt.as_ref(),
262 );
263
264 let return_value = interpreter.extend.last_frame_output();
265 let return_data: Bytes = return_value.data.clone().into();
266
267 match call_result {
268 Ok(address) => {
269 if return_value.did_revert() {
270 interpreter.return_data.set_buffer(return_data);
273 let _ = interpreter.stack.push(primitives::U256::ZERO);
274 } else {
275 interpreter.return_data.clear();
277 let stack_item: Address = address.0.into();
278 let _ = interpreter.stack.push(stack_item.into_word().into());
279 }
280 },
281 Err(err) => {
282 let _ = interpreter.stack.push(primitives::U256::ZERO);
283 if let Some(reason) = exec_error_into_halt_reason::<E>(err) {
284 interpreter.halt(reason);
285 }
286 },
287 }
288}
289
290pub struct EVMInterpreter<'a, E: Ext> {
297 _phantom: core::marker::PhantomData<&'a E>,
298}
299
300impl<'a, E: Ext> InterpreterTypes for EVMInterpreter<'a, E> {
301 type Stack = Stack;
302 type Memory = SharedMemory;
303 type Bytecode = ExtBytecode;
304 type ReturnData = ReturnDataImpl;
305 type Input = EVMInputs;
306 type RuntimeFlag = RuntimeFlags;
307 type Extend = &'a mut E;
308 type Output = InterpreterAction;
309}
310
311#[derive(Debug, Clone, Default)]
320pub struct EVMInputs(CallInput);
321
322impl EVMInputs {
323 pub fn new(input: Vec<u8>) -> Self {
324 Self(CallInput::Bytes(input.into()))
325 }
326}
327
328impl InputsTr for EVMInputs {
329 fn target_address(&self) -> Address {
330 panic!()
331 }
332
333 fn caller_address(&self) -> Address {
334 panic!()
335 }
336
337 fn bytecode_address(&self) -> Option<&Address> {
338 panic!()
339 }
340
341 fn input(&self) -> &CallInput {
342 &self.0
343 }
344
345 fn call_value(&self) -> primitives::U256 {
346 panic!()
347 }
348}
349
350fn exec_error_into_halt_reason<E: Ext>(from: ExecError) -> Option<InstructionResult> {
364 log::trace!("call frame execution error in EVM caller: {:?}", &from);
365
366 if super::exec_error_into_return_code::<E>(from).is_ok() {
367 return None;
368 }
369
370 let static_memory_too_large = Error::<E::T>::StaticMemoryTooLarge.into();
371 let code_rejected = Error::<E::T>::CodeRejected.into();
372 let transfer_failed = Error::<E::T>::TransferFailed.into();
373 let duplicate_contract = Error::<E::T>::DuplicateContract.into();
374 let balance_conversion_failed = Error::<E::T>::BalanceConversionFailed.into();
375 let value_too_large = Error::<E::T>::ValueTooLarge.into();
376 let out_of_gas = Error::<E::T>::OutOfGas.into();
377 let out_of_deposit = Error::<E::T>::StorageDepositLimitExhausted.into();
378
379 Some(match from.error {
380 err if err == static_memory_too_large => InstructionResult::MemoryLimitOOG,
381 err if err == code_rejected => InstructionResult::OpcodeNotFound,
382 err if err == transfer_failed => InstructionResult::OutOfFunds,
383 err if err == duplicate_contract => InstructionResult::CreateCollision,
384 err if err == balance_conversion_failed => InstructionResult::OverflowPayment,
385 err if err == value_too_large => InstructionResult::OverflowPayment,
386 err if err == out_of_deposit => InstructionResult::OutOfFunds,
387 err if err == out_of_gas => InstructionResult::OutOfGas,
388 _ => InstructionResult::Revert,
389 })
390}
391
392fn instruction_result_into_exec_error<E: Ext>(from: InstructionResult) -> Option<ExecError> {
396 match from {
397 InstructionResult::OutOfGas |
398 InstructionResult::InvalidOperandOOG |
399 InstructionResult::ReentrancySentryOOG |
400 InstructionResult::PrecompileOOG |
401 InstructionResult::MemoryOOG => Some(Error::<E::T>::OutOfGas),
402 InstructionResult::MemoryLimitOOG => Some(Error::<E::T>::StaticMemoryTooLarge),
403 InstructionResult::OpcodeNotFound |
404 InstructionResult::InvalidJump |
405 InstructionResult::NotActivated |
406 InstructionResult::InvalidFEOpcode |
407 InstructionResult::CreateContractStartingWithEF => Some(Error::<E::T>::InvalidInstruction),
408 InstructionResult::CallNotAllowedInsideStatic |
409 InstructionResult::StateChangeDuringStaticCall => Some(Error::<E::T>::StateChangeDenied),
410 InstructionResult::StackUnderflow |
411 InstructionResult::StackOverflow |
412 InstructionResult::NonceOverflow |
413 InstructionResult::PrecompileError |
414 InstructionResult::FatalExternalError => Some(Error::<E::T>::ContractTrapped),
415 InstructionResult::OutOfOffset => Some(Error::<E::T>::OutOfBounds),
416 InstructionResult::CreateCollision => Some(Error::<E::T>::DuplicateContract),
417 InstructionResult::OverflowPayment => Some(Error::<E::T>::BalanceConversionFailed),
418 InstructionResult::CreateContractSizeLimit | InstructionResult::CreateInitCodeSizeLimit =>
419 Some(Error::<E::T>::StaticMemoryTooLarge),
420 InstructionResult::CallTooDeep => Some(Error::<E::T>::MaxCallDepthReached),
421 InstructionResult::OutOfFunds => Some(Error::<E::T>::TransferFailed),
422 InstructionResult::CreateInitCodeStartingEF00 |
423 InstructionResult::InvalidEOFInitCode |
424 InstructionResult::InvalidExtDelegateCallTarget => Some(Error::<E::T>::ContractTrapped),
425 InstructionResult::Stop |
426 InstructionResult::Return |
427 InstructionResult::Revert |
428 InstructionResult::SelfDestruct => None,
429 }
430 .map(Into::into)
431}
432
433pub trait U256Converter {
435 fn into_revm_u256(&self) -> revm::primitives::U256;
437
438 fn from_revm_u256(value: &revm::primitives::U256) -> Self;
440}
441
442impl U256Converter for sp_core::U256 {
443 fn into_revm_u256(&self) -> revm::primitives::U256 {
444 let bytes = self.to_big_endian();
445 revm::primitives::U256::from_be_bytes(bytes)
446 }
447
448 fn from_revm_u256(value: &revm::primitives::U256) -> Self {
449 let bytes = value.to_be_bytes::<32>();
450 sp_core::U256::from_big_endian(&bytes)
451 }
452}