diff --git a/runtimes/peregrine/Cargo.toml b/runtimes/peregrine/Cargo.toml index 95ad7135a..11f80570e 100644 --- a/runtimes/peregrine/Cargo.toml +++ b/runtimes/peregrine/Cargo.toml @@ -26,7 +26,7 @@ parity-scale-codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -hex-literal = { workspace = true, optional = true } +hex-literal = { workspace = true } # RPC & Runtime API frame-system-rpc-runtime-api = { workspace = true } @@ -151,7 +151,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "hex-literal", "ismp-parachain/runtime-benchmarks", "kilt-support/runtime-benchmarks", "pallet-asset-switch/runtime-benchmarks", diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index 17b72c9f5..27c384a6a 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -66,6 +66,7 @@ mod ismp; use crate::runtime_apis::RUNTIME_API_VERSION; mod weights; pub mod xcm; +pub mod xcm_components; #[cfg(feature = "runtime-benchmarks")] mod benchmarks; diff --git a/runtimes/peregrine/src/xcm.rs b/runtimes/peregrine/src/xcm.rs index dfb476bc8..3ace10ca5 100644 --- a/runtimes/peregrine/src/xcm.rs +++ b/runtimes/peregrine/src/xcm.rs @@ -18,8 +18,8 @@ use crate::{ kilt::{CheckingAccount, KiltToEKiltSwitchPallet}, - AllPalletsWithSystem, AssetSwitchPool1, Balances, Fungibles, MessageQueue, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, WeightToFee, XcmpQueue, + xcm_components, AllPalletsWithSystem, AssetSwitchPool1, Balances, Fungibles, MessageQueue, ParachainInfo, + ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Treasury, WeightToFee, XcmpQueue, }; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; @@ -203,12 +203,22 @@ impl xcm_executor::Config for XcmConfig { >, // Transactor for fungibles matching the "Here" location. LocalAssetTransactor, + // Transactor for BKilts + FungiblesAdapter< + Fungibles, + xcm_components::matcher::MatchesBkiltAsset, + LocationToAccountIdConverter, + AccountId, + NoChecking, + CheckingAccount, + >, ); type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = ( NativeAsset, IsSwitchPairRemoteAsset, IsSwitchPairXcmFeeAsset, + xcm_components::is_reserve::IsBKilt, ); // Teleporting is disabled. diff --git a/runtimes/peregrine/src/xcm_components/is_reserve.rs b/runtimes/peregrine/src/xcm_components/is_reserve.rs new file mode 100644 index 000000000..2c831bbf5 --- /dev/null +++ b/runtimes/peregrine/src/xcm_components/is_reserve.rs @@ -0,0 +1,54 @@ +// KILT Blockchain – +// Copyright (C) 2025, KILT Foundation + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at + +use frame_support::traits::ContainsPair; +use xcm::v4::{Asset, Location}; + +use super::{get_remote_asset_id, get_remote_reserve_location}; + +const LOG_TARGET: &str = "xcm::barriers::bkilt::AllowBkiltAsset"; + +pub struct IsBKilt; + +impl ContainsPair for IsBKilt { + fn contains(a: &Asset, b: &Location) -> bool { + log::info!(target: LOG_TARGET, "contains {:?}, {:?}", a, b); + + // 1 get asset location. + let asset_location = get_remote_reserve_location(); + if asset_location != *b { + log::trace!( + target: LOG_TARGET, + "Remote origin {:?} does not match expected origin {:?}", + b, + asset_location + ); + return false; + } + + let target_asset_id = get_remote_asset_id(); + + let is_target_asset_id = target_asset_id == a.id; + + if !is_target_asset_id { + log::trace!(target: LOG_TARGET, "Asset ID does not match the expected asset ID. Expected: {:?}, Actual: {:?}", target_asset_id, a.id); + } + + is_target_asset_id + } +} diff --git a/runtimes/peregrine/src/xcm_components/matcher.rs b/runtimes/peregrine/src/xcm_components/matcher.rs new file mode 100644 index 000000000..eabef41f1 --- /dev/null +++ b/runtimes/peregrine/src/xcm_components/matcher.rs @@ -0,0 +1,49 @@ +// KILT Blockchain – +// Copyright (C) 2025, KILT Foundation + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at + +use frame_support::ensure; +use xcm::v4::{Asset, AssetId, Fungibility, Location}; +use xcm_executor::traits::{Error as XcmExecutorError, MatchesFungibles}; + +use super::get_remote_asset_id; + +const LOG_TARGET: &str = "xcm::matcher::MatchesBkiltAsset"; + +pub struct MatchesBkiltAsset; + +impl MatchesFungibles for MatchesBkiltAsset +where + FungiblesBalance: From, +{ + fn matches_fungibles(a: &Asset) -> Result<(Location, FungiblesBalance), XcmExecutorError> { + log::info!(target: LOG_TARGET, "matches_fungibles {:?}", a); + + let asset_id = get_remote_asset_id(); + ensure!(asset_id == a.id, XcmExecutorError::AssetNotHandled); + + let AssetId(location) = asset_id; + + let Fungibility::Fungible(amount) = a.fun else { + log::info!(target: LOG_TARGET, "Input asset {:?} is supposed to be fungible but it is not.", a); + return Err(XcmExecutorError::AmountToBalanceConversionFailed); + }; + + log::trace!(target: LOG_TARGET, "matched {:?}", (location.clone(), amount)); + Ok((location, amount.into())) + } +} diff --git a/runtimes/peregrine/src/xcm_components/mod.rs b/runtimes/peregrine/src/xcm_components/mod.rs new file mode 100644 index 000000000..0d8b4466f --- /dev/null +++ b/runtimes/peregrine/src/xcm_components/mod.rs @@ -0,0 +1,31 @@ +use cumulus_primitives_core::Junction; +use hex_literal::hex; +use xcm::v4::{AssetId, Junctions, Location, NetworkId}; + +pub mod is_reserve; +pub mod matcher; + +fn get_remote_asset_id() -> AssetId { + let asset_address: [u8; 20] = hex!("5d3d01fd6d2ad1169b17918eb4f153c6616288eb"); + + AssetId(Location { + parents: 1, + interior: Junctions::X2( + [ + Junction::GlobalConsensus(NetworkId::Ethereum { chain_id: 11155111 }), + Junction::AccountKey20 { + network: None, + key: asset_address, + }, + ] + .into(), + ), + }) +} + +fn get_remote_reserve_location() -> Location { + Location { + parents: 1, + interior: Junctions::X1([Junction::Parachain(100u32)].into()), + } +}