diff --git a/Cargo.lock b/Cargo.lock index 71d6eab4a6e..ac7cba187b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8078,12 +8078,15 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-std", + "xcm", ] [[package]] diff --git a/parachain-template/pallets/template/Cargo.toml b/parachain-template/pallets/template/Cargo.toml index 1ccdc6622ba..1abe5394c57 100644 --- a/parachain-template/pallets/template/Cargo.toml +++ b/parachain-template/pallets/template/Cargo.toml @@ -19,6 +19,10 @@ scale-info = { version = "2.2.0", default-features = false, features = ["derive" frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } + +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } [dev-dependencies] serde = { version = "1.0.163" } @@ -37,5 +41,8 @@ std = [ "frame-benchmarking/std", "frame-support/std", "frame-system/std", + "sp-std/std", + "pallet-xcm/std", + "xcm/std", ] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = [ "frame-support/try-runtime", "pallet-xcm/try-runtime" ] diff --git a/parachain-template/pallets/template/src/lib.rs b/parachain-template/pallets/template/src/lib.rs index 5f3252bfc3a..911896d15d4 100644 --- a/parachain-template/pallets/template/src/lib.rs +++ b/parachain-template/pallets/template/src/lib.rs @@ -18,10 +18,12 @@ mod benchmarking; pub mod pallet { use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use sp_std::boxed::Box; + use xcm::{v3::prelude::*, VersionedMultiLocation, VersionedXcm}; /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config + pallet_xcm::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -45,6 +47,8 @@ pub mod pallet { /// Event documentation should end with an array that provides descriptive names for event /// parameters. [something, who] SomethingStored(u32, T::AccountId), + /// XCM message sent. \[to, message\] + Sent { from: T::AccountId, to: MultiLocation, message: Xcm<()> }, } // Errors inform users that something went wrong. @@ -54,6 +58,15 @@ pub mod pallet { NoneValue, /// Errors should have helpful documentation associated with them. StorageOverflow, + /// The message and destination combination was not recognized as being + /// reachable. + Unreachable, + /// The message and destination was recognized as being reachable but + /// the operation could not be completed. + SendFailure, + /// The version of the `Versioned` value used is not able to be + /// interpreted. + BadVersion, } #[pallet::hooks] @@ -102,5 +115,27 @@ pub mod pallet { }, } } + + /// Send an XCM message as parachain sovereign. + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(100_000_000, 0))] + pub fn send_xcm( + origin: OriginFor, + dest: Box, + message: Box>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; + let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + + pallet_xcm::Pallet::::send_xcm(Here, dest, message.clone()).map_err( + |e| match e { + SendError::Unroutable => Error::::Unreachable, + _ => Error::::SendFailure, + }, + )?; + Self::deposit_event(Event::Sent { from: who, to: dest, message }); + Ok(()) + } } }