From 55e973b8f0ba2e2afd777c6ef6128def0185b5f7 Mon Sep 17 00:00:00 2001 From: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> Date: Fri, 10 Oct 2025 19:48:52 +0200 Subject: [PATCH] fix: change pallet_evm alias to EVM to fix `eth_getCode` (#213) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - rename the FRAME alias for `pallet_evm` from `Evm` to `EVM` across the mainnet, stagenet, and testnet runtimes - adjust benchmarks, configuration modules, genesis builders, and runtime tests to rely on the new alias - keep precompile genesis setup and proxy/precompile tests aligned with the updated names ## Context Frontier’s `StorageOverrideHandler` (see `fc_storage::StorageQuerier::account_code`) reads contract bytecode from `pallet_evm::AccountCodes` using the constant `PALLET_EVM = b"EVM"` to build the storage key: `twox_128("EVM") ++ twox_128("AccountCodes") ++ …` Our runtimes exported `pallet_evm` as `Evm`, so substrate stored bytecode under the *camel-cased* prefix (`twox_128("Evm")`). Every call that ultimately hits the storage override—including `eth_getCode`, `eth_call`, and state queries during replay—therefore failed to locate code for *any* account (deployed contracts and precompiles alike). Renaming the alias to `EVM` realigns the storage prefix with Frontier’s expectations so the override layers can pull bytecode correctly. ## Testing - `cargo check -p datahaven-node` - `cargo build --release -p datahaven-node` - `eth_getCode 0x0000000000000000000000000000000000000802` → returns `0x60006000fd` ## Storage Migration Renaming a pallet alias changes the storage prefix for all pallet data. Without migration, existing EVM data (smart contracts, account codes, storage) would become inaccessible. **Migration details:** - **Type**: Multi-Block Migration (MBM) - **Storage migrated**: `AccountCodes`, `AccountCodesMetadata`, `AccountStorages` - **Migration ID**: `datahaven-evm-mbm` (version 0 → 1) **Testing the migration:** ```bash # Build runtime with try-runtime cargo build --release --features try-runtime -p datahaven-stagenet-runtime # Test against stagenet try-runtime \ --runtime ./target/release/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.wasm \ on-runtime-upgrade \ --blocktime 6000 \ --checks all \ --disable-spec-version-check \ live --uri wss://dh-validator-0.datahaven-kt.xyz ``` Test results from stagenet: - ✅ Migration completes in 1 block - ✅ PoV size: ~5.3 KB - ✅ Weight consumption: <0.1% of block capacity - ✅ All 39 keys successfully migrated ## ⚠️ Breaking Changes ⚠️ If you are manually computing storage keys for the EVM pallet (e.g., directly querying chain state), you must update your code to use the new storage prefix: - Old prefix: twox128("Evm") = 0x8b90cb... - New prefix: twox128("EVM") = 0x6a5e91... All EVM-facing interfaces remain unchanged. --- operator/Cargo.lock | 3 + operator/precompiles/batch/src/mock.rs | 2 +- operator/precompiles/batch/src/tests.rs | 24 +- operator/precompiles/call-permit/src/mock.rs | 2 +- .../precompiles/erc20-balances/src/mock.rs | 2 +- .../precompiles/erc20-balances/src/tests.rs | 10 +- .../precompile-registry/src/mock.rs | 2 +- operator/precompiles/proxy/src/mock.rs | 2 +- operator/precompiles/proxy/src/tests.rs | 2 +- operator/runtime/common/Cargo.toml | 16 + operator/runtime/common/src/migrations.rs | 349 +++++++++++++++++- operator/runtime/mainnet/src/benchmarks.rs | 2 +- operator/runtime/mainnet/src/configs/mod.rs | 5 +- .../mainnet/src/genesis_config_presets.rs | 4 +- operator/runtime/mainnet/src/lib.rs | 2 +- operator/runtime/mainnet/tests/treasury.rs | 6 +- operator/runtime/stagenet/src/benchmarks.rs | 2 +- operator/runtime/stagenet/src/configs/mod.rs | 5 +- .../stagenet/src/genesis_config_presets.rs | 4 +- operator/runtime/stagenet/src/lib.rs | 2 +- operator/runtime/stagenet/tests/treasury.rs | 6 +- operator/runtime/testnet/src/benchmarks.rs | 2 +- operator/runtime/testnet/src/configs/mod.rs | 5 +- .../testnet/src/genesis_config_presets.rs | 4 +- operator/runtime/testnet/src/lib.rs | 2 +- operator/runtime/testnet/tests/treasury.rs | 6 +- test/.papi/descriptors/package.json | 2 +- test/.papi/metadata/datahaven.scale | Bin 616961 -> 616961 bytes 28 files changed, 423 insertions(+), 50 deletions(-) diff --git a/operator/Cargo.lock b/operator/Cargo.lock index 4890eb0d..7037c491 100644 --- a/operator/Cargo.lock +++ b/operator/Cargo.lock @@ -3163,12 +3163,14 @@ dependencies = [ "fp-account", "frame-support", "frame-system", + "log", "pallet-authorship", "pallet-balances", "pallet-evm", "pallet-evm-precompile-proxy", "pallet-migrations", "pallet-safe-mode", + "pallet-timestamp", "pallet-treasury", "pallet-tx-pause", "parity-scale-codec", @@ -3177,6 +3179,7 @@ dependencies = [ "precompile-utils", "scale-info", "sp-core", + "sp-io", "sp-runtime", "sp-std", "staging-xcm", diff --git a/operator/precompiles/batch/src/mock.rs b/operator/precompiles/batch/src/mock.rs index 05cdb1cf..b834a37b 100644 --- a/operator/precompiles/batch/src/mock.rs +++ b/operator/precompiles/batch/src/mock.rs @@ -37,7 +37,7 @@ construct_runtime!( pub enum Runtime { System: frame_system, Balances: pallet_balances, - Evm: pallet_evm, + EVM: pallet_evm, Timestamp: pallet_timestamp, } ); diff --git a/operator/precompiles/batch/src/tests.rs b/operator/precompiles/batch/src/tests.rs index 3d47b43d..61883b45 100644 --- a/operator/precompiles/batch/src/tests.rs +++ b/operator/precompiles/batch/src/tests.rs @@ -662,7 +662,7 @@ fn evm_batch_some_transfers_enough() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some { to: vec![Address(Bob.into()), Address(Charlie.into())].into(), @@ -682,7 +682,7 @@ fn evm_batch_some_until_failure_transfers_enough() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some_until_failure { to: vec![Address(Bob.into()), Address(Charlie.into())].into(), @@ -702,7 +702,7 @@ fn evm_batch_all_transfers_enough() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_all { to: vec![Address(Bob.into()), Address(Charlie.into())].into(), @@ -725,7 +725,7 @@ fn evm_batch_some_transfers_too_much() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some { to: vec![ @@ -760,7 +760,7 @@ fn evm_batch_some_until_failure_transfers_too_much() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some_until_failure { to: vec![ @@ -795,7 +795,7 @@ fn evm_batch_all_transfers_too_much() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_all { to: vec![ @@ -830,7 +830,7 @@ fn evm_batch_some_contract_revert() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some { to: vec![ @@ -865,7 +865,7 @@ fn evm_batch_some_until_failure_contract_revert() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_some_until_failure { to: vec![ @@ -900,7 +900,7 @@ fn evm_batch_all_contract_revert() { .with_balances(vec![(Alice.into(), 10_000)]) .build() .execute_with(|| { - assert_ok!(RuntimeCall::Evm(evm_call( + assert_ok!(RuntimeCall::EVM(evm_call( Alice, PCall::batch_all { to: vec![ @@ -954,7 +954,7 @@ fn evm_batch_recursion_under_limit() { } .into(); - assert_ok!(RuntimeCall::Evm(evm_call(Alice, input)).dispatch(RuntimeOrigin::root())); + assert_ok!(RuntimeCall::EVM(evm_call(Alice, input)).dispatch(RuntimeOrigin::root())); assert_eq!(balance(Alice), 9_000); // gasprice = 0 assert_eq!(balance(Bob), 1_000); @@ -993,7 +993,7 @@ fn evm_batch_recursion_over_limit() { ) .into(); - assert_ok!(RuntimeCall::Evm(evm_call(Alice, input)).dispatch(RuntimeOrigin::root())); + assert_ok!(RuntimeCall::EVM(evm_call(Alice, input)).dispatch(RuntimeOrigin::root())); assert_eq!(balance(Alice), 10_000); // gasprice = 0 assert_eq!(balance(Bob), 0); @@ -1030,7 +1030,7 @@ fn batch_is_not_callable_by_dummy_code() { } .into(); - match RuntimeCall::Evm(evm_call(Alice, input)).dispatch(RuntimeOrigin::root()) { + match RuntimeCall::EVM(evm_call(Alice, input)).dispatch(RuntimeOrigin::root()) { Err(DispatchErrorWithPostInfo { error: DispatchError::Module(ModuleError { diff --git a/operator/precompiles/call-permit/src/mock.rs b/operator/precompiles/call-permit/src/mock.rs index 90986aea..efe85f83 100644 --- a/operator/precompiles/call-permit/src/mock.rs +++ b/operator/precompiles/call-permit/src/mock.rs @@ -37,7 +37,7 @@ construct_runtime!( pub enum Runtime { System: frame_system, Balances: pallet_balances, - Evm: pallet_evm, + EVM: pallet_evm, Timestamp: pallet_timestamp, } ); diff --git a/operator/precompiles/erc20-balances/src/mock.rs b/operator/precompiles/erc20-balances/src/mock.rs index 6b6bd741..170f2da8 100644 --- a/operator/precompiles/erc20-balances/src/mock.rs +++ b/operator/precompiles/erc20-balances/src/mock.rs @@ -156,7 +156,7 @@ construct_runtime!( pub enum Runtime { System: frame_system, Balances: pallet_balances, - Evm: pallet_evm, + EVM: pallet_evm, Timestamp: pallet_timestamp, } ); diff --git a/operator/precompiles/erc20-balances/src/tests.rs b/operator/precompiles/erc20-balances/src/tests.rs index 7da81d04..42bfa824 100644 --- a/operator/precompiles/erc20-balances/src/tests.rs +++ b/operator/precompiles/erc20-balances/src/tests.rs @@ -565,7 +565,7 @@ fn deposit(data: Vec) { // Deposit // We need to call using EVM pallet so we can check the EVM correctly sends the amount // to the precompile. - Evm::call( + EVM::call( RuntimeOrigin::root(), CryptoAlith.into(), Precompile1.into(), @@ -602,7 +602,7 @@ fn deposit(data: Vec) { amount: 500 }), // Log is correctly emited. - RuntimeEvent::Evm(pallet_evm::Event::Log { + RuntimeEvent::EVM(pallet_evm::Event::Log { log: log2( Precompile1, SELECTOR_LOG_DEPOSIT, @@ -610,7 +610,7 @@ fn deposit(data: Vec) { solidity::encode_event_data(U256::from(500)), ) }), - RuntimeEvent::Evm(pallet_evm::Event::Executed { + RuntimeEvent::EVM(pallet_evm::Event::Executed { address: Precompile1.into() }), ] @@ -681,7 +681,7 @@ fn deposit_zero() { // Deposit // We need to call using EVM pallet so we can check the EVM correctly sends the amount // to the precompile. - Evm::call( + EVM::call( RuntimeOrigin::root(), CryptoAlith.into(), Precompile1.into(), @@ -697,7 +697,7 @@ fn deposit_zero() { assert_eq!( events(), - vec![RuntimeEvent::Evm(pallet_evm::Event::ExecutedFailed { + vec![RuntimeEvent::EVM(pallet_evm::Event::ExecutedFailed { address: Precompile1.into() }),] ); diff --git a/operator/precompiles/precompile-registry/src/mock.rs b/operator/precompiles/precompile-registry/src/mock.rs index c7bf887f..45f364ce 100644 --- a/operator/precompiles/precompile-registry/src/mock.rs +++ b/operator/precompiles/precompile-registry/src/mock.rs @@ -36,7 +36,7 @@ construct_runtime!( pub enum Runtime { System: frame_system, Balances: pallet_balances, - Evm: pallet_evm, + EVM: pallet_evm, Timestamp: pallet_timestamp, } ); diff --git a/operator/precompiles/proxy/src/mock.rs b/operator/precompiles/proxy/src/mock.rs index f36cadc0..f3fc144d 100644 --- a/operator/precompiles/proxy/src/mock.rs +++ b/operator/precompiles/proxy/src/mock.rs @@ -50,7 +50,7 @@ construct_runtime!( pub enum Runtime { System: frame_system, Balances: pallet_balances, - Evm: pallet_evm, + EVM: pallet_evm, Timestamp: pallet_timestamp, Proxy: pallet_proxy, } diff --git a/operator/precompiles/proxy/src/tests.rs b/operator/precompiles/proxy/src/tests.rs index 90aa2a1e..b7d7c906 100644 --- a/operator/precompiles/proxy/src/tests.rs +++ b/operator/precompiles/proxy/src/tests.rs @@ -541,7 +541,7 @@ fn test_nested_evm_bypass_proxy_should_allow_elevating_proxy_type() { } .into(); - let evm_call = RuntimeCall::Evm(EvmCall::call { + let evm_call = RuntimeCall::EVM(EvmCall::call { source: Alice.into(), target: Precompile1.into(), input: add_proxy_precompile, diff --git a/operator/runtime/common/Cargo.toml b/operator/runtime/common/Cargo.toml index baeceea0..34129282 100644 --- a/operator/runtime/common/Cargo.toml +++ b/operator/runtime/common/Cargo.toml @@ -9,8 +9,10 @@ codec = { workspace = true } fp-account = { workspace = true, features = ["serde"] } frame-support = { workspace = true } frame-system = { workspace = true } +log = { workspace = true } pallet-authorship = { workspace = true } pallet-balances = { workspace = true } +pallet-timestamp = { workspace = true } pallet-evm = { workspace = true } pallet-evm-precompile-proxy = { workspace = true } pallet-migrations = { workspace = true } @@ -22,6 +24,7 @@ polkadot-runtime-common = { workspace = true } precompile-utils = { workspace = true } scale-info = { workspace = true } sp-core = { workspace = true, features = ["serde"] } +sp-io = { workspace = true } sp-runtime = { workspace = true, features = ["serde"] } sp-std = { workspace = true } xcm = { workspace = true } @@ -31,8 +34,10 @@ default = ["std"] std = [ "codec/std", "frame-support/std", + "log/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-timestamp/std", "pallet-evm/std", "pallet-evm-precompile-proxy/std", "pallet-migrations/std", @@ -44,6 +49,7 @@ std = [ "precompile-utils/std", "scale-info/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", "xcm/std", @@ -59,5 +65,15 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", ] +try-runtime = [ + "frame-support/try-runtime", + "pallet-migrations/try-runtime", + "pallet-safe-mode/try-runtime", + "pallet-tx-pause/try-runtime", + "pallet-timestamp/try-runtime", + "polkadot-runtime-common/try-runtime", + "sp-runtime/try-runtime", +] + # Set timing constants (e.g. session period) to faster versions to speed up testing. fast-runtime = [] diff --git a/operator/runtime/common/src/migrations.rs b/operator/runtime/common/src/migrations.rs index 281207dd..45b3c238 100644 --- a/operator/runtime/common/src/migrations.rs +++ b/operator/runtime/common/src/migrations.rs @@ -3,7 +3,7 @@ //! The types and constants defined here keep the pallet configuration consistent between //! networks while leaving each runtime free to decide which migrations should actually run. -use frame_support::pallet_prelude::ConstU32; +use frame_support::pallet_prelude::*; /// Maximum encoded length permitted for a migration cursor. pub const MIGRATION_CURSOR_MAX_LEN: u32 = 65_536; @@ -20,7 +20,7 @@ pub type MigrationIdentifierMaxLen = ConstU32; /// The tuple starts empty and can be extended with concrete migrations over time. Keeping it in a /// shared module reduces duplication once we coordinate migrations across networks. #[cfg(not(feature = "runtime-benchmarks"))] -pub type MultiBlockMigrationList = (); +pub type MultiBlockMigrationList = (evm_alias::EvmAliasMigration,); /// During benchmarking we switch to the pallet-provided mocked migrations to guarantee success. #[cfg(feature = "runtime-benchmarks")] @@ -31,3 +31,348 @@ pub type MigrationStatusHandler = (); /// Default handler triggered on migration failures. pub type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration; + +/// Multi-block migration for renaming the EVM pallet alias. +pub mod evm_alias { + use core::marker::PhantomData; + use frame_support::{ + migrations::{MigrationId, SteppedMigration, SteppedMigrationError}, + pallet_prelude::*, + weights::WeightMeter, + BoundedVec, StorageHasher, + }; + use sp_io::storage; + use sp_std::{convert::TryFrom, vec::Vec}; + + #[cfg(feature = "try-runtime")] + use sp_std::collections::btree_map::BTreeMap; + + /// Multi-block migration that renames the Frontier EVM pallet alias from `Evm` to `EVM`. + pub struct EvmAliasMigration(PhantomData); + + impl SteppedMigration for EvmAliasMigration + where + T: pallet_evm::Config, + { + type Cursor = BoundedVec>; + type Identifier = MigrationId<17>; + + fn id() -> Self::Identifier { + MigrationId { + pallet_id: *b"datahaven-evm-mbm", + version_from: 0, + version_to: 1, + } + } + + fn step( + cursor: Option, + meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + if cursor.is_none() { + log::info!( + "🚀 [EVM Migration] Starting pallet alias migration from 'Evm' to 'EVM'" + ); + } + + let old_prefix = Twox128::hash(b"Evm"); + let new_prefix = Twox128::hash(b"EVM"); + let mut current_key: Vec = cursor + .map(Into::into) + .unwrap_or_else(|| old_prefix.to_vec()); + let mut processed = 0u32; + let required = T::DbWeight::get().reads_writes(1, 2); + + loop { + let next_key = match storage::next_key(¤t_key) { + Some(next) if next.starts_with(&old_prefix) => next, + _ => { + log::info!( + "✅ [EVM Migration] Completed! Processed {} keys in this step", + processed + ); + return Ok(None); + } + }; + + if meter.try_consume(required).is_err() { + if processed == 0 { + log::warn!( + "⚠️ [EVM Migration] Insufficient weight for even one key migration" + ); + return Err(SteppedMigrationError::InsufficientWeight { required }); + } + log::info!( + "⏸️ [EVM Migration] Pausing after migrating {} keys (weight limit reached)", + processed + ); + return BoundedVec::try_from(current_key) + .map(Some) + .map_err(|_| SteppedMigrationError::Failed); + } + + if let Some(value) = storage::get(&next_key) { + let mut new_key = Vec::with_capacity(next_key.len()); + new_key.extend_from_slice(&new_prefix); + new_key.extend_from_slice(&next_key[16..]); + storage::set(&new_key, &value); + } + storage::clear(&next_key); + + processed = processed.saturating_add(1); + current_key = next_key; + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + use codec::Encode; + + let storage_prefix = |item: &[u8]| { + let mut key = [0u8; 32]; + key[0..16].copy_from_slice(&Twox128::hash(b"Evm")); + key[16..32].copy_from_slice(&Twox128::hash(item)); + key + }; + + let mut counts = BTreeMap::new(); + + for name in [ + b"AccountCodes" as &[u8], + b"AccountCodesMetadata", + b"AccountStorages", + ] { + let count = count_keys(&storage_prefix(name)); + counts.insert(name.to_vec(), count.encode()); + } + + Ok(counts.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + use codec::Decode; + + let snapshot: BTreeMap, Vec> = + Decode::decode(&mut &state[..]).expect("Failed to decode snapshot"); + + let old_storage = |item: &[u8]| { + let mut key = [0u8; 32]; + key[0..16].copy_from_slice(&Twox128::hash(b"Evm")); + key[16..32].copy_from_slice(&Twox128::hash(item)); + key + }; + + let new_storage = |item: &[u8]| { + let mut key = [0u8; 32]; + key[0..16].copy_from_slice(&Twox128::hash(b"EVM")); + key[16..32].copy_from_slice(&Twox128::hash(item)); + key + }; + + for name in [ + b"AccountCodes" as &[u8], + b"AccountCodesMetadata", + b"AccountStorages", + ] { + let old_count = count_keys(&old_storage(name)); + assert_eq!(old_count, 0, "Old Evm prefix still present after migration"); + + let expected = snapshot + .get(name) + .and_then(|v| u32::decode(&mut &v[..]).ok()) + .unwrap_or(0); + let actual = count_keys(&new_storage(name)); + + assert_eq!(expected, actual, "Migrated entry count mismatch"); + } + + Ok(()) + } + } + + /// Helper function to count storage keys with a given prefix. + #[cfg(any(feature = "try-runtime", test))] + pub(crate) fn count_keys(prefix: &[u8]) -> u32 { + let mut count = 0u32; + let mut cursor = prefix.to_vec(); + loop { + match storage::next_key(&cursor) { + Some(next) if next.starts_with(prefix) => { + count = count.saturating_add(1); + cursor = next; + } + _ => break, + } + } + count + } +} + +#[cfg(test)] +mod tests { + use super::evm_alias::{count_keys, EvmAliasMigration}; + use codec::Encode; + use frame_support::{ + derive_impl, + migrations::SteppedMigration, + parameter_types, + weights::{constants::RocksDbWeight, Weight, WeightMeter}, + StorageHasher, Twox128, + }; + use pallet_evm::AccountCodes; + use sp_core::{H160, H256, U256}; + use sp_io::storage; + use sp_runtime::BuildStorage; + use sp_std::vec; + + frame_support::construct_runtime!( + pub enum TestRuntime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage}, + EVM: pallet_evm::{Pallet, Call, Storage, Config, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, 0)); + } + + #[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for TestRuntime { + type Nonce = u64; + type Block = frame_system::mocking::MockBlock; + type BlockHashCount = BlockHashCount; + type AccountData = pallet_balances::AccountData; + } + + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + } + + #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] + impl pallet_balances::Config for TestRuntime { + type RuntimeHoldReason = (); + type Balance = u64; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + } + + #[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)] + impl pallet_timestamp::Config for TestRuntime {} + + parameter_types! { + pub MockPrecompiles: MockPrecompileSet = MockPrecompileSet; + } + + #[derive_impl(pallet_evm::config_preludes::TestDefaultConfig)] + impl pallet_evm::Config for TestRuntime { + type AccountProvider = pallet_evm::FrameSystemAccountProvider; + type FeeCalculator = FixedGasPrice; + type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping; + type Currency = Balances; + type Runner = pallet_evm::runner::stack::Runner; + type Timestamp = Timestamp; + type PrecompilesType = MockPrecompileSet; + type PrecompilesValue = MockPrecompiles; + } + + pub struct FixedGasPrice; + impl pallet_evm::FeeCalculator for FixedGasPrice { + fn min_gas_price() -> (U256, Weight) { + (1_000_000_000u128.into(), Weight::from_parts(1_000, 0)) + } + } + + pub struct MockPrecompileSet; + impl pallet_evm::PrecompileSet for MockPrecompileSet { + fn execute( + &self, + _handle: &mut impl pallet_evm::PrecompileHandle, + ) -> Option { + None + } + + fn is_precompile(&self, _address: H160, _gas: u64) -> pallet_evm::IsPrecompileResult { + pallet_evm::IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } + } + } + + fn old_storage_prefix(item: &[u8]) -> [u8; 32] { + let mut key = [0u8; 32]; + key[0..16].copy_from_slice(&Twox128::hash(b"Evm")); + key[16..32].copy_from_slice(&Twox128::hash(item)); + key + } + + fn raw_key(storage_name: &[u8], address: H160, index: Option) -> Vec { + let mut key = old_storage_prefix(storage_name).to_vec(); + key.extend_from_slice(&sp_io::hashing::blake2_128(&address.encode())); + key.extend_from_slice(address.as_bytes()); + if let Some(idx) = index { + key.extend_from_slice(&sp_io::hashing::blake2_128(&idx.encode())); + key.extend_from_slice(idx.as_bytes()); + } + key + } + + #[test] + fn multi_block_evm_alias_migration_moves_all_entries() { + let mut storage = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + pallet_balances::GenesisConfig::::default() + .assimilate_storage(&mut storage) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(storage); + ext.execute_with(|| { + let addresses: Vec = (1u64..=3).map(H160::from_low_u64_be).collect(); + + for (idx, &address) in addresses.iter().enumerate() { + storage::set( + &raw_key(b"AccountCodes", address, None), + &vec![idx as u8; 3].encode(), + ); + storage::set( + &raw_key(b"AccountCodesMetadata", address, None), + &(42u64 + idx as u64, H256::repeat_byte(idx as u8)).encode(), + ); + storage::set( + &raw_key( + b"AccountStorages", + address, + Some(H256::repeat_byte(0xAA + idx as u8)), + ), + &H256::repeat_byte(idx as u8).encode(), + ); + } + + let mut cursor = None; + loop { + let mut meter = WeightMeter::with_limit(RocksDbWeight::get().reads_writes(1, 2)); + match EvmAliasMigration::::step(cursor, &mut meter) { + Ok(None) => break, + Ok(Some(next)) => cursor = Some(next), + Err(err) => panic!("migration failed: {:?}", err), + } + } + + for address in addresses { + assert!(!AccountCodes::::get(address).is_empty()); + } + + assert_eq!(count_keys(&old_storage_prefix(b"AccountCodes")[..]), 0); + assert_eq!( + count_keys(&old_storage_prefix(b"AccountCodesMetadata")[..]), + 0 + ); + assert_eq!(count_keys(&old_storage_prefix(b"AccountStorages")[..]), 0); + }); + } +} diff --git a/operator/runtime/mainnet/src/benchmarks.rs b/operator/runtime/mainnet/src/benchmarks.rs index 3677711d..1354295d 100644 --- a/operator/runtime/mainnet/src/benchmarks.rs +++ b/operator/runtime/mainnet/src/benchmarks.rs @@ -57,7 +57,7 @@ frame_benchmarking::define_benchmarks!( [pallet_tx_pause, TxPause] // EVM pallets - [pallet_evm, Evm] + [pallet_evm, EVM] // Governance pallets [pallet_collective_technical_committee, TechnicalCommittee] diff --git a/operator/runtime/mainnet/src/configs/mod.rs b/operator/runtime/mainnet/src/configs/mod.rs index a4d41b0e..9d3dff01 100644 --- a/operator/runtime/mainnet/src/configs/mod.rs +++ b/operator/runtime/mainnet/src/configs/mod.rs @@ -231,7 +231,7 @@ impl Contains for NormalCallFilter { // See https://github.com/PureStake/sr-moonbeam/issues/30 // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so // this can be seen as an additional security - RuntimeCall::Evm(_) => false, + RuntimeCall::EVM(_) => false, _ => true, } } @@ -823,6 +823,9 @@ impl pallet_parameters::Config for Runtime { impl pallet_migrations::Config for Runtime { type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; + #[cfg(feature = "runtime-benchmarks")] type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; type CursorMaxLen = MigrationCursorMaxLen; type IdentifierMaxLen = MigrationIdentifierMaxLen; diff --git a/operator/runtime/mainnet/src/genesis_config_presets.rs b/operator/runtime/mainnet/src/genesis_config_presets.rs index 0552a536..82cab44e 100644 --- a/operator/runtime/mainnet/src/genesis_config_presets.rs +++ b/operator/runtime/mainnet/src/genesis_config_presets.rs @@ -1,5 +1,5 @@ use crate::{ - configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EvmConfig, Precompiles, + configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EVMConfig, Precompiles, RuntimeGenesisConfig, SessionKeys, Signature, SudoConfig, TechnicalCommitteeConfig, TreasuryCouncilConfig, }; @@ -44,7 +44,7 @@ fn testnet_genesis( epoch_config: BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, - evm: EvmConfig { + evm: EVMConfig { // We need _some_ code inserted at the precompile address so that // the evm will actually call the address. accounts: Precompiles::used_addresses() diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index 726c9ae0..0e552171 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -411,7 +411,7 @@ mod runtime { pub type Ethereum = pallet_ethereum; #[runtime::pallet_index(51)] - pub type Evm = pallet_evm; + pub type EVM = pallet_evm; #[runtime::pallet_index(52)] pub type EvmChainId = pallet_evm_chain_id; diff --git a/operator/runtime/mainnet/tests/treasury.rs b/operator/runtime/mainnet/tests/treasury.rs index a649c4df..df4680a6 100644 --- a/operator/runtime/mainnet/tests/treasury.rs +++ b/operator/runtime/mainnet/tests/treasury.rs @@ -63,7 +63,7 @@ fn author_does_receive_priority_fee() { Balances::make_free_balance_be(&author, 100 * HAVE); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -105,7 +105,7 @@ fn total_issuance_after_evm_transaction_with_priority_fee() { let _author = get_validator_by_index(0); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -174,7 +174,7 @@ fn total_issuance_after_evm_transaction_without_priority_fee() { set_block_author_by_index(0); let issuance_before = ::Currency::total_issuance(); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), diff --git a/operator/runtime/stagenet/src/benchmarks.rs b/operator/runtime/stagenet/src/benchmarks.rs index 22db3d3c..6944df0f 100644 --- a/operator/runtime/stagenet/src/benchmarks.rs +++ b/operator/runtime/stagenet/src/benchmarks.rs @@ -64,7 +64,7 @@ frame_benchmarking::define_benchmarks!( [pallet_whitelist, Whitelist] // EVM pallets - [pallet_evm, Evm] + [pallet_evm, EVM] // DataHaven custom pallets [pallet_external_validators, ExternalValidators] diff --git a/operator/runtime/stagenet/src/configs/mod.rs b/operator/runtime/stagenet/src/configs/mod.rs index 8ae6683b..957f52c7 100644 --- a/operator/runtime/stagenet/src/configs/mod.rs +++ b/operator/runtime/stagenet/src/configs/mod.rs @@ -231,7 +231,7 @@ impl Contains for NormalCallFilter { // See https://github.com/PureStake/sr-moonbeam/issues/30 // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so // this can be seen as an additional security - RuntimeCall::Evm(_) => false, + RuntimeCall::EVM(_) => false, _ => true, } } @@ -822,6 +822,9 @@ impl pallet_parameters::Config for Runtime { impl pallet_migrations::Config for Runtime { type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; + #[cfg(feature = "runtime-benchmarks")] type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; type CursorMaxLen = MigrationCursorMaxLen; type IdentifierMaxLen = MigrationIdentifierMaxLen; diff --git a/operator/runtime/stagenet/src/genesis_config_presets.rs b/operator/runtime/stagenet/src/genesis_config_presets.rs index d739052d..15167767 100644 --- a/operator/runtime/stagenet/src/genesis_config_presets.rs +++ b/operator/runtime/stagenet/src/genesis_config_presets.rs @@ -1,5 +1,5 @@ use crate::{ - configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EvmConfig, Precompiles, + configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EVMConfig, Precompiles, RuntimeGenesisConfig, SessionKeys, Signature, SudoConfig, TechnicalCommitteeConfig, TreasuryCouncilConfig, }; @@ -44,7 +44,7 @@ fn testnet_genesis( epoch_config: BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, - evm: EvmConfig { + evm: EVMConfig { // We need _some_ code inserted at the precompile address so that // the evm will actually call the address. accounts: Precompiles::used_addresses() diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index 3407f555..d6207766 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -413,7 +413,7 @@ mod runtime { pub type Ethereum = pallet_ethereum; #[runtime::pallet_index(51)] - pub type Evm = pallet_evm; + pub type EVM = pallet_evm; #[runtime::pallet_index(52)] pub type EvmChainId = pallet_evm_chain_id; diff --git a/operator/runtime/stagenet/tests/treasury.rs b/operator/runtime/stagenet/tests/treasury.rs index 2039509f..fefc3f06 100644 --- a/operator/runtime/stagenet/tests/treasury.rs +++ b/operator/runtime/stagenet/tests/treasury.rs @@ -63,7 +63,7 @@ fn author_does_receive_priority_fee() { Balances::make_free_balance_be(&author, 100 * HAVE); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -105,7 +105,7 @@ fn total_issuance_after_evm_transaction_with_priority_fee() { let _author = get_validator_by_index(0); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -174,7 +174,7 @@ fn total_issuance_after_evm_transaction_without_priority_fee() { set_block_author_by_index(0); let issuance_before = ::Currency::total_issuance(); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), diff --git a/operator/runtime/testnet/src/benchmarks.rs b/operator/runtime/testnet/src/benchmarks.rs index 9f5147b4..e6ec2c3d 100644 --- a/operator/runtime/testnet/src/benchmarks.rs +++ b/operator/runtime/testnet/src/benchmarks.rs @@ -56,7 +56,7 @@ frame_benchmarking::define_benchmarks!( [pallet_tx_pause, TxPause] // EVM pallets - [pallet_evm, Evm] + [pallet_evm, EVM] // Governance pallets [pallet_collective_technical_committee, TechnicalCommittee] diff --git a/operator/runtime/testnet/src/configs/mod.rs b/operator/runtime/testnet/src/configs/mod.rs index b3a6e806..1a6ee34c 100644 --- a/operator/runtime/testnet/src/configs/mod.rs +++ b/operator/runtime/testnet/src/configs/mod.rs @@ -231,7 +231,7 @@ impl Contains for NormalCallFilter { // See https://github.com/PureStake/sr-moonbeam/issues/30 // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so // this can be seen as an additional security - RuntimeCall::Evm(_) => false, + RuntimeCall::EVM(_) => false, _ => true, } } @@ -822,6 +822,9 @@ impl pallet_parameters::Config for Runtime { impl pallet_migrations::Config for Runtime { type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; + #[cfg(feature = "runtime-benchmarks")] type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList; type CursorMaxLen = MigrationCursorMaxLen; type IdentifierMaxLen = MigrationIdentifierMaxLen; diff --git a/operator/runtime/testnet/src/genesis_config_presets.rs b/operator/runtime/testnet/src/genesis_config_presets.rs index 56f0eddb..8ffdd83f 100644 --- a/operator/runtime/testnet/src/genesis_config_presets.rs +++ b/operator/runtime/testnet/src/genesis_config_presets.rs @@ -1,5 +1,5 @@ use crate::{ - configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EvmConfig, Precompiles, + configs::BABE_GENESIS_EPOCH_CONFIG, AccountId, BalancesConfig, EVMConfig, Precompiles, RuntimeGenesisConfig, SessionKeys, Signature, SudoConfig, TechnicalCommitteeConfig, TreasuryCouncilConfig, }; @@ -44,7 +44,7 @@ fn testnet_genesis( epoch_config: BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, - evm: EvmConfig { + evm: EVMConfig { // We need _some_ code inserted at the precompile address so that // the evm will actually call the address. accounts: Precompiles::used_addresses() diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index 87ea4db4..a7247d02 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -410,7 +410,7 @@ mod runtime { pub type Ethereum = pallet_ethereum; #[runtime::pallet_index(51)] - pub type Evm = pallet_evm; + pub type EVM = pallet_evm; #[runtime::pallet_index(52)] pub type EvmChainId = pallet_evm_chain_id; diff --git a/operator/runtime/testnet/tests/treasury.rs b/operator/runtime/testnet/tests/treasury.rs index 7f9dde99..2648f9c1 100644 --- a/operator/runtime/testnet/tests/treasury.rs +++ b/operator/runtime/testnet/tests/treasury.rs @@ -62,7 +62,7 @@ fn author_does_receive_priority_fee() { Balances::make_free_balance_be(&author, 100 * HAVE); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -104,7 +104,7 @@ fn total_issuance_after_evm_transaction_with_priority_fee() { let _author = get_validator_by_index(0); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), @@ -174,7 +174,7 @@ fn total_issuance_after_evm_transaction_without_priority_fee() { set_block_author_by_index(0); let issuance_before = ::Currency::total_issuance(); // EVM transfer. - assert_ok!(RuntimeCall::Evm(pallet_evm::Call::::call { + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { source: H160::from(BOB), target: H160::from(ALICE), input: Vec::new(), diff --git a/test/.papi/descriptors/package.json b/test/.papi/descriptors/package.json index e5757e41..1ce15a99 100644 --- a/test/.papi/descriptors/package.json +++ b/test/.papi/descriptors/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.0-autogenerated.11494808361211823293", + "version": "0.1.0-autogenerated.12438105935477919494", "name": "@polkadot-api/descriptors", "files": [ "dist" diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index 98e2427e1967d74c2178defc0223411a566fd751..9ff8eff9a42574bd427e973dda7e1ab3025714d6 100644 GIT binary patch delta 90 zcmZp?qS|;xb%PZrQ<(2&8_w4gIKq5c7))6h7f#+dBZk>E%(uC3R(szpMj&PaV&?6A nvsl7YfU37Y|HpE%hds=fkq4-%eSbGA5VHX>`}Y0a98UKDA>SkT delta 90 zcmZp?qS|;xb%PZrQ(5k28_w4gILdNa7))6h7f#+dBZk?vEVsFDR(szpMj&PaV&?6A nvsl7YfU37Y|HpE%hrKM9kq4-%eSbGA5VHX>`}Y0a98UKDX