diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 37dfd05e8f..826a6c0be6 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -52,7 +52,9 @@ macro_rules! gas_or_fail { macro_rules! memory_resize { ($interp:expr, $offset:expr, $len:expr) => { - if let Some(new_size) = revm_primitives::next_multiple_of_32($offset.saturating_add($len)) { + if let Some(new_size) = + crate::interpreter::next_multiple_of_32($offset.saturating_add($len)) + { #[cfg(feature = "memory_limit")] if new_size > ($interp.memory_limit as usize) { $interp.instruction_result = InstructionResult::MemoryLimitOOG; diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 429a2db876..f274b5cb54 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -8,7 +8,7 @@ use crate::{alloc::boxed::Box, opcode::eval, Gas, Host, InstructionResult}; pub use analysis::BytecodeLocked; pub use contract::Contract; -pub use memory::Memory; +pub use memory::{next_multiple_of_32, Memory}; pub use stack::Stack; /// EIP-170: Contract code size limit diff --git a/crates/interpreter/src/interpreter/memory.rs b/crates/interpreter/src/interpreter/memory.rs index b2d1ae2e6f..f0c15bcd2d 100644 --- a/crates/interpreter/src/interpreter/memory.rs +++ b/crates/interpreter/src/interpreter/memory.rs @@ -1,6 +1,10 @@ use crate::primitives::U256; use alloc::vec::Vec; -use core::{cmp::min, fmt}; +use core::{ + cmp::min, + fmt, + ops::{BitAnd, Not}, +}; /// A sequential memory. It uses Rust's `Vec` for internal /// representation. @@ -180,6 +184,13 @@ impl Memory { } } +/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned. +#[inline] +pub fn next_multiple_of_32(x: usize) -> Option { + let r = x.bitand(31).not().wrapping_add(1).bitand(31); + x.checked_add(r) +} + #[cfg(test)] mod tests { use super::*; @@ -201,4 +212,22 @@ mod tests { let copied_data = memory.slice(5, 4); assert_eq!(copied_data, &[1, 2, 3, 4]); } + + #[test] + fn test_next_multiple_of_32() { + // next_multiple_of_32 returns x when it is a multiple of 32 + for i in 0..32 { + let x = i * 32; + assert_eq!(Some(x), next_multiple_of_32(x)); + } + + // next_multiple_of_32 rounds up to the nearest multiple of 32 when `x % 32 != 0` + for x in 0..1024 { + if x % 32 == 0 { + continue; + } + let next_multiple = x + 32 - (x % 32); + assert_eq!(Some(next_multiple), next_multiple_of_32(x)); + } + } } diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index 8ece1fe71e..d79f6c9e1c 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -1,10 +1,13 @@ use crate::{ - primitives::{B256, STACK_LIMIT, U256}, + primitives::{B256, U256}, InstructionResult, }; use alloc::vec::Vec; use core::fmt; +/// EVM interpreter stack limit. +pub const STACK_LIMIT: usize = 1024; + /// EVM stack. #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index cf55c5916b..c57045b656 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -1,11 +1,5 @@ use crate::Address; -/// EVM interpreter stack limit. -pub const STACK_LIMIT: usize = 1024; - -/// EVM call stack limit. -pub const CALL_STACK_LIMIT: u64 = 1024; - /// EIP-170: Contract code size limit /// By default limit is 0x6000 (~25kb) pub const MAX_CODE_SIZE: usize = 0x6000; diff --git a/crates/primitives/src/utilities.rs b/crates/primitives/src/utilities.rs index 58a2b2b0ce..1d04a358e3 100644 --- a/crates/primitives/src/utilities.rs +++ b/crates/primitives/src/utilities.rs @@ -3,7 +3,6 @@ use crate::{ TARGET_BLOB_GAS_PER_BLOCK, U256, }; pub use alloy_primitives::keccak256; -use core::ops::{BitAnd, Not}; /// The Keccak-256 hash of the empty string `""`. pub const KECCAK_EMPTY: B256 = @@ -73,13 +72,6 @@ pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 { output / denominator } -/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned. -#[inline] -pub fn next_multiple_of_32(x: usize) -> Option { - let r = x.bitand(31).not().wrapping_add(1).bitand(31); - x.checked_add(r) -} - #[cfg(test)] mod tests { use super::*; @@ -188,22 +180,4 @@ mod tests { assert_eq!(actual, expected, "test: {t:?}"); } } - - #[test] - fn test_next_multiple_of_32() { - // next_multiple_of_32 returns x when it is a multiple of 32 - for i in 0..32 { - let x = i * 32; - assert_eq!(Some(x), next_multiple_of_32(x)); - } - - // next_multiple_of_32 rounds up to the nearest multiple of 32 when `x % 32 != 0` - for x in 0..1024 { - if x % 32 == 0 { - continue; - } - let next_multiple = x + 32 - (x % 32); - assert_eq!(Some(next_multiple), next_multiple_of_32(x)); - } - } } diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 1d86cb07d2..d8ee88617a 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -8,7 +8,7 @@ use crate::journaled_state::{is_precompile, JournalCheckpoint}; use crate::primitives::{ create2_address, create_address, keccak256, Address, AnalysisKind, Bytecode, Bytes, EVMError, EVMResult, Env, ExecutionResult, InvalidTransaction, Log, Output, ResultAndState, Spec, - SpecId::*, TransactTo, B256, CALL_STACK_LIMIT, U256, + SpecId::*, TransactTo, B256, U256, }; use crate::{db::Database, journaled_state::JournaledState, precompile, Inspector}; use alloc::boxed::Box; @@ -21,6 +21,9 @@ use revm_precompile::{Precompile, Precompiles}; #[cfg(feature = "optimism")] use crate::optimism; +/// EVM call stack limit. +pub const CALL_STACK_LIMIT: u64 = 1024; + pub struct EVMData<'a, DB: Database> { pub env: &'a mut Env, pub journaled_state: JournaledState, diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index fbaeab6c18..61c0e5ae14 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -28,7 +28,7 @@ pub use db::{ pub use db::{Database, DatabaseCommit, InMemoryDB}; pub use evm::{evm_inner, new, EVM}; -pub use evm_impl::{EVMData, EVMImpl, Transact}; +pub use evm_impl::{EVMData, EVMImpl, Transact, CALL_STACK_LIMIT}; pub use journaled_state::{is_precompile, JournalCheckpoint, JournalEntry, JournaledState}; // reexport `revm_precompiles`