1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), warn(unused_extern_crates))]
3#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6extern crate alloc;
7
8use alloc::vec::Vec;
9use core::{fmt, mem::MaybeUninit, ptr};
10use revm_interpreter::{
11 Contract, FunctionStack, Gas, Host, InstructionResult, Interpreter, InterpreterAction,
12 InterpreterResult, SharedMemory, EMPTY_SHARED_MEMORY,
13};
14use revm_primitives::{Address, Bytes, Env, U256};
15
16#[cfg(feature = "host-ext-any")]
17use core::any::Any;
18
19pub struct EvmContext<'a> {
24 pub memory: &'a mut SharedMemory,
26 pub contract: &'a mut Contract,
28 pub gas: &'a mut Gas,
30 pub host: &'a mut dyn HostExt,
32 pub next_action: &'a mut InterpreterAction,
34 pub return_data: &'a [u8],
36 pub is_static: bool,
38 #[doc(hidden)]
41 pub resume_at: u32,
42}
43
44impl fmt::Debug for EvmContext<'_> {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 f.debug_struct("EvmContext").field("memory", &self.memory).finish_non_exhaustive()
47 }
48}
49
50impl<'a> EvmContext<'a> {
51 #[inline]
53 pub fn from_interpreter(interpreter: &'a mut Interpreter, host: &'a mut dyn HostExt) -> Self {
54 Self::from_interpreter_with_stack(interpreter, host).0
55 }
56
57 #[inline]
59 pub fn from_interpreter_with_stack<'b: 'a>(
60 interpreter: &'a mut Interpreter,
61 host: &'b mut dyn HostExt,
62 ) -> (Self, &'a mut EvmStack, &'a mut usize) {
63 let (stack, stack_len) = EvmStack::from_interpreter_stack(&mut interpreter.stack);
64 let this = Self {
65 memory: &mut interpreter.shared_memory,
66 contract: &mut interpreter.contract,
67 gas: &mut interpreter.gas,
68 host,
69 next_action: &mut interpreter.next_action,
70 return_data: &interpreter.return_data_buffer,
71 is_static: interpreter.is_static,
72 resume_at: ResumeAt::load(interpreter.instruction_pointer),
73 };
74 (this, stack, stack_len)
75 }
76
77 pub fn to_interpreter(&self, stack: revm_interpreter::Stack) -> Interpreter {
79 let bytecode = self.contract.bytecode.bytecode().clone();
80 Interpreter {
81 is_eof: self.contract.bytecode.is_eof(),
82 instruction_pointer: bytecode.as_ptr(),
83 bytecode,
84 function_stack: FunctionStack::new(),
85 is_eof_init: false,
86 contract: self.contract.clone(),
87 instruction_result: InstructionResult::Continue,
88 gas: *self.gas,
89 shared_memory: self.memory.clone(),
90 stack,
91 return_data_buffer: self.return_data.to_vec().into(),
92 is_static: self.is_static,
93 next_action: self.next_action.clone(),
94 }
95 }
96}
97
98#[cfg(not(feature = "host-ext-any"))]
100pub trait HostExt: Host {}
101
102#[cfg(not(feature = "host-ext-any"))]
103impl<T: Host> HostExt for T {}
104
105#[cfg(feature = "host-ext-any")]
107pub trait HostExt: Host + Any {
108 #[doc(hidden)]
109 fn as_any(&self) -> &dyn Any;
110 #[doc(hidden)]
111 fn as_any_mut(&mut self) -> &mut dyn Any;
112}
113
114#[cfg(feature = "host-ext-any")]
115impl<T: Host + Any> HostExt for T {
116 fn as_any(&self) -> &dyn Any {
117 self
118 }
119
120 fn as_any_mut(&mut self) -> &mut dyn Any {
121 self
122 }
123}
124
125#[cfg(feature = "host-ext-any")]
126#[doc(hidden)]
127impl dyn HostExt {
128 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
130 self.as_any().downcast_ref()
131 }
132
133 pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
135 self.as_any_mut().downcast_mut()
136 }
137}
138
139#[macro_export]
154macro_rules! extern_revmc {
155 ($( $(#[$attr:meta])* $vis:vis fn $name:ident; )+) => {
156 #[allow(improper_ctypes)]
157 extern "C" {
158 $(
159 $(#[$attr])*
160 $vis fn $name(
161 gas: *mut $crate::private::revm_interpreter::Gas,
162 stack: *mut $crate::EvmStack,
163 stack_len: *mut usize,
164 env: *const $crate::private::revm_primitives::Env,
165 contract: *const $crate::private::revm_interpreter::Contract,
166 ecx: *mut $crate::EvmContext<'_>,
167 ) -> $crate::private::revm_interpreter::InstructionResult;
168 )+
169 }
170 };
171}
172
173pub type RawEvmCompilerFn = unsafe extern "C" fn(
179 gas: *mut Gas,
180 stack: *mut EvmStack,
181 stack_len: *mut usize,
182 env: *const Env,
183 contract: *const Contract,
184 ecx: *mut EvmContext<'_>,
185) -> InstructionResult;
186
187#[derive(Clone, Copy, Debug, PartialEq, Eq)]
189pub struct EvmCompilerFn(RawEvmCompilerFn);
190
191impl From<RawEvmCompilerFn> for EvmCompilerFn {
192 #[inline]
193 fn from(f: RawEvmCompilerFn) -> Self {
194 Self::new(f)
195 }
196}
197
198impl From<EvmCompilerFn> for RawEvmCompilerFn {
199 #[inline]
200 fn from(f: EvmCompilerFn) -> Self {
201 f.into_inner()
202 }
203}
204
205impl EvmCompilerFn {
206 #[inline]
208 pub const fn new(f: RawEvmCompilerFn) -> Self {
209 Self(f)
210 }
211
212 #[inline]
214 pub const fn into_inner(self) -> RawEvmCompilerFn {
215 self.0
216 }
217
218 #[inline]
227 pub unsafe fn call_with_interpreter_and_memory(
228 self,
229 interpreter: &mut Interpreter,
230 memory: &mut SharedMemory,
231 host: &mut dyn HostExt,
232 ) -> InterpreterAction {
233 interpreter.shared_memory = core::mem::replace(memory, EMPTY_SHARED_MEMORY);
234 let result = self.call_with_interpreter(interpreter, host);
235 *memory = interpreter.take_memory();
236 result
237 }
238
239 #[inline]
249 pub unsafe fn call_with_interpreter(
250 self,
251 interpreter: &mut Interpreter,
252 host: &mut dyn HostExt,
253 ) -> InterpreterAction {
254 interpreter.next_action = InterpreterAction::None;
255
256 let (mut ecx, stack, stack_len) =
257 EvmContext::from_interpreter_with_stack(interpreter, host);
258 let result = self.call(Some(stack), Some(stack_len), &mut ecx);
259
260 if result == InstructionResult::OutOfGas {
263 ecx.gas.spend_all();
264 }
265
266 let resume_at = ecx.resume_at;
267 ResumeAt::store(&mut interpreter.instruction_pointer, resume_at);
268
269 interpreter.instruction_result = result;
270 if interpreter.next_action.is_some() {
271 core::mem::take(&mut interpreter.next_action)
272 } else {
273 InterpreterAction::Return {
274 result: InterpreterResult { result, output: Bytes::new(), gas: interpreter.gas },
275 }
276 }
277 }
278
279 #[inline]
293 pub unsafe fn call(
294 self,
295 stack: Option<&mut EvmStack>,
296 stack_len: Option<&mut usize>,
297 ecx: &mut EvmContext<'_>,
298 ) -> InstructionResult {
299 assert!(!ecx.contract.bytecode.is_eof(), "EOF is not yet implemented");
300 (self.0)(
301 ecx.gas,
302 option_as_mut_ptr(stack),
303 option_as_mut_ptr(stack_len),
304 ecx.host.env(),
305 ecx.contract,
306 ecx,
307 )
308 }
309
310 #[inline(never)]
316 pub unsafe fn call_noinline(
317 self,
318 stack: Option<&mut EvmStack>,
319 stack_len: Option<&mut usize>,
320 ecx: &mut EvmContext<'_>,
321 ) -> InstructionResult {
322 self.call(stack, stack_len, ecx)
323 }
324}
325
326#[repr(C)]
328#[allow(missing_debug_implementations)]
329pub struct EvmStack([MaybeUninit<EvmWord>; 1024]);
330
331#[allow(clippy::new_without_default)]
332impl EvmStack {
333 pub const SIZE: usize = 32 * Self::CAPACITY;
335
336 pub const CAPACITY: usize = 1024;
338
339 #[inline]
343 pub fn new() -> Self {
344 Self(unsafe { MaybeUninit::uninit().assume_init() })
345 }
346
347 #[inline]
349 pub fn new_heap() -> Vec<EvmWord> {
350 Vec::with_capacity(1024)
351 }
352
353 #[inline]
355 pub fn from_interpreter_stack(stack: &mut revm_interpreter::Stack) -> (&mut Self, &mut usize) {
356 debug_assert!(stack.data().capacity() >= Self::CAPACITY);
357 unsafe {
358 let data = Self::from_mut_ptr(stack.data_mut().as_mut_ptr().cast());
359 let len = &mut *(stack.data_mut() as *mut Vec<_>).cast::<usize>().add(2);
361 debug_assert_eq!(stack.len(), *len);
362 (data, len)
363 }
364 }
365
366 #[inline]
372 pub fn from_vec(vec: &Vec<EvmWord>) -> &Self {
373 assert!(vec.capacity() >= Self::CAPACITY);
374 unsafe { Self::from_ptr(vec.as_ptr()) }
375 }
376
377 #[inline]
395 pub fn from_mut_vec(vec: &mut Vec<EvmWord>) -> &mut Self {
396 assert!(vec.capacity() >= Self::CAPACITY);
397 unsafe { Self::from_mut_ptr(vec.as_mut_ptr()) }
398 }
399
400 #[inline]
406 pub const fn from_slice(slice: &[EvmWord]) -> &Self {
407 assert!(slice.len() >= Self::CAPACITY);
408 unsafe { Self::from_ptr(slice.as_ptr()) }
409 }
410
411 #[inline]
417 pub fn from_mut_slice(slice: &mut [EvmWord]) -> &mut Self {
418 assert!(slice.len() >= Self::CAPACITY);
419 unsafe { Self::from_mut_ptr(slice.as_mut_ptr()) }
420 }
421
422 #[inline]
429 pub const unsafe fn from_ptr<'a>(ptr: *const EvmWord) -> &'a Self {
430 &*ptr.cast()
431 }
432
433 #[inline]
440 pub unsafe fn from_mut_ptr<'a>(ptr: *mut EvmWord) -> &'a mut Self {
441 &mut *ptr.cast()
442 }
443
444 #[inline]
446 pub const fn as_bytes(&self) -> &[u8; Self::SIZE] {
447 unsafe { &*self.0.as_ptr().cast() }
448 }
449
450 #[inline]
452 pub fn as_bytes_mut(&mut self) -> &mut [u8; Self::SIZE] {
453 unsafe { &mut *self.0.as_mut_ptr().cast() }
454 }
455
456 #[inline]
458 pub const fn as_slice(&self) -> &[EvmWord; Self::CAPACITY] {
459 unsafe { &*self.0.as_ptr().cast() }
460 }
461
462 #[inline]
464 pub fn as_mut_slice(&mut self) -> &mut [EvmWord; Self::CAPACITY] {
465 unsafe { &mut *self.0.as_mut_ptr().cast() }
466 }
467}
468
469#[repr(C, align(8))]
473#[derive(Clone, Copy, PartialEq, Eq)]
474pub struct EvmWord([u8; 32]);
475
476macro_rules! impl_fmt {
477 ($($trait:ident),* $(,)?) => {
478 $(
479 impl fmt::$trait for EvmWord {
480 #[inline]
481 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
482 self.to_u256().fmt(f)
483 }
484 }
485 )*
486 };
487}
488
489impl_fmt!(Debug, Display, Binary, Octal, LowerHex, UpperHex);
490
491macro_rules! impl_conversions_through_u256 {
492 ($($ty:ty),*) => {
493 $(
494 impl From<$ty> for EvmWord {
495 #[inline]
496 fn from(value: $ty) -> Self {
497 Self::from_u256(U256::from(value))
498 }
499 }
500
501 impl From<&$ty> for EvmWord {
502 #[inline]
503 fn from(value: &$ty) -> Self {
504 Self::from(*value)
505 }
506 }
507
508 impl From<&mut $ty> for EvmWord {
509 #[inline]
510 fn from(value: &mut $ty) -> Self {
511 Self::from(*value)
512 }
513 }
514
515 impl TryFrom<EvmWord> for $ty {
516 type Error = ();
517
518 #[inline]
519 fn try_from(value: EvmWord) -> Result<Self, Self::Error> {
520 value.to_u256().try_into().map_err(drop)
521 }
522 }
523
524 impl TryFrom<&EvmWord> for $ty {
525 type Error = ();
526
527 #[inline]
528 fn try_from(value: &EvmWord) -> Result<Self, Self::Error> {
529 (*value).try_into()
530 }
531 }
532
533 impl TryFrom<&mut EvmWord> for $ty {
534 type Error = ();
535
536 #[inline]
537 fn try_from(value: &mut EvmWord) -> Result<Self, Self::Error> {
538 (*value).try_into()
539 }
540 }
541 )*
542 };
543}
544
545impl_conversions_through_u256!(bool, u8, u16, u32, u64, usize, u128);
546
547impl From<U256> for EvmWord {
548 #[inline]
549 fn from(value: U256) -> Self {
550 Self::from_u256(value)
551 }
552}
553
554impl From<&U256> for EvmWord {
555 #[inline]
556 fn from(value: &U256) -> Self {
557 Self::from(*value)
558 }
559}
560
561impl From<&mut U256> for EvmWord {
562 #[inline]
563 fn from(value: &mut U256) -> Self {
564 Self::from(*value)
565 }
566}
567
568impl EvmWord {
569 pub const ZERO: Self = Self([0; 32]);
571
572 #[inline]
574 pub const fn from_ne_bytes(x: [u8; 32]) -> Self {
575 Self(x)
576 }
577
578 #[inline]
580 pub fn from_be_bytes(x: [u8; 32]) -> Self {
581 Self::from_be(Self(x))
582 }
583
584 #[inline]
586 pub fn from_le_bytes(x: [u8; 32]) -> Self {
587 Self::from_le(Self(x))
588 }
589
590 #[inline]
592 pub fn from_be(x: Self) -> Self {
593 #[cfg(target_endian = "little")]
594 return x.swap_bytes();
595 #[cfg(target_endian = "big")]
596 return x;
597 }
598
599 #[inline]
601 pub fn from_le(x: Self) -> Self {
602 #[cfg(target_endian = "little")]
603 return x;
604 #[cfg(target_endian = "big")]
605 return x.swap_bytes();
606 }
607
608 #[inline]
610 pub const fn from_u256(value: U256) -> Self {
611 #[cfg(target_endian = "little")]
612 return unsafe { core::mem::transmute::<U256, Self>(value) };
613 #[cfg(target_endian = "big")]
614 return Self(value.to_be_bytes());
615 }
616
617 #[inline]
619 #[cfg(target_endian = "little")]
620 pub const fn from_u256_ref(value: &U256) -> &Self {
621 unsafe { &*(value as *const U256 as *const Self) }
622 }
623
624 #[inline]
626 #[cfg(target_endian = "little")]
627 pub fn from_u256_mut(value: &mut U256) -> &mut Self {
628 unsafe { &mut *(value as *mut U256 as *mut Self) }
629 }
630
631 #[inline]
634 pub fn to_be_bytes(self) -> [u8; 32] {
635 self.to_be().to_ne_bytes()
636 }
637
638 #[inline]
641 pub fn to_le_bytes(self) -> [u8; 32] {
642 self.to_le().to_ne_bytes()
643 }
644
645 #[inline]
647 pub const fn to_ne_bytes(self) -> [u8; 32] {
648 self.0
649 }
650
651 #[inline]
653 pub fn to_be(self) -> Self {
654 #[cfg(target_endian = "little")]
655 return self.swap_bytes();
656 #[cfg(target_endian = "big")]
657 return self;
658 }
659
660 #[inline]
662 pub fn to_le(self) -> Self {
663 #[cfg(target_endian = "little")]
664 return self;
665 #[cfg(target_endian = "big")]
666 return self.swap_bytes();
667 }
668
669 #[inline]
671 pub fn swap_bytes(mut self) -> Self {
672 self.0.reverse();
673 self
674 }
675
676 #[cfg(target_endian = "little")]
678 #[inline]
679 pub const fn as_u256(&self) -> &U256 {
680 unsafe { &*(self as *const Self as *const U256) }
681 }
682
683 #[cfg(target_endian = "little")]
685 #[inline]
686 pub fn as_u256_mut(&mut self) -> &mut U256 {
687 unsafe { &mut *(self as *mut Self as *mut U256) }
688 }
689
690 #[inline]
692 pub const fn to_u256(&self) -> U256 {
693 #[cfg(target_endian = "little")]
694 return *self.as_u256();
695 #[cfg(target_endian = "big")]
696 return U256::from_be_bytes(self.0);
697 }
698
699 #[inline]
701 pub const fn into_u256(self) -> U256 {
702 #[cfg(target_endian = "little")]
703 return unsafe { core::mem::transmute::<Self, U256>(self) };
704 #[cfg(target_endian = "big")]
705 return U256::from_be_bytes(self.0);
706 }
707
708 #[inline]
710 pub fn to_address(self) -> Address {
711 Address::from_word(self.to_be_bytes().into())
712 }
713}
714
715struct ResumeAt;
719
720impl ResumeAt {
721 fn load(ip: *const u8) -> u32 {
722 if (ip as usize) <= u16::MAX as usize {
725 ip as u32
726 } else {
727 0
728 }
729 }
730
731 fn store(ip: &mut *const u8, value: u32) {
732 *ip = value as _;
733 }
734}
735
736#[inline(always)]
737fn option_as_mut_ptr<T>(opt: Option<&mut T>) -> *mut T {
738 match opt {
739 Some(ref_) => ref_,
740 None => ptr::null_mut(),
741 }
742}
743
744#[doc(hidden)]
747pub mod private {
748 pub use revm_interpreter;
749 pub use revm_primitives;
750}
751
752#[cfg(test)]
753mod tests {
754 use super::*;
755
756 #[test]
757 fn conversions() {
758 let mut word = EvmWord::ZERO;
759 assert_eq!(usize::try_from(word), Ok(0));
760 assert_eq!(usize::try_from(&word), Ok(0));
761 assert_eq!(usize::try_from(&mut word), Ok(0));
762 }
763
764 extern_revmc! {
765 #[link_name = "__test_fn"]
766 fn test_fn;
767 }
768
769 #[no_mangle]
770 extern "C" fn __test_fn(
771 _gas: *mut Gas,
772 _stack: *mut EvmStack,
773 _stack_len: *mut usize,
774 _env: *const Env,
775 _contract: *const Contract,
776 _ecx: *mut EvmContext<'_>,
777 ) -> InstructionResult {
778 InstructionResult::Continue
779 }
780
781 #[test]
782 fn extern_macro() {
783 let _f1 = EvmCompilerFn::new(test_fn);
784 let _f2 = EvmCompilerFn::new(__test_fn);
785 assert_eq!(test_fn as usize, __test_fn as usize);
786 }
787
788 #[test]
789 fn borrowing_host() {
790 #[allow(unused)]
791 struct BHost<'a>(&'a mut Env);
792 #[allow(unused)]
793 impl Host for BHost<'_> {
794 fn env(&self) -> &Env {
795 self.0
796 }
797 fn env_mut(&mut self) -> &mut Env {
798 self.0
799 }
800 fn load_account(
801 &mut self,
802 address: Address,
803 ) -> Option<revm_interpreter::LoadAccountResult> {
804 unimplemented!()
805 }
806 fn block_hash(&mut self, number: U256) -> Option<revm_primitives::B256> {
807 unimplemented!()
808 }
809 fn balance(&mut self, address: Address) -> Option<(U256, bool)> {
810 unimplemented!()
811 }
812 fn code(&mut self, address: Address) -> Option<(revm_primitives::Bytes, bool)> {
813 unimplemented!()
814 }
815 fn code_hash(&mut self, address: Address) -> Option<(revm_primitives::B256, bool)> {
816 unimplemented!()
817 }
818 fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)> {
819 unimplemented!()
820 }
821 fn sstore(
822 &mut self,
823 address: Address,
824 index: U256,
825 value: U256,
826 ) -> Option<revm_interpreter::SStoreResult> {
827 unimplemented!()
828 }
829 fn tload(&mut self, address: Address, index: U256) -> U256 {
830 unimplemented!()
831 }
832 fn tstore(&mut self, address: Address, index: U256, value: U256) {
833 unimplemented!()
834 }
835 fn log(&mut self, log: revm_primitives::Log) {
836 unimplemented!()
837 }
838 fn selfdestruct(
839 &mut self,
840 address: Address,
841 target: Address,
842 ) -> Option<revm_interpreter::SelfDestructResult> {
843 unimplemented!()
844 }
845 }
846
847 #[allow(unused_mut)]
848 let mut env = Env::default();
849 #[cfg(not(feature = "host-ext-any"))]
850 let env = &mut env;
851 #[cfg(feature = "host-ext-any")]
852 let env = Box::leak(Box::new(env));
853
854 let mut host = BHost(env);
855 let f = EvmCompilerFn::new(test_fn);
856 let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
857
858 let (mut ecx, stack, stack_len) =
859 EvmContext::from_interpreter_with_stack(&mut interpreter, &mut host);
860 let r = unsafe { f.call(Some(stack), Some(stack_len), &mut ecx) };
861 assert_eq!(r, InstructionResult::Continue);
862
863 let r = unsafe { f.call_with_interpreter(&mut interpreter, &mut host) };
864 assert_eq!(
865 r,
866 InterpreterAction::Return {
867 result: InterpreterResult {
868 result: InstructionResult::Continue,
869 output: Bytes::new(),
870 gas: Gas::new(u64::MAX),
871 }
872 }
873 );
874 }
875}