orml_xcm/
lib.rs

1//! # Xcm Module
2
3#![cfg_attr(not(feature = "std"), no_std)]
4#![allow(clippy::large_enum_variant)]
5
6use frame_support::{pallet_prelude::*, traits::EnsureOrigin};
7use frame_system::pallet_prelude::*;
8use sp_std::boxed::Box;
9use xcm::{v5::prelude::*, VersionedLocation, VersionedXcm};
10
11pub use module::*;
12
13#[frame_support::pallet]
14pub mod module {
15	use super::*;
16
17	#[pallet::config]
18	pub trait Config: frame_system::Config + pallet_xcm::Config {
19		/// The required origin for sending XCM as parachain sovereign.
20		///
21		/// Typically root or the majority of collective.
22		type SovereignOrigin: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
23	}
24
25	#[pallet::pallet]
26	pub struct Pallet<T>(_);
27
28	#[pallet::event]
29	#[pallet::generate_deposit(pub(super) fn deposit_event)]
30	pub enum Event<T: Config> {
31		/// XCM message sent. \[to, message\]
32		Sent { to: Location, message: Xcm<()> },
33	}
34
35	#[pallet::error]
36	pub enum Error<T> {
37		/// The message and destination combination was not recognized as being
38		/// reachable.
39		Unreachable,
40		/// The message and destination was recognized as being reachable but
41		/// the operation could not be completed.
42		SendFailure,
43		/// The version of the `Versioned` value used is not able to be
44		/// interpreted.
45		BadVersion,
46	}
47
48	#[pallet::call]
49	impl<T: Config> Pallet<T> {
50		/// Send an XCM message as parachain sovereign.
51		#[pallet::call_index(0)]
52		// FIXME: Benchmark send
53		#[pallet::weight(Weight::from_parts(100_000_000, 0))]
54		pub fn send_as_sovereign(
55			origin: OriginFor<T>,
56			dest: Box<VersionedLocation>,
57			message: Box<VersionedXcm<()>>,
58		) -> DispatchResult {
59			let _ = T::SovereignOrigin::ensure_origin(origin)?;
60			let dest = Location::try_from(*dest).map_err(|()| Error::<T>::BadVersion)?;
61			let message: Xcm<()> = (*message).try_into().map_err(|()| Error::<T>::BadVersion)?;
62
63			pallet_xcm::Pallet::<T>::send_xcm(Here, dest.clone(), message.clone()).map_err(|e| match e {
64				SendError::Unroutable => Error::<T>::Unreachable,
65				_ => Error::<T>::SendFailure,
66			})?;
67			Self::deposit_event(Event::Sent { to: dest, message });
68			Ok(())
69		}
70	}
71}