mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
Merge branch 'perm-runtime-510' into perm-client-v0.5.2
This commit is contained in:
commit
f65385cee1
23 changed files with 216 additions and 30 deletions
1
operator/Cargo.lock
generated
1
operator/Cargo.lock
generated
|
|
@ -3171,6 +3171,7 @@ dependencies = [
|
|||
"pallet-authorship",
|
||||
"pallet-balances",
|
||||
"pallet-evm",
|
||||
"pallet-evm-chain-id",
|
||||
"pallet-evm-precompile-proxy",
|
||||
"pallet-migrations",
|
||||
"pallet-safe-mode",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use sc_service::ChainType;
|
|||
|
||||
use super::ChainSpec;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1289;
|
||||
const EVM_CHAIN_ID: u64 = 55930;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
const TOKEN_DECIMALS: u8 = 18;
|
||||
const TOKEN_SYMBOL: &str = "HAVE";
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use sc_service::ChainType;
|
|||
|
||||
use super::ChainSpec;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1283;
|
||||
const EVM_CHAIN_ID: u64 = 55932;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
const TOKEN_DECIMALS: u8 = 18;
|
||||
const TOKEN_SYMBOL: &str = "HAVE";
|
||||
const TOKEN_SYMBOL: &str = "STAGE";
|
||||
|
||||
pub fn development_chain_spec() -> Result<ChainSpec, String> {
|
||||
// Give the token a unit name and decimal places
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use sc_service::ChainType;
|
|||
|
||||
use super::ChainSpec;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1288;
|
||||
const EVM_CHAIN_ID: u64 = 55931;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
const TOKEN_DECIMALS: u8 = 18;
|
||||
const TOKEN_SYMBOL: &str = "HAVE";
|
||||
const TOKEN_SYMBOL: &str = "MOCK";
|
||||
|
||||
pub fn development_chain_spec() -> Result<ChainSpec, String> {
|
||||
// Give the token a unit name and decimal places
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ pallet-authorship = { workspace = true }
|
|||
pallet-balances = { workspace = true }
|
||||
pallet-timestamp = { workspace = true }
|
||||
pallet-evm = { workspace = true }
|
||||
pallet-evm-chain-id = { workspace = true }
|
||||
pallet-evm-precompile-proxy = { workspace = true }
|
||||
pallet-migrations = { workspace = true }
|
||||
pallet-safe-mode = { workspace = true }
|
||||
|
|
@ -40,6 +41,7 @@ std = [
|
|||
"pallet-balances/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-evm/std",
|
||||
"pallet-evm-chain-id/std",
|
||||
"pallet-evm-precompile-proxy/std",
|
||||
"pallet-migrations/std",
|
||||
"pallet-safe-mode/std",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,101 @@ pub type MigrationStatusHandler = ();
|
|||
/// Default handler triggered on migration failures.
|
||||
pub type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration;
|
||||
|
||||
/// Multi-block migration for updating the EVM chain ID to the new value.
|
||||
pub mod evm_chain_id {
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::{
|
||||
migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
|
||||
pallet_prelude::*,
|
||||
weights::WeightMeter,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use codec::Encode;
|
||||
|
||||
/// Multi-block migration that updates the stored EVM chain ID to match the new configuration.
|
||||
pub struct EvmChainIdMigration<T, const NEW_CHAIN_ID: u64>(PhantomData<T>);
|
||||
|
||||
impl<T, const NEW_CHAIN_ID: u64> SteppedMigration for EvmChainIdMigration<T, NEW_CHAIN_ID>
|
||||
where
|
||||
T: pallet_evm_chain_id::Config,
|
||||
{
|
||||
type Cursor = ();
|
||||
type Identifier = MigrationId<20>;
|
||||
|
||||
fn id() -> Self::Identifier {
|
||||
MigrationId {
|
||||
pallet_id: *b"dh-evm-chain-id-v1 ",
|
||||
version_from: 0,
|
||||
version_to: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn step(
|
||||
cursor: Option<Self::Cursor>,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
|
||||
// This migration completes in a single step
|
||||
if cursor.is_some() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let required = T::DbWeight::get().reads_writes(1, 1);
|
||||
if meter.try_consume(required).is_err() {
|
||||
return Err(SteppedMigrationError::InsufficientWeight { required });
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"🔄 [EVM Chain ID Migration] Updating chain ID to {}",
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
|
||||
// Update the chain ID storage
|
||||
pallet_evm_chain_id::ChainId::<T>::put(NEW_CHAIN_ID);
|
||||
|
||||
log::info!(
|
||||
"✅ [EVM Chain ID Migration] Successfully updated chain ID to {}",
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
let old_chain_id = pallet_evm_chain_id::ChainId::<T>::get();
|
||||
log::info!(
|
||||
"📋 [EVM Chain ID Migration] Current chain ID: {}",
|
||||
old_chain_id
|
||||
);
|
||||
Ok(old_chain_id.encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
use codec::Decode;
|
||||
|
||||
let old_chain_id =
|
||||
u64::decode(&mut &state[..]).map_err(|_| "Failed to decode old chain ID")?;
|
||||
let new_chain_id = pallet_evm_chain_id::ChainId::<T>::get();
|
||||
|
||||
log::info!(
|
||||
"🔍 [EVM Chain ID Migration] Chain ID updated from {} to {}",
|
||||
old_chain_id,
|
||||
new_chain_id
|
||||
);
|
||||
|
||||
if new_chain_id != NEW_CHAIN_ID {
|
||||
return Err(sp_runtime::TryRuntimeError::Other(
|
||||
"Chain ID was not updated correctly",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi-block migration for renaming the EVM pallet alias.
|
||||
pub mod evm_alias {
|
||||
use core::marker::PhantomData;
|
||||
|
|
@ -232,6 +327,7 @@ mod tests {
|
|||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
Timestamp: pallet_timestamp::{Pallet, Call, Storage},
|
||||
EVM: pallet_evm::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
EvmChainId: pallet_evm_chain_id::{Pallet, Storage},
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -280,6 +376,8 @@ mod tests {
|
|||
type PrecompilesValue = MockPrecompiles;
|
||||
}
|
||||
|
||||
impl pallet_evm_chain_id::Config for TestRuntime {}
|
||||
|
||||
pub struct FixedGasPrice;
|
||||
impl pallet_evm::FeeCalculator for FixedGasPrice {
|
||||
fn min_gas_price() -> (U256, Weight) {
|
||||
|
|
@ -375,4 +473,77 @@ mod tests {
|
|||
assert_eq!(count_keys(&old_storage_prefix(b"AccountStorages")[..]), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evm_chain_id_migration_updates_storage() {
|
||||
use super::evm_chain_id::EvmChainIdMigration;
|
||||
|
||||
let mut storage = frame_system::GenesisConfig::<TestRuntime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
pallet_balances::GenesisConfig::<TestRuntime>::default()
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(storage);
|
||||
|
||||
ext.execute_with(|| {
|
||||
// Set an old chain ID value
|
||||
const OLD_CHAIN_ID: u64 = 12345;
|
||||
const NEW_CHAIN_ID: u64 = 55931;
|
||||
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::put(OLD_CHAIN_ID);
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
OLD_CHAIN_ID
|
||||
);
|
||||
|
||||
// Run the migration
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
// Verify migration succeeded and completed in one step
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), None);
|
||||
|
||||
// Verify the chain ID was updated
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evm_chain_id_migration_is_idempotent() {
|
||||
use super::evm_chain_id::EvmChainIdMigration;
|
||||
|
||||
let mut storage = frame_system::GenesisConfig::<TestRuntime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
pallet_balances::GenesisConfig::<TestRuntime>::default()
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(storage);
|
||||
|
||||
ext.execute_with(|| {
|
||||
const NEW_CHAIN_ID: u64 = 55932;
|
||||
|
||||
// Run the migration twice
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result1 = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result2 = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
// Both should succeed
|
||||
assert!(result1.is_ok());
|
||||
assert!(result2.is_ok());
|
||||
|
||||
// Chain ID should be set correctly
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ use datahaven_runtime_common::benchmarking::BenchmarkHelper;
|
|||
|
||||
pub(crate) use crate::weights as mainnet_weights;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1289;
|
||||
const EVM_CHAIN_ID: u64 = 55930;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
|
||||
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use sp_core::{ecdsa, Pair, Public};
|
|||
use sp_genesis_builder::{self, PresetId};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
const MAINNET_EVM_CHAIN_ID: u64 = 1289;
|
||||
const MAINNET_EVM_CHAIN_ID: u64 = 55930;
|
||||
|
||||
// Returns the genesis config presets populated with given parameters.
|
||||
fn testnet_genesis(
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||
// `spec_version`, and `authoring_version` are the same between Wasm and native.
|
||||
// This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
|
||||
// the compatible custom types.
|
||||
spec_version: 500,
|
||||
spec_version: 510,
|
||||
impl_version: 1,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
transaction_version: 1,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(all(feature = "std", feature = "metadata-hash"))]
|
||||
fn main() {
|
||||
substrate_wasm_builder::WasmBuilder::init_with_defaults()
|
||||
.enable_metadata_hash("HAVE", 18)
|
||||
.enable_metadata_hash("STAGE", 18)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ use datahaven_runtime_common::benchmarking::BenchmarkHelper;
|
|||
|
||||
pub(crate) use crate::weights as stagenet_weights;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1283;
|
||||
const EVM_CHAIN_ID: u64 = 55932;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
|
||||
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
|
||||
|
|
@ -855,7 +855,13 @@ 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<Runtime>;
|
||||
type Migrations = (
|
||||
datahaven_runtime_common::migrations::MultiBlockMigrationList<Runtime>,
|
||||
datahaven_runtime_common::migrations::evm_chain_id::EvmChainIdMigration<
|
||||
Runtime,
|
||||
EVM_CHAIN_ID,
|
||||
>,
|
||||
);
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
type CursorMaxLen = MigrationCursorMaxLen;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use sp_core::{ecdsa, Pair, Public};
|
|||
use sp_genesis_builder::{self, PresetId};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
const STAGENET_EVM_CHAIN_ID: u64 = 1283;
|
||||
const STAGENET_EVM_CHAIN_ID: u64 = 55932;
|
||||
|
||||
// Returns the genesis config presets populated with given parameters.
|
||||
fn testnet_genesis(
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||
// `spec_version`, and `authoring_version` are the same between Wasm and native.
|
||||
// This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
|
||||
// the compatible custom types.
|
||||
spec_version: 500,
|
||||
spec_version: 510,
|
||||
impl_version: 1,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
transaction_version: 1,
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ pub struct NativeErc20Metadata;
|
|||
|
||||
impl Erc20Metadata for NativeErc20Metadata {
|
||||
fn name() -> &'static str {
|
||||
"HAVE"
|
||||
"STAGE"
|
||||
}
|
||||
|
||||
fn symbol() -> &'static str {
|
||||
"HAVE"
|
||||
"STAGE"
|
||||
}
|
||||
|
||||
fn decimals() -> u8 {
|
||||
|
|
|
|||
|
|
@ -205,8 +205,8 @@ pub fn root_origin() -> RuntimeOrigin {
|
|||
#[allow(dead_code)]
|
||||
pub fn datahaven_token_metadata() -> snowbridge_core::AssetMetadata {
|
||||
snowbridge_core::AssetMetadata {
|
||||
name: b"HAVE".to_vec().try_into().unwrap(),
|
||||
symbol: b"wHAVE".to_vec().try_into().unwrap(),
|
||||
name: b"STAGE".to_vec().try_into().unwrap(),
|
||||
symbol: b"wSTAGE".to_vec().try_into().unwrap(),
|
||||
decimals: 18,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(all(feature = "std", feature = "metadata-hash"))]
|
||||
fn main() {
|
||||
substrate_wasm_builder::WasmBuilder::init_with_defaults()
|
||||
.enable_metadata_hash("HAVE", 18)
|
||||
.enable_metadata_hash("MOCK", 18)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ use bridge_hub_common::AggregateMessageOrigin;
|
|||
#[cfg(feature = "runtime-benchmarks")]
|
||||
use datahaven_runtime_common::benchmarking::BenchmarkHelper;
|
||||
|
||||
const EVM_CHAIN_ID: u64 = 1288;
|
||||
const EVM_CHAIN_ID: u64 = 55931;
|
||||
const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
||||
|
||||
//╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
|
||||
|
|
@ -858,7 +858,13 @@ 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<Runtime>;
|
||||
type Migrations = (
|
||||
datahaven_runtime_common::migrations::MultiBlockMigrationList<Runtime>,
|
||||
datahaven_runtime_common::migrations::evm_chain_id::EvmChainIdMigration<
|
||||
Runtime,
|
||||
EVM_CHAIN_ID,
|
||||
>,
|
||||
);
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
type CursorMaxLen = MigrationCursorMaxLen;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use sp_core::{ecdsa, Pair, Public};
|
|||
use sp_genesis_builder::{self, PresetId};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
const TESTNET_EVM_CHAIN_ID: u64 = 1288;
|
||||
const TESTNET_EVM_CHAIN_ID: u64 = 55931;
|
||||
|
||||
// Returns the genesis config presets populated with given parameters.
|
||||
fn testnet_genesis(
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||
// `spec_version`, and `authoring_version` are the same between Wasm and native.
|
||||
// This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
|
||||
// the compatible custom types.
|
||||
spec_version: 500,
|
||||
spec_version: 510,
|
||||
impl_version: 1,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
transaction_version: 1,
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ pub struct NativeErc20Metadata;
|
|||
|
||||
impl Erc20Metadata for NativeErc20Metadata {
|
||||
fn name() -> &'static str {
|
||||
"HAVE"
|
||||
"MOCK"
|
||||
}
|
||||
|
||||
fn symbol() -> &'static str {
|
||||
"HAVE"
|
||||
"MOCK"
|
||||
}
|
||||
|
||||
fn decimals() -> u8 {
|
||||
|
|
|
|||
|
|
@ -205,8 +205,8 @@ pub fn root_origin() -> RuntimeOrigin {
|
|||
#[allow(dead_code)]
|
||||
pub fn datahaven_token_metadata() -> snowbridge_core::AssetMetadata {
|
||||
snowbridge_core::AssetMetadata {
|
||||
name: b"HAVE".to_vec().try_into().unwrap(),
|
||||
symbol: b"wHAVE".to_vec().try_into().unwrap(),
|
||||
name: b"MOCK".to_vec().try_into().unwrap(),
|
||||
symbol: b"wMOCK".to_vec().try_into().unwrap(),
|
||||
decimals: 18,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -146,8 +146,8 @@ describe("Native Token Transfer", () => {
|
|||
sender: { type: "V5", value: { parents: 0, interior: { type: "Here", value: undefined } } },
|
||||
asset_id: { type: "V5", value: { parents: 0, interior: { type: "Here", value: undefined } } },
|
||||
metadata: {
|
||||
name: Binary.fromText("HAVE"),
|
||||
symbol: Binary.fromText("wHAVE"),
|
||||
name: Binary.fromText("STAGE"),
|
||||
symbol: Binary.fromText("wSTAGE"),
|
||||
decimals: 18
|
||||
}
|
||||
});
|
||||
|
|
@ -220,8 +220,8 @@ describe("Native Token Transfer", () => {
|
|||
}) as Promise<number>
|
||||
]);
|
||||
|
||||
expect(tokenName).toBe("HAVE");
|
||||
expect(tokenSymbol).toBe("wHAVE");
|
||||
expect(tokenName).toBe("STAGE");
|
||||
expect(tokenSymbol).toBe("wSTAGE");
|
||||
expect(tokenDecimals).toBe(18);
|
||||
}, 300_000); // 5 minute timeout for registration
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue