diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 10d7c3564..e5292b3c6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -50,8 +50,9 @@ jobs: with: repository: ethereum/tests path: ethtests - ref: v13.2 + ref: v13.3 submodules: recursive + fetch-depth: 1 - name: Run Ethereum state tests run: | diff --git a/Cargo.toml b/Cargo.toml index 87a41a33b..b035486da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "evm" -version = "0.42.0" -license = "Apache-2.0" -authors = ["Wei Tang ", "Parity Technologies "] -description = "SputnikVM - a Portable Blockchain Virtual Machine" -repository = "https://github.com/sorpaas/rust-evm" -keywords = ["no_std", "ethereum"] -edition = "2021" +version.workspace = true +license.workspace = true +authors.workspace = true +description.workspace = true +repository.workspace = true +keywords.workspace = true +edition.workspace = true [dependencies] auto_impl = "1.0" @@ -22,9 +22,9 @@ scale-codec = { package = "parity-scale-codec", version = "3.2", default-feature scale-info = { version = "2.11", default-features = false, features = ["derive"], optional = true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } -evm-core = { version = "0.42", path = "core", default-features = false } -evm-gasometer = { version = "0.42", path = "gasometer", default-features = false } -evm-runtime = { version = "0.42", path = "runtime", default-features = false } +evm-core = { version = "0.43", path = "core", default-features = false } +evm-runtime = { version = "0.43", path = "runtime", default-features = false } +evm-gasometer = { version = "0.43", path = "gasometer", default-features = false } [dev-dependencies] criterion = "0.5" @@ -77,7 +77,17 @@ force-debug = [ create-fixed = [] print-debug = ["evm-gasometer/print-debug"] +[workspace.package] +version = "0.43.0" +license = "Apache-2.0" +authors = ["Aurora Labs ", "Wei Tang ", "Parity Technologies "] +description = "Portable Ethereum Virtual Machine implementation written in pure Rust." +repository = "https://github.com/sorpaas/rust-evm" +keywords = ["no_std", "ethereum"] +edition = "2021" + [workspace] +resolver = "2" members = [ "core", "gasometer", diff --git a/core/Cargo.toml b/core/Cargo.toml index b762447da..ff424b7de 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "evm-core" -version = "0.42.0" -license = "Apache-2.0" -authors = ["Wei Tang ", "Parity Technologies "] -description = "Portable Ethereum Virtual Machine implementation written in pure Rust." -repository = "https://github.com/sorpaas/rust-evm" -keywords = ["no_std", "ethereum"] -edition = "2021" +version.workspace = true +license.workspace = true +authors.workspace = true +edition.workspace = true +keywords.workspace = true +description.workspace = true +repository.workspace = true [dependencies] log = { version = "0.4", optional = true } diff --git a/evm-tests/jsontests/Cargo.toml b/evm-tests/jsontests/Cargo.toml index c74f5aca2..924eca292 100644 --- a/evm-tests/jsontests/Cargo.toml +++ b/evm-tests/jsontests/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "evm-jsontests" -version = "0.42.0" +version.workspace = true license = "GPL-3.0" -authors = ["Aurora Labs ", "Wei Tang ", "Parity Technologies "] -description = "SputnikVM - a Portable Blockchain Virtual Machine" -repository = "https://github.com/sorpaas/rust-evm" -keywords = ["no_std", "ethereum"] -edition = "2021" +authors.workspace = true +description = "EVM json tests" +repository.workspace = true +keywords.workspace = true +edition.workspace = true [dependencies] -evm = { path = "../.." } +evm = { path = "../..", version = "0.43" } ethereum = "0.15.0" primitive-types = "0.12" serde = { version = "1.0", features = ["derive"] } diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml index 35300b1af..a10a0bf75 100644 --- a/fuzzer/Cargo.toml +++ b/fuzzer/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" [dependencies] honggfuzz = "0.5" -evm-core = { version = "0.42", path = "../core" } +evm-core = { version = "0.43", path = "../core" } [[bin]] name = "evm_fuzz" diff --git a/gasometer/Cargo.toml b/gasometer/Cargo.toml index 907d532f7..859241974 100644 --- a/gasometer/Cargo.toml +++ b/gasometer/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "evm-gasometer" -version = "0.42.0" -license = "Apache-2.0" -authors = ["Wei Tang ", "Parity Technologies "] -description = "Portable Ethereum Virtual Machine implementation written in pure Rust." -repository = "https://github.com/sorpaas/rust-evm" -keywords = ["no_std", "ethereum"] -edition = "2021" +version.workspace = true +license.workspace = true +authors.workspace = true +edition.workspace = true +keywords.workspace = true +description.workspace = true +repository.workspace = true [dependencies] environmental = { version = "1.1.2", default-features = false, optional = true } log = { version = "0.4", optional = true } primitive-types = { version = "0.12", default-features = false } -evm-core = { version = "0.42", path = "../core", default-features = false } -evm-runtime = { version = "0.42", path = "../runtime", default-features = false } +evm-core = { version = "0.43", path = "../core", default-features = false } +evm-runtime = { version = "0.43", path = "../runtime", default-features = false } [features] default = ["std"] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index c8f0bf548..12937e52e 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "evm-runtime" -version = "0.42.0" -license = "Apache-2.0" -authors = ["Wei Tang ", "Parity Technologies "] -description = "SputnikVM - a Portable Blockchain Virtual Machine" -repository = "https://github.com/sorpaas/rust-evm" -keywords = ["no_std", "ethereum"] -edition = "2021" +version.workspace = true +license.workspace = true +authors.workspace = true +edition.workspace = true +keywords.workspace = true +description.workspace = true +repository.workspace = true [dependencies] auto_impl = "1.0" @@ -14,7 +14,7 @@ environmental = { version = "1.1", default-features = false, optional = true } primitive-types = { version = "0.12", default-features = false } sha3 = { version = "0.10", default-features = false } -evm-core = { version = "0.42", path = "../core", default-features = false } +evm-core = { version = "0.43", path = "../core", default-features = false } [features] default = ["std"] diff --git a/runtime/src/handler.rs b/runtime/src/handler.rs index c832ccc47..648fc888b 100644 --- a/runtime/src/handler.rs +++ b/runtime/src/handler.rs @@ -35,6 +35,8 @@ pub trait Handler { fn code(&self, address: H160) -> Vec; /// Get storage value of address at index. fn storage(&self, address: H160, index: H256) -> H256; + /// Check if the storage of the address is empty. + fn is_empty_storage(&self, address: H160) -> bool; /// Get original storage value of address at index. fn original_storage(&self, address: H160, index: H256) -> H256; diff --git a/src/backend/memory.rs b/src/backend/memory.rs index 541bada24..6be03cd4e 100644 --- a/src/backend/memory.rs +++ b/src/backend/memory.rs @@ -164,6 +164,13 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> { .unwrap_or_default() } + fn is_empty_storage(&self, address: H160) -> bool { + self.state + .get(&address) + .map(|v| v.storage.is_empty()) + .unwrap_or(true) + } + fn original_storage(&self, address: H160, index: H256) -> Option { Some(self.storage(address, index)) } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 56fbdef11..935d05646 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -82,6 +82,8 @@ pub trait Backend { fn code(&self, address: H160) -> Vec; /// Get storage value of address at index. fn storage(&self, address: H160, index: H256) -> H256; + /// Check if the storage of the address is empty. + fn is_empty_storage(&self, address: H160) -> bool; /// Get original storage value of address at index, if available. fn original_storage(&self, address: H160, index: H256) -> Option; /// CANCUN hard fork diff --git a/src/executor/stack/executor.rs b/src/executor/stack/executor.rs index 0066c40fe..98d287361 100644 --- a/src/executor/stack/executor.rs +++ b/src/executor/stack/executor.rs @@ -703,6 +703,14 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> self.state.basic(address).nonce } + /// Check if the existing account is "create collision". + /// [EIP-7610](https://eips.ethereum.org/EIPS/eip-7610) + pub fn is_create_collision(&self, address: H160) -> bool { + self.code_size(address) != U256::zero() + || self.nonce(address) > U256::zero() + || !self.state.is_empty_storage(address) + } + /// Get the created address from given scheme. pub fn create_address(&self, scheme: CreateScheme) -> H160 { match scheme { @@ -839,18 +847,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> self.enter_substate(gas_limit, false); - { - if self.code_size(address) != U256::zero() { - let _ = self.exit_substate(StackExitKind::Failed); - return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())); - } - - if self.nonce(address) > U256::zero() { - let _ = self.exit_substate(StackExitKind::Failed); - return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())); - } - - self.state.reset_storage(address); + // Check create collision: EIP-7610 + if self.is_create_collision(address) { + let _ = self.exit_substate(StackExitKind::Failed); + return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())); } let context = Context { @@ -1258,6 +1258,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler self.state.storage(address, index) } + fn is_empty_storage(&self, address: H160) -> bool { + self.state.is_empty(address) + } + fn original_storage(&self, address: H160, index: H256) -> H256 { self.state .original_storage(address, index) diff --git a/src/executor/stack/memory.rs b/src/executor/stack/memory.rs index 885afed16..828543f3e 100644 --- a/src/executor/stack/memory.rs +++ b/src/executor/stack/memory.rs @@ -511,6 +511,10 @@ impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'conf .unwrap_or_else(|| self.backend.storage(address, key)) } + fn is_empty_storage(&self, address: H160) -> bool { + self.backend.is_empty_storage(address) + } + fn original_storage(&self, address: H160, key: H256) -> Option { if let Some(value) = self.substate.known_original_storage(address) { return Some(value);