From 0365ac76bacfaf41d5599e2a044dbf572026ae97 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 7 Nov 2022 22:38:51 -0500 Subject: [PATCH] feat: upgrade asset manager (#814) * feat: add asset-manager changes Signed-off-by: Brandon H. Gomes * Compiles and tests pass, cleaned warnings Signed-off-by: Georgi Zlatarev * Split Dolphin and Calamari AssetId types Signed-off-by: Georgi Zlatarev * Migration code for asset-manager and assets pallets, needs cleanup and invariants checkes, but works. Signed-off-by: Georgi Zlatarev * Add invariant checks Signed-off-by: Georgi Zlatarev * Update Signed-off-by: Georgi Zlatarev * Migrate Accounts storage double map with storage aliasing Signed-off-by: Georgi Zlatarev * Add equivalence checks before and after migration Signed-off-by: Georgi Zlatarev * Remove post-upgrade check that old storage is empty Signed-off-by: Georgi Zlatarev * Clean up and formatting Signed-off-by: Georgi Zlatarev * Revert default AssetRegistryMetadata. Fix benchmarks Signed-off-by: Georgi Zlatarev * Clean up and docs Signed-off-by: Georgi Zlatarev * Cleanup Signed-off-by: Georgi Zlatarev * Fix clippy Signed-off-by: Georgi Zlatarev * Address review comments. Incremenet storage version of both pallets and check for correctness Signed-off-by: Georgi Zlatarev * Use MaybeSerializeDesirialize from sp-runtime Signed-off-by: Georgi Zlatarev * Improve asset-manager benchmarking code Signed-off-by: Georgi Zlatarev * Fix clippy, rmeove pallet-assets from pallet-asset-manager cargo.toml Signed-off-by: Georgi Zlatarev * Use more explicitly named trait for asset metadata defaults for testing - TestingDefault Signed-off-by: Georgi Zlatarev * Fix docs Signed-off-by: Georgi Zlatarev * Migrate AssetRegistryMetadata Signed-off-by: Georgi Zlatarev * Bump AssetManager StorageVersion in pallet Signed-off-by: Georgi Zlatarev * Use AtLeast32BitUnsigned instead of local impl of CheckedIncrement Signed-off-by: Georgi Zlatarev * taplo fmt Signed-off-by: Georgi Zlatarev * Use One trait Signed-off-by: Georgi Zlatarev * Fix tests Signed-off-by: Georgi Zlatarev * Rename try_ name to more explicit and clean up docs Signed-off-by: Georgi Zlatarev * clean up asset-manager benchmarking code, removed redundant GenesisConfig impl and #[pallet::generate_store(pub(super) trait Store)] in pallet-asset-manager, remove unnecessary comments, use StandardAssetId in pallet-manta-pay benchmarking Signed-off-by: Georgi Zlatarev * Fix clippy and asset-manager benchamrking tests Signed-off-by: Georgi Zlatarev * Add missing doccoment in old asset-manager migration code Signed-off-by: Georgi Zlatarev * Refactor AssetIdMigration generics and get rid of magic numbers' * Missing doccoments related to xtokents and xcm Signed-off-by: Georgi Zlatarev * More missing dcocoments Signed-off-by: Georgi Zlatarev * Add progress logs to AssetId migration Signed-off-by: Georgi Zlatarev * Add #[compact] to all AssetId extrinsic params' : Signed-off-by: Georgi Zlatarev * Remove evm_address field from metadata Signed-off-by: Georgi Zlatarev * Fix clippy Signed-off-by: Georgi Zlatarev * Fix pre-runtime hook storage version check for pallet-assets Signed-off-by: Georgi Zlatarev Signed-off-by: Brandon H. Gomes Signed-off-by: Georgi Zlatarev Co-authored-by: Georgi Zlatarev --- Cargo.lock | 2 +- node/src/chain_specs/calamari.rs | 54 +- node/src/chain_specs/dolphin.rs | 58 +- node/src/chain_specs/manta.rs | 46 +- pallets/asset-manager/Cargo.toml | 36 +- pallets/asset-manager/src/benchmarking.rs | 101 ++- pallets/asset-manager/src/lib.rs | 395 ++++++---- pallets/asset-manager/src/migrations.rs | 25 +- pallets/asset-manager/src/mock.rs | 96 ++- pallets/asset-manager/src/tests.rs | 48 +- pallets/manta-pay/src/benchmark/mod.rs | 24 +- pallets/manta-pay/src/lib.rs | 20 +- pallets/manta-pay/src/mock.rs | 75 +- pallets/manta-pay/src/test/payment.rs | 47 +- pallets/manta-pay/src/types.rs | 6 +- primitives/manta/Cargo.toml | 4 - primitives/manta/src/assets.rs | 618 +++++++++------ primitives/manta/src/constants.rs | 56 +- primitives/manta/src/lib.rs | 10 +- primitives/manta/src/types.rs | 54 +- primitives/manta/src/xcm.rs | 379 ++++----- primitives/session-keys/Cargo.toml | 12 +- primitives/session-keys/src/aura.rs | 4 +- primitives/session-keys/src/helpers.rs | 50 -- primitives/session-keys/src/lib.rs | 14 +- primitives/session-keys/src/nimbus.rs | 15 +- primitives/session-keys/src/util.rs | 76 ++ primitives/session-keys/src/vrf.rs | 53 +- runtime/calamari/src/assets_config.rs | 74 +- runtime/calamari/src/lib.rs | 5 +- runtime/calamari/src/migrations/asset_id.rs | 737 ++++++++++++++++++ runtime/calamari/src/migrations/mod.rs | 1 + runtime/calamari/src/xcm_config.rs | 81 +- .../integrations_mock/integration_tests.rs | 180 ++--- .../calamari/tests/integrations_mock/mock.rs | 12 +- runtime/calamari/tests/xcm_mock/parachain.rs | 130 +-- runtime/calamari/tests/xcm_mock/xcm_tests.rs | 144 ++-- runtime/dolphin/src/assets_config.rs | 74 +- runtime/dolphin/src/lib.rs | 4 +- runtime/dolphin/src/xcm_config.rs | 55 +- runtime/manta/src/lib.rs | 2 +- 41 files changed, 2441 insertions(+), 1436 deletions(-) delete mode 100644 primitives/session-keys/src/helpers.rs create mode 100644 primitives/session-keys/src/util.rs create mode 100644 runtime/calamari/src/migrations/asset_id.rs diff --git a/Cargo.lock b/Cargo.lock index ed687e722..052b65334 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5074,7 +5074,6 @@ dependencies = [ "frame-support", "frame-system", "log", - "manta-accounting", "parity-scale-codec", "scale-info", "smallvec", @@ -5929,6 +5928,7 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", + "sp-arithmetic", "sp-core", "sp-io", "sp-runtime", diff --git a/node/src/chain_specs/calamari.rs b/node/src/chain_specs/calamari.rs index 295b971e7..58f02c017 100644 --- a/node/src/chain_specs/calamari.rs +++ b/node/src/chain_specs/calamari.rs @@ -23,7 +23,7 @@ use calamari_runtime::{ currency::KMA, opaque::SessionKeys, CouncilConfig, DemocracyConfig, GenesisConfig, ParachainStakingConfig, TechnicalCommitteeConfig, }; -use session_key_primitives::helpers::{get_account_id_from_seed, get_collator_keys_from_seed}; +use session_key_primitives::util::{unchecked_account_id, unchecked_collator_keys}; /// Calamari Protocol Identifier pub const CALAMARI_PROTOCOL_ID: &str = "calamari"; @@ -60,16 +60,16 @@ pub fn calamari_development_config() -> CalamariChainSpec { move || { calamari_dev_genesis( vec![( - get_account_id_from_seed::("Alice"), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + unchecked_account_id::("Alice"), + SessionKeys::new(unchecked_collator_keys("Alice")), )], // Delegations vec![], vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), ], ) }, @@ -95,39 +95,39 @@ pub fn calamari_local_config() -> CalamariChainSpec { calamari_dev_genesis( vec![ ( - get_account_id_from_seed::("Alice"), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + unchecked_account_id::("Alice"), + SessionKeys::new(unchecked_collator_keys("Alice")), ), ( - get_account_id_from_seed::("Bob"), - SessionKeys::new(get_collator_keys_from_seed("Bob")), + unchecked_account_id::("Bob"), + SessionKeys::new(unchecked_collator_keys("Bob")), ), ( - get_account_id_from_seed::("Charlie"), - SessionKeys::new(get_collator_keys_from_seed("Charlie")), + unchecked_account_id::("Charlie"), + SessionKeys::new(unchecked_collator_keys("Charlie")), ), ( - get_account_id_from_seed::("Dave"), - SessionKeys::new(get_collator_keys_from_seed("Dave")), + unchecked_account_id::("Dave"), + SessionKeys::new(unchecked_collator_keys("Dave")), ), ( - get_account_id_from_seed::("Eve"), - SessionKeys::new(get_collator_keys_from_seed("Eve")), + unchecked_account_id::("Eve"), + SessionKeys::new(unchecked_collator_keys("Eve")), ), ], // Delegations vec![], vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Charlie"), + unchecked_account_id::("Dave"), + unchecked_account_id::("Eve"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), + unchecked_account_id::("Charlie//stash"), + unchecked_account_id::("Dave//stash"), + unchecked_account_id::("Eve//stash"), ], ) }, diff --git a/node/src/chain_specs/dolphin.rs b/node/src/chain_specs/dolphin.rs index 57d93c97c..d9aef8236 100644 --- a/node/src/chain_specs/dolphin.rs +++ b/node/src/chain_specs/dolphin.rs @@ -21,7 +21,7 @@ use crate::command::{DOLPHIN_ON_BAIKAL_PARACHAIN_ID, DOLPHIN_PARACHAIN_ID}; use dolphin_runtime::{ opaque::SessionKeys, CouncilConfig, DemocracyConfig, GenesisConfig, TechnicalCommitteeConfig, }; -use session_key_primitives::helpers::{get_account_id_from_seed, get_collator_keys_from_seed}; +use session_key_primitives::util::{unchecked_account_id, unchecked_collator_keys}; /// Dolphin Protocol Identifier pub const DOLPHIN_PROTOCOL_ID: &str = "dolphin"; /// Kusama Relaychain Local Network Identifier @@ -54,15 +54,15 @@ pub fn dolphin_development_config() -> DolphinChainSpec { move || { dolphin_dev_genesis( vec![( - get_account_id_from_seed::("Alice"), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + unchecked_account_id::("Alice"), + SessionKeys::new(unchecked_collator_keys("Alice")), )], - get_account_id_from_seed::("Alice"), + unchecked_account_id::("Alice"), vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), ], ) }, @@ -88,38 +88,38 @@ pub fn dolphin_local_config() -> DolphinChainSpec { dolphin_dev_genesis( vec![ ( - get_account_id_from_seed::("Alice"), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + unchecked_account_id::("Alice"), + SessionKeys::new(unchecked_collator_keys("Alice")), ), ( - get_account_id_from_seed::("Bob"), - SessionKeys::new(get_collator_keys_from_seed("Bob")), + unchecked_account_id::("Bob"), + SessionKeys::new(unchecked_collator_keys("Bob")), ), ( - get_account_id_from_seed::("Charlie"), - SessionKeys::new(get_collator_keys_from_seed("Charlie")), + unchecked_account_id::("Charlie"), + SessionKeys::new(unchecked_collator_keys("Charlie")), ), ( - get_account_id_from_seed::("Dave"), - SessionKeys::new(get_collator_keys_from_seed("Dave")), + unchecked_account_id::("Dave"), + SessionKeys::new(unchecked_collator_keys("Dave")), ), ( - get_account_id_from_seed::("Eve"), - SessionKeys::new(get_collator_keys_from_seed("Eve")), + unchecked_account_id::("Eve"), + SessionKeys::new(unchecked_collator_keys("Eve")), ), ], - get_account_id_from_seed::("Alice"), + unchecked_account_id::("Alice"), vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Charlie"), + unchecked_account_id::("Dave"), + unchecked_account_id::("Eve"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), + unchecked_account_id::("Charlie//stash"), + unchecked_account_id::("Dave//stash"), + unchecked_account_id::("Eve//stash"), ], ) }, diff --git a/node/src/chain_specs/manta.rs b/node/src/chain_specs/manta.rs index cf4d57ad9..228a1c829 100644 --- a/node/src/chain_specs/manta.rs +++ b/node/src/chain_specs/manta.rs @@ -19,7 +19,7 @@ use super::*; use crate::command::MANTA_PARACHAIN_ID; use manta_runtime::opaque::SessionKeys; -use session_key_primitives::helpers::{get_account_id_from_seed, get_collator_keys_from_seed}; +use session_key_primitives::util::{unchecked_account_id, unchecked_collator_keys}; /// Manta Protocol Identifier pub const MANTA_PROTOCOL_ID: &str = "manta"; @@ -60,15 +60,15 @@ pub fn manta_development_config() -> MantaChainSpec { move || { manta_dev_genesis( vec![( - get_account_id_from_seed::("Alice"), - get_collator_keys_from_seed("Alice").0, + unchecked_account_id::("Alice"), + unchecked_collator_keys("Alice").0, )], - get_account_id_from_seed::("Alice"), + unchecked_account_id::("Alice"), vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), ], ) }, @@ -94,26 +94,26 @@ pub fn manta_local_config() -> MantaChainSpec { manta_dev_genesis( vec![ ( - get_account_id_from_seed::("Alice"), - get_collator_keys_from_seed("Alice").0, + unchecked_account_id::("Alice"), + unchecked_collator_keys("Alice").0, ), ( - get_account_id_from_seed::("Bob"), - get_collator_keys_from_seed("Bob").0, + unchecked_account_id::("Bob"), + unchecked_collator_keys("Bob").0, ), ], - get_account_id_from_seed::("Alice"), + unchecked_account_id::("Alice"), vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), + unchecked_account_id::("Alice"), + unchecked_account_id::("Bob"), + unchecked_account_id::("Charlie"), + unchecked_account_id::("Dave"), + unchecked_account_id::("Eve"), + unchecked_account_id::("Alice//stash"), + unchecked_account_id::("Bob//stash"), + unchecked_account_id::("Charlie//stash"), + unchecked_account_id::("Dave//stash"), + unchecked_account_id::("Eve//stash"), ], ) }, diff --git a/pallets/asset-manager/Cargo.toml b/pallets/asset-manager/Cargo.toml index e50defee6..5c39393da 100644 --- a/pallets/asset-manager/Cargo.toml +++ b/pallets/asset-manager/Cargo.toml @@ -1,52 +1,54 @@ [package] -authors = ['Manta Network'] +authors = ["Manta Network"] edition = "2021" -homepage = 'https://manta.network' -license = 'GPL-3.0' +homepage = "https://manta.network" +license = "GPL-3.0" name = "pallet-asset-manager" repository = 'https://github.com/Manta-Network/Manta/' version = '3.4.3' [dependencies] -codec = { package = "parity-scale-codec", version = '3.1.2', default-features = false } -frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.26", default-features = false, optional = true } +codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } log = { version = "0.4.0", default-features = false } manta-primitives = { path = "../../primitives/manta", default-features = false } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } +sp-arithmetic = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } -xcm = { git = 'https://github.com/paritytech/polkadot.git', default-features = false, branch = "release-v0.9.26" } +xcm = { git = "https://github.com/paritytech/polkadot.git", default-features = false, branch = "release-v0.9.26" } # 3rd party dependencies orml-traits = { git = "https://github.com/manta-network/open-runtime-module-library.git", default-features = false, branch = "polkadot-v0.9.26" } [dev-dependencies] -pallet-assets = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.26" } -pallet-balances = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.26" } +pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26" } [features] default = ["std"] runtime-benchmarks = [ - 'frame-benchmarking', - 'frame-support/runtime-benchmarks', - 'frame-system/runtime-benchmarks', - 'manta-primitives/runtime-benchmarks', + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "manta-primitives/runtime-benchmarks", ] std = [ "codec/std", - "scale-info/std", - "sp-runtime/std", "frame-support/std", "frame-system/std", - "sp-std/std", + "log/std", "manta-primitives/std", "orml-traits/std", - 'log/std', - 'xcm/std', + "scale-info/std", + "sp-runtime/std", + "sp-std/std", + "sp-arithmetic/std", + "xcm/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/pallets/asset-manager/src/benchmarking.rs b/pallets/asset-manager/src/benchmarking.rs index 0d6b73bc7..8a0430d35 100644 --- a/pallets/asset-manager/src/benchmarking.rs +++ b/pallets/asset-manager/src/benchmarking.rs @@ -20,121 +20,118 @@ use crate::{Call, Config, Event, Pallet}; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::traits::Get; use frame_system::{EventRecord, RawOrigin}; +use manta_primitives::assets::{AssetConfig, TestingDefault, UnitsPerSecond}; use xcm::latest::prelude::*; -use manta_primitives::assets::{AssetConfig, UnitsToWeightRatio}; - fn assert_last_event(generic_event: ::Event) { let events = frame_system::Pallet::::events(); let system_event: ::Event = generic_event.into(); - // compare to the last event record let EventRecord { event, .. } = &events[events.len() - 1]; assert_eq!(event, &system_event); } benchmarks! { - where_clause { where >::AssetLocation: From } + where_clause { where T::Location: From, ::Balance: From, ::AssetId: From } register_asset { - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); }: _(RawOrigin::Root, location.clone(), metadata) verify { assert_eq!(Pallet::::asset_id_location(>::StartNonNativeAssetId::get()), Some(location)); } set_units_per_second { - let start = >::StartNonNativeAssetId::get(); - let end = start + 1000; - for i in start..end { + let assets_count = 1000; + for i in 8..assets_count + 8 { let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i))); - let location = >::AssetLocation::from(location.clone()); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::from(location.clone()); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?; - Pallet::::set_units_per_second(RawOrigin::Root.into(), i, 0)?; + Pallet::::set_units_per_second(RawOrigin::Root.into(), ::AssetId::from(i), 0)?; } // does not really matter what we register, as long as it is different than the previous - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); let amount = 10; Pallet::::register_asset(RawOrigin::Root.into(), location, metadata)?; - }: _(RawOrigin::Root, end, amount) + let some_valid_asset_id = ::AssetId::from(assets_count + 8); + }: _(RawOrigin::Root, some_valid_asset_id, amount) verify { - assert_eq!(Pallet::::get_units_per_second(end), Some(amount)); + assert_eq!(Pallet::::units_per_second(&some_valid_asset_id), Some(amount)); } update_asset_location { - let start = >::StartNonNativeAssetId::get(); - let end = start + 1000; - for i in start..end { + let assets_count = 1000; + for i in 0..assets_count { let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i))); - let location = >::AssetLocation::from(location.clone()); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::from(location.clone()); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?; } // does not really matter what we register, as long as it is different than the previous - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location, metadata)?; - let new_location = >::AssetLocation::from(MultiLocation::new(0, X1(Parachain(end)))); - }: _(RawOrigin::Root, end, new_location.clone()) + let new_location = T::Location::from(MultiLocation::new(0, X1(Parachain(1000)))); + let some_valid_asset_id = ::AssetId::from(assets_count); + }: _(RawOrigin::Root, some_valid_asset_id, new_location.clone()) verify { - assert_eq!(Pallet::::asset_id_location(end), Some(new_location)); + assert_eq!(Pallet::::asset_id_location(some_valid_asset_id), Some(new_location)); } update_asset_metadata { - let start = >::StartNonNativeAssetId::get(); - let end = start + 1000; - for i in start..end { + let assets_count = 1000; + for i in 0..assets_count { let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i))); - let location = >::AssetLocation::from(location.clone()); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::from(location.clone()); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?; } // does not really matter what we register, as long as it is different than the previous - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location, metadata.clone())?; - }: _(RawOrigin::Root, end, metadata.clone()) + let some_valid_asset_id = ::AssetId::from(assets_count); + }: _(RawOrigin::Root, some_valid_asset_id, metadata.clone()) verify { - assert_last_event::(Event::AssetMetadataUpdated { asset_id: end, metadata }.into()); + assert_last_event::(Event::AssetMetadataUpdated { asset_id: some_valid_asset_id, metadata }.into()); } mint_asset { - let start = >::StartNonNativeAssetId::get(); - let end = start + 1000; - for i in start..end { - let location = >::AssetLocation::from(MultiLocation::new(0, X1(Parachain(i)))); - let metadata = >::AssetRegistrarMetadata::default(); + let assets_count = 1000; + for i in 0..assets_count { + let location = T::Location::from(MultiLocation::new(0, X1(Parachain(i)))); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?; } let beneficiary: T::AccountId = whitelisted_caller(); let amount = 100; // does not really matter what we register, as long as it is different than the previous - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location, metadata)?; - }: _(RawOrigin::Root, end, beneficiary.clone(), amount) + let some_valid_asset_id = ::AssetId::from(assets_count); + }: _(RawOrigin::Root, ::AssetId::from(assets_count), beneficiary.clone(), ::Balance::from(amount) ) verify { - assert_last_event::(Event::AssetMinted { asset_id: end, beneficiary, amount }.into()); + assert_last_event::(Event::AssetMinted { asset_id: some_valid_asset_id, beneficiary, amount: ::Balance::from(amount) }.into()); } set_min_xcm_fee { - let start = >::StartNonNativeAssetId::get(); - let end = start + 1000; - for i in start..end { + let assets_count = 1000; + for i in 8..assets_count + 8 { let location: MultiLocation = MultiLocation::new(0, X1(Parachain(i))); - let location = >::AssetLocation::from(location.clone()); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::from(location.clone()); + let metadata = >::AssetRegistryMetadata::testing_default(); Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata.clone())?; - Pallet::::set_units_per_second(RawOrigin::Root.into(), i, 0)?; + Pallet::::set_units_per_second(RawOrigin::Root.into(), ::AssetId::from(i), 0)?; } // does not really matter what we register, as long as it is different than the previous - let location = >::AssetLocation::default(); - let metadata = >::AssetRegistrarMetadata::default(); + let location = T::Location::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); let min_xcm_fee = 10; Pallet::::register_asset(RawOrigin::Root.into(), location.clone(), metadata)?; diff --git a/pallets/asset-manager/src/lib.rs b/pallets/asset-manager/src/lib.rs index 13201471e..0500d9865 100644 --- a/pallets/asset-manager/src/lib.rs +++ b/pallets/asset-manager/src/lib.rs @@ -30,8 +30,6 @@ mod benchmarking; pub mod migrations; pub mod weights; -pub use crate::weights::WeightInfo; -pub use pallet::*; #[cfg(test)] mod mock; @@ -39,9 +37,12 @@ mod mock; #[cfg(test)] mod tests; +pub use crate::weights::WeightInfo; +pub use pallet::*; + +/// Asset Manager Pallet #[frame_support::pallet] pub mod pallet { - use crate::weights::WeightInfo; use frame_support::{ pallet_prelude::*, @@ -49,63 +50,59 @@ pub mod pallet { transactional, PalletId, }; use frame_system::pallet_prelude::*; - use manta_primitives::{ - assets::{ - AssetConfig, AssetIdLocationGetter, AssetMetadata, AssetRegistrar, FungibleLedger, - UnitsToWeightRatio, - }, - types::{AssetId, Balance}, + use manta_primitives::assets::{ + self, AssetConfig, AssetIdLocationMap, AssetIdType, AssetMetadata, AssetRegistry, + FungibleLedger, LocationType, }; use orml_traits::GetByKey; use sp_runtime::{ - traits::{AccountIdConversion, One}, + traits::{ + AccountIdConversion, AtLeast32BitUnsigned, CheckedAdd, MaybeSerializeDeserialize, One, + }, ArithmeticError, }; use xcm::latest::prelude::*; - const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + /// Storage Version + pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); - /// Alias for the junction Parachain(#[codec(compact)] u32), + /// Alias for the junction type `Parachain(#[codec(compact)] u32)` pub(crate) type ParaId = u32; - pub(crate) type AssetCount = u32; - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(_); - - /// Convert AssetId and AssetLocation - impl AssetIdLocationGetter<>::AssetLocation> - for Pallet - { - fn get_asset_id( - loc: &>::AssetLocation, - ) -> Option { - LocationAssetId::::get(loc) - } - - fn get_asset_location( - id: AssetId, - ) -> Option<>::AssetLocation> { - AssetIdLocation::::get(id) - } - } - - /// Get unit per second from `AssetId` - impl UnitsToWeightRatio for Pallet { - fn get_units_per_second(id: AssetId) -> Option { - UnitsPerSecond::::get(id) - } - } + /// Asset Count Type + pub(crate) type AssetCount = u32; + /// Pallet Configuration #[pallet::config] pub trait Config: frame_system::Config { /// The overarching event type. type Event: From> + IsType<::Event>; - /// Asset configuration, e.g. AssetId, Balance, Metadata - type AssetConfig: AssetConfig; + /// Asset Id Type + type AssetId: AtLeast32BitUnsigned + + Default + + Parameter + + MaybeSerializeDeserialize + + TypeInfo + + Copy; + + /// Balance Type + type Balance: Default + Member + Parameter + TypeInfo; + + /// Location Type + type Location: Default + + Parameter + + TypeInfo + + From + + Into>; + + /// Asset Configuration + type AssetConfig: AssetConfig< + Self, + AssetId = Self::AssetId, + Balance = Self::Balance, + Location = Self::Location, + >; /// The origin which may forcibly create or destroy an asset or otherwise alter privileged /// attributes. @@ -118,24 +115,70 @@ pub mod pallet { type WeightInfo: crate::weights::WeightInfo; } + /// Asset Manager Pallet + #[pallet::pallet] + #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(_); + + impl AssetIdType for Pallet + where + T: Config, + { + type AssetId = T::AssetId; + } + + impl LocationType for Pallet + where + T: Config, + { + type Location = T::Location; + } + + impl AssetIdLocationMap for Pallet + where + T: Config, + { + #[inline] + fn location(asset_id: &Self::AssetId) -> Option { + AssetIdLocation::::get(asset_id) + } + + #[inline] + fn asset_id(location: &Self::Location) -> Option { + LocationAssetId::::get(location) + } + } + + impl assets::UnitsPerSecond for Pallet + where + T: Config, + { + #[inline] + fn units_per_second(id: &Self::AssetId) -> Option { + UnitsPerSecond::::get(id) + } + } + + /// Genesis Configuration #[pallet::genesis_config] pub struct GenesisConfig { - pub start_id: AssetId, - pub _marker: PhantomData, + pub start_id: T::AssetId, } #[cfg(feature = "std")] impl Default for GenesisConfig { + #[inline] fn default() -> Self { Self { start_id: >::StartNonNativeAssetId::get(), - _marker: PhantomData, } } } #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { + #[inline] fn build(&self) { NextAssetId::::set(self.start_id); let asset_id = >::NativeAssetId::get(); @@ -147,100 +190,135 @@ pub mod pallet { } } + /// Asset Manager Event #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A new asset registered. + /// A new asset was registered AssetRegistered { - asset_id: AssetId, - asset_address: >::AssetLocation, - metadata: >::AssetRegistrarMetadata, + /// Asset Id of new Asset + asset_id: T::AssetId, + + /// Location of the new Asset + location: T::Location, + + /// Metadata Registered to Asset Manager + metadata: >::AssetRegistryMetadata, }, - /// An asset's location has been updated. + + /// Updated the location of an asset AssetLocationUpdated { - asset_id: AssetId, - location: >::AssetLocation, + /// Asset Id of the updated Asset + asset_id: T::AssetId, + + /// Updated Location for the Asset + location: T::Location, }, - /// An asset;s metadata has been updated. + + /// Updated the metadata of an asset AssetMetadataUpdated { - asset_id: AssetId, - metadata: >::AssetRegistrarMetadata, + /// Asset Id of the updated Asset + asset_id: T::AssetId, + + /// Updated Metadata for the Asset + metadata: >::AssetRegistryMetadata, }, - /// Update units per second of an asset + + /// Updated the units-per-second for an asset UnitsPerSecondUpdated { - asset_id: AssetId, + /// Asset Id of the updated Asset + asset_id: T::AssetId, + + /// Updated units-per-second for the Asset units_per_second: u128, }, - /// Asset minted. + + /// An asset was minted AssetMinted { - asset_id: AssetId, + /// Asset Id of the minted Asset + asset_id: T::AssetId, + + /// Beneficiary Account beneficiary: T::AccountId, - amount: Balance, + + /// Amount Minted + amount: T::Balance, }, - /// Update min xcm fee of an asset + + /// Updated the minimum XCM fee for an asset MinXcmFeeUpdated { - reserve_chain: >::AssetLocation, + /// Reserve Chain Location + reserve_chain: T::Location, + + /// Updated Minimum XCM Fee min_xcm_fee: u128, }, } - /// Error. + /// Asset Manager Error #[pallet::error] pub enum Error { - /// Location already exists. + /// Location Already Exists LocationAlreadyExists, - /// Error creating asset, e.g. error returned from the implementation layer. + + /// An error occured while creating a new asset at the [`AssetRegistry`]. ErrorCreatingAsset, - /// Update a non-exist asset. - UpdateNonExistAsset, - /// Cannot update reserved assets metadata (0 and 1) + + /// There was an attempt to update a non-existent asset. + UpdateNonExistentAsset, + + /// Cannot Update Native Asset Metadata CannotUpdateNativeAssetMetadata, - /// Asset already registered. + + /// Asset Already Registered AssetAlreadyRegistered, - /// Error on minting asset. + + /// An error occurred while minting an asset. MintError, - /// Fail to update para id. + + /// An error occurred while updating the parachain id. UpdateParaIdError, } - /// AssetId to MultiLocation Map. + /// [`AssetId`](AssetConfig::AssetId) to [`MultiLocation`] Map + /// /// This is mostly useful when sending an asset to a foreign location. #[pallet::storage] #[pallet::getter(fn asset_id_location)] pub(super) type AssetIdLocation = - StorageMap<_, Blake2_128Concat, AssetId, >::AssetLocation>; + StorageMap<_, Blake2_128Concat, T::AssetId, T::Location>; - /// MultiLocation to AssetId Map. + /// [`MultiLocation`] to [`AssetId`](AssetConfig::AssetId) Map + /// /// This is mostly useful when receiving an asset from a foreign location. #[pallet::storage] #[pallet::getter(fn location_asset_id)] pub(super) type LocationAssetId = - StorageMap<_, Blake2_128Concat, >::AssetLocation, AssetId>; + StorageMap<_, Blake2_128Concat, T::Location, T::AssetId>; - /// AssetId to AssetRegistrar Map. + /// AssetId to AssetRegistry Map. #[pallet::storage] #[pallet::getter(fn asset_id_metadata)] pub(super) type AssetIdMetadata = StorageMap< _, Blake2_128Concat, - AssetId, - >::AssetRegistrarMetadata, + T::AssetId, + >::AssetRegistryMetadata, >; - /// Get the next available AssetId. + /// The Next Available [`AssetId`](AssetConfig::AssetId) #[pallet::storage] #[pallet::getter(fn next_asset_id)] - pub type NextAssetId = StorageValue<_, AssetId, ValueQuery>; + pub type NextAssetId = StorageValue<_, T::AssetId, ValueQuery>; - /// XCM transfer cost for different asset. + /// XCM transfer cost for each [`AssetId`](AssetConfig::AssetId) #[pallet::storage] - pub type UnitsPerSecond = StorageMap<_, Blake2_128Concat, AssetId, u128>; + pub type UnitsPerSecond = StorageMap<_, Blake2_128Concat, T::AssetId, u128>; /// Minimum xcm execution fee paid on destination chain. #[pallet::storage] #[pallet::getter(fn get_min_xcm_fee)] - pub type MinXcmFee = - StorageMap<_, Blake2_128Concat, >::AssetLocation, u128>; + pub type MinXcmFee = StorageMap<_, Blake2_128Concat, T::Location, u128>; /// The count of associated assets for each para id except relaychain. #[pallet::storage] @@ -262,19 +340,19 @@ pub mod pallet { #[transactional] pub fn register_asset( origin: OriginFor, - location: >::AssetLocation, - metadata: >::AssetRegistrarMetadata, + location: T::Location, + metadata: >::AssetRegistryMetadata, ) -> DispatchResult { T::ModifierOrigin::ensure_origin(origin)?; ensure!( !LocationAssetId::::contains_key(&location), Error::::LocationAlreadyExists ); - let asset_id = Self::get_next_asset_id()?; - >::AssetRegistrar::create_asset( + let asset_id = Self::next_asset_id_and_increment()?; + >::AssetRegistry::create_asset( asset_id, - metadata.min_balance(), metadata.clone().into(), + metadata.min_balance().clone(), metadata.is_sufficient(), ) .map_err(|_| Error::::ErrorCreatingAsset)?; @@ -285,14 +363,14 @@ pub mod pallet { // If it's a new para id, which will be inserted with AssetCount as 1. // If not, AssetCount will increased by 1. if let Some(para_id) = - Self::get_para_id_from_multilocation(location.clone().into().as_ref()) + Self::para_id_from_multilocation(location.clone().into().as_ref()) { - Self::increase_count_of_associated_assets(para_id)?; + Self::increase_count_of_associated_assets(*para_id)?; } Self::deposit_event(Event::::AssetRegistered { asset_id, - asset_address: location, + location, metadata, }); Ok(()) @@ -308,14 +386,14 @@ pub mod pallet { #[transactional] pub fn update_asset_location( origin: OriginFor, - #[pallet::compact] asset_id: AssetId, - location: >::AssetLocation, + #[pallet::compact] asset_id: T::AssetId, + location: T::Location, ) -> DispatchResult { // checks validity T::ModifierOrigin::ensure_origin(origin)?; ensure!( AssetIdLocation::::contains_key(asset_id), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); ensure!( !LocationAssetId::::contains_key(&location), @@ -323,7 +401,7 @@ pub mod pallet { ); // change the ledger state. let old_location = - AssetIdLocation::::get(asset_id).ok_or(Error::::UpdateNonExistAsset)?; + AssetIdLocation::::get(asset_id).ok_or(Error::::UpdateNonExistentAsset)?; LocationAssetId::::remove(&old_location); LocationAssetId::::insert(&location, asset_id); AssetIdLocation::::insert(asset_id, &location); @@ -332,7 +410,7 @@ pub mod pallet { // the old para id will be deleted if AssetCount <= 1, or decreased by 1. // 2. If the new location doesn't contain a new para id, do nothing to AssetCount if let Some(old_para_id) = - Self::get_para_id_from_multilocation(old_location.into().as_ref()) + Self::para_id_from_multilocation(old_location.into().as_ref()) { if AllowedDestParaIds::::get(old_para_id) <= Some(::one()) { AllowedDestParaIds::::remove(old_para_id); @@ -350,9 +428,9 @@ pub mod pallet { // If it's a new para id, which will be inserted with AssetCount as 1. // If not, AssetCount will increased by 1. if let Some(para_id) = - Self::get_para_id_from_multilocation(location.clone().into().as_ref()) + Self::para_id_from_multilocation(location.clone().into().as_ref()) { - Self::increase_count_of_associated_assets(para_id)?; + Self::increase_count_of_associated_assets(*para_id)?; } // deposit event. @@ -370,8 +448,8 @@ pub mod pallet { #[transactional] pub fn update_asset_metadata( origin: OriginFor, - #[pallet::compact] asset_id: AssetId, - metadata: >::AssetRegistrarMetadata, + asset_id: T::AssetId, + metadata: >::AssetRegistryMetadata, ) -> DispatchResult { T::ModifierOrigin::ensure_origin(origin)?; ensure!( @@ -380,10 +458,10 @@ pub mod pallet { ); ensure!( AssetIdLocation::::contains_key(asset_id), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); - >::AssetRegistrar::update_asset_metadata( - asset_id, + >::AssetRegistry::update_asset_metadata( + &asset_id, metadata.clone().into(), )?; AssetIdMetadata::::insert(asset_id, &metadata); @@ -401,13 +479,13 @@ pub mod pallet { #[transactional] pub fn set_units_per_second( origin: OriginFor, - #[pallet::compact] asset_id: AssetId, + #[pallet::compact] asset_id: T::AssetId, #[pallet::compact] units_per_second: u128, ) -> DispatchResult { T::ModifierOrigin::ensure_origin(origin)?; ensure!( AssetIdLocation::::contains_key(asset_id), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); UnitsPerSecond::::insert(asset_id, units_per_second); Self::deposit_event(Event::::UnitsPerSecondUpdated { @@ -428,31 +506,22 @@ pub mod pallet { #[transactional] pub fn mint_asset( origin: OriginFor, - #[pallet::compact] asset_id: AssetId, + #[pallet::compact] asset_id: T::AssetId, beneficiary: T::AccountId, - amount: Balance, + amount: T::Balance, ) -> DispatchResult { T::ModifierOrigin::ensure_origin(origin)?; ensure!( AssetIdLocation::::contains_key(asset_id), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); - - >::FungibleLedger::can_deposit( + >::FungibleLedger::deposit_minting_with_check( asset_id, &beneficiary, - amount, + amount.clone(), true, ) .map_err(|_| Error::::MintError)?; - - >::FungibleLedger::deposit_can_mint( - asset_id, - &beneficiary, - amount, - ) - .map_err(|_| Error::::MintError)?; - Self::deposit_event(Event::::AssetMinted { asset_id, beneficiary, @@ -471,7 +540,7 @@ pub mod pallet { #[transactional] pub fn set_min_xcm_fee( origin: OriginFor, - reserve_chain: >::AssetLocation, + reserve_chain: T::Location, #[pallet::compact] min_xcm_fee: u128, ) -> DispatchResult { T::ModifierOrigin::ensure_origin(origin)?; @@ -484,38 +553,37 @@ pub mod pallet { } } - impl Pallet { - /// Get and increment the `NextAssetID` by one. - fn get_next_asset_id() -> Result { - NextAssetId::::try_mutate(|current| -> Result { + impl Pallet + where + T: Config, + { + /// Returns and increments the [`NextAssetId`] by one. + #[inline] + fn next_asset_id_and_increment() -> Result { + NextAssetId::::try_mutate(|current| { let id = *current; - *current = current.checked_add(1u32).ok_or(ArithmeticError::Overflow)?; + *current = current + .checked_add(&One::one()) + .ok_or(ArithmeticError::Overflow)?; Ok(id) }) } - /// The account ID of AssetManager + /// Returns the account identifier of the [`AssetManager`] pallet. + #[inline] pub fn account_id() -> T::AccountId { T::PalletId::get().into_account_truncating() } - /// Get para id from asset location - pub fn get_para_id_from_multilocation(location: Option<&MultiLocation>) -> Option { - if let Some(MultiLocation { interior, .. }) = location { - match interior { - Junctions::X1(Junction::Parachain(para_id)) - | Junctions::X2(Junction::Parachain(para_id), ..) - | Junctions::X3(Junction::Parachain(para_id), ..) - | Junctions::X4(Junction::Parachain(para_id), ..) - | Junctions::X5(Junction::Parachain(para_id), ..) - | Junctions::X6(Junction::Parachain(para_id), ..) - | Junctions::X7(Junction::Parachain(para_id), ..) - | Junctions::X8(Junction::Parachain(para_id), ..) => Some(*para_id), - _ => None, + /// Returns the [`ParaId`] associated to `location`. + pub fn para_id_from_multilocation(location: Option<&MultiLocation>) -> Option<&ParaId> { + location.and_then(|location| { + if let Some(Parachain(para_id)) = location.first_interior() { + Some(para_id) + } else { + None } - } else { - None - } + }) } /// Increases the count of associated assets for the para id. @@ -537,8 +605,12 @@ pub mod pallet { } } - /// Check the multilocation is supported by calamari/manta. - impl Contains for Pallet { + /// Check the multilocation destination is supported by calamari/manta. + impl Contains for Pallet + where + T: Config, + { + #[inline] fn contains(location: &MultiLocation) -> bool { // check parents if location.parents != 1 { @@ -559,29 +631,14 @@ pub mod pallet { } } - /// Get min-xcm-fee by multilocation. - impl GetByKey> for Pallet { + /// Get min-xcm-fee for reserve chain by multilocation. + impl GetByKey> for Pallet + where + T: Config, + { + #[inline] fn get(location: &MultiLocation) -> Option { - let location = - >::AssetLocation::from(location.clone()); - MinXcmFee::::get(&location) - } - } - - #[cfg(feature = "std")] - impl GenesisConfig { - /// Direct implementation of `GenesisBuild::build_storage`. - /// - /// Kept in order not to break dependency. - pub fn build_storage(&self) -> Result { - >::build_storage(self) - } - - /// Direct implementation of `GenesisBuild::assimilate_storage`. - /// - /// Kept in order not to break dependency. - pub fn assimilate_storage(&self, storage: &mut sp_runtime::Storage) -> Result<(), String> { - >::assimilate_storage(self, storage) + MinXcmFee::::get(&T::Location::from(location.clone())) } } } diff --git a/pallets/asset-manager/src/migrations.rs b/pallets/asset-manager/src/migrations.rs index 563721b22..1f2f62e13 100644 --- a/pallets/asset-manager/src/migrations.rs +++ b/pallets/asset-manager/src/migrations.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -///! Do storage migration for AllowedDestParaIds which records the count of associated assets for each para id. +//! Do storage migration for AllowedDestParaIds which records the count of associated assets for +//! each para id. + use super::*; use core::marker::PhantomData; use frame_support::{ @@ -23,35 +25,36 @@ use frame_support::{ traits::{Get, OnRuntimeUpgrade, PalletInfoAccess, StorageVersion}, }; +/// Storage migration to populate the existing assets' +/// entries in the new AllowedDestParaIds storage item pub struct AllowedDestParaIdsMigration(PhantomData); -impl OnRuntimeUpgrade - for AllowedDestParaIdsMigration + +impl OnRuntimeUpgrade for AllowedDestParaIdsMigration +where + T: GetStorageVersion + Config + PalletInfoAccess, { fn on_runtime_upgrade() -> Weight { // currently, it's 0 on calamari. let storage_version = ::on_chain_storage_version(); if storage_version < 1 { log::info!(target: "asset-manager", "Start to execute storage migration for asset-manager."); - let mut reads: Weight = 0; let mut writes: Weight = 0; LocationAssetId::::iter().for_each(|(location, _asset_id)| { reads += 1; if let Some(para_id) = - Pallet::::get_para_id_from_multilocation(location.into().as_ref()) + Pallet::::para_id_from_multilocation(location.into().as_ref()) { - if para_id != 2084 { - let _ = Pallet::::increase_count_of_associated_assets(para_id); + if *para_id != 2084 { + let _ = Pallet::::increase_count_of_associated_assets(*para_id); reads += 1; // There's one read in method increase_count_of_associated_assets. writes += 1; // There's one write in method increase_count_of_associated_assets. } } }); - // Update storage version. StorageVersion::new(1u16).put::(); writes += 1; - T::DbWeight::get() .reads(reads) .saturating_add(T::DbWeight::get().writes(writes)) @@ -65,22 +68,18 @@ impl OnRuntimeUpgrade #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result<(), &'static str> { let storage_version = ::on_chain_storage_version(); - if storage_version >= 1 { return Err("Storage version is >= 1, the migration won't be executed."); } - Ok(()) } #[cfg(feature = "try-runtime")] fn post_upgrade() -> Result<(), &'static str> { let storage_version = ::on_chain_storage_version(); - if storage_version < 1 { return Err("Storage version is >= 1, the migration won't be executed."); } - let acala = (2000, 3); // karura has 3 asset locations on calamari. let moonbeam = (2023, 1); // moonbean has 1 asset location on calamari. let calamari = 2084; // our own asset location won't be counted. diff --git a/pallets/asset-manager/src/mock.rs b/pallets/asset-manager/src/mock.rs index 29aa302ec..72a25d99c 100644 --- a/pallets/asset-manager/src/mock.rs +++ b/pallets/asset-manager/src/mock.rs @@ -20,6 +20,7 @@ //! Mock runtime for asset-manager use crate as pallet_asset_manager; +use crate::mock::sp_api_hidden_includes_construct_runtime::hidden_include::traits::GenesisBuild; use frame_support::{ construct_runtime, pallet_prelude::DispatchResult, parameter_types, traits::ConstU32, PalletId, }; @@ -27,21 +28,19 @@ use frame_system as system; use frame_system::EnsureRoot; use manta_primitives::{ assets::{ - AssetConfig, AssetLocation, AssetRegistrar, AssetRegistrarMetadata, AssetStorageMetadata, - ConcreteFungibleLedger, + AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, + AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, }, constants::{ASSET_MANAGER_PALLET_ID, ASSET_STRING_LIMIT}, - types::{AccountId, AssetId, Balance, BlockNumber, Header}, + types::{AccountId, Balance, BlockNumber, CalamariAssetId, Header}, }; -use sp_core::{H160, H256}; +use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; -use sp_std::marker::PhantomData; use xcm::{ prelude::{Parachain, X1}, v1::MultiLocation, VersionedMultiLocation, }; - parameter_types! { pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = manta_primitives::constants::CALAMARI_SS58PREFIX; @@ -86,7 +85,7 @@ parameter_types! { impl pallet_assets::Config for Runtime { type Event = Event; type Balance = Balance; - type AssetId = AssetId; + type AssetId = CalamariAssetId; type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -118,12 +117,21 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; } -pub struct MantaAssetRegistrar; -impl AssetRegistrar for MantaAssetRegistrar { +pub struct MantaAssetRegistry; +impl BalanceType for MantaAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for MantaAssetRegistry { + type AssetId = CalamariAssetId; +} +impl AssetRegistry for MantaAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + fn create_asset( - asset_id: AssetId, - min_balance: Balance, + asset_id: CalamariAssetId, metadata: AssetStorageMetadata, + min_balance: Balance, is_sufficient: bool, ) -> DispatchResult { Assets::force_create( @@ -144,10 +152,13 @@ impl AssetRegistrar for MantaAssetRegistrar { ) } - fn update_asset_metadata(asset_id: AssetId, metadata: AssetStorageMetadata) -> DispatchResult { + fn update_asset_metadata( + asset_id: &CalamariAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { Assets::force_set_metadata( Origin::root(), - asset_id, + *asset_id, metadata.name, metadata.symbol, metadata.decimals, @@ -157,41 +168,51 @@ impl AssetRegistrar for MantaAssetRegistrar { } parameter_types! { - pub const DummyAssetId: AssetId = 0; - pub const NativeAssetId: AssetId = 1; - pub const StartNonNativeAssetId: AssetId = 8; + pub const StartNonNativeAssetId: CalamariAssetId = 8; + pub const NativeAssetId: CalamariAssetId = 1; pub NativeAssetLocation: AssetLocation = AssetLocation( VersionedMultiLocation::V1(MultiLocation::new(1, X1(Parachain(1024))))); - pub NativeAssetMetadata: AssetRegistrarMetadata = AssetRegistrarMetadata { - name: b"Dolphin".to_vec(), - symbol: b"DOL".to_vec(), - decimals: 18, + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Dolphin".to_vec(), + symbol: b"DOL".to_vec(), + decimals: 18, + is_frozen: false, + }, min_balance: 1u128, - evm_address: None, - is_frozen: false, is_sufficient: true, }; pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; } +/// AssetConfig implementations for this runtime #[derive(Clone, Eq, PartialEq)] pub struct MantaAssetConfig; - +impl LocationType for MantaAssetConfig { + type Location = AssetLocation; +} +impl AssetIdType for MantaAssetConfig { + type AssetId = CalamariAssetId; +} +impl BalanceType for MantaAssetConfig { + type Balance = Balance; +} impl AssetConfig for MantaAssetConfig { - type DummyAssetId = DummyAssetId; - type NativeAssetId = NativeAssetId; type StartNonNativeAssetId = StartNonNativeAssetId; - type AssetRegistrarMetadata = AssetRegistrarMetadata; + type NativeAssetId = NativeAssetId; + type AssetRegistryMetadata = AssetRegistryMetadata; type NativeAssetLocation = NativeAssetLocation; type NativeAssetMetadata = NativeAssetMetadata; type StorageMetadata = AssetStorageMetadata; - type AssetLocation = AssetLocation; - type AssetRegistrar = MantaAssetRegistrar; - type FungibleLedger = ConcreteFungibleLedger; + type AssetRegistry = MantaAssetRegistry; + type FungibleLedger = NativeAndNonNative; } impl pallet_asset_manager::Config for Runtime { type Event = Event; + type AssetId = CalamariAssetId; + type Balance = Balance; + type Location = AssetLocation; type AssetConfig = MantaAssetConfig; type ModifierOrigin = EnsureRoot; type PalletId = AssetManagerPalletId; @@ -222,7 +243,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .unwrap(); pallet_asset_manager::GenesisConfig:: { start_id: >::StartNonNativeAssetId::get(), - _marker: PhantomData::::default(), } .assimilate_storage(&mut t) .unwrap(); @@ -234,17 +254,17 @@ pub(crate) fn create_asset_metadata( symbol: &str, decimals: u8, min_balance: u128, - evm_address: Option, is_frozen: bool, is_sufficient: bool, -) -> AssetRegistrarMetadata { - AssetRegistrarMetadata { - name: name.as_bytes().to_vec(), - symbol: symbol.as_bytes().to_vec(), - decimals, +) -> AssetRegistryMetadata { + AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: name.as_bytes().to_vec(), + symbol: symbol.as_bytes().to_vec(), + decimals, + is_frozen, + }, min_balance, - evm_address, - is_frozen, is_sufficient, } } diff --git a/pallets/asset-manager/src/tests.rs b/pallets/asset-manager/src/tests.rs index 2d27c15d0..7ebe2fa8a 100644 --- a/pallets/asset-manager/src/tests.rs +++ b/pallets/asset-manager/src/tests.rs @@ -56,7 +56,7 @@ fn basic_setup_should_work() { #[test] fn wrong_modifier_origin_should_not_work() { new_test_ext().execute_with(|| { - let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, None, false, true); + let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, false, true); let source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); assert_noop!( AssetManager::register_asset( @@ -92,15 +92,14 @@ fn wrong_modifier_origin_should_not_work() { #[test] fn register_asset_should_work() { let para_id = 1; - let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, None, false, true); + let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, false, true); let source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let new_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 1, X2(Parachain(para_id), PalletInstance(PALLET_BALANCES_INDEX)), ))); new_test_ext().execute_with(|| { - let mut counter: u32 = - >::StartNonNativeAssetId::get(); + let mut counter = >::StartNonNativeAssetId::get(); // Register relay chain native token assert_ok!(AssetManager::register_asset( Origin::root(), @@ -135,22 +134,15 @@ fn register_asset_should_work() { fn update_asset() { let para_id = 1; let original_decimals = 12; - let asset_metadata = create_asset_metadata( - "Kusama", - "KSM", - original_decimals, - 1u128, - None, - false, - false, - ); + let asset_metadata = + create_asset_metadata("Kusama", "KSM", original_decimals, 1u128, false, false); let mut new_metadata = asset_metadata.clone(); let new_name = b"NotKusama".to_vec(); let new_symbol = b"NotKSM".to_vec(); let new_decimals = original_decimals + 1; - new_metadata.name = new_name.clone(); - new_metadata.symbol = new_symbol.clone(); - new_metadata.decimals = new_decimals; + new_metadata.metadata.name = new_name.clone(); + new_metadata.metadata.symbol = new_symbol.clone(); + new_metadata.metadata.decimals = new_decimals; let source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let new_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 1, @@ -207,7 +199,7 @@ fn update_asset() { next_asset_id, new_location.clone() ), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); assert_noop!( AssetManager::update_asset_metadata( @@ -215,7 +207,7 @@ fn update_asset() { next_asset_id, new_metadata.clone() ), - Error::::UpdateNonExistAsset + Error::::UpdateNonExistentAsset ); // Re-registering the original location and metadata should work, // as we modified the previous asset. @@ -259,8 +251,7 @@ fn update_asset() { fn check_para_id_info_when_update_asset_location() { new_test_ext().execute_with(|| { let manta_para_id = 2015; - let manta_asset_metadata = - create_asset_metadata("Manta", "MANTA", 18, 1u128, None, false, false); + let manta_asset_metadata = create_asset_metadata("Manta", "MANTA", 18, 1u128, false, false); let mut manta_native_location = AssetLocation(VersionedMultiLocation::V1( MultiLocation::new(1, X1(Parachain(manta_para_id))), )); @@ -283,7 +274,7 @@ fn check_para_id_info_when_update_asset_location() { // create a non manta asset. let manta_non_native_asset_metadata = - create_asset_metadata("Manta", "eMANTA", 18, 1u128, None, false, false); + create_asset_metadata("Manta", "eMANTA", 18, 1u128, false, false); let mut manta_non_native_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 1, @@ -367,7 +358,7 @@ fn mint_asset() { // mint native asset let native_asset_id = >::NativeAssetId::get(); assert_ok!( - >::FungibleLedger::deposit_can_mint( + >::FungibleLedger::deposit_minting( native_asset_id, &ALICE, 1_000_000 @@ -377,7 +368,7 @@ fn mint_asset() { // mint non-native asset let non_native_asset_id = >::StartNonNativeAssetId::get(); - let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, None, false, true); + let asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, false, true); let source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); assert_ok!(AssetManager::register_asset( Origin::root(), @@ -385,7 +376,7 @@ fn mint_asset() { asset_metadata )); assert_ok!( - >::FungibleLedger::deposit_can_mint( + >::FungibleLedger::deposit_minting( non_native_asset_id, &ALICE, 1_000_000 @@ -396,13 +387,11 @@ fn mint_asset() { #[test] fn filter_asset_location_should_work() { - let kusama_asset_metadata = - create_asset_metadata("Kusama", "KSM", 12, 1u128, None, false, false); + let kusama_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1u128, false, false); let kusama_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_id = 2015; - let manta_asset_metadata = - create_asset_metadata("Manta", "MANTA", 18, 1u128, None, false, false); + let manta_asset_metadata = create_asset_metadata("Manta", "MANTA", 18, 1u128, false, false); let manta_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 1, X1(Parachain(para_id)), @@ -492,8 +481,7 @@ fn filter_asset_location_should_work() { #[test] fn set_min_xcm_fee_should_work() { - let manta_asset_metadata = - create_asset_metadata("Manta", "MANTA", 18, 1u128, None, false, false); + let manta_asset_metadata = create_asset_metadata("Manta", "MANTA", 18, 1u128, false, false); let manta_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 1, X2( diff --git a/pallets/manta-pay/src/benchmark/mod.rs b/pallets/manta-pay/src/benchmark/mod.rs index 615d6022d..b668233d5 100644 --- a/pallets/manta-pay/src/benchmark/mod.rs +++ b/pallets/manta-pay/src/benchmark/mod.rs @@ -18,14 +18,14 @@ use crate::{ benchmark::precomputed_coins::{ MINT, PRIVATE_TRANSFER, PRIVATE_TRANSFER_INPUT, RECLAIM, RECLAIM_INPUT, }, - Asset, Call, Config, Event, Pallet, TransferPost, + Asset, Call, Config, Event, Pallet, StandardAssetId, TransferPost, }; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_system::RawOrigin; use manta_primitives::{ - assets::{AssetConfig, AssetRegistrar, FungibleLedger}, - constants::DEFAULT_ASSET_ED, - types::{AssetId, Balance}, + assets::{AssetConfig, AssetRegistry, FungibleLedger, TestingDefault}, + constants::TEST_DEFAULT_ASSET_ED, + types::Balance, }; use scale_codec::Decode; @@ -44,30 +44,30 @@ where /// Init assets for manta-pay #[inline] -pub fn init_asset(owner: &T::AccountId, id: AssetId, value: Balance) +pub fn init_asset(owner: &T::AccountId, id: StandardAssetId, value: Balance) where T: Config, { - let metadata = >::AssetRegistrarMetadata::default(); + let metadata = >::AssetRegistryMetadata::testing_default(); let storage_metadata: >::StorageMetadata = metadata.into(); - >::AssetRegistrar::create_asset( + >::AssetRegistry::create_asset( id, - DEFAULT_ASSET_ED, storage_metadata, + TEST_DEFAULT_ASSET_ED, true, ) .expect("Unable to create asset."); let pallet_account: T::AccountId = Pallet::::account_id(); - >::FungibleLedger::deposit_can_mint( + >::FungibleLedger::deposit_minting( id, owner, - value + DEFAULT_ASSET_ED, + value + TEST_DEFAULT_ASSET_ED, ) .expect("Unable to mint asset to its new owner."); - >::FungibleLedger::deposit_can_mint( + >::FungibleLedger::deposit_minting( id, &pallet_account, - DEFAULT_ASSET_ED, + TEST_DEFAULT_ASSET_ED, ) .expect("Unable to mint existential deposit to pallet account."); } diff --git a/pallets/manta-pay/src/lib.rs b/pallets/manta-pay/src/lib.rs index b4160490b..7c7a1f9f5 100644 --- a/pallets/manta-pay/src/lib.rs +++ b/pallets/manta-pay/src/lib.rs @@ -58,9 +58,9 @@ extern crate alloc; use alloc::{vec, vec::Vec}; use core::marker::PhantomData; use frame_support::{traits::tokens::ExistenceRequirement, transactional, PalletId}; - use manta_accounting::{ asset, + asset::AssetValueType, transfer::{ canonical::TransferShape, InvalidSinkAccount, InvalidSourceAccount, Proof, ReceiverLedger, ReceiverPostError, ReceiverPostingKey, SenderLedger, SenderPostError, SenderPostingKey, @@ -74,8 +74,8 @@ use manta_crypto::{ }; use manta_pay::config; use manta_primitives::{ - assets::{AssetConfig, FungibleLedger as _, FungibleLedgerError}, - types::{AssetId, Balance}, + assets::{self, AssetConfig, FungibleLedger as _}, + types::Balance, }; use manta_util::codec::Decode as _; use scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -105,6 +105,12 @@ pub mod rpc; #[cfg(feature = "runtime")] pub mod runtime; +/// Standard Asset Id +pub type StandardAssetId = u32; + +/// Fungible Ledger Error +pub type FungibleLedgerError = assets::FungibleLedgerError; + /// MantaPay Pallet #[frame_support::pallet] pub mod pallet { @@ -128,7 +134,7 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Asset Configuration - type AssetConfig: AssetConfig; + type AssetConfig: AssetConfig; /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -431,7 +437,7 @@ pub mod pallet { #[inline] fn from(err: FungibleLedgerError) -> Self { match err { - FungibleLedgerError::InvalidAssetId => Self::PublicUpdateInvalidAssetId, + FungibleLedgerError::InvalidAssetId(_) => Self::PublicUpdateInvalidAssetId, FungibleLedgerError::BelowMinimum => Self::PublicUpdateBelowMinimum, FungibleLedgerError::CannotCreate => Self::PublicUpdateCannotCreate, FungibleLedgerError::UnknownAsset => Self::PublicUpdateUnknownAsset, @@ -820,10 +826,10 @@ where { sources .map(move |(account_id, withdraw)| { - FungibleLedger::::can_reduce_by_amount( + FungibleLedger::::can_withdraw( asset_id.0, &account_id, - withdraw.0, + &withdraw.0, ExistenceRequirement::KeepAlive, ) .map(|_| WrapPair(account_id.clone(), withdraw)) diff --git a/pallets/manta-pay/src/mock.rs b/pallets/manta-pay/src/mock.rs index 764d403fb..6988234a6 100644 --- a/pallets/manta-pay/src/mock.rs +++ b/pallets/manta-pay/src/mock.rs @@ -23,11 +23,11 @@ use frame_support::{ use frame_system::EnsureRoot; use manta_primitives::{ assets::{ - AssetConfig, AssetLocation, AssetRegistrar, AssetRegistrarMetadata, AssetStorageMetadata, - ConcreteFungibleLedger, + AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, + AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, }, constants::{ASSET_MANAGER_PALLET_ID, MANTA_PAY_PALLET_ID}, - types::{AssetId, Balance, BlockNumber, Header}, + types::{Balance, BlockNumber, Header}, }; use sp_core::H256; use sp_runtime::{ @@ -40,6 +40,8 @@ use xcm::{ VersionedMultiLocation, }; +use crate::StandardAssetId; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -119,7 +121,7 @@ parameter_types! { impl pallet_assets::Config for Test { type Event = Event; type Balance = Balance; - type AssetId = AssetId; + type AssetId = StandardAssetId; type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -133,12 +135,21 @@ impl pallet_assets::Config for Test { type WeightInfo = pallet_assets::weights::SubstrateWeight; } -pub struct MantaAssetRegistrar; -impl AssetRegistrar for MantaAssetRegistrar { +pub struct MantaAssetRegistry; +impl BalanceType for MantaAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for MantaAssetRegistry { + type AssetId = StandardAssetId; +} +impl AssetRegistry for MantaAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + fn create_asset( - asset_id: AssetId, - min_balance: Balance, + asset_id: StandardAssetId, metadata: AssetStorageMetadata, + min_balance: Balance, is_sufficient: bool, ) -> DispatchResult { Assets::force_create( @@ -171,10 +182,13 @@ impl AssetRegistrar for MantaAssetRegistrar { ) } - fn update_asset_metadata(asset_id: AssetId, metadata: AssetStorageMetadata) -> DispatchResult { + fn update_asset_metadata( + asset_id: &StandardAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { Assets::force_set_metadata( Origin::root(), - asset_id, + *asset_id, metadata.name, metadata.symbol, metadata.decimals, @@ -184,41 +198,52 @@ impl AssetRegistrar for MantaAssetRegistrar { } parameter_types! { - pub const DummyAssetId: AssetId = 0; - pub const NativeAssetId: AssetId = 1; - pub const StartNonNativeAssetId: AssetId = 8; + pub const DummyAssetId: StandardAssetId = 0; + pub const NativeAssetId: StandardAssetId = 1; + pub const StartNonNativeAssetId: StandardAssetId = 8; pub NativeAssetLocation: AssetLocation = AssetLocation( VersionedMultiLocation::V1(MultiLocation::new(1, X1(Parachain(1024))))); - pub NativeAssetMetadata: AssetRegistrarMetadata = AssetRegistrarMetadata { - name: b"Dolphin".to_vec(), - symbol: b"DOL".to_vec(), - decimals: 18, + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Dolphin".to_vec(), + symbol: b"DOL".to_vec(), + decimals: 18, + is_frozen: false, + }, min_balance: 1u128, - evm_address: None, - is_frozen: false, is_sufficient: true, }; pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; } +/// AssetConfig implementations for this runtime #[derive(Clone, Eq, PartialEq)] pub struct MantaAssetConfig; - +impl LocationType for MantaAssetConfig { + type Location = AssetLocation; +} +impl AssetIdType for MantaAssetConfig { + type AssetId = StandardAssetId; +} +impl BalanceType for MantaAssetConfig { + type Balance = Balance; +} impl AssetConfig for MantaAssetConfig { - type DummyAssetId = DummyAssetId; type NativeAssetId = NativeAssetId; type StartNonNativeAssetId = StartNonNativeAssetId; - type AssetRegistrarMetadata = AssetRegistrarMetadata; + type AssetRegistryMetadata = AssetRegistryMetadata; type NativeAssetLocation = NativeAssetLocation; type NativeAssetMetadata = NativeAssetMetadata; type StorageMetadata = AssetStorageMetadata; - type AssetLocation = AssetLocation; - type AssetRegistrar = MantaAssetRegistrar; - type FungibleLedger = ConcreteFungibleLedger; + type AssetRegistry = MantaAssetRegistry; + type FungibleLedger = NativeAndNonNative; } impl pallet_asset_manager::Config for Test { type Event = Event; + type AssetId = StandardAssetId; + type Balance = Balance; + type Location = AssetLocation; type AssetConfig = MantaAssetConfig; type ModifierOrigin = EnsureRoot; type PalletId = AssetManagerPalletId; diff --git a/pallets/manta-pay/src/test/payment.rs b/pallets/manta-pay/src/test/payment.rs index e5027727c..703228449 100644 --- a/pallets/manta-pay/src/test/payment.rs +++ b/pallets/manta-pay/src/test/payment.rs @@ -15,7 +15,7 @@ // along with Manta. If not, see . use crate::{ - mock::{new_test_ext, MantaAssetConfig, MantaAssetRegistrar, MantaPayPallet, Origin, Test}, + mock::{new_test_ext, MantaAssetConfig, MantaAssetRegistry, MantaPayPallet, Origin, Test}, Error, FungibleLedger, }; use frame_support::{assert_noop, assert_ok}; @@ -34,8 +34,11 @@ use manta_pay::config::{ UtxoCommitmentScheme, VoidNumberCommitmentScheme, }; use manta_primitives::{ - assets::{AssetConfig, AssetRegistrar, AssetRegistrarMetadata, FungibleLedger as _}, - constants::DEFAULT_ASSET_ED, + assets::{ + AssetConfig, AssetRegistry, AssetRegistryMetadata, AssetStorageMetadata, + FungibleLedger as _, + }, + constants::TEST_DEFAULT_ASSET_ED, }; use manta_util::codec::{Decode, IoReader}; use std::fs::File; @@ -163,7 +166,7 @@ where }; let total_free_balance = AssetValue(rng.gen()); let balances = value_distribution(count, total_free_balance, rng); - initialize_test(asset_id, total_free_balance + DEFAULT_ASSET_ED); + initialize_test(asset_id, total_free_balance + TEST_DEFAULT_ASSET_ED); let mut utxo_accumulator = UtxoAccumulator::new(UTXO_ACCUMULATOR_MODEL.clone()); let mut posts = Vec::new(); for balance in balances { @@ -237,7 +240,7 @@ where None => rng.gen(), }; let balances = value_distribution(count, total_supply, rng); - initialize_test(asset_id, total_supply + DEFAULT_ASSET_ED); + initialize_test(asset_id, total_supply + TEST_DEFAULT_ASSET_ED); let mut utxo_accumulator = UtxoAccumulator::new(UTXO_ACCUMULATOR_MODEL.clone()); let mut posts = Vec::new(); for balance in balances { @@ -294,20 +297,29 @@ where /// Initializes a test by allocating `value`-many assets of the given `id` to the default account. #[inline] fn initialize_test(id: AssetId, value: AssetValue) { - let metadata = AssetRegistrarMetadata::default(); - assert_ok!(MantaAssetRegistrar::create_asset( + let metadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Calamari".to_vec(), + symbol: b"KMA".to_vec(), + decimals: 12, + is_frozen: false, + }, + min_balance: TEST_DEFAULT_ASSET_ED, + is_sufficient: true, + }; + assert_ok!(MantaAssetRegistry::create_asset( id.0, - DEFAULT_ASSET_ED, metadata.into(), + TEST_DEFAULT_ASSET_ED, true )); - assert_ok!(FungibleLedger::::deposit_can_mint( + assert_ok!(FungibleLedger::::deposit_minting( id.0, &ALICE, value.0 )); - assert_ok!(FungibleLedger::::deposit_can_mint( + assert_ok!(FungibleLedger::::deposit_minting( id.0, &MantaPayPallet::account_id(), - DEFAULT_ASSET_ED + TEST_DEFAULT_ASSET_ED )); } @@ -319,7 +331,7 @@ fn to_private_should_work() { new_test_ext().execute_with(|| { let asset_id = rng.gen(); let total_free_supply = AssetValue(rng.gen()); - initialize_test(asset_id, total_free_supply + DEFAULT_ASSET_ED); + initialize_test(asset_id, total_free_supply + TEST_DEFAULT_ASSET_ED); mint_tokens( asset_id, &value_distribution(5, total_free_supply, &mut rng), @@ -335,7 +347,7 @@ fn native_asset_to_private_should_work() { let mut rng = OsRng; new_test_ext().execute_with(|| { let total_free_supply = AssetValue(rng.gen()); - initialize_test(NATIVE_ASSET_ID, total_free_supply + DEFAULT_ASSET_ED); + initialize_test(NATIVE_ASSET_ID, total_free_supply + TEST_DEFAULT_ASSET_ED); mint_tokens( NATIVE_ASSET_ID, &value_distribution(5, total_free_supply, &mut rng), @@ -353,12 +365,15 @@ fn overdrawn_mint_should_not_work() { new_test_ext().execute_with(|| { let asset_id = rng.gen(); let total_supply = AssetValue(rng.gen()); - initialize_test(asset_id, total_supply + DEFAULT_ASSET_ED); + initialize_test(asset_id, total_supply + TEST_DEFAULT_ASSET_ED); assert_noop!( MantaPayPallet::to_private( Origin::signed(ALICE), - sample_mint(asset_id.with(total_supply + DEFAULT_ASSET_ED + 1), &mut rng) - .into() + sample_mint( + asset_id.with(total_supply + TEST_DEFAULT_ASSET_ED + 1), + &mut rng + ) + .into() ), Error::::InvalidSourceAccount ); diff --git a/pallets/manta-pay/src/types.rs b/pallets/manta-pay/src/types.rs index 5346ff010..23bb85daf 100644 --- a/pallets/manta-pay/src/types.rs +++ b/pallets/manta-pay/src/types.rs @@ -86,7 +86,7 @@ pub type Proof = [u8; PROOF_LENGTH]; )] pub struct Asset { /// Asset Id - pub id: AssetId, + pub id: StandardAssetId, /// Asset Value pub value: Balance, @@ -95,7 +95,7 @@ pub struct Asset { impl Asset { /// Builds a new [`Asset`] from `id` and `value`. #[inline] - pub fn new(id: AssetId, value: Balance) -> Self { + pub fn new(id: StandardAssetId, value: Balance) -> Self { Self { id, value } } } @@ -225,7 +225,7 @@ impl TryFrom for config::ReceiverPost { #[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] pub struct TransferPost { /// Asset Id - pub asset_id: Option, + pub asset_id: Option, /// Sources pub sources: Vec, diff --git a/primitives/manta/Cargo.toml b/primitives/manta/Cargo.toml index 9324378c5..8d23aede2 100644 --- a/primitives/manta/Cargo.toml +++ b/primitives/manta/Cargo.toml @@ -16,9 +16,6 @@ log = "0.4.16" scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } smallvec = "1.8.0" -# manta-rs dependencies -manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.4", default-features = false } - # Substrate primitives frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.26", default-features = false, optional = true } frame-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.26" } @@ -44,7 +41,6 @@ std = [ 'scale-info/std', 'sp-io/std', 'sp-std/std', - 'manta-accounting/std', 'log/std', 'frame-support/std', 'frame-system/std', diff --git a/primitives/manta/src/assets.rs b/primitives/manta/src/assets.rs index ae55c6d15..a510a230a 100644 --- a/primitives/manta/src/assets.rs +++ b/primitives/manta/src/assets.rs @@ -14,49 +14,83 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -///! Manta/Calamari/Dolphin Asset -use crate::{ - constants::DEFAULT_ASSET_ED, - types::{AssetId, Balance}, -}; -use codec::{Codec, Decode, Encode}; +//! Asset Utilities +use crate::{constants::TEST_DEFAULT_ASSET_ED, types::Balance as MantaBalance}; +use alloc::vec::Vec; +use codec::{Decode, Encode}; +use core::{borrow::Borrow, marker::PhantomData}; use frame_support::{ + dispatch::DispatchError, pallet_prelude::Get, traits::tokens::{ currency::Currency, - fungible::Inspect as FungibleInspect, - fungibles::{Inspect as FungiblesInspect, Mutate, Transfer}, + fungible, + fungibles::{self, Mutate, Transfer}, DepositConsequence, ExistenceRequirement, WithdrawReasons, }, Parameter, }; +use frame_system::Config; use scale_info::TypeInfo; -use sp_core::H160; -use sp_runtime::{traits::Member, DispatchError, DispatchResult}; -use sp_std::{borrow::Borrow, marker::PhantomData, prelude::Vec}; use xcm::{ v1::{Junctions, MultiLocation}, VersionedMultiLocation, }; +use xcm_executor::traits::Convert; + +/// Asset Id +pub trait AssetIdType { + /// Asset Id Type + type AssetId; +} + +/// Asset Id Type +pub type AssetId = ::AssetId; + +/// Balance +pub trait BalanceType { + /// Balance Type + type Balance; +} + +/// Balance Type +pub type Balance = ::Balance; + +/// Location +pub trait LocationType { + /// Location Type + type Location; +} + +/// Location Type +pub type Location = ::Location; -/// The minimal interface of asset metadata -pub trait AssetMetadata { - /// Returns the minimum balance to hold this asset - fn min_balance(&self) -> Balance; +/// Asset Metadata +pub trait AssetMetadata: BalanceType { + /// Returns the minimum balance to hold this asset. + fn min_balance(&self) -> &Self::Balance; - /// Returns a boolean value indicating whether this asset needs an existential deposit + /// Returns a boolean value indicating whether this asset needs an existential deposit. fn is_sufficient(&self) -> bool; } -/// The registrar trait: defines the interface of creating an asset in the asset implementation +/// Asset Registry +/// +/// The registry trait: defines the interface of creating an asset in the asset implementation /// layer. We may revisit this interface design (e.g. add change asset interface). However, change /// in StorageMetadata should be rare. -pub trait AssetRegistrar> { - /// Create an new asset. +pub trait AssetRegistry: AssetIdType + BalanceType { + /// Metadata Type + type Metadata; + + /// Error Type + type Error; + + /// Creates an new asset. /// /// * `asset_id`: the asset id to be created - /// * `min_balance`: the minimum balance to hold this asset /// * `metadata`: the metadata that the implementation layer stores + /// * `min_balance`: the minimum balance to hold this asset /// * `is_sufficient`: whether this asset can be used as reserve asset, /// to the first approximation. More specifically, Whether a non-zero balance of this asset /// is deposit of sufficient value to account for the state bloat associated with its @@ -64,128 +98,155 @@ pub trait AssetRegistrar> { /// `consumer` reference (and thus an ED in the Balances pallet or whatever else is used to /// control user-account state growth). fn create_asset( - asset_id: AssetId, - min_balance: Balance, - metadata: T::StorageMetadata, + asset_id: Self::AssetId, + metadata: Self::Metadata, + min_balance: Self::Balance, is_sufficient: bool, - ) -> DispatchResult; + ) -> Result<(), Self::Error>; /// Update asset metadata by `AssetId`. /// /// * `asset_id`: the asset id to be created. /// * `metadata`: the metadata that the implementation layer stores. - fn update_asset_metadata(asset_id: AssetId, metadata: T::StorageMetadata) -> DispatchResult; + fn update_asset_metadata( + asset_id: &Self::AssetId, + metadata: Self::Metadata, + ) -> Result<(), Self::Error>; } -pub trait AssetConfig: 'static + Eq + Clone +/// Asset Configuration +pub trait AssetConfig: AssetIdType + BalanceType + LocationType where - C: frame_system::Config, + C: Config, { + /// Metadata type that required in token storage: e.g. AssetMetadata in Pallet-Assets. + type StorageMetadata: From; + + /// The Asset Metadata type stored in this pallet. + type AssetRegistryMetadata: AssetMetadata + Parameter + TestingDefault; + /// The AssetId that the non-native asset starts from. + /// /// A typical configuration is 8, so that asset 0 - 7 is reserved. - type StartNonNativeAssetId: Get; - - /// Dummy Asset ID, a typical configuration is 0. - type DummyAssetId: Get; + type StartNonNativeAssetId: Get; /// The Native Asset Id, a typical configuration is 1. - type NativeAssetId: Get; + type NativeAssetId: Get; /// Native Asset Location - type NativeAssetLocation: Get; + type NativeAssetLocation: Get; /// Native Asset Metadata - type NativeAssetMetadata: Get; - - /// The trait we use to register Assets and mint assets - type AssetRegistrar: AssetRegistrar; - - /// Metadata type that required in token storage: e.g. AssetMetadata in Pallet-Assets. - type StorageMetadata: Member + Parameter + Default + From; + type NativeAssetMetadata: Get; - /// The Asset Metadata type stored in this pallet. - type AssetRegistrarMetadata: Member + Parameter + Codec + Default + AssetMetadata; - - /// The AssetLocation type: could be just a thin wrapper of MultiLocation - type AssetLocation: Member - + Parameter - + Default - + TypeInfo - + From - + Into>; - - /// The Fungible ledger implementation of this trait - type FungibleLedger: FungibleLedger; + /// Asset Registry + /// + /// The trait we use to register Assets and mint assets. + type AssetRegistry: AssetRegistry< + AssetId = Self::AssetId, + Balance = Self::Balance, + Metadata = Self::StorageMetadata, + Error = DispatchError, + >; + + /// Fungible Ledger + type FungibleLedger: FungibleLedger< + AccountId = C::AccountId, + AssetId = Self::AssetId, + Balance = Self::Balance, + >; } -/// The metadata of a Manta Asset -#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] -pub struct AssetRegistrarMetadata { +/// Asset Storage Metadata +#[derive(Clone, Debug, Decode, Encode, Eq, Hash, Ord, PartialEq, PartialOrd, TypeInfo)] +pub struct AssetStorageMetadata { + /// Asset Name pub name: Vec, + + /// Asset Symbol pub symbol: Vec, + + /// Number of Decimals pub decimals: u8, - pub evm_address: Option, + + /// Frozen Flag + /// + /// Whether or not transfers of the asset are allowed. pub is_frozen: bool, - pub min_balance: Balance, - /// `is_sufficient`: Whether a non-zero balance of this asset is deposit of sufficient - /// value to account for the state bloat associated with its balance storage. If set to - /// `true`, then non-zero balances may be stored without a `consumer` reference (and thus - /// an ED in the Balances pallet or whatever else is used to control user-account state - /// growth). - /// For example, if is_sufficient set to `false`, a fresh account cannot receive XCM tokens. +} + +impl From> for AssetStorageMetadata { + #[inline] + fn from(source: AssetRegistryMetadata) -> Self { + source.metadata + } +} + +/// Asset Registry Metadata +#[derive(Clone, Debug, Decode, Encode, Eq, Hash, Ord, PartialEq, PartialOrd, TypeInfo)] +pub struct AssetRegistryMetadata { + /// Asset Storage Metadata + pub metadata: AssetStorageMetadata, + + /// Minimum Balance + pub min_balance: B, + + /// Sufficiency Flag + /// + /// This flag should be set to `true` whenever a non-zero balance of this asset is deposit of + /// sufficient value to account for the state bloat associated with its balance storage. If set + /// to `true`, then non-zero balances may be stored without a `consumer` reference (and thus an + /// existential deposit in the balances pallet or whatever else is used to control user-account + /// state growth). + /// + /// If this flag is set to `false`, a fresh account cannot receive XCM tokens. pub is_sufficient: bool, } -impl Default for AssetRegistrarMetadata { - fn default() -> Self { +/// Because there is no obvious defaults for an asset's metadata, we explicitly +/// name a trait to carry this logic for testing and benchmarking +pub trait TestingDefault { + /// Returns some default asset metadata + fn testing_default() -> Self; +} + +impl TestingDefault for AssetRegistryMetadata { + fn testing_default() -> Self { Self { - name: b"Dolphin".to_vec(), - symbol: b"DOL".to_vec(), - decimals: 12, - evm_address: None, - is_frozen: false, - min_balance: DEFAULT_ASSET_ED, + metadata: AssetStorageMetadata { + name: b"Default".to_vec(), + symbol: b"DEF".to_vec(), + decimals: 12, + is_frozen: false, + }, + min_balance: TEST_DEFAULT_ASSET_ED, is_sufficient: true, } } } -impl AssetMetadata for AssetRegistrarMetadata { - fn min_balance(&self) -> Balance { - self.min_balance +impl BalanceType for AssetRegistryMetadata { + type Balance = B; +} + +impl AssetMetadata for AssetRegistryMetadata { + #[inline] + fn min_balance(&self) -> &B { + &self.min_balance } + #[inline] fn is_sufficient(&self) -> bool { self.is_sufficient } } -/// Asset storage metadata -/// Currently, `AssetStorageMetadata` is stored at `pallet-asset`. -#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] -pub struct AssetStorageMetadata { - pub name: Vec, - pub symbol: Vec, - pub decimals: u8, - pub is_frozen: bool, -} - -impl From for AssetStorageMetadata { - fn from(source: AssetRegistrarMetadata) -> Self { - Self { - name: source.name, - symbol: source.symbol, - decimals: source.decimals, - is_frozen: source.is_frozen, - } - } -} - /// Asset Location -#[derive(Clone, Eq, Debug, PartialEq, Encode, Decode, TypeInfo)] +#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] pub struct AssetLocation(pub VersionedMultiLocation); impl Default for AssetLocation { + #[inline] fn default() -> Self { Self(VersionedMultiLocation::V1(MultiLocation { parents: 0, @@ -201,6 +262,7 @@ impl From for AssetLocation { /// /// This method does not guarantee that the output [`AssetLocation`] is registered, i.e. has a /// valid [`AssetId`]. + #[inline] fn from(location: MultiLocation) -> Self { AssetLocation(VersionedMultiLocation::V1(location)) } @@ -209,6 +271,7 @@ impl From for AssetLocation { impl From for Option { /// Converts an [`AssetLocation`] into an optional [`MultiLocation`], returning `None` if it /// represents a native asset. + #[inline] fn from(location: AssetLocation) -> Self { match location { AssetLocation(VersionedMultiLocation::V1(location)) => Some(location), @@ -217,52 +280,52 @@ impl From for Option { } } -/// Defines the trait to obtain a generic AssetId -pub trait AssetIdLocationGetter { - /// Gets the [`AssetLocation`] from [`AssetId`]. - fn get_asset_location(asset_id: AssetId) -> Option; +/// +pub trait AssetIdLocationMap: AssetIdType + LocationType { + /// Returns the [`Location`](LocationType::Location) of `asset_id`. + fn location(asset_id: &Self::AssetId) -> Option; - /// Gets the [`AssetId`] from [`AssetLocation`]. - fn get_asset_id(loc: &AssetLocation) -> Option; + /// Returns the [`AssetId`](AssetIdType::AssetId) located at `location`. + fn asset_id(location: &Self::Location) -> Option; } /// Defines the units per second charged given an `AssetId`. -pub trait UnitsToWeightRatio { - /// Get units per second from asset id - fn get_units_per_second(asset_id: AssetId) -> Option; +pub trait UnitsPerSecond: AssetIdType { + /// Returns the units per second for `asset_id`. + fn units_per_second(asset_id: &Self::AssetId) -> Option; } -/// Converter struct implementing `Convert`. -/// This enforce the `AssetInfoGetter` implements `AssetIdLocationGetter` -pub struct AssetIdLocationConvert( - PhantomData<(AssetLocation, AssetInfoGetter)>, -); -impl xcm_executor::traits::Convert - for AssetIdLocationConvert +/// Converter struct implementing `Convert`. MultiLocation to AssetId and the reverse. +pub struct AssetIdLocationConvert(PhantomData); + +impl Convert for AssetIdLocationConvert where - AssetLocation: From + Into> + Clone, - AssetInfoGetter: AssetIdLocationGetter, + M: AssetIdLocationMap, + M::AssetId: Clone, + M::Location: Clone + From + Into>, { - fn convert_ref(loc: impl Borrow) -> Result { - AssetInfoGetter::get_asset_id(&loc.borrow().clone().into()).ok_or(()) + #[inline] + fn convert_ref(location: impl Borrow) -> Result { + M::asset_id(&location.borrow().clone().into()).ok_or(()) } - fn reverse_ref(id: impl Borrow) -> Result { - AssetInfoGetter::get_asset_location(*id.borrow()) + #[inline] + fn reverse_ref(asset_id: impl Borrow) -> Result { + M::location(asset_id.borrow()) .and_then(Into::into) .ok_or(()) } } /// Fungible Ledger Error -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum FungibleLedgerError { +#[derive(Clone, Copy, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] +pub enum FungibleLedgerError { /// Invalid Asset Id - InvalidAssetId, + InvalidAssetId(I), - /// Deposit couldn't happen due to the amount being too low. This is usually because the - /// account doesn't yet exist and the deposit wouldn't bring it to at least the minimum needed - /// for existence. + /// Deposit couldn't happen due to the amount being too low. This is usually because the account + /// doesn't yet exist and the deposit wouldn't bring it to at least the minimum needed for + /// existence. BelowMinimum, /// Deposit cannot happen since the account cannot be created (usually because it's a consumer @@ -279,7 +342,7 @@ pub enum FungibleLedgerError { Overflow, /// Cannot withdraw more than the specified amount - CannotWithdrawMoreThan(Balance), + CannotWithdrawMoreThan(B), /// Unable to Mint an Asset InvalidMint(DispatchError), @@ -291,7 +354,7 @@ pub enum FungibleLedgerError { InvalidTransfer(DispatchError), } -impl FungibleLedgerError { +impl FungibleLedgerError { /// Converts a deposit `consequence` into a [`FungibleLedgerError`] or into `Ok(())` when the /// value of `consequence` is [`Success`](DepositConsequence::Success). #[inline] @@ -306,151 +369,183 @@ impl FungibleLedgerError { } } +impl AssetIdType for FungibleLedgerError { + type AssetId = I; +} + +impl BalanceType for FungibleLedgerError { + type Balance = B; +} + /// Unified Interface for Fungible Assets /// /// This trait unifies the interface for the [`fungible`] and [`fungibles`] modules. /// -/// [`fungible`]: frame_support::traits::tokens::fungible -/// [`fungibles`]: frame_support::traits::tokens::fungibles -/// -/// It is assumed that the supply of native asset cannot be changed, -/// while the supply of non-native assets can increase or decrease. -pub trait FungibleLedger -where - C: frame_system::Config, -{ +/// It is assumed that the supply of native asset cannot be changed, while the supply of non-native +/// assets can increase or decrease. +pub trait FungibleLedger: AssetIdType + BalanceType { + /// Account Id Type + type AccountId; + /// Checks if an asset id is valid and returning and [`Error`](FungibleLedgerError) otherwise. - fn ensure_valid(asset_id: AssetId) -> Result<(), FungibleLedgerError>; + fn ensure_valid( + asset_id: Self::AssetId, + ) -> Result>; /// Check whether `account` can increase its balance by `amount` in the given `asset_id`. - /// Non-native assets will use the `can_increase_total_supply` check, while native assets will not. fn can_deposit( - asset_id: AssetId, - account: &C::AccountId, - amount: Balance, + asset_id: Self::AssetId, + account: &Self::AccountId, + amount: Self::Balance, can_increase_total_supply: bool, - ) -> Result<(), FungibleLedgerError>; - - /// Check whether `account` can decrease its balance by `amount` in the given `asset_id`. - fn can_reduce_by_amount( - asset_id: AssetId, - account: &C::AccountId, - amount: Balance, - existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError>; - - /// Deposit `amount` of an asset with the given `asset_id` to `beneficiary`. - /// Will mint and increase the total supply of non-native assets. - fn deposit_can_mint( - asset_id: AssetId, - beneficiary: &C::AccountId, - amount: Balance, - ) -> Result<(), FungibleLedgerError>; + ) -> Result>; + + /// Deposit `amount` of an asset with the given `asset_id` to `account`. + fn deposit_minting( + asset_id: Self::AssetId, + account: &Self::AccountId, + amount: Self::Balance, + ) -> Result<(), FungibleLedgerError>; + + /// Checks if `amount` of `asset_id` can be deposited into `account` and then deposits it if + /// that is successful. + fn deposit_minting_with_check( + asset_id: Self::AssetId, + account: &Self::AccountId, + amount: Self::Balance, + can_increase_total_supply: bool, + ) -> Result<(), FungibleLedgerError>; /// Performs a transfer from `source` to `destination` of fn transfer( - asset_id: AssetId, - source: &C::AccountId, - destination: &C::AccountId, - amount: Balance, + asset_id: Self::AssetId, + source: &Self::AccountId, + destination: &Self::AccountId, + amount: Self::Balance, existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError>; + ) -> Result<(), FungibleLedgerError>; + + /// Check whether `account` can decrease its balance by `amount` in the given `asset_id`. + fn can_withdraw( + asset_id: Self::AssetId, + account: &Self::AccountId, + amount: &Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> Result>; /// Performs a withdraw from `who` for `amount` of `asset_id` - /// Will burn and decrease total supply of non-native assets - fn withdraw_can_burn( - asset_id: AssetId, - who: &C::AccountId, - amount: Balance, + fn withdraw_burning( + asset_id: Self::AssetId, + who: &Self::AccountId, + amount: Self::Balance, existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError>; + ) -> Result<(), FungibleLedgerError>; } -/// Concrete Fungible Ledger Implementation -pub struct ConcreteFungibleLedger { +/// Fungible Ledger Implementation for Native and NonNative Assets +/// +/// The `Native` assets are defined by an implementation of a [`fungible`] asset and the `NonNative` +/// by a set of fungible assets using [`fungibles`]. +pub struct NativeAndNonNative { /// Type Parameter Marker __: PhantomData<(C, A, Native, NonNative)>, } -impl FungibleLedger for ConcreteFungibleLedger +impl AssetIdType for NativeAndNonNative where - C: frame_system::Config, + C: Config, A: AssetConfig, - Native: FungibleInspect - + Currency, - NonNative: FungiblesInspect - + Mutate - + Transfer, { + type AssetId = A::AssetId; +} + +impl BalanceType for NativeAndNonNative +where + C: Config, + A: AssetConfig, +{ + type Balance = A::Balance; +} + +impl FungibleLedger for NativeAndNonNative +where + C: Config, + A: AssetConfig, + A::AssetId: Clone + PartialOrd, + A::Balance: Clone + PartialOrd, + Native: fungible::Inspect + + Currency, + NonNative: fungibles::Inspect + + Mutate + + Transfer, +{ + type AccountId = C::AccountId; + #[inline] - fn ensure_valid(asset_id: AssetId) -> Result<(), FungibleLedgerError> { + fn ensure_valid( + asset_id: Self::AssetId, + ) -> Result> { if asset_id >= A::StartNonNativeAssetId::get() || asset_id == A::NativeAssetId::get() { - Ok(()) + Ok(asset_id) } else { - Err(FungibleLedgerError::InvalidAssetId) + Err(FungibleLedgerError::InvalidAssetId(asset_id)) } } + /// Non-native assets will use the `can_increase_total_supply` flag, while native assets will + /// not. #[inline] fn can_deposit( - asset_id: AssetId, + asset_id: Self::AssetId, account: &C::AccountId, - amount: Balance, + amount: Self::Balance, can_increase_total_supply: bool, - ) -> Result<(), FungibleLedgerError> { - Self::ensure_valid(asset_id)?; + ) -> Result> { + let asset_id = Self::ensure_valid(asset_id)?; FungibleLedgerError::from_deposit(if asset_id == A::NativeAssetId::get() { - >::can_deposit(account, amount, false) + Native::can_deposit(account, amount, false) } else { - >::can_deposit( - asset_id, - account, - amount, - can_increase_total_supply, - ) + NonNative::can_deposit(asset_id.clone(), account, amount, can_increase_total_supply) }) + .map(|_| asset_id) } + /// Will mint and increase the total supply of non-native assets. #[inline] - fn can_reduce_by_amount( - asset_id: AssetId, + fn deposit_minting( + asset_id: Self::AssetId, account: &C::AccountId, - amount: Balance, - existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError> { - Self::ensure_valid(asset_id)?; - - let keep_alive = match existence_requirement { - ExistenceRequirement::KeepAlive => true, - ExistenceRequirement::AllowDeath => false, - }; - let reducible_amount = if asset_id == A::NativeAssetId::get() { - >::reducible_balance(account, keep_alive) + amount: Self::Balance, + ) -> Result<(), FungibleLedgerError> { + let asset_id = Self::ensure_valid(asset_id)?; + if asset_id == A::NativeAssetId::get() { + Native::deposit_creating(account, amount); } else { - >::reducible_balance( - asset_id, account, keep_alive, - ) - }; - - if reducible_amount >= amount { - return Ok(()); + NonNative::mint_into(asset_id, account, amount) + .map_err(FungibleLedgerError::InvalidMint)?; } - Err(FungibleLedgerError::CannotWithdrawMoreThan( - reducible_amount, - )) + Ok(()) } #[inline] - fn deposit_can_mint( - asset_id: AssetId, - beneficiary: &C::AccountId, - amount: Balance, - ) -> Result<(), FungibleLedgerError> { - Self::ensure_valid(asset_id)?; + fn deposit_minting_with_check( + asset_id: Self::AssetId, + account: &Self::AccountId, + amount: Self::Balance, + can_increase_total_supply: bool, + ) -> Result<(), FungibleLedgerError> { + let asset_id = Self::ensure_valid(asset_id)?; if asset_id == A::NativeAssetId::get() { - >::deposit_creating(beneficiary, amount); + FungibleLedgerError::from_deposit(Native::can_deposit(account, amount.clone(), false))?; + Native::deposit_creating(account, amount); } else { - >::mint_into(asset_id, beneficiary, amount) + FungibleLedgerError::from_deposit(NonNative::can_deposit( + asset_id.clone(), + account, + amount.clone(), + can_increase_total_supply, + ))?; + NonNative::mint_into(asset_id, account, amount) .map_err(FungibleLedgerError::InvalidMint)?; } Ok(()) @@ -458,31 +553,25 @@ where #[inline] fn transfer( - asset_id: AssetId, + asset_id: Self::AssetId, source: &C::AccountId, destination: &C::AccountId, - amount: Balance, + amount: Self::Balance, existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError> { - Self::ensure_valid(asset_id)?; + ) -> Result<(), FungibleLedgerError> { + let asset_id = Self::ensure_valid(asset_id)?; if asset_id == A::NativeAssetId::get() { - >::transfer( - source, - destination, - amount, - existence_requirement, - ) + Native::transfer(source, destination, amount, existence_requirement) } else { - let keep_alive = match existence_requirement { - ExistenceRequirement::KeepAlive => true, - ExistenceRequirement::AllowDeath => false, - }; - >::transfer( + NonNative::transfer( asset_id, source, destination, amount, - keep_alive, + match existence_requirement { + ExistenceRequirement::KeepAlive => true, + ExistenceRequirement::AllowDeath => false, + }, ) .map(|_| ()) } @@ -490,16 +579,46 @@ where } #[inline] - fn withdraw_can_burn( - asset_id: AssetId, + fn can_withdraw( + asset_id: Self::AssetId, + account: &C::AccountId, + amount: &Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> Result> { + let asset_id = Self::ensure_valid(asset_id)?; + let keep_alive = match existence_requirement { + ExistenceRequirement::KeepAlive => true, + ExistenceRequirement::AllowDeath => false, + }; + let reducible_amount = if asset_id == A::NativeAssetId::get() { + Native::reducible_balance(account, keep_alive) + } else { + NonNative::reducible_balance(asset_id.clone(), account, keep_alive) + }; + if reducible_amount >= *amount { + return Ok(asset_id); + } + Err(FungibleLedgerError::CannotWithdrawMoreThan( + reducible_amount, + )) + } + + /// Will burn and decrease total supply of non-native assets. + #[inline] + fn withdraw_burning( + asset_id: Self::AssetId, who: &C::AccountId, - amount: Balance, + amount: Self::Balance, existence_requirement: ExistenceRequirement, - ) -> Result<(), FungibleLedgerError> { - Self::ensure_valid(asset_id)?; - Self::can_reduce_by_amount(asset_id, who, amount, existence_requirement)?; + ) -> Result<(), FungibleLedgerError> { + let asset_id = Self::can_withdraw( + Self::ensure_valid(asset_id)?, + who, + &amount, + existence_requirement, + )?; if asset_id == A::NativeAssetId::get() { - >::withdraw( + Native::withdraw( who, amount, WithdrawReasons::TRANSFER, @@ -507,9 +626,10 @@ where ) .map_err(FungibleLedgerError::InvalidBurn)?; } else { - // `existence_requirement` is used in the `can_reduce_by_amount` checks, - // so it doesn't matter that `burn_from` uses `allow_death` by default in our chosen implementation - >::burn_from(asset_id, who, amount) + // NOTE: The `existence_requirement` is used in the `can_reduce_by_amount` checks, + // so it doesn't matter that `burn_from` uses `allow_death` by default in this + // implementation. + NonNative::burn_from(asset_id, who, amount) .map_err(FungibleLedgerError::InvalidBurn)?; } Ok(()) diff --git a/primitives/manta/src/constants.rs b/primitives/manta/src/constants.rs index 881c06e1c..f4d4fc331 100644 --- a/primitives/manta/src/constants.rs +++ b/primitives/manta/src/constants.rs @@ -14,49 +14,85 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . +//! Manta Protocol Constants + use crate::types::Balance; use frame_support::PalletId; -// Calamari constants +/// Calamari SS58 Prefix pub const CALAMARI_SS58PREFIX: u8 = 78; + +/// Calamari Decimals pub const CALAMARI_DECIMAL: u8 = 12; + +/// Calamari Token Symbol pub const CALAMARI_TOKEN_SYMBOL: &str = "KMA"; -// Manta constants +/// Manta SS58 Prefix pub const MANTA_SS58PREFIX: u8 = 77; + +/// Manta Decimals pub const MANTA_DECIMAL: u8 = 18; + +/// Manta Token Symbol pub const MANTA_TOKEN_SYMBOL: &str = "MANTA"; -// Dolphin constants +/// Dolphin Decimals pub const DOLPHIN_DECIMAL: u8 = 18; + +/// Dolphin Token Symbol pub const DOLPHIN_TOKEN_SYMBOL: &str = "DOL"; /// Manta parachain time-related pub mod time { use crate::types::{BlockNumber, Moment}; + + /// Seconds per Block + /// + /// This constant is currently set to 12 seconds. + /// /// This determines the average expected block time that we are targeting. Blocks will be - /// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by - /// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn - /// slot_duration()`. + /// produced at a minimum duration defined by [`SLOT_DURATION`]. [`SLOT_DURATION`] is picked up + /// by [`pallet_timestamp`] which is in turn picked up by [`pallet_aura`] to implement the + /// `slot_duration` function. /// /// Change this to adjust the block time. pub const SECONDS_PER_BLOCK: Moment = 12; + + /// Milliseconds per Block pub const MILLISECS_PER_BLOCK: Moment = SECONDS_PER_BLOCK * 1000; + + /// Slot Duration pub const SLOT_DURATION: Moment = MILLISECS_PER_BLOCK; - // Time is measured by number of blocks. + /// Number of Blocks per Minute pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + + /// Number of Blocks per Hour pub const HOURS: BlockNumber = MINUTES * 60; + + /// Number of Blocks per Day pub const DAYS: BlockNumber = HOURS * 24; } +/// Asset String Limit pub const ASSET_STRING_LIMIT: u32 = 50; -// Identifiers of pallets +/// Staking Pallet Identifier pub const STAKING_PALLET_ID: PalletId = PalletId(*b"PotStake"); + +/// Treasury Pallet Identifier pub const TREASURY_PALLET_ID: PalletId = PalletId(*b"py/trsry"); + +/// Asset Manager Pallet Identifier pub const ASSET_MANAGER_PALLET_ID: PalletId = PalletId(*b"asstmngr"); + +/// Manta Pay Pallet Identifier pub const MANTA_PAY_PALLET_ID: PalletId = PalletId(*b"mantapay"); -/// Default Asset Existential Deposit: Should only be used in TEST -pub const DEFAULT_ASSET_ED: Balance = 1; +/// Test Default Asset Existential Deposit +/// +/// # Warning +/// +/// This should only be used for testing and should not be used in production. +pub const TEST_DEFAULT_ASSET_ED: Balance = 1; diff --git a/primitives/manta/src/lib.rs b/primitives/manta/src/lib.rs index 7ac86c79c..90c1f8b73 100644 --- a/primitives/manta/src/lib.rs +++ b/primitives/manta/src/lib.rs @@ -14,10 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -#![allow(non_upper_case_globals)] -#![allow(clippy::unnecessary_cast)] -#![allow(clippy::upper_case_acronyms)] +//! Manta Primitives + #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![forbid(rustdoc::broken_intra_doc_links)] +#![forbid(missing_docs)] + +extern crate alloc; pub mod assets; pub mod constants; diff --git a/primitives/manta/src/types.rs b/primitives/manta/src/types.rs index dd28805f3..973236ead 100644 --- a/primitives/manta/src/types.rs +++ b/primitives/manta/src/types.rs @@ -14,42 +14,56 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -use sp_runtime::traits::{BlakeTwo256, IdentifyAccount, Verify}; +//! Types -pub use manta_accounting::asset::{AssetIdType, AssetValueType}; +use sp_core::H256; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, OpaqueExtrinsic, +}; -/// An index to a block. +/// Block Number Type pub type BlockNumber = u32; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = sp_runtime::MultiSignature; +pub type Signature = MultiSignature; + +/// Signer Type +pub type Signer = ::Signer; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type AccountId = ::AccountId; -/// The type for looking up accounts. We don't expect more than 4 billion of them, but you -/// never know... +/// Account Index Type +/// +/// This index is used to look up accounts. pub type AccountIndex = u32; -/// Balance of an account. -pub type Balance = AssetValueType; +/// Calamari Asset Id Type +pub type CalamariAssetId = u128; + +/// Dolphin Asset Id Type +pub type DolphinAssetId = u32; + +/// Balance of an Account +pub type Balance = u128; -/// Index of a transaction in the chain. +/// Transaction Index Type pub type Index = u32; /// A hash of some data used by the chain. -pub type Hash = sp_core::H256; +pub type Hash = H256; -/// Block header type as expected by this runtime. -pub type Header = sp_runtime::generic::Header; -pub type Block = sp_runtime::generic::Block; +/// Block Header Type +pub type Header = generic::Header; -/// Digest item type. -pub type DigestItem = sp_runtime::generic::DigestItem; +/// Block Type +pub type Block = generic::Block; -// Moment -pub type Moment = u64; +/// Digest Item Type +pub type DigestItem = generic::DigestItem; -// AssetId -pub type AssetId = AssetIdType; +/// Moment Type +pub type Moment = u64; diff --git a/primitives/manta/src/xcm.rs b/primitives/manta/src/xcm.rs index 97fb89083..43bb4c9f2 100644 --- a/primitives/manta/src/xcm.rs +++ b/primitives/manta/src/xcm.rs @@ -14,50 +14,54 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -use super::{ - assets::{AssetConfig, FungibleLedger}, - types::{AssetId, Balance}, -}; +//! XCM primitives and implementations + +use super::assets::{AssetConfig, FungibleLedger}; use sp_runtime::traits::{CheckedConversion, Convert, Zero}; -use sp_std::{marker::PhantomData, result}; +use sp_std::marker::PhantomData; +use crate::assets::{AssetIdLocationMap, UnitsPerSecond}; use frame_support::{ pallet_prelude::Get, traits::{fungibles::Mutate, tokens::ExistenceRequirement}, weights::{constants::WEIGHT_PER_SECOND, Weight}, }; - -use crate::assets::{AssetIdLocationGetter, UnitsToWeightRatio}; +use frame_system::Config; use xcm::{ - latest::{prelude::Concrete, Error as XcmError, Result as XcmResult}, + latest::{prelude::Concrete, Error as XcmError}, v1::{ - AssetId as xcmAssetId, Fungibility, - Fungibility::*, + AssetId as XcmAssetId, Fungibility, Junction::{AccountId32, Parachain}, - Junctions::*, + Junctions::X1, MultiAsset, MultiLocation, NetworkId, }, }; use xcm_builder::TakeRevenue; -use xcm_executor::traits::{ - Convert as XcmConvert, FilterAssetLocation, MatchesFungible, MatchesFungibles, TransactAsset, - WeightTrader, +use xcm_executor::{ + traits::{ + Convert as XcmConvert, FilterAssetLocation, MatchesFungible, MatchesFungibles, + TransactAsset, WeightTrader, + }, + Assets, }; +/// XCM Result +pub type Result = core::result::Result; + +/// Reserve Location pub trait Reserve { - /// Returns assets reserve location. + /// Returns the reserve location for `self`. fn reserve(&self) -> Option; } -// Takes the chain part of a MultiAsset impl Reserve for MultiAsset { + /// Returns the chain part of a concrete location `self`, returning `None` if `self` has more + /// than one parent or `self` is not concrete. + #[inline] fn reserve(&self) -> Option { - // We only care about concrete location now. - if let xcmAssetId::Concrete(location) = self.id.clone() { - let first_interior = location.first_interior(); - let parents = location.parent_count(); - match (parents, first_interior) { + if let XcmAssetId::Concrete(location) = &self.id { + match (location.parent_count(), location.first_interior()) { (0, Some(Parachain(id))) => Some(MultiLocation::new(0, X1(Parachain(*id)))), (1, Some(Parachain(id))) => Some(MultiLocation::new(1, X1(Parachain(*id)))), (1, _) => Some(MultiLocation::parent()), @@ -69,21 +73,27 @@ impl Reserve for MultiAsset { } } -/// A `FilterAssetLocation` implementation. Filters multi native assets whose -/// reserve is same with `origin`. +/// Multi-Native Asset Filter +/// +/// Filters multi-native assets whose reserve is same as the `origin`. pub struct MultiNativeAsset; + impl FilterAssetLocation for MultiNativeAsset { + #[inline] fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { asset.reserve().map(|r| r == *origin).unwrap_or(false) } } -pub struct AccountIdToMultiLocation(PhantomData); -impl Convert for AccountIdToMultiLocation +/// AccountId to [`MultiLocation`] Converter +pub struct AccountIdToMultiLocation; + +impl Convert for AccountIdToMultiLocation where - AccountId: Into<[u8; 32]> + Clone, + A: Into<[u8; 32]>, { - fn convert(account: AccountId) -> MultiLocation { + #[inline] + fn convert(account: A) -> MultiLocation { MultiLocation { parents: 0, interior: X1(AccountId32 { @@ -94,41 +104,43 @@ where } } -// This trader defines how to charge a XCM call. -// This takes the first fungible asset, and takes UnitPerSecondGetter that implements -// UnitToWeightRatio trait. -pub struct FirstAssetTrader< - AssetId: Clone, - AssetLocation: From + Clone, - AssetIdInfoGetter: UnitsToWeightRatio + AssetIdLocationGetter, +/// +/// This trader defines how to charge a XCM call. +/// This takes the first fungible asset, and takes UnitPerSecondGetter that implements +/// UnitToWeightRatio trait. +pub struct FirstAssetTrader +where R: TakeRevenue, -> { +{ + /// Weight weight: Weight, + + /// Refund Cache refund_cache: Option<(MultiLocation, u128, u128)>, - __: sp_std::marker::PhantomData<(AssetId, AssetLocation, AssetIdInfoGetter, R)>, + + /// Type Parameter Marker + __: PhantomData<(M, R)>, } -impl< - AssetId: Clone, - AssetLocation: From + Clone, - AssetIdInfoGetter: UnitsToWeightRatio + AssetIdLocationGetter, - R: TakeRevenue, - > WeightTrader for FirstAssetTrader +impl WeightTrader for FirstAssetTrader +where + M: AssetIdLocationMap + UnitsPerSecond, + M::Location: From, + R: TakeRevenue, { + #[inline] fn new() -> Self { - FirstAssetTrader { + Self { weight: Zero::zero(), refund_cache: None, - __: sp_std::marker::PhantomData, + __: PhantomData, } } - /// buy weight for XCM execution. We always return `TooExpensive` error if this fails. - fn buy_weight( - &mut self, - weight: Weight, - payment: xcm_executor::Assets, - ) -> Result { + /// Buys weight for XCM execution. We always return the [`TooExpensive`](Error::TooExpensive) + /// error if this fails. + #[inline] + fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { log::debug!( target: "FirstAssetTrader::buy_weight", "weight: {:?}, payment: {:?}", @@ -147,27 +159,23 @@ impl< // Check the first asset match (first_asset.id, first_asset.fun) { - (xcmAssetId::Concrete(id), Fungibility::Fungible(_)) => { - let asset_loc: AssetLocation = id.clone().into(); - - let asset_id = AssetIdInfoGetter::get_asset_id(&asset_loc).ok_or({ + (XcmAssetId::Concrete(id), Fungibility::Fungible(_)) => { + let asset_id = M::asset_id(&id.clone().into()).ok_or({ log::debug!( target: "FirstAssetTrader::buy_weight", - "asset_id missing for asset_loc with id: {:?}", + "asset_id missing for asset location with id: {:?}", + id, + ); + XcmError::TooExpensive + })?; + let units_per_second = M::units_per_second(&asset_id).ok_or({ + log::debug!( + target: "FirstAssetTrader::buy_weight", + "units_per_second missing for asset with id: {:?}", id, ); XcmError::TooExpensive })?; - - let units_per_second = - AssetIdInfoGetter::get_units_per_second(asset_id).ok_or({ - log::debug!( - target: "FirstAssetTrader::buy_weight", - "units_per_second missing for asset with id: {:?}", - id, - ); - XcmError::TooExpensive - })?; let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128); // we don't need to proceed if amount is zero. @@ -177,7 +185,7 @@ impl< } let required = MultiAsset { fun: Fungibility::Fungible(amount), - id: xcmAssetId::Concrete(id.clone()), + id: XcmAssetId::Concrete(id.clone()), }; log::debug!( @@ -203,10 +211,10 @@ impl< // In short, we only refund on the asset the trader first successfully was able // to pay for an execution - let new_asset = match self.refund_cache.clone() { + let new_asset = match &self.refund_cache { Some((prev_id, prev_amount, units_per_second)) => { - if prev_id == id { - Some((id, prev_amount.saturating_add(amount), units_per_second)) + if prev_id == &id { + Some((id, prev_amount.saturating_add(amount), *units_per_second)) } else { None } @@ -224,28 +232,25 @@ impl< _ => { log::debug!( target: "FirstAssetTrader::buy_weight", - "no matching xcmAssetId for first_asset in payment: {:?}", + "no matching XcmAssetId for first_asset in payment: {:?}", payment, ); - Err(XcmError::TooExpensive) } } } + /// + #[inline] fn refund_weight(&mut self, weight: Weight) -> Option { - if let Some((id, prev_amount, units_per_second)) = self.refund_cache.clone() { + if let Some((id, prev_amount, units_per_second)) = &mut self.refund_cache { let weight = weight.min(self.weight); self.weight -= weight; - let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128); - self.refund_cache = Some(( - id.clone(), - prev_amount.saturating_sub(amount), - units_per_second, - )); + let amount = *units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128); + *prev_amount = prev_amount.saturating_sub(amount); Some(MultiAsset { fun: Fungibility::Fungible(amount), - id: xcmAssetId::Concrete(id), + id: XcmAssetId::Concrete(id.clone()), }) } else { None @@ -253,49 +258,42 @@ impl< } } -/// Handle spent fees, deposit them as defined by R -impl< - AssetId: Clone, - AssetLocation: From + Clone, - AssetIdInfoGetter: UnitsToWeightRatio + AssetIdLocationGetter, - R: TakeRevenue, - > Drop for FirstAssetTrader +impl Drop for FirstAssetTrader +where + R: TakeRevenue, { + /// Handles spent fees, depositing them as defined by `R`. + #[inline] fn drop(&mut self) { - if let Some((id, amount, _)) = self.refund_cache.clone() { - R::take_revenue((id, amount).into()); + if let Some((id, amount, _)) = &self.refund_cache { + R::take_revenue((id.clone(), *amount).into()); } } } +/// /// XCM fee depositor to which we implement the TakeRevenue trait /// It receives a fungibles::Mutate implemented argument, a matcher to convert MultiAsset into /// AssetId and amount, and the fee receiver account -pub struct XcmFeesToAccount( - PhantomData<(Assets, Matcher, AccountId, ReceiverAccount)>, -); -impl< - Assets: Mutate, - Matcher: MatchesFungibles, - AccountId: Clone, - ReceiverAccount: Get, - > TakeRevenue for XcmFeesToAccount +pub struct XcmFeesToAccount(PhantomData<(AccountId, A, M, R)>); + +impl TakeRevenue for XcmFeesToAccount +where + A: Mutate, + M: MatchesFungibles, + R: Get, { + #[inline] fn take_revenue(revenue: MultiAsset) { - match Matcher::matches_fungibles(&revenue) { + match M::matches_fungibles(&revenue) { Ok((asset_id, amount)) => { if !amount.is_zero() { - Assets::mint_into(asset_id, &ReceiverAccount::get(), amount) - .map_err( - |err| log::debug!(target: "manta-xcm", "mint_into failed with {:?}", err), - ) - .ok(); + if let Err(err) = A::mint_into(asset_id, &R::get(), amount) { + log::debug!(target: "manta-xcm", "mint_into failed with {:?}", err); + } } } - Err(_) => log::debug!( - target: "manta-xcm", - "take revenue failed matching fungible" - ), + _ => log::debug!(target: "manta-xcm", "take revenue failed matching fungible"), } } } @@ -306,13 +304,15 @@ impl< /// `T` should specify a `SelfLocation` in the form of absolute path to the /// relaychain. pub struct IsNativeConcrete(PhantomData); + impl MatchesFungible for IsNativeConcrete where T: Get, Balance: TryFrom, { - fn matches_fungible(a: &MultiAsset) -> Option { - if let (Fungible(ref amount), Concrete(ref location)) = (&a.fun, &a.id) { + #[inline] + fn matches_fungible(asset: &MultiAsset) -> Option { + if let (Fungibility::Fungible(amount), Concrete(location)) = (&asset.fun, &asset.id) { if location == &T::get() || MultiLocation::is_here(location) { return CheckedConversion::checked_from(*amount); } @@ -321,128 +321,87 @@ where } } -pub struct MultiAssetAdapter< - Runtime, - AccountIdConverter, - NativeMatcher, - NonNativeMatcher, - MultiAdapterFungibleLedger, - MultiAdapterAssetConfig, ->( - PhantomData<( - Runtime, - NativeMatcher, - AccountIdConverter, - NonNativeMatcher, - MultiAdapterFungibleLedger, - MultiAdapterAssetConfig, - )>, +/// +pub struct MultiAssetAdapter( + PhantomData<(T, A, AccountIdConverter, Native, NonNative)>, ); -impl< - Runtime: frame_system::Config, - AccountIdConverter: XcmConvert, - NativeMatcher: MatchesFungible, - NonNativeMatcher: MatchesFungibles, - MultiAdapterFungibleLedger: FungibleLedger, - MultiAdapterAssetConfig: AssetConfig, - > TransactAsset - for MultiAssetAdapter< - Runtime, - AccountIdConverter, - NativeMatcher, - NonNativeMatcher, - MultiAdapterFungibleLedger, - MultiAdapterAssetConfig, - > -{ - fn deposit_asset(asset: &MultiAsset, location: &MultiLocation) -> XcmResult { - log::debug!( - target: "xcm::multi_asset_adapter", - "deposit_asset asset: {:?}, location: {:?}", - asset, location, - ); - - let (asset_id, amount, who) = Self::match_asset_and_location(asset, location)?; - - // If it's non-native asset we want to check with increase in total supply. - // Otherwise it will just use false, as it is assumed the native asset supply cannot be changed. - MultiAdapterFungibleLedger::can_deposit(asset_id, &who, amount, true).map_err(|_| { - XcmError::FailedToTransactAsset("Failed MultiAdapterFungibleLedger::can_deposit") - })?; - - MultiAdapterFungibleLedger::deposit_can_mint(asset_id, &who, amount).map_err(|_| { - XcmError::FailedToTransactAsset("Failed MultiAdapterFungibleLedger::deposit_can_mint") - })?; - - Ok(()) - } - - fn withdraw_asset( - asset: &MultiAsset, - location: &MultiLocation, - ) -> result::Result { - log::debug!( - target: "xcm::multi_asset_adapter", - "withdraw_asset asset: {:?}, location: {:?}", - asset, location, - ); - - let (asset_id, amount, who) = Self::match_asset_and_location(asset, location)?; - - MultiAdapterFungibleLedger::withdraw_can_burn( - asset_id, - &who, - amount, - ExistenceRequirement::AllowDeath, - ) - .map_err(|_| XcmError::FailedToTransactAsset("Failed Burn"))?; - - Ok(asset.clone().into()) - } -} - -impl< - Runtime: frame_system::Config, - AccountIdConverter: XcmConvert, - NativeMatcher: MatchesFungible, - NonNativeMatcher: MatchesFungibles, - MultiAdapterFungibleLedger: FungibleLedger, - MultiAdapterAssetConfig: AssetConfig, - > - MultiAssetAdapter< - Runtime, - AccountIdConverter, - NativeMatcher, - NonNativeMatcher, - MultiAdapterFungibleLedger, - MultiAdapterAssetConfig, - > +impl + MultiAssetAdapter +where + T: Config, + A: AssetConfig, + AccountIdConverter: XcmConvert, + Native: MatchesFungible, + NonNative: MatchesFungibles, { /// Matches the incoming `asset` to an `asset_id` and `amount` on this chain. /// Matches the incoming `location` to a `receiver` account on this chain. /// Uses the matcher implementation of both native and non-native assets. /// Returns the `asset_id`, `amount` and `receiver` if all three were matched. + #[inline] fn match_asset_and_location( asset: &MultiAsset, location: &MultiLocation, - ) -> result::Result<(AssetId, Balance, Runtime::AccountId), XcmError> { + ) -> Result<(A::AssetId, T::AccountId, A::Balance)> { let receiver = AccountIdConverter::convert_ref(location).map_err(|_| { XcmError::FailedToTransactAsset("Failed Location to AccountId Conversion") })?; - let (asset_id, amount) = match ( - NativeMatcher::matches_fungible(asset), - NonNativeMatcher::matches_fungibles(asset), + Native::matches_fungible(asset), + NonNative::matches_fungibles(asset), ) { // native asset - (Some(amount), _) => (MultiAdapterAssetConfig::NativeAssetId::get(), amount), + (Some(amount), _) => (A::NativeAssetId::get(), amount), // assets asset (_, Ok((asset_id, amount))) => (asset_id, amount), // unknown asset _ => return Err(XcmError::FailedToTransactAsset("Unknown Asset")), }; + Ok((asset_id, receiver, amount)) + } +} - Ok((asset_id, amount, receiver)) +impl TransactAsset + for MultiAssetAdapter +where + T: Config, + A: AssetConfig, + A::AssetId: Clone, + A::Balance: Clone, + AccountIdConverter: XcmConvert, + Native: MatchesFungible, + NonNative: MatchesFungibles, +{ + #[inline] + fn deposit_asset(asset: &MultiAsset, location: &MultiLocation) -> Result { + log::debug!( + target: "xcm::multi_asset_adapter", + "deposit_asset asset: {:?}, location: {:?}", + asset, location, + ); + let (asset_id, who, amount) = Self::match_asset_and_location(asset, location)?; + // NOTE: If it's non-native asset we want to check with increase in total supply. Otherwise + // it will just use false, as it is assumed the native asset supply cannot be changed. + A::FungibleLedger::deposit_minting_with_check(asset_id, &who, amount, true) + .map_err(|_| XcmError::FailedToTransactAsset("Failed deposit minting")) + } + + #[inline] + fn withdraw_asset(asset: &MultiAsset, location: &MultiLocation) -> Result { + log::debug!( + target: "xcm::multi_asset_adapter", + "withdraw_asset asset: {:?}, location: {:?}", + asset, location, + ); + let (asset_id, who, amount) = Self::match_asset_and_location(asset, location)?; + A::FungibleLedger::withdraw_burning( + asset_id, + &who, + amount, + ExistenceRequirement::AllowDeath, + ) + .map_err(|_| XcmError::FailedToTransactAsset("Failed Burn"))?; + Ok(asset.clone().into()) } } diff --git a/primitives/session-keys/Cargo.toml b/primitives/session-keys/Cargo.toml index ecf26adca..1ebc9ebdb 100644 --- a/primitives/session-keys/Cargo.toml +++ b/primitives/session-keys/Cargo.toml @@ -1,8 +1,8 @@ [package] -authors = ['Manta Network'] +authors = ["Manta Network"] description = "Primitives for session keys" edition = "2021" -license = 'GPL-3.0' +license = "GPL-3.0" name = "session-key-primitives" version = '3.4.3' @@ -12,8 +12,8 @@ nimbus-primitives = { git = "https://github.com/manta-network/nimbus.git", tag = parity-scale-codec = { version = "3.1.2", default-features = false, features = ["derive"] } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } sp-application-crypto = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } -sp-consensus-aura = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.26" } -sp-core = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.26" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "polkadot-v0.9.26" } +sp-core = { git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "polkadot-v0.9.26" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.26", default-features = false } [features] @@ -24,7 +24,7 @@ std = [ "parity-scale-codec/std", "scale-info/std", "sp-application-crypto/std", + "sp-consensus-aura/std", + "sp-core/std", "sp-runtime/std", - 'sp-core/std', - 'sp-consensus-aura/std', ] diff --git a/primitives/session-keys/src/aura.rs b/primitives/session-keys/src/aura.rs index 091ab0c4f..090fef766 100644 --- a/primitives/session-keys/src/aura.rs +++ b/primitives/session-keys/src/aura.rs @@ -14,5 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -// Aura consensus authority. +//! Aura Keys + +/// Aura Consensus Authority pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; diff --git a/primitives/session-keys/src/helpers.rs b/primitives/session-keys/src/helpers.rs deleted file mode 100644 index a7cd0e818..000000000 --- a/primitives/session-keys/src/helpers.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020-2022 Manta Network. -// This file is part of Manta. -// -// Manta is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Manta is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Manta. If not, see . - -//! Helper methods to generate dummy keys used in testing - -use crate::{AuraId, NimbusId, VrfId}; -use manta_primitives::types::{AccountId, Signature}; -use sp_core::{Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; - -/// Helper function to generate a crypto pair from seed -pub fn get_pair_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() -} - -/// Generate collator keys from seed. -/// -/// This function's return type must always match the session keys of the chain in tuple format. -pub fn get_collator_keys_from_seed(seed: &str) -> (AuraId, NimbusId, VrfId) { - ( - get_pair_from_seed::(seed), - get_pair_from_seed::(seed), - get_pair_from_seed::(seed), - ) -} - -type AccountPublic = ::Signer; - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId -where - AccountPublic: From<::Public>, -{ - AccountPublic::from(get_pair_from_seed::(seed)).into_account() -} diff --git a/primitives/session-keys/src/lib.rs b/primitives/session-keys/src/lib.rs index a0725a6fb..04ed5b495 100644 --- a/primitives/session-keys/src/lib.rs +++ b/primitives/session-keys/src/lib.rs @@ -14,15 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -//! Primitives for session keys +//! Session Key Primitives + #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![forbid(rustdoc::broken_intra_doc_links)] +#![forbid(missing_docs)] pub mod aura; -pub use aura::AuraId; pub mod nimbus; -pub use nimbus::NimbusId; pub mod vrf; + +pub use aura::AuraId; +pub use nimbus::NimbusId; pub use vrf::VrfId; #[cfg(feature = "std")] -pub mod helpers; +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +pub mod util; diff --git a/primitives/session-keys/src/nimbus.rs b/primitives/session-keys/src/nimbus.rs index 770e55ddf..4ee0e86aa 100644 --- a/primitives/session-keys/src/nimbus.rs +++ b/primitives/session-keys/src/nimbus.rs @@ -14,18 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -//! Helpers for handling nimbus keys -#![cfg_attr(not(feature = "std"), no_std)] - -use crate::AuraId; -use sp_application_crypto::{sr25519, UncheckedFrom}; +//! Nimbus Keys +/// Nimbus Id pub type NimbusId = nimbus_primitives::NimbusId; - -/// Reinterprets Aura public key as a NimbusId -/// NO CORRESPONDING PRIVATE KEY TO THAT KEY WILL EXIST -pub fn dummy_key_from(aura_id: AuraId) -> NimbusId { - let aura_as_sr25519: sr25519::Public = aura_id.into(); - let sr25519_as_bytes: [u8; 32] = aura_as_sr25519.into(); - sr25519::Public::unchecked_from(sr25519_as_bytes).into() -} diff --git a/primitives/session-keys/src/util.rs b/primitives/session-keys/src/util.rs new file mode 100644 index 000000000..0f8ed2e7a --- /dev/null +++ b/primitives/session-keys/src/util.rs @@ -0,0 +1,76 @@ +// Copyright 2020-2022 Manta Network. +// This file is part of Manta. +// +// Manta is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Manta is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Manta. If not, see . + +//! Key Generation Utilities + +use crate::{AuraId, NimbusId, VrfId}; +use manta_primitives::types::{AccountId, Signer}; +use sp_application_crypto::{sr25519, UncheckedFrom}; +use sp_core::{crypto::CryptoType, Pair}; +use sp_runtime::traits::IdentifyAccount; + +/// Public Key Type +pub type PublicKey = <::Pair as Pair>::Public; + +/// Derives [`PublicKey`] from `seed` for the corresponding crypto type `T` without checking that +/// the `seed` is valid. +#[inline] +pub fn unchecked_public_key(seed: &str) -> PublicKey +where + T: CryptoType, +{ + T::Pair::from_string(&format!("//{}", seed), None) + .expect("The validity of the seed is unchecked.") + .public() +} + +/// Derives [`AccountId`] from `seed` for the corresponding crypto type `T` without checking that +/// the `seed` is valid. +#[inline] +pub fn unchecked_account_id(seed: &str) -> AccountId +where + T: CryptoType, + Signer: From>, +{ + Signer::from(unchecked_public_key::(seed)).into_account() +} + +/// Derives the collator keys from `seed` without checking that the `seed` is valid. +/// +/// # Implementation Note +/// +/// The return type of this function must always match the session keys of the chain as a tuple. +#[inline] +pub fn unchecked_collator_keys(seed: &str) -> (AuraId, NimbusId, VrfId) { + ( + unchecked_public_key::(seed), + unchecked_public_key::(seed), + unchecked_public_key::(seed), + ) +} + +/// Reinterprets `aura_id` as a key of type `K`. +/// +/// # Safety +/// +/// No corresponding private key will exist for the returned `K`. +#[inline] +pub fn dummy_key(aura_id: AuraId) -> K +where + K: From, +{ + sr25519::Public::unchecked_from(<[u8; 32]>::from(sr25519::Public::from(aura_id))).into() +} diff --git a/primitives/session-keys/src/vrf.rs b/primitives/session-keys/src/vrf.rs index 56bb87d50..a2840328e 100644 --- a/primitives/session-keys/src/vrf.rs +++ b/primitives/session-keys/src/vrf.rs @@ -14,55 +14,58 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -//! VRF Key type, which is sr25519 -use crate::AuraId; -use sp_application_crypto::{sr25519, KeyTypeId, UncheckedFrom}; +//! VRF Keys + +use sp_application_crypto::KeyTypeId; use sp_runtime::{BoundToRuntimeAppPublic, ConsensusEngineId}; -/// Struct to implement `BoundToRuntimeAppPublic` by assigning Public = VrfId +/// Implementation of [`BoundToRuntimeAppPublic`] with the public key set to [`VrfId`] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct VrfSessionKey; impl BoundToRuntimeAppPublic for VrfSessionKey { type Public = VrfId; } -/// Reinterprets Aura public key as a VRFId. -/// NO CORRESPONDING PRIVATE KEY TO THAT KEY WILL EXIST -pub fn dummy_key_from(aura_id: AuraId) -> VrfId { - let aura_as_sr25519: sr25519::Public = aura_id.into(); - let sr25519_as_bytes: [u8; 32] = aura_as_sr25519.into(); - sr25519::Public::unchecked_from(sr25519_as_bytes).into() -} - -/// The ConsensusEngineId for VRF keys +/// Consensus Engine Identifier for the [`VrfId`] Key pub const VRF_ENGINE_ID: ConsensusEngineId = *b"rand"; -/// The KeyTypeId used for VRF keys +/// Key Type Identifier for the [`VrfId`] Key pub const VRF_KEY_ID: KeyTypeId = KeyTypeId(VRF_ENGINE_ID); -// The strongly-typed crypto wrappers to be used by VRF in the keystore +/// The strongly-typed crypto wrappers to be used by VRF in the keystore. mod vrf_crypto { use sp_application_crypto::{app_crypto, sr25519}; app_crypto!(sr25519, crate::vrf::VRF_KEY_ID); } -/// A vrf public key. +/// Public Key for VRF pub type VrfId = vrf_crypto::Public; -/// A vrf signature. +/// Signature for the [`VrfId`] Key pub type VrfSignature = vrf_crypto::Signature; sp_application_crypto::with_pair! { - /// A vrf key pair + /// Key Pair for the [`VrfId`] Key pub type VrfPair = vrf_crypto::Pair; } -#[test] -fn creating_dummy_vrf_id_from_aura_id_is_sane() { - for x in 0u8..10u8 { - let aura_id: AuraId = sr25519::Public::unchecked_from([x; 32]).into(); - let expected_vrf_id: VrfId = sr25519::Public::unchecked_from([x; 32]).into(); - let aura_to_vrf_id: VrfId = dummy_key_from(aura_id); - assert_eq!(expected_vrf_id, aura_to_vrf_id); +/// Testing Suite +#[cfg(test)] +mod test { + use super::*; + use crate::{util::dummy_key, AuraId}; + use sp_application_crypto::{sr25519, UncheckedFrom}; + + /// Checks that the dummy [`VrfId`] created from an [`AuraId`] is of the expected form. + #[test] + fn creating_dummy_vrf_id_from_aura_id_is_sane() { + for x in 0..0xFF { + let raw_key = sr25519::Public::unchecked_from([x; 32]); + assert_eq!( + VrfId::from(raw_key), + dummy_key::(AuraId::from(raw_key)) + ); + } } } diff --git a/runtime/calamari/src/assets_config.rs b/runtime/calamari/src/assets_config.rs index 602699210..7f95aa77d 100644 --- a/runtime/calamari/src/assets_config.rs +++ b/runtime/calamari/src/assets_config.rs @@ -21,11 +21,11 @@ use super::{ use manta_primitives::{ assets::{ - AssetConfig, AssetLocation, AssetRegistrar, AssetRegistrarMetadata, AssetStorageMetadata, - ConcreteFungibleLedger, + AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, + AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, }, constants::{ASSET_MANAGER_PALLET_ID, CALAMARI_DECIMAL}, - types::{AccountId, AssetId, Balance}, + types::{AccountId, Balance, CalamariAssetId}, }; use frame_support::{pallet_prelude::DispatchResult, parameter_types, traits::ConstU32, PalletId}; @@ -46,7 +46,7 @@ parameter_types! { impl pallet_assets::Config for Runtime { type Event = Event; type Balance = Balance; - type AssetId = AssetId; + type AssetId = CalamariAssetId; type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -60,12 +60,21 @@ impl pallet_assets::Config for Runtime { type WeightInfo = weights::pallet_assets::SubstrateWeight; } -pub struct CalamariAssetRegistrar; -impl AssetRegistrar for CalamariAssetRegistrar { +pub struct CalamariAssetRegistry; +impl BalanceType for CalamariAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for CalamariAssetRegistry { + type AssetId = CalamariAssetId; +} +impl AssetRegistry for CalamariAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + fn create_asset( - asset_id: AssetId, - min_balance: Balance, + asset_id: CalamariAssetId, metadata: AssetStorageMetadata, + min_balance: Balance, is_sufficient: bool, ) -> DispatchResult { Assets::force_create( @@ -86,10 +95,13 @@ impl AssetRegistrar for CalamariAssetRegistrar { ) } - fn update_asset_metadata(asset_id: AssetId, metadata: AssetStorageMetadata) -> DispatchResult { + fn update_asset_metadata( + asset_id: &CalamariAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { Assets::force_set_metadata( Origin::root(), - asset_id, + *asset_id, metadata.name, metadata.symbol, metadata.decimals, @@ -99,44 +111,54 @@ impl AssetRegistrar for CalamariAssetRegistrar { } parameter_types! { - pub const DummyAssetId: AssetId = 0; - pub const NativeAssetId: AssetId = 1; - pub const StartNonNativeAssetId: AssetId = 8; + pub const StartNonNativeAssetId: CalamariAssetId = 8; + pub const NativeAssetId: CalamariAssetId = 1; pub NativeAssetLocation: AssetLocation = AssetLocation( VersionedMultiLocation::V1(SelfReserve::get())); - pub NativeAssetMetadata: AssetRegistrarMetadata = AssetRegistrarMetadata { - name: b"Calamari".to_vec(), - symbol: b"KMA".to_vec(), - decimals: CALAMARI_DECIMAL, + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Calamari".to_vec(), + symbol: b"KMA".to_vec(), + decimals: CALAMARI_DECIMAL, + is_frozen: false, + }, min_balance: NativeTokenExistentialDeposit::get(), - evm_address: None, - is_frozen: false, is_sufficient: true, }; pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; } pub type CalamariConcreteFungibleLedger = - ConcreteFungibleLedger; + NativeAndNonNative; +/// AssetConfig implementations for this runtime #[derive(Clone, Eq, PartialEq)] pub struct CalamariAssetConfig; - +impl LocationType for CalamariAssetConfig { + type Location = AssetLocation; +} +impl BalanceType for CalamariAssetConfig { + type Balance = Balance; +} +impl AssetIdType for CalamariAssetConfig { + type AssetId = CalamariAssetId; +} impl AssetConfig for CalamariAssetConfig { - type DummyAssetId = DummyAssetId; - type NativeAssetId = NativeAssetId; type StartNonNativeAssetId = StartNonNativeAssetId; - type AssetRegistrarMetadata = AssetRegistrarMetadata; + type NativeAssetId = NativeAssetId; + type AssetRegistryMetadata = AssetRegistryMetadata; type NativeAssetLocation = NativeAssetLocation; type NativeAssetMetadata = NativeAssetMetadata; type StorageMetadata = AssetStorageMetadata; - type AssetLocation = AssetLocation; - type AssetRegistrar = CalamariAssetRegistrar; + type AssetRegistry = CalamariAssetRegistry; type FungibleLedger = CalamariConcreteFungibleLedger; } impl pallet_asset_manager::Config for Runtime { type Event = Event; + type AssetId = CalamariAssetId; + type Balance = Balance; + type Location = AssetLocation; type AssetConfig = CalamariAssetConfig; type ModifierOrigin = EnsureRoot; type PalletId = AssetManagerPalletId; diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index 02497be96..b93793892 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -813,7 +813,7 @@ construct_runtime!( // Treasury Treasury: pallet_treasury::{Pallet, Call, Storage, Event} = 26, - // Preimage registrar. + // Preimage registry. Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 28, // System scheduler. Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 29, @@ -864,8 +864,7 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic,); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/runtime/calamari/src/migrations/asset_id.rs b/runtime/calamari/src/migrations/asset_id.rs new file mode 100644 index 000000000..04459b642 --- /dev/null +++ b/runtime/calamari/src/migrations/asset_id.rs @@ -0,0 +1,737 @@ +// Copyright 2020-2022 Manta Network. +// This file is part of Manta. +// +// Manta is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Manta is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Manta. If not, see . + +#![allow(clippy::unnecessary_cast)] + +use crate::sp_api_hidden_includes_construct_runtime::hidden_include::StorageHasher; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +#[allow(deprecated)] +use frame_support::migration::{ + get_storage_value, put_storage_value, storage_key_iter, take_storage_value, +}; +use frame_support::{ + dispatch::GetStorageVersion, + pallet_prelude::Weight, + storage_alias, + traits::{Currency, Get, OnRuntimeUpgrade, StorageVersion}, + Blake2_128Concat, +}; +use manta_primitives::{ + assets::{AssetLocation, AssetRegistryMetadata, AssetStorageMetadata}, + types::Balance, +}; +use scale_info::TypeInfo; +use sp_core::H160; +use sp_runtime::BoundedVec; +use sp_std::vec::Vec; + +pub type DepositBalanceOf = <>::Currency as Currency< + ::AccountId, +>>::Balance; +pub type AssetAccountOf = pallet_assets::AssetAccount< + >::Balance, + DepositBalanceOf, + >::Extra, +>; + +type OldAssetId = u32; +type NewAssetId = u128; + +pub mod old { + use crate::migrations::asset_id::OldAssetId; + use frame_support::{storage_alias, Blake2_128Concat}; + + #[storage_alias] + pub type Account, I: 'static = ()> = StorageDoubleMap< + Assets, + Blake2_128Concat, + OldAssetId, + Blake2_128Concat, + ::AccountId, + super::AssetAccountOf, + >; +} + +#[storage_alias] +type Account, I: 'static = ()> = StorageDoubleMap< + Assets, + Blake2_128Concat, + NewAssetId, + Blake2_128Concat, + ::AccountId, + AssetAccountOf, +>; + +type AssetMapKVP = ( + OldAssetId, + pallet_assets::AssetDetails< + ::Balance, + ::AccountId, + DepositBalanceOf, + >, +); + +type MetadataMapKVP = ( + OldAssetId, + pallet_assets::AssetMetadata< + DepositBalanceOf, + BoundedVec::StringLimit>, + >, +); + +#[derive(Clone, Debug, Decode, Encode, Eq, Hash, Ord, PartialEq, PartialOrd, TypeInfo)] +pub struct OldAssetRegistrarMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, + pub evm_address: Option, + pub is_frozen: bool, + pub min_balance: Balance, + pub is_sufficient: bool, +} + +pub const INITIAL_PALLET_ASSETS_MANAGER_VERSION: u16 = 1; +pub const INITIAL_PALLET_ASSETS_VERSION: u16 = 0; + +pub struct AssetIdMigration(PhantomData); +impl OnRuntimeUpgrade for AssetIdMigration +where + T: pallet_asset_manager::Config + pallet_assets::Config, +{ + fn on_runtime_upgrade() -> Weight { + let mut num_reads = 0; + let mut num_writes = 0; + + let asset_manager_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + let assets_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + num_reads += 2; + if asset_manager_storage_version != INITIAL_PALLET_ASSETS_MANAGER_VERSION + || assets_storage_version != INITIAL_PALLET_ASSETS_VERSION + { + log::info!("Aborting migration due to unexpected on-chain storage versions for pallet-assets-manager: {:?} and pallet-assets: {:?}. Expectation was: {:?} and {:?}.", asset_manager_storage_version, assets_storage_version, INITIAL_PALLET_ASSETS_MANAGER_VERSION, INITIAL_PALLET_ASSETS_VERSION ); + return T::DbWeight::get().reads(num_reads as Weight); + } + + // AssetIdLocation + + log::info!(target: "asset-manager", "Starting migration for AssetManager..."); + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdLocation"; + let stored_data: Vec<_> = storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .drain() + .collect(); + for (old_key, value) in stored_data { + let new_key: NewAssetId = old_key as NewAssetId; + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&new_key.encode()), + value, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "asset-manager", "Storage migration for AssetManager's AssetIdLocation storage item has been executed." + ); + + // LocationAssetId + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"LocationAssetId"; + let stored_data: Vec<_> = storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .drain() + .collect(); + for (old_key, value) in stored_data { + let new_key: NewAssetId = value as NewAssetId; + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&old_key.encode()), + new_key, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "asset-manager", "Storage migration for AssetManager's LocationAssetId storage item has been executed." + ); + + // AssetIdMetadata + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdMetadata"; + let stored_data: Vec<_> = storage_key_iter::< + OldAssetId, + OldAssetRegistrarMetadata, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .drain() + .collect(); + for (old_key, old_value) in stored_data { + let new_key: NewAssetId = old_key as NewAssetId; + let new_value: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: old_value.name, + symbol: old_value.symbol, + decimals: old_value.decimals, + is_frozen: old_value.is_frozen, + }, + min_balance: old_value.min_balance, + is_sufficient: old_value.is_sufficient, + }; + + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&new_key.encode()), + new_value, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "asset-manager", "Storage migration for AssetManager's AssetIdMetadata storage item has been executed." + ); + + // UnitsPerSecond + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"UnitsPerSecond"; + let stored_data: Vec<_> = storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .drain() + .collect(); + for (old_key, value) in stored_data { + let new_key: NewAssetId = old_key as NewAssetId; + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&new_key.encode()), + value, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "asset-manager", "Storage migration for AssetManager's UnitsPerSecond storage item has been executed." + ); + + // NextAssetId + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"NextAssetId"; + num_reads += 1; + num_writes += 1; + let value = match take_storage_value::(pallet_prefix, storage_item_prefix, &[]) + { + Some(value) => value, + None => { + return T::DbWeight::get() + .reads(num_reads as Weight) + .saturating_add(T::DbWeight::get().writes(num_writes as Weight)); + } + }; + let new_value: NewAssetId = value as NewAssetId; + put_storage_value(pallet_prefix, storage_item_prefix, &[], new_value); + log::info!( + target: "asset-manager", "Storage migration for AssetManager's NextAssetId storage item has been executed." + ); + + StorageVersion::new(INITIAL_PALLET_ASSETS_MANAGER_VERSION + 1) + .put::>(); + + log::info!(target: "asset-manager", "✅ Storage migration for AssetManager has been executed successfully and storage version has been update to: {:?}.", INITIAL_PALLET_ASSETS_MANAGER_VERSION + 1); + + log::info!(target: "assets", "Starting migration for pallet-assets..."); + + // Asset + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Asset"; + let stored_data: Vec<_> = storage_key_iter::< + OldAssetId, + pallet_assets::AssetDetails< + ::Balance, + ::AccountId, + DepositBalanceOf, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .drain() + .collect(); + for (old_key, value) in stored_data { + let new_key: NewAssetId = old_key as NewAssetId; + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&new_key.encode()), + value, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "assets", "Storage migration for Assets' Asset storage item has been executed." + ); + + // Account + + let mut stored_data: Vec<_> = Vec::new(); + old::Account::::drain().for_each(|(asset_id_key, account_id_key, value)| { + let new_asset_id_key: NewAssetId = asset_id_key as NewAssetId; + stored_data.push((new_asset_id_key, account_id_key, value)); + }); + stored_data + .iter() + .for_each(|(new_asset_id_key, account_id_key, value)| { + Account::::insert(new_asset_id_key, account_id_key, value); + }); + log::info!( + target: "assets", "Storage migration for Assets' Account storage item has been executed." + ); + + // Metadata + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Metadata"; + let stored_data: Vec<_> = storage_key_iter::< + OldAssetId, + pallet_assets::AssetMetadata< + DepositBalanceOf, + BoundedVec::StringLimit>, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .drain() + .collect(); + for (asset_id_key, value) in stored_data { + let new_key: NewAssetId = asset_id_key as NewAssetId; + put_storage_value( + pallet_prefix, + storage_item_prefix, + &Blake2_128Concat::hash(&new_key.encode()), + value, + ); + num_reads += 1; + num_writes += 1; + } + log::info!( + target: "assets", "Storage migration for Assets' Metadata storage item has been executed." + ); + + StorageVersion::new(INITIAL_PALLET_ASSETS_VERSION + 1).put::>(); + + log::info!(target: "assets", "✅ Storage migration for Assets has been executed successfully and storage version has been update to: {:?}.", INITIAL_PALLET_ASSETS_VERSION + 1); + + T::DbWeight::get() + .reads(num_reads as Weight) + .saturating_add(T::DbWeight::get().writes(num_writes as Weight)) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + use frame_support::traits::OnRuntimeUpgradeHelpersExt; + + let asset_manager_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + if asset_manager_storage_version != INITIAL_PALLET_ASSETS_MANAGER_VERSION { + return Err("AssetManager storage version is not 1, the migration won't be executed."); + } + + let assets_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + if assets_storage_version != INITIAL_PALLET_ASSETS_VERSION { + return Err("Assets storage version is not 0, the migration won't be executed."); + } + + // We want to test that: + // There are no entries in the new storage beforehand + // The same number of mappings exist before and after + // + // We have to manually check that there are no entries + // with the old storage keys, as the new u128 asset-id + // would still decode into the old u32 values. + + // AssetIdLocation + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdLocation"; + assert_eq!( + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .count(), + 0 + ); + let stored_data_old: Vec<_> = + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + Self::set_temp_storage(stored_data_old, "asset_id_location_stored_data_old"); + + // LocationAssetId + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"LocationAssetId"; + assert_eq!( + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .count(), + 0 + ); + let stored_data_old: Vec<_> = + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + Self::set_temp_storage(stored_data_old, "location_asset_id_stored_data_old"); + + // AssetIdMetadata + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdMetadata"; + assert_eq!( + storage_key_iter::, Blake2_128Concat>( + pallet_prefix, + storage_item_prefix + ) + .count(), + 0 + ); + let stored_data_old: Vec<_> = storage_key_iter::< + OldAssetId, + OldAssetRegistrarMetadata, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + Self::set_temp_storage(stored_data_old, "asset_id_metadata_stored_data_old"); + + // UnitsPerSecond + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"UnitsPerSecond"; + assert_eq!( + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .count(), + 0 + ); + let stored_data_old: Vec<_> = storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + Self::set_temp_storage(stored_data_old, "units_per_sec_stored_data_old"); + + // NextAssetId + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"NextAssetId"; + assert!(get_storage_value::(pallet_prefix, storage_item_prefix, &[]).is_none()); + let next_asset_id: OldAssetId = + get_storage_value::(pallet_prefix, storage_item_prefix, &[]).unwrap(); + Self::set_temp_storage(next_asset_id, "next_asset_id"); + + // Asset + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Asset"; + assert_eq!( + storage_key_iter::< + NewAssetId, + pallet_assets::AssetDetails< + ::Balance, + ::AccountId, + DepositBalanceOf, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .count(), + 0 + ); + let stored_data_old: Vec<_> = storage_key_iter::< + OldAssetId, + pallet_assets::AssetDetails< + ::Balance, + ::AccountId, + DepositBalanceOf, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + Self::set_temp_storage(stored_data_old, "asset_map_stored_data_old"); + + // Account + + let mut stored_data_new: Vec<_> = Vec::new(); + Account::::iter().for_each(|kvp| { + stored_data_new.push(kvp); + }); + assert_eq!(stored_data_new.len(), 0); + let mut stored_data_old: Vec<_> = Vec::new(); + old::Account::::iter().for_each(|kvp| { + stored_data_old.push(kvp); + }); + Self::set_temp_storage(stored_data_old, "account_map_stored_data_old"); + + // Metadata + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Metadata"; + assert_eq!( + storage_key_iter::< + NewAssetId, + pallet_assets::AssetMetadata< + DepositBalanceOf, + BoundedVec::StringLimit>, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .count(), + 0 + ); + let stored_data_old: Vec<_> = storage_key_iter::< + OldAssetId, + pallet_assets::AssetMetadata< + DepositBalanceOf, + BoundedVec::StringLimit>, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + Self::set_temp_storage(stored_data_old, "metadata_map_stored_data_old"); + + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + use frame_support::traits::OnRuntimeUpgradeHelpersExt; + + let asset_manager_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + if asset_manager_storage_version != INITIAL_PALLET_ASSETS_MANAGER_VERSION + 1 { + return Err("AssetManager storage version is not 2, the migration wasn't executed."); + } + + let assets_storage_version = + as GetStorageVersion>::on_chain_storage_version(); + if assets_storage_version != INITIAL_PALLET_ASSETS_VERSION + 1 { + return Err("Assets storage version is not 1, the migration wasn't executed."); + } + + // We want to test that: + // There are no entries in the new storage beforehand + // The same number of mappings exist before and after + // + // We have to manually check that there are no entries + // with the old storage keys, as the new u128 asset-id + // would still decode into the old u32 values. + + // AssetIdLocation + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdLocation"; + let stored_data_new: Vec<_> = + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + let stored_data_old: Vec<(OldAssetId, AssetLocation)> = + Self::get_temp_storage("asset_id_location_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let check = (*key as NewAssetId, value.clone()); + assert!(stored_data_new.contains(&check)); + }); + log::info!("✅ Storage migration for AssetManager's AssetIdLocation storage item has been executed successfully."); + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"LocationAssetId"; + let stored_data_new: Vec<_> = + storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + let stored_data_old: Vec<(AssetLocation, OldAssetId)> = + Self::get_temp_storage("location_asset_id_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let check = (key.clone(), *value as NewAssetId); + assert!(stored_data_new.contains(&check)); + }); + log::info!("✅ Storage migration for AssetManager's LocationAssetId storage item has been executed successfully."); + + // AssetIdMetadata + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"AssetIdMetadata"; + let stored_data_new: Vec<_> = storage_key_iter::< + NewAssetId, + AssetRegistryMetadata, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + let stored_data_old: Vec<(OldAssetId, OldAssetRegistrarMetadata)> = + Self::get_temp_storage("asset_id_metadata_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let new_storage = ( + *key as NewAssetId, + AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: value.name.clone(), + symbol: value.symbol.clone(), + decimals: value.decimals, + is_frozen: value.is_frozen, + }, + min_balance: value.min_balance, + is_sufficient: value.is_sufficient, + }, + ); + assert!(stored_data_new.contains(&new_storage)); + }); + log::info!("✅ Storage migration for AssetManager's AssetIdMetadata storage item has been executed successfully."); + + // UnitsPerSecond + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"UnitsPerSecond"; + let stored_data_new: Vec<_> = storage_key_iter::( + pallet_prefix, + storage_item_prefix, + ) + .collect(); + let stored_data_old: Vec<(OldAssetId, u128)> = + Self::get_temp_storage("units_per_sec_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let check = (*key as NewAssetId, *value); + assert!(stored_data_new.contains(&check)); + }); + log::info!("✅ Storage migration for AssetManager's UnitsPerSecond storage item has been executed successfully."); + + // NextAssetId + + let pallet_prefix: &[u8] = b"AssetManager"; + let storage_item_prefix: &[u8] = b"NextAssetId"; + let next_asset_id: NewAssetId = + get_storage_value::(pallet_prefix, storage_item_prefix, &[]).unwrap(); + let old_next_asset_id: u32 = Self::get_temp_storage("next_asset_id").unwrap(); + assert_eq!(old_next_asset_id as u128, next_asset_id); + log::info!("✅ Storage migration for AssetManager's NextAssetId storage item has been executed successfully."); + + // Asset + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Asset"; + let stored_data_new: Vec<_> = storage_key_iter::< + NewAssetId, + pallet_assets::AssetDetails< + ::Balance, + ::AccountId, + DepositBalanceOf, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + let stored_data_old: Vec> = + Self::get_temp_storage("asset_map_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let check = (*key as NewAssetId, value.clone()); + assert!(stored_data_new.contains(&check)); + }); + log::info!( + "✅ Storage migration for Assets' Asset storage item has been executed successfully." + ); + + // Account + + let mut stored_data_new: Vec<_> = Vec::new(); + Account::::iter().for_each(|(asset_id_key, account_id_key, value)| { + stored_data_new.push((asset_id_key, account_id_key, value)); + }); + let stored_data_old: Vec<( + OldAssetId, + ::AccountId, + AssetAccountOf, + )> = Self::get_temp_storage("account_map_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old + .iter() + .for_each(|(asset_id_key, account_id_key, value)| { + let check = ( + *asset_id_key as NewAssetId, + account_id_key.clone(), + value.clone(), + ); + assert!(stored_data_new.contains(&check)); + }); + log::info!( + "✅ Storage migration for Assets' Account storage item has been executed successfully." + ); + + // Metadata + + let pallet_prefix: &[u8] = b"Assets"; + let storage_item_prefix: &[u8] = b"Metadata"; + let stored_data_new: Vec<_> = storage_key_iter::< + NewAssetId, + pallet_assets::AssetMetadata< + DepositBalanceOf, + BoundedVec::StringLimit>, + >, + Blake2_128Concat, + >(pallet_prefix, storage_item_prefix) + .collect(); + let stored_data_old: Vec> = + Self::get_temp_storage("metadata_map_stored_data_old").unwrap(); + assert_eq!(stored_data_old.len(), stored_data_new.len()); + stored_data_old.iter().for_each(|(key, value)| { + let check = (*key as NewAssetId, value.clone()); + assert!(stored_data_new.contains(&check)); + }); + log::info!( + "✅ Storage migration for Assets' Metadata storage item has been executed successfully." + ); + + Ok(()) + } +} diff --git a/runtime/calamari/src/migrations/mod.rs b/runtime/calamari/src/migrations/mod.rs index cf7d94541..5aaece584 100644 --- a/runtime/calamari/src/migrations/mod.rs +++ b/runtime/calamari/src/migrations/mod.rs @@ -14,5 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . +pub mod asset_id; pub mod staking; pub mod sudo; diff --git a/runtime/calamari/src/xcm_config.rs b/runtime/calamari/src/xcm_config.rs index d644bb3f6..3a005d510 100644 --- a/runtime/calamari/src/xcm_config.rs +++ b/runtime/calamari/src/xcm_config.rs @@ -15,18 +15,13 @@ // along with Manta. If not, see . use super::{ - assets_config::{CalamariAssetConfig, CalamariConcreteFungibleLedger}, - AssetManager, Assets, Call, DmpQueue, EnsureRootOrMoreThanHalfCouncil, Event, Origin, - ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, Treasury, XcmpQueue, - MAXIMUM_BLOCK_WEIGHT, + assets_config::CalamariAssetConfig, AssetManager, Assets, Call, DmpQueue, + EnsureRootOrMoreThanHalfCouncil, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, Treasury, XcmpQueue, MAXIMUM_BLOCK_WEIGHT, }; - use codec::{Decode, Encode}; -use scale_info::TypeInfo; - +use core::marker::PhantomData; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use sp_std::prelude::*; - use frame_support::{ match_types, parameter_types, traits::{Everything, Nothing}, @@ -34,22 +29,18 @@ use frame_support::{ }; use frame_system::EnsureRoot; use manta_primitives::{ - assets::{AssetIdLocationConvert, AssetLocation}, - types::{AccountId, AssetId, Balance}, + assets::AssetIdLocationConvert, + types::{AccountId, Balance, CalamariAssetId}, xcm::{ AccountIdToMultiLocation, FirstAssetTrader, IsNativeConcrete, MultiAssetAdapter, MultiNativeAsset, }, }; - -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; - use orml_traits::location::AbsoluteReserveProvider; -// Polkadot imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; - +use scale_info::TypeInfo; +use sp_std::prelude::*; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, @@ -60,6 +51,9 @@ use xcm_builder::{ }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; @@ -125,11 +119,11 @@ pub type XcmOriginToCallOrigin = ( ); parameter_types! { - // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + /// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. pub UnitWeightCost: Weight = 1_000_000_000; - // Used in native traders - // This might be able to skipped. - // We have to use `here()` because of reanchoring logic + /// Used in native traders + /// This might be able to skipped. + /// We have to use `here()` because of reanchoring logic pub ParaTokenPerSecond: (xcm::v2::AssetId, u128) = (Concrete(MultiLocation::here()), 1_000_000_000); pub const MaxInstructions: u32 = 100; } @@ -138,21 +132,19 @@ parameter_types! { /// Transactor for assets in pallet-assets, i.e. implements `fungibles` trait pub type MultiAssetTransactor = MultiAssetAdapter< Runtime, + // Used to find the query the native asset id of the chain. + CalamariAssetConfig, // "default" implementation of converting a `MultiLocation` to an `AccountId` LocationToAccountId, // Used when the incoming asset is a fungible concrete asset matching the given location or name: IsNativeConcrete, // Used to match incoming assets which are not the native asset. ConvertedConcreteAssetId< - AssetId, + CalamariAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - // Precondition checks and actual implementations of mint and burn logic. - CalamariConcreteFungibleLedger, - // Used to find the query the native asset id of the chain. - CalamariAssetConfig, >; match_types! { @@ -189,14 +181,14 @@ parameter_types! { } pub type XcmFeesToAccount = manta_primitives::xcm::XcmFeesToAccount< + AccountId, Assets, ConvertedConcreteAssetId< - AssetId, + CalamariAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - AccountId, XcmFeesAccount, >; @@ -222,7 +214,7 @@ impl Config for XcmExecutorConfig { // i.e. units_per_second in `AssetManager` type Trader = ( FixedRateOfFungible, - FirstAssetTrader, + FirstAssetTrader, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -286,17 +278,20 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type ExecuteOverweightOrigin = EnsureRoot; } -// We wrap AssetId for XToken +/// We wrap AssetId for XToken #[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] pub enum CurrencyId { - MantaCurrency(AssetId), + /// Assets registered in pallet-assets + MantaCurrency(CalamariAssetId), } -pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +/// Maps a xTokens CurrencyId to a xcm MultiLocation implemented by some asset manager +pub struct CurrencyIdtoMultiLocation(PhantomData); + impl sp_runtime::traits::Convert> for CurrencyIdtoMultiLocation where - AssetXConverter: xcm_executor::traits::Convert, + AssetXConverter: xcm_executor::traits::Convert, { fn convert(currency: CurrencyId) -> Option { match currency { @@ -318,16 +313,20 @@ impl orml_xtokens::Config for Runtime { type Event = Event; type Balance = Balance; type CurrencyId = CurrencyId; - type AccountIdToMultiLocation = AccountIdToMultiLocation; - type CurrencyIdConvert = - CurrencyIdtoMultiLocation>; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdConvert = CurrencyIdtoMultiLocation>; type XcmExecutor = XcmExecutor; type SelfLocation = SelfReserve; - // Take note that this pallet does not have the typical configurable WeightInfo. - // It uses the Weigher configuration to calculate weights for the user callable extrinsics on this chain, - // as well as weights for execution on the destination chain. Both based on the composed xcm messages. + + /// Weigher Configuration + /// + /// Take note that this pallet does not have the typical configurable WeightInfo. + /// It uses the Weigher configuration to calculate weights for the user callable + /// extrinsics on this chain, as well as weights for execution on the destination + /// chain. Both based on the composed xcm messages. type Weigher = WeightInfoBounds, Call, MaxInstructions>; + type BaseXcmWeight = BaseXcmWeight; type LocationInverter = LocationInverter; type MaxAssetsForTransfer = MaxAssetsForTransfer; diff --git a/runtime/calamari/tests/integrations_mock/integration_tests.rs b/runtime/calamari/tests/integrations_mock/integration_tests.rs index d79852943..92d0ed0e5 100644 --- a/runtime/calamari/tests/integrations_mock/integration_tests.rs +++ b/runtime/calamari/tests/integrations_mock/integration_tests.rs @@ -43,12 +43,13 @@ use frame_support::{ }; use manta_primitives::{ assets::{ - AssetConfig, AssetLocation, AssetRegistrarMetadata, FungibleLedger, FungibleLedgerError, + AssetConfig, AssetLocation, AssetRegistryMetadata, AssetStorageMetadata, FungibleLedger, + FungibleLedgerError, }, constants::time::{DAYS, HOURS}, - types::{AccountId, Balance, Header}, + types::{AccountId, Balance, CalamariAssetId, Header}, }; -use session_key_primitives::helpers::{get_account_id_from_seed, get_collator_keys_from_seed}; +use session_key_primitives::util::{unchecked_account_id, unchecked_collator_keys}; use xcm::{ opaque::latest::{ Junction::{PalletInstance, Parachain}, @@ -220,7 +221,7 @@ fn ensure_block_per_round_and_leave_delays_equal_7days() { #[test] fn slow_governance_works() { - let alice = get_account_id_from_seed::("Alice"); + let alice = unchecked_account_id::("Alice"); ExtBuilder::default().build().execute_with(|| { let _preimage_hash = start_governance_assertions(&alice); @@ -263,7 +264,7 @@ fn slow_governance_works() { #[test] fn fast_track_governance_works() { - let alice = get_account_id_from_seed::("Alice"); + let alice = unchecked_account_id::("Alice"); ExtBuilder::default().build().execute_with(|| { let preimage_hash = start_governance_assertions(&alice); @@ -324,7 +325,7 @@ fn fast_track_governance_works() { fn governance_filters_work() { assert!(::InstantAllowed::get()); - let alice = get_account_id_from_seed::("Alice"); + let alice = unchecked_account_id::("Alice"); ExtBuilder::default().build().execute_with(|| { // Setup the preimage and preimage hash @@ -370,10 +371,10 @@ fn governance_filters_work() { #[test] fn balances_operations_should_work() { - let alice = get_account_id_from_seed::("Alice"); - let bob = get_account_id_from_seed::("Bob"); - let charlie = get_account_id_from_seed::("Charlie"); - let dave = get_account_id_from_seed::("Dave"); + let alice = unchecked_account_id::("Alice"); + let bob = unchecked_account_id::("Bob"); + let charlie = unchecked_account_id::("Charlie"); + let dave = unchecked_account_id::("Dave"); ExtBuilder::default() .with_balances(vec![ @@ -384,7 +385,7 @@ fn balances_operations_should_work() { ]) .with_authorities(vec![( alice.clone(), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + SessionKeys::new(unchecked_collator_keys("Alice")), )]) .with_collators(vec![alice.clone()], 0) .build() @@ -476,9 +477,9 @@ fn seal_header(mut header: Header, author: AccountId) -> Header { #[test] fn reward_fees_to_block_author_and_treasury() { - let alice = get_account_id_from_seed::("Alice"); - let bob = get_account_id_from_seed::("Bob"); - let charlie = get_account_id_from_seed::("Charlie"); + let alice = unchecked_account_id::("Alice"); + let bob = unchecked_account_id::("Bob"); + let charlie = unchecked_account_id::("Charlie"); let desired_candidates = 0; ExtBuilder::default() @@ -489,7 +490,7 @@ fn reward_fees_to_block_author_and_treasury() { ]) .with_authorities(vec![( alice.clone(), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + SessionKeys::new(unchecked_collator_keys("Alice")), )]) .with_collators(vec![alice.clone()], desired_candidates) .build() @@ -582,10 +583,10 @@ fn sanity_check_round_duration() { // #[test] // fn session_and_collator_selection_work() { -// let alice = get_account_id_from_seed::("Alice"); -// let bob = get_account_id_from_seed::("Bob"); -// let alice_session_keys = SessionKeys::new(get_collator_keys_from_seed("Alice")); -// let bob_session_keys = SessionKeys::new(get_collator_keys_from_seed("Bob")); +// let alice = unchecked_account_id::("Alice"); +// let bob = unchecked_account_id::("Bob"); +// let alice_session_keys = SessionKeys::new(unchecked_collator_keys("Alice")); +// let bob_session_keys = SessionKeys::new(unchecked_collator_keys("Bob")); // let desired_candidates = 1; // ExtBuilder::default() @@ -637,8 +638,8 @@ fn sanity_check_weight_per_time_constants_are_as_expected() { #[test] fn calamari_vesting_works() { ExtBuilder::default().build().execute_with(|| { - let alice = get_account_id_from_seed::("Alice"); - let bob = get_account_id_from_seed::("Bob"); + let alice = unchecked_account_id::("Alice"); + let bob = unchecked_account_id::("Bob"); let unvested = 100 * KMA; assert_ok!(CalamariVesting::vested_transfer( @@ -848,9 +849,9 @@ fn verify_pallet_indices() { #[test] fn concrete_fungible_ledger_transfers_work() { - let alice = get_account_id_from_seed::("Alice"); - let bob = get_account_id_from_seed::("Bob"); - let charlie = get_account_id_from_seed::("Charlie"); + let alice = unchecked_account_id::("Alice"); + let bob = unchecked_account_id::("Bob"); + let charlie = unchecked_account_id::("Charlie"); ExtBuilder::default() .with_balances(vec![ @@ -931,7 +932,7 @@ fn concrete_fungible_ledger_transfers_work() { ); // Should not be able to create new account with lower than ED balance - let new_account = get_account_id_from_seed::("NewAccount"); + let new_account = unchecked_account_id::("NewAccount"); assert_err!( CalamariConcreteFungibleLedger::transfer( >::NativeAssetId::get(), @@ -996,13 +997,14 @@ fn concrete_fungible_ledger_transfers_work() { // Transfer tests for non-native assets: let min_balance = 10u128; - let asset_metadata = AssetRegistrarMetadata { - name: b"Kusama".to_vec(), - symbol: b"KSM".to_vec(), - decimals: 12, + let asset_metadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Kusama".to_vec(), + symbol: b"KSM".to_vec(), + decimals: 12, + is_frozen: false, + }, min_balance, - evm_address: None, - is_frozen: false, is_sufficient: true, }; let source_location = @@ -1015,7 +1017,7 @@ fn concrete_fungible_ledger_transfers_work() { // Register and mint for testing. let amount = Balance::MAX; - assert_ok!(CalamariConcreteFungibleLedger::deposit_can_mint( + assert_ok!(CalamariConcreteFungibleLedger::deposit_minting( >::StartNonNativeAssetId::get(), &alice.clone(), amount, @@ -1113,27 +1115,10 @@ fn concrete_fungible_ledger_transfers_work() { 0 ); - // Transferring invalid asset ID should not work. - assert_err!( - CalamariConcreteFungibleLedger::transfer( - >::DummyAssetId::get(), - &alice.clone(), - &charlie.clone(), - transfer_amount, - ExistenceRequirement::KeepAlive - ), - FungibleLedgerError::InvalidAssetId - ); - assert_eq!(Balances::free_balance(alice.clone()), current_balance_alice); - assert_eq!( - Balances::free_balance(charlie.clone()), - current_balance_charlie - ); - // Transferring unregistered asset ID should not work. assert_err!( CalamariConcreteFungibleLedger::transfer( - u32::MAX, + CalamariAssetId::MAX, &alice.clone(), &charlie.clone(), transfer_amount, @@ -1153,7 +1138,7 @@ fn concrete_fungible_ledger_transfers_work() { #[test] fn concrete_fungible_ledger_can_deposit_and_mint_works() { - let alice = get_account_id_from_seed::("Alice"); + let alice = unchecked_account_id::("Alice"); ExtBuilder::default() .with_balances(vec![(alice.clone(), INITIAL_BALANCE)]) @@ -1161,7 +1146,7 @@ fn concrete_fungible_ledger_can_deposit_and_mint_works() { .execute_with(|| { // Native asset tests: - let new_account = get_account_id_from_seed::("NewAccount"); + let new_account = unchecked_account_id::("NewAccount"); assert_err!( CalamariConcreteFungibleLedger::can_deposit( >::NativeAssetId::get(), @@ -1175,13 +1160,14 @@ fn concrete_fungible_ledger_can_deposit_and_mint_works() { // Non-native asset tests: let min_balance = 10u128; - let asset_metadata = AssetRegistrarMetadata { - name: b"Kusama".to_vec(), - symbol: b"KSM".to_vec(), - decimals: 12, + let asset_metadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Kusama".to_vec(), + symbol: b"KSM".to_vec(), + decimals: 12, + is_frozen: false, + }, min_balance, - evm_address: None, - is_frozen: false, is_sufficient: true, }; let source_location = @@ -1210,7 +1196,7 @@ fn concrete_fungible_ledger_can_deposit_and_mint_works() { ), FungibleLedgerError::UnknownAsset ); - assert_ok!(CalamariConcreteFungibleLedger::deposit_can_mint( + assert_ok!(CalamariConcreteFungibleLedger::deposit_minting( >::StartNonNativeAssetId::get(), &alice.clone(), u128::MAX, @@ -1232,13 +1218,14 @@ fn concrete_fungible_ledger_can_deposit_and_mint_works() { FungibleLedgerError::Overflow ); - let asset_metadata = AssetRegistrarMetadata { - name: b"Rococo".to_vec(), - symbol: b"Roc".to_vec(), - decimals: 12, + let asset_metadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Rococo".to_vec(), + symbol: b"Roc".to_vec(), + decimals: 12, + is_frozen: false, + }, min_balance, - evm_address: None, - is_frozen: false, is_sufficient: false, }; @@ -1263,15 +1250,15 @@ fn concrete_fungible_ledger_can_deposit_and_mint_works() { }); } -// `can_reduce_by_amount` uses `reducible_amount` implementation in order to use the `keep_alive` argument. +// `can_withdraw` uses `reducible_amount` implementation in order to use the `keep_alive` argument. // Unfortunately that function does not return the reason for failure cases like `can_withdraw`. // The errors that would've been returned if `can_withdraw` was used instead of `reducible_amount` // are included as comments on top of each case for more clarity. #[test] -fn concrete_fungible_ledger_can_reduce_by_amount_works() { - let alice = get_account_id_from_seed::("Alice"); - let bob = get_account_id_from_seed::("Bob"); - let charlie = get_account_id_from_seed::("Charlie"); +fn concrete_fungible_ledger_can_withdraw_works() { + let alice = unchecked_account_id::("Alice"); + let bob = unchecked_account_id::("Bob"); + let charlie = unchecked_account_id::("Charlie"); ExtBuilder::default() .with_balances(vec![(charlie.clone(), INITIAL_BALANCE)]) @@ -1282,10 +1269,10 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { // Native asset tests: assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::NativeAssetId::get(), &charlie.clone(), - INITIAL_BALANCE + 1, + &(INITIAL_BALANCE + 1), ExistenceRequirement::KeepAlive ), // Underflow @@ -1293,28 +1280,28 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { ); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::NativeAssetId::get(), &charlie.clone(), - INITIAL_BALANCE, + &INITIAL_BALANCE, ExistenceRequirement::KeepAlive ), // WouldDie FungibleLedgerError::CannotWithdrawMoreThan(INITIAL_BALANCE - existential_deposit) ); - assert_ok!(CalamariConcreteFungibleLedger::can_reduce_by_amount( + assert_ok!(CalamariConcreteFungibleLedger::can_withdraw( >::NativeAssetId::get(), &charlie.clone(), - INITIAL_BALANCE, + &INITIAL_BALANCE, ExistenceRequirement::AllowDeath ),); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::NativeAssetId::get(), &bob.clone(), - INITIAL_BALANCE, + &INITIAL_BALANCE, ExistenceRequirement::KeepAlive ), // NoFunds @@ -1324,13 +1311,14 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { // Non-native asset tests: let min_balance = 10u128; - let asset_metadata = AssetRegistrarMetadata { - name: b"Kusama".to_vec(), - symbol: b"KSM".to_vec(), - decimals: 12, + let asset_metadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Kusama".to_vec(), + symbol: b"KSM".to_vec(), + decimals: 12, + is_frozen: false, + }, min_balance, - evm_address: None, - is_frozen: false, is_sufficient: true, }; let source_location = @@ -1341,7 +1329,7 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { asset_metadata ),); - assert_ok!(CalamariConcreteFungibleLedger::deposit_can_mint( + assert_ok!(CalamariConcreteFungibleLedger::deposit_minting( >::StartNonNativeAssetId::get(), &alice.clone(), INITIAL_BALANCE, @@ -1355,44 +1343,44 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { ); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::StartNonNativeAssetId::get(), &alice.clone(), - INITIAL_BALANCE + 1, + &(INITIAL_BALANCE + 1), ExistenceRequirement::AllowDeath ), // Underflow FungibleLedgerError::CannotWithdrawMoreThan(INITIAL_BALANCE) ); - assert_ok!(CalamariConcreteFungibleLedger::can_reduce_by_amount( + assert_ok!(CalamariConcreteFungibleLedger::can_withdraw( >::StartNonNativeAssetId::get(), &alice.clone(), - INITIAL_BALANCE, + &INITIAL_BALANCE, ExistenceRequirement::AllowDeath ),); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::StartNonNativeAssetId::get(), &bob.clone(), - 10, + &10u128, ExistenceRequirement::AllowDeath ), // NoFunds FungibleLedgerError::CannotWithdrawMoreThan(0) ); - assert_ok!(CalamariConcreteFungibleLedger::deposit_can_mint( + assert_ok!(CalamariConcreteFungibleLedger::deposit_minting( >::StartNonNativeAssetId::get(), &bob.clone(), INITIAL_BALANCE, ),); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::StartNonNativeAssetId::get(), &alice.clone(), - INITIAL_BALANCE, + &INITIAL_BALANCE, ExistenceRequirement::KeepAlive ), FungibleLedgerError::CannotWithdrawMoreThan(INITIAL_BALANCE - min_balance) @@ -1404,10 +1392,10 @@ fn concrete_fungible_ledger_can_reduce_by_amount_works() { sp_runtime::MultiAddress::Id(alice.clone()), )); assert_err!( - CalamariConcreteFungibleLedger::can_reduce_by_amount( + CalamariConcreteFungibleLedger::can_withdraw( >::StartNonNativeAssetId::get(), &alice.clone(), - 10, + &10u128, ExistenceRequirement::AllowDeath ), // Frozen diff --git a/runtime/calamari/tests/integrations_mock/mock.rs b/runtime/calamari/tests/integrations_mock/mock.rs index a3012e174..12fe732c1 100644 --- a/runtime/calamari/tests/integrations_mock/mock.rs +++ b/runtime/calamari/tests/integrations_mock/mock.rs @@ -28,7 +28,7 @@ use manta_primitives::{ assets::AssetConfig, types::{AccountId, Balance}, }; -use session_key_primitives::helpers::{get_account_id_from_seed, get_collator_keys_from_seed}; +use session_key_primitives::util::{unchecked_account_id, unchecked_collator_keys}; use sp_core::sr25519; pub struct ExtBuilder { balances: Vec<(AccountId, Balance)>, @@ -37,20 +37,19 @@ pub struct ExtBuilder { desired_candidates: u32, safe_xcm_version: Option, } -use sp_std::marker::PhantomData; impl Default for ExtBuilder { fn default() -> ExtBuilder { ExtBuilder { balances: vec![( - get_account_id_from_seed::("Alice"), + unchecked_account_id::("Alice"), INITIAL_BALANCE, )], authorities: vec![( - get_account_id_from_seed::("Alice"), - SessionKeys::new(get_collator_keys_from_seed("Alice")), + unchecked_account_id::("Alice"), + SessionKeys::new(unchecked_collator_keys("Alice")), )], - invulnerables: vec![get_account_id_from_seed::("Alice")], + invulnerables: vec![unchecked_account_id::("Alice")], safe_xcm_version: None, desired_candidates: 1, } @@ -120,7 +119,6 @@ impl ExtBuilder { pallet_asset_manager::GenesisConfig:: { start_id: >::StartNonNativeAssetId::get(), - _marker: PhantomData::::default(), } .assimilate_storage(&mut t) .unwrap(); diff --git a/runtime/calamari/tests/xcm_mock/parachain.rs b/runtime/calamari/tests/xcm_mock/parachain.rs index ba151432c..aa9deae0b 100644 --- a/runtime/calamari/tests/xcm_mock/parachain.rs +++ b/runtime/calamari/tests/xcm_mock/parachain.rs @@ -30,7 +30,7 @@ use frame_support::{ }; use frame_system::EnsureRoot; use scale_info::TypeInfo; -use sp_core::{H160, H256}; +use sp_core::H256; use sp_runtime::{ traits::{BlakeTwo256, Hash, IdentityLookup}, AccountId32, @@ -39,11 +39,11 @@ use sp_std::prelude::*; use manta_primitives::{ assets::{ - AssetConfig, AssetIdLocationConvert, AssetLocation, AssetRegistrar, AssetRegistrarMetadata, - AssetStorageMetadata, ConcreteFungibleLedger, + AssetConfig, AssetIdLocationConvert, AssetIdType, AssetLocation, AssetRegistry, + AssetRegistryMetadata, AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, }, constants::{ASSET_MANAGER_PALLET_ID, CALAMARI_DECIMAL}, - types::{AssetId, BlockNumber, Header}, + types::{BlockNumber, CalamariAssetId, Header}, xcm::{FirstAssetTrader, IsNativeConcrete, MultiAssetAdapter, MultiNativeAsset}, }; use pallet_xcm::XcmPassthrough; @@ -139,7 +139,7 @@ parameter_types! { impl pallet_assets::Config for Runtime { type Event = Event; type Balance = Balance; - type AssetId = AssetId; + type AssetId = CalamariAssetId; type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -196,21 +196,19 @@ parameter_types! { /// Transactor for assets in pallet-assets, i.e. implements `fungibles` trait pub type MultiAssetTransactor = MultiAssetAdapter< Runtime, + // Used to find the query the native asset id of the chain. + ParachainAssetConfig, // "default" implementation of converting a `MultiLocation` to an `AccountId` LocationToAccountId, // Used when the incoming asset is a fungible concrete asset matching the given location or name: IsNativeConcrete, // Used to match incoming assets which are not the native asset. ConvertedConcreteAssetId< - AssetId, + CalamariAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - // Precondition checks and actual implementations of mint and burn logic. - ConcreteFungibleLedger, - // Used to find the query the native asset id of the chain. - ParachainAssetConfig, >; pub type XcmRouter = super::ParachainXcmRouter; @@ -249,14 +247,14 @@ parameter_types! { } pub type XcmFeesToAccount = manta_primitives::xcm::XcmFeesToAccount< + AccountId, Assets, ConvertedConcreteAssetId< - AssetId, + CalamariAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - AccountId, XcmFeesAccount, >; @@ -285,7 +283,7 @@ impl Config for XcmExecutorConfig { // i.e. units_per_second in `AssetManager` type Trader = ( FixedRateOfFungible, - FirstAssetTrader, + FirstAssetTrader, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -499,12 +497,21 @@ pub(crate) fn set_current_xcm_version(version: XcmVersion) { CurrentXcmVersion::set(version); } -pub struct CalamariAssetRegistrar; -impl AssetRegistrar for CalamariAssetRegistrar { +pub struct CalamariAssetRegistry; +impl BalanceType for CalamariAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for CalamariAssetRegistry { + type AssetId = CalamariAssetId; +} +impl AssetRegistry for CalamariAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + fn create_asset( - asset_id: AssetId, - min_balance: Balance, + asset_id: CalamariAssetId, metadata: AssetStorageMetadata, + min_balance: Balance, is_sufficient: bool, ) -> DispatchResult { Assets::force_create( @@ -525,10 +532,13 @@ impl AssetRegistrar for CalamariAssetRegistrar { ) } - fn update_asset_metadata(asset_id: AssetId, metadata: AssetStorageMetadata) -> DispatchResult { + fn update_asset_metadata( + asset_id: &CalamariAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { Assets::force_set_metadata( Origin::root(), - asset_id, + *asset_id, metadata.name, metadata.symbol, metadata.decimals, @@ -538,41 +548,51 @@ impl AssetRegistrar for CalamariAssetRegistrar { } parameter_types! { - pub const DummyAssetId: AssetId = 0; - pub const NativeAssetId: AssetId = 1; - pub const StartNonNativeAssetId: AssetId = 8; + pub const StartNonNativeAssetId: CalamariAssetId = 8; + pub const NativeAssetId: CalamariAssetId = 1; pub NativeAssetLocation: AssetLocation = AssetLocation( VersionedMultiLocation::V1(SelfReserve::get())); - pub NativeAssetMetadata: AssetRegistrarMetadata = AssetRegistrarMetadata { - name: b"ParaAToken".to_vec(), - symbol: b"ParaA".to_vec(), - decimals: CALAMARI_DECIMAL, + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: CALAMARI_DECIMAL, + is_frozen: false, + }, min_balance: 1, - evm_address: None, - is_frozen: false, is_sufficient: true, }; pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; } +/// AssetConfig implementations for this runtime #[derive(Clone, Eq, PartialEq)] pub struct ParachainAssetConfig; - +impl LocationType for ParachainAssetConfig { + type Location = AssetLocation; +} +impl AssetIdType for ParachainAssetConfig { + type AssetId = CalamariAssetId; +} +impl BalanceType for ParachainAssetConfig { + type Balance = Balance; +} impl AssetConfig for ParachainAssetConfig { - type DummyAssetId = DummyAssetId; - type NativeAssetId = NativeAssetId; type StartNonNativeAssetId = StartNonNativeAssetId; - type AssetRegistrarMetadata = AssetRegistrarMetadata; + type NativeAssetId = NativeAssetId; + type AssetRegistryMetadata = AssetRegistryMetadata; type NativeAssetLocation = NativeAssetLocation; type NativeAssetMetadata = NativeAssetMetadata; type StorageMetadata = AssetStorageMetadata; - type AssetLocation = AssetLocation; - type AssetRegistrar = CalamariAssetRegistrar; - type FungibleLedger = ConcreteFungibleLedger; + type AssetRegistry = CalamariAssetRegistry; + type FungibleLedger = NativeAndNonNative; } impl pallet_asset_manager::Config for Runtime { type Event = Event; + type AssetId = CalamariAssetId; + type Balance = Balance; + type Location = AssetLocation; type AssetConfig = ParachainAssetConfig; type ModifierOrigin = EnsureRoot; type PalletId = AssetManagerPalletId; @@ -587,14 +607,15 @@ impl cumulus_pallet_xcm::Config for Runtime { // We wrap AssetId for XToken #[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] pub enum CurrencyId { - MantaCurrency(AssetId), + MantaCurrency(CalamariAssetId), } +/// Maps a xTokens CurrencyId to a xcm MultiLocation implemented by some asset manager pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); impl sp_runtime::traits::Convert> for CurrencyIdtoMultiLocation where - AssetXConverter: xcm_executor::traits::Convert, + AssetXConverter: xcm_executor::traits::Convert, { fn convert(currency: CurrencyId) -> Option { match currency { @@ -616,9 +637,8 @@ impl orml_xtokens::Config for Runtime { type Event = Event; type Balance = Balance; type CurrencyId = CurrencyId; - type AccountIdToMultiLocation = manta_primitives::xcm::AccountIdToMultiLocation; - type CurrencyIdConvert = - CurrencyIdtoMultiLocation>; + type AccountIdToMultiLocation = manta_primitives::xcm::AccountIdToMultiLocation; + type CurrencyIdConvert = CurrencyIdtoMultiLocation>; type XcmExecutor = XcmExecutor; type SelfLocation = SelfReserve; type Weigher = WeightInfoBounds< @@ -691,17 +711,17 @@ pub(crate) fn create_asset_metadata( symbol: &str, decimals: u8, min_balance: u128, - evm_address: Option, is_frozen: bool, is_sufficient: bool, -) -> AssetRegistrarMetadata { - AssetRegistrarMetadata { - name: name.as_bytes().to_vec(), - symbol: symbol.as_bytes().to_vec(), - decimals, +) -> AssetRegistryMetadata { + AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: name.as_bytes().to_vec(), + symbol: symbol.as_bytes().to_vec(), + decimals, + is_frozen, + }, min_balance, - evm_address, - is_frozen, is_sufficient, } } @@ -715,9 +735,9 @@ pub(crate) fn create_asset_location(parents: u8, para_id: u32) -> AssetLocation fn insert_dummy_data( dummy_mult_loc: MultiLocation, - dummy_asset_metadata: &AssetRegistrarMetadata, - start_from: u32, - insert_until: u32, + dummy_asset_metadata: &AssetRegistryMetadata, + start_from: CalamariAssetId, + insert_until: CalamariAssetId, ) { let mut next_asset_id = start_from; let mut next_dummy_mult_loc = dummy_mult_loc; @@ -734,10 +754,10 @@ fn insert_dummy_data( pub(crate) fn register_assets_on_parachain

( source_location: &AssetLocation, - asset_metadata: &AssetRegistrarMetadata, + asset_metadata: &AssetRegistryMetadata, units_per_second: Option, mint_asset: Option<(AccountId, Balance, bool, bool)>, -) -> AssetId +) -> CalamariAssetId where P: XcmpMessageHandlerT + DmpMessageHandlerT + TestExt, { diff --git a/runtime/calamari/tests/xcm_mock/xcm_tests.rs b/runtime/calamari/tests/xcm_mock/xcm_tests.rs index f2d558e2d..e98c73693 100644 --- a/runtime/calamari/tests/xcm_mock/xcm_tests.rs +++ b/runtime/calamari/tests/xcm_mock/xcm_tests.rs @@ -191,8 +191,8 @@ fn reserve_transfer_relaychain_to_parachain_a_then_back() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let _ = register_assets_on_parachain::( ¶_a_source_location, @@ -287,10 +287,8 @@ fn send_para_a_native_asset_to_para_b() { let amount = INITIAL_BALANCE; - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, false); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, false); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -365,10 +363,8 @@ fn send_para_a_native_asset_to_para_b_barriers_should_work() { let amount = 10000000000000u128; let units_per_sec = 125000000000; - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, false); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, false); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -458,10 +454,8 @@ fn send_insufficient_asset_from_para_a_to_para_b() { self_reserve_xtokens_weight_on_receiver(), ); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, false); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, false); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -579,10 +573,8 @@ fn send_para_a_native_asset_to_para_b_must_fail_cases() { let amount = 1u128; let units_per_sec = 125000000000; - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, false); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, false); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -678,8 +670,7 @@ fn register_insufficient_with_zero_min_balance_should_fail() { MockNet::reset(); let a_source_location = create_asset_location(1, PARA_A_ID); - let a_asset_metadata_on_b = - create_asset_metadata("ParaAToken", "ParaA", 18, 0, None, false, false); + let a_asset_metadata_on_b = create_asset_metadata("ParaAToken", "ParaA", 18, 0, false, false); ParaB::execute_with(|| { assert_err!( @@ -709,12 +700,10 @@ fn send_para_a_custom_asset_to_para_b() { let para_b_source_location = create_asset_location(1, PARA_B_ID); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); let para_a_doge_asset_metadata = - create_asset_metadata("ParaADogeToken", "ParaADoge", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); + create_asset_metadata("ParaADogeToken", "ParaADoge", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); let _ = register_assets_on_parachain::( ¶_a_source_location, @@ -802,10 +791,8 @@ fn send_para_a_native_asset_para_b_and_then_send_back() { let fee_on_b_when_send_back = calculate_fee(ParaTokenPerSecond::get().1, weight); assert!(fee_on_b_when_send_back < amount); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -909,12 +896,9 @@ fn send_para_a_native_asset_from_para_b_to_para_c() { let fee_at_reserve = calculate_fee(ParaTokenPerSecond::get().1, weight); assert!(amount >= fee_at_reserve * 2_u128); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, false); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, false); - let para_c_asset_metadata = - create_asset_metadata("ParaCToken", "ParaC", 18, 1, None, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, false); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, false); + let para_c_asset_metadata = create_asset_metadata("ParaCToken", "ParaC", 18, 1, false, false); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -1032,8 +1016,8 @@ fn receive_relay_asset_with_trader_on_parachain() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let amount = 666u128; // We charge 10^9 as units per second on ParaA @@ -1099,10 +1083,8 @@ fn send_para_a_asset_to_para_b_with_trader_and_fee() { let units_per_second = 1_250_000u128; let fee = calculate_fee(units_per_second, self_reserve_xtokens_weight_on_receiver()); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -1177,12 +1159,9 @@ fn send_para_a_asset_from_para_b_to_para_c_with_trader() { non_self_reserve_xtokens_weight_on_receiver(), ); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); - let para_c_asset_metadata = - create_asset_metadata("ParaCToken", "ParaC", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); + let para_c_asset_metadata = create_asset_metadata("ParaCToken", "ParaC", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -1300,8 +1279,8 @@ fn receive_relay_asset_on_parachain_with_insufficient_fee_payment_should_fail() let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let amount = 20u128; // We charge 2 x 10^10 as units per second on ParaA @@ -1360,8 +1339,8 @@ fn receive_relay_should_fail_without_specifying_units_per_second() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let amount = 333u128; @@ -1422,10 +1401,8 @@ fn send_para_a_asset_to_para_b_with_insufficient_fee() { let fee = calculate_fee(units_per_second, dest_weight); assert!(fee > amount); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -1495,10 +1472,8 @@ fn send_para_a_asset_to_para_b_without_specifying_units_per_second() { let amount = 567u128; let dest_weight = 800_000u64; - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -1567,8 +1542,8 @@ fn receive_insufficient_relay_asset_on_parachain() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, false); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, false); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let amount = 123u128; let units_per_sec = 0u128; @@ -1656,8 +1631,8 @@ fn receive_sufficient_relay_asset_on_parachain() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); let amount = 123u128; let units_per_sec = 0; @@ -1808,8 +1783,8 @@ fn test_versioning_on_runtime_upgrade_with_relay() { let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); let para_a_source_location = create_asset_location(1, PARA_A_ID); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); - let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaA", "ParaA", 12, 1, false, true); // register relay asset in parachain A (XCM version 1) ParaA::execute_with(|| { @@ -1939,10 +1914,8 @@ fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { let para_a_source_location = create_asset_location(1, PARA_A_ID); let para_b_source_location = create_asset_location(1, PARA_B_ID); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let response = Response::Version(2); // This is irrelevant, nothing will be done with this message, @@ -2098,10 +2071,8 @@ fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { fn filtered_multilocation_should_not_work() { let para_a_source_location = create_asset_location(1, PARA_A_ID); let para_b_source_location = create_asset_location(1, PARA_B_ID); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let a_asset_id_on_a = register_assets_on_parachain::( ¶_a_source_location, @@ -2296,13 +2267,11 @@ fn less_than_min_xcm_fee_should_not_work() { ))); let para_b_as_reserve_chain = create_asset_location(1, PARA_B_ID); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); let _ = register_assets_on_parachain::( ¶_a_source_location, @@ -2471,13 +2440,11 @@ fn transfer_multicurrencies_should_work_scenarios() { ))); let units_per_sec = 0; - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); let _ = register_assets_on_parachain::( ¶_a_source_location, @@ -2673,15 +2640,12 @@ fn transfer_multicurrencies_should_fail_scenarios() { let para_b_source_location = create_asset_location(1, para_b_id); let para_c_source_location = create_asset_location(1, para_c_id); - let para_a_asset_metadata = - create_asset_metadata("ParaAToken", "ParaA", 18, 1, None, false, true); - let para_b_asset_metadata = - create_asset_metadata("ParaBToken", "ParaB", 18, 1, None, false, true); - let para_c_asset_metadata = - create_asset_metadata("ParaCToken", "ParaC", 18, 1, None, false, true); + let para_a_asset_metadata = create_asset_metadata("ParaAToken", "ParaA", 18, 1, false, true); + let para_b_asset_metadata = create_asset_metadata("ParaBToken", "ParaB", 18, 1, false, true); + let para_c_asset_metadata = create_asset_metadata("ParaCToken", "ParaC", 18, 1, false, true); let relay_source_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::parent())); - let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, None, false, true); + let relay_asset_metadata = create_asset_metadata("Kusama", "KSM", 12, 1, false, true); let units_per_sec = 0; let a_asset_id_on_a = register_assets_on_parachain::( diff --git a/runtime/dolphin/src/assets_config.rs b/runtime/dolphin/src/assets_config.rs index c81603836..f243ae19c 100644 --- a/runtime/dolphin/src/assets_config.rs +++ b/runtime/dolphin/src/assets_config.rs @@ -21,11 +21,11 @@ use super::{ use manta_primitives::{ assets::{ - AssetConfig, AssetLocation, AssetRegistrar, AssetRegistrarMetadata, AssetStorageMetadata, - ConcreteFungibleLedger, + AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, + AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, }, constants::{ASSET_MANAGER_PALLET_ID, DOLPHIN_DECIMAL, MANTA_PAY_PALLET_ID}, - types::{AccountId, AssetId, Balance}, + types::{AccountId, Balance, DolphinAssetId}, }; use frame_support::{pallet_prelude::DispatchResult, parameter_types, PalletId}; @@ -44,7 +44,7 @@ parameter_types! { impl pallet_assets::Config for Runtime { type Event = Event; type Balance = Balance; - type AssetId = AssetId; + type AssetId = DolphinAssetId; type Currency = Balances; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -58,12 +58,21 @@ impl pallet_assets::Config for Runtime { type WeightInfo = weights::pallet_assets::SubstrateWeight; } -pub struct MantaAssetRegistrar; -impl AssetRegistrar for MantaAssetRegistrar { +pub struct MantaAssetRegistry; +impl BalanceType for MantaAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for MantaAssetRegistry { + type AssetId = DolphinAssetId; +} +impl AssetRegistry for MantaAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + fn create_asset( - asset_id: AssetId, - min_balance: Balance, + asset_id: DolphinAssetId, metadata: AssetStorageMetadata, + min_balance: Balance, is_sufficient: bool, ) -> DispatchResult { Assets::force_create( @@ -96,10 +105,13 @@ impl AssetRegistrar for MantaAssetRegistrar { ) } - fn update_asset_metadata(asset_id: AssetId, metadata: AssetStorageMetadata) -> DispatchResult { + fn update_asset_metadata( + asset_id: &DolphinAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { Assets::force_set_metadata( Origin::root(), - asset_id, + *asset_id, metadata.name, metadata.symbol, metadata.decimals, @@ -109,44 +121,54 @@ impl AssetRegistrar for MantaAssetRegistrar { } parameter_types! { - pub const DummyAssetId: AssetId = 0; - pub const NativeAssetId: AssetId = 1; - pub const StartNonNativeAssetId: AssetId = 8; + pub const StartNonNativeAssetId: DolphinAssetId = 8; + pub const NativeAssetId: DolphinAssetId = 1; pub NativeAssetLocation: AssetLocation = AssetLocation( VersionedMultiLocation::V1(SelfReserve::get())); - pub NativeAssetMetadata: AssetRegistrarMetadata = AssetRegistrarMetadata { - name: b"Dolphin".to_vec(), - symbol: b"DOL".to_vec(), - decimals: DOLPHIN_DECIMAL, + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Dolphin".to_vec(), + symbol: b"DOL".to_vec(), + decimals: DOLPHIN_DECIMAL, + is_frozen: false, + }, min_balance: NativeTokenExistentialDeposit::get(), - evm_address: None, - is_frozen: false, is_sufficient: true, }; pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; } pub type DolphinConcreteFungibleLedger = - ConcreteFungibleLedger; + NativeAndNonNative; +/// AssetConfig implementations for this runtime #[derive(Clone, Eq, PartialEq)] pub struct DolphinAssetConfig; - +impl LocationType for DolphinAssetConfig { + type Location = AssetLocation; +} +impl BalanceType for DolphinAssetConfig { + type Balance = Balance; +} +impl AssetIdType for DolphinAssetConfig { + type AssetId = DolphinAssetId; +} impl AssetConfig for DolphinAssetConfig { - type DummyAssetId = DummyAssetId; - type NativeAssetId = NativeAssetId; type StartNonNativeAssetId = StartNonNativeAssetId; - type AssetRegistrarMetadata = AssetRegistrarMetadata; + type NativeAssetId = NativeAssetId; + type AssetRegistryMetadata = AssetRegistryMetadata; type NativeAssetLocation = NativeAssetLocation; type NativeAssetMetadata = NativeAssetMetadata; type StorageMetadata = AssetStorageMetadata; - type AssetLocation = AssetLocation; - type AssetRegistrar = MantaAssetRegistrar; + type AssetRegistry = MantaAssetRegistry; type FungibleLedger = DolphinConcreteFungibleLedger; } impl pallet_asset_manager::Config for Runtime { type Event = Event; + type AssetId = DolphinAssetId; + type Balance = Balance; + type Location = AssetLocation; type AssetConfig = DolphinAssetConfig; type ModifierOrigin = EnsureRoot; type PalletId = AssetManagerPalletId; diff --git a/runtime/dolphin/src/lib.rs b/runtime/dolphin/src/lib.rs index b753edba1..7db1ed1c2 100644 --- a/runtime/dolphin/src/lib.rs +++ b/runtime/dolphin/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Manta. If not, see . -//! Dolphin Parachain runtime. +//! Dolphin Parachain Runtime #![allow(clippy::identity_op)] // keep e.g. 1 * DAYS for legibility #![cfg_attr(not(feature = "std"), no_std)] @@ -726,7 +726,7 @@ construct_runtime!( // Treasury Treasury: pallet_treasury::{Pallet, Call, Storage, Event} = 26, - // Preimage registrar. + // Preimage registry. Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 28, // System scheduler. Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 29, diff --git a/runtime/dolphin/src/xcm_config.rs b/runtime/dolphin/src/xcm_config.rs index a3acdf992..46b003f0d 100644 --- a/runtime/dolphin/src/xcm_config.rs +++ b/runtime/dolphin/src/xcm_config.rs @@ -15,18 +15,12 @@ // along with Manta. If not, see . use super::{ - assets_config::{DolphinAssetConfig, DolphinConcreteFungibleLedger}, - AssetManager, Assets, Call, DmpQueue, EnsureRootOrMoreThanHalfCouncil, Event, Origin, - ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, Treasury, XcmpQueue, - MAXIMUM_BLOCK_WEIGHT, + assets_config::DolphinAssetConfig, AssetManager, Assets, Call, DmpQueue, + EnsureRootOrMoreThanHalfCouncil, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, Treasury, XcmpQueue, MAXIMUM_BLOCK_WEIGHT, }; - use codec::{Decode, Encode}; -use scale_info::TypeInfo; - use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; -use sp_std::prelude::*; - use frame_support::{ match_types, parameter_types, traits::{Everything, Nothing}, @@ -34,21 +28,17 @@ use frame_support::{ }; use frame_system::EnsureRoot; use manta_primitives::{ - assets::{AssetIdLocationConvert, AssetLocation}, - types::{AccountId, AssetId, Balance}, + assets::AssetIdLocationConvert, + types::{AccountId, Balance, DolphinAssetId}, xcm::{ AccountIdToMultiLocation, FirstAssetTrader, IsNativeConcrete, MultiAssetAdapter, MultiNativeAsset, }, }; - -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; - -// Polkadot imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; - +use scale_info::TypeInfo; +use sp_std::prelude::*; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, @@ -59,6 +49,9 @@ use xcm_builder::{ }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; @@ -137,21 +130,19 @@ parameter_types! { /// Transactor for assets in pallet-assets, i.e. implements `fungibles` trait pub type MultiAssetTransactor = MultiAssetAdapter< Runtime, + // Used to find the query the native asset id of the chain. + DolphinAssetConfig, // "default" implementation of converting a `MultiLocation` to an `AccountId` LocationToAccountId, // Used when the incoming asset is a fungible concrete asset matching the given location or name: IsNativeConcrete, // Used to match incoming assets which are not the native asset. ConvertedConcreteAssetId< - AssetId, + DolphinAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - // Precondition checks and actual implementations of mint and burn logic. - DolphinConcreteFungibleLedger, - // Used to find the query the native asset id of the chain. - DolphinAssetConfig, >; match_types! { @@ -188,14 +179,14 @@ parameter_types! { } pub type XcmFeesToAccount = manta_primitives::xcm::XcmFeesToAccount< + AccountId, Assets, ConvertedConcreteAssetId< - AssetId, + DolphinAssetId, Balance, - AssetIdLocationConvert, + AssetIdLocationConvert, JustTry, >, - AccountId, XcmFeesAccount, >; @@ -221,7 +212,7 @@ impl Config for XcmExecutorConfig { // i.e. units_per_second in `AssetManager` type Trader = ( FixedRateOfFungible, - FirstAssetTrader, + FirstAssetTrader, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -288,14 +279,15 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { // We wrap AssetId for XToken #[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] pub enum CurrencyId { - MantaCurrency(AssetId), + MantaCurrency(DolphinAssetId), } +/// Maps a xTokens CurrencyId to a xcm MultiLocation implemented by some asset manager pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); impl sp_runtime::traits::Convert> for CurrencyIdtoMultiLocation where - AssetXConverter: xcm_executor::traits::Convert, + AssetXConverter: xcm_executor::traits::Convert, { fn convert(currency: CurrencyId) -> Option { match currency { @@ -317,9 +309,8 @@ impl orml_xtokens::Config for Runtime { type Event = Event; type Balance = Balance; type CurrencyId = CurrencyId; - type AccountIdToMultiLocation = AccountIdToMultiLocation; - type CurrencyIdConvert = - CurrencyIdtoMultiLocation>; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdConvert = CurrencyIdtoMultiLocation>; type XcmExecutor = XcmExecutor; type SelfLocation = SelfReserve; // Take note that this pallet does not have the typical configurable WeightInfo. diff --git a/runtime/manta/src/lib.rs b/runtime/manta/src/lib.rs index 74a62e5b2..55c6145d1 100644 --- a/runtime/manta/src/lib.rs +++ b/runtime/manta/src/lib.rs @@ -633,7 +633,7 @@ construct_runtime!( Aura: pallet_aura::{Pallet, Storage, Config} = 23, AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24, - // Preimage registrar. + // Preimage registry. Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 28, // System scheduler Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 29,