diff --git a/Cargo.lock b/Cargo.lock index ce85704..e05d3ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2222,6 +2222,15 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "dp-xcm-reserve" +version = "0.1.0" +dependencies = [ + "frame-support", + "log", + "staging-xcm", +] + [[package]] name = "dtoa" version = "1.0.10" @@ -5873,6 +5882,7 @@ dependencies = [ name = "pallet-xcm-executor-utils" version = "0.1.0" dependencies = [ + "dp-xcm-reserve", "frame-benchmarking", "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 6cdc9f8..a58657b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ dp-consensus = { path = "primitives/consensus", default-features = false } dp-container-chain-genesis-data = { path = "primitives/container-chain-genesis-data", default-features = false } dp-core = { path = "primitives/core", default-features = false } dp-impl-tanssi-pallets-config = { path = "primitives/core", default-features = false } +dp-xcm-reserve = { path = "primitives/xcm-reserve", default-features = false } test-relay-sproof-builder = { path = "test-sproof-builder", default-features = false } # Moonkit (wasm) diff --git a/pallets/xcm-executor-utils/Cargo.toml b/pallets/xcm-executor-utils/Cargo.toml index e4704cf..66be0fb 100644 --- a/pallets/xcm-executor-utils/Cargo.toml +++ b/pallets/xcm-executor-utils/Cargo.toml @@ -29,6 +29,9 @@ sp-io = { workspace = true } sp-runtime = { workspace = true } staging-xcm = { workspace = true } +# Dancekit +dp-xcm-reserve = { workspace = true } + # Moonkit pallet-migrations = { workspace = true } @@ -36,6 +39,7 @@ pallet-migrations = { workspace = true } [features] default = [ "std" ] std = [ + "dp-xcm-reserve/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", diff --git a/pallets/xcm-executor-utils/src/filters.rs b/pallets/xcm-executor-utils/src/filters.rs index eb40767..819205b 100644 --- a/pallets/xcm-executor-utils/src/filters.rs +++ b/pallets/xcm-executor-utils/src/filters.rs @@ -16,8 +16,9 @@ use { crate::{Config, DefaultTrustPolicy, TrustPolicy}, + dp_xcm_reserve::NativeAssetReserve, frame_support::{pallet_prelude::*, traits::ContainsPair}, - staging_xcm::latest::{Asset, Junction::Parachain, Junctions::Here, Location}, + staging_xcm::latest::{Asset, Location}, }; /// Returns true if the policy allows this asset @@ -74,62 +75,6 @@ where } } -// TODO: this should probably move to somewhere in the polkadot-sdk repo -pub struct NativeAssetReserve; -impl ContainsPair for NativeAssetReserve { - fn contains(asset: &Asset, origin: &Location) -> bool { - let reserve = if asset.id.0.parents == 0 - && !matches!(asset.id.0.first_interior(), Some(Parachain(_))) - { - Some(Location::here()) - } else { - asset.id.0.chain_part() - }; - - if let Some(ref reserve) = reserve { - if reserve == origin { - return true; - } - } - false - } -} - -pub trait Parse { - /// Returns the "chain" location part. It could be parent, sibling - /// parachain, or child parachain. - fn chain_part(&self) -> Option; - /// Returns "non-chain" location part. - fn non_chain_part(&self) -> Option; -} - -impl Parse for Location { - fn chain_part(&self) -> Option { - match (self.parents, self.first_interior()) { - // sibling parachain - (1, Some(Parachain(id))) => Some(Location::new(1, [Parachain(*id)])), - // parent - (1, _) => Some(Location::parent()), - // children parachain - (0, Some(Parachain(id))) => Some(Location::new(0, [Parachain(*id)])), - _ => None, - } - } - - fn non_chain_part(&self) -> Option { - let junctions = self.interior(); - while matches!(junctions.first(), Some(Parachain(_))) { - let _ = junctions.clone().take_first(); - } - - if junctions.clone() != Here { - Some(Location::new(0, junctions.clone())) - } else { - None - } - } -} - #[cfg(test)] mod test { use { diff --git a/primitives/xcm-reserve/Cargo.toml b/primitives/xcm-reserve/Cargo.toml new file mode 100644 index 0000000..95f2ffe --- /dev/null +++ b/primitives/xcm-reserve/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "dp-xcm-reserve" +authors = { workspace = true } +description = "Dancekit xcm reserve primitives" +edition = "2021" +license = "GPL-3.0-only" +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[lints] +workspace = true + +[dependencies] +log = { workspace = true } + +# Substrate +frame-support = { workspace = true } +staging-xcm = { workspace = true } + +[features] +default = [ "std" ] +std = [ + "frame-support/std", + "log/std", + "staging-xcm/std", +] diff --git a/primitives/xcm-reserve/src/lib.rs b/primitives/xcm-reserve/src/lib.rs new file mode 100644 index 0000000..e602144 --- /dev/null +++ b/primitives/xcm-reserve/src/lib.rs @@ -0,0 +1,58 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi 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. + +// Tanssi 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 Tanssi. If not, see + +#![cfg_attr(not(feature = "std"), no_std)] + +use { + frame_support::traits::ContainsPair, + staging_xcm::latest::{Asset, Junction::Parachain, Location}, +}; + +// TODO: this should probably move to somewhere in the polkadot-sdk repo +pub struct NativeAssetReserve; +impl ContainsPair for NativeAssetReserve { + fn contains(asset: &Asset, origin: &Location) -> bool { + log::trace!(target: "xcm::contains", "NativeAssetReserve asset: {:?}, origin: {:?}", asset, origin); + let reserve = if asset.id.0.parents == 0 + && !matches!(asset.id.0.first_interior(), Some(Parachain(_))) + { + Some(Location::here()) + } else { + chain_part(&asset.id.0) + }; + + if let Some(ref reserve) = reserve { + if reserve == origin { + return true; + } + } + false + } +} + +/// Returns the "chain" location part. It could be parent, sibling +/// parachain, or child parachain. +pub fn chain_part(this: &Location) -> Option { + match (this.parents, this.first_interior()) { + // sibling parachain + (1, Some(Parachain(id))) => Some(Location::new(1, [Parachain(*id)])), + // parent + (1, _) => Some(Location::parent()), + // children parachain + (0, Some(Parachain(id))) => Some(Location::new(0, [Parachain(*id)])), + _ => None, + } +}