referrerpolicy=no-referrer-when-downgrade

snowbridge_runtime_common/v2/
register_token.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3
4use frame_support::{
5	dispatch::RawOrigin,
6	sp_runtime::traits::MaybeEquivalence,
7	traits::{ContainsPair, EnsureOrigin, EnsureOriginWithArg, Everything, OriginTrait},
8};
9use frame_system::ensure_signed;
10use pallet_xcm::{EnsureXcm, Origin as XcmOrigin};
11use xcm::prelude::Location;
12
13/// Origin check that verifies that an origin is the owner of a foreign asset.
14/// 1. Allows XCM origins
15/// 2. Checks that the asset exists
16/// 3. The origin must be the owner of the asset
17pub struct ForeignAssetOwner<IsForeign, AssetInspect, AccountId, LocationToAccountId, L = Location>(
18	core::marker::PhantomData<(IsForeign, AssetInspect, AccountId, LocationToAccountId, L)>,
19);
20impl<
21		IsForeign: ContainsPair<L, L>,
22		AssetInspect: frame_support::traits::fungibles::roles::Inspect<AccountId>,
23		AccountId: Eq + Clone,
24		LocationToAccountId: xcm_executor::traits::ConvertLocation<AccountId>,
25		RuntimeOrigin: From<XcmOrigin> + OriginTrait + Clone,
26		L: From<Location> + Into<Location> + Clone,
27	> EnsureOriginWithArg<RuntimeOrigin, L>
28	for ForeignAssetOwner<IsForeign, AssetInspect, AccountId, LocationToAccountId, L>
29where
30	for<'a> &'a RuntimeOrigin::PalletsOrigin: TryInto<&'a XcmOrigin>,
31	<AssetInspect as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId: From<Location>,
32{
33	type Success = L;
34
35	fn try_origin(
36		origin: RuntimeOrigin,
37		asset_location: &L,
38	) -> Result<Self::Success, RuntimeOrigin> {
39		let origin_location = EnsureXcm::<Everything, L>::try_origin(origin.clone())?;
40		if !IsForeign::contains(asset_location, &origin_location) {
41			return Err(origin)
42		}
43		let asset_location: Location = asset_location.clone().into();
44		let owner = AssetInspect::owner(asset_location.into());
45		let location: Location = origin_location.clone().into();
46		let from = LocationToAccountId::convert_location(&location);
47		if from != owner {
48			return Err(origin)
49		}
50		Ok(location.into())
51	}
52
53	#[cfg(feature = "runtime-benchmarks")]
54	fn try_successful_origin(a: &L) -> Result<RuntimeOrigin, ()> {
55		let latest_location: Location = (*a).clone().try_into().map_err(|_| ())?;
56		Ok(pallet_xcm::Origin::Xcm(latest_location).into())
57	}
58}
59
60/// Origin check that verifies that an origin is the owner of a local trusted asset.
61/// 1. Allows signed origins
62/// 2. Checks that the asset exists
63/// 3. The origin must be the owner of the asset
64pub struct LocalAssetOwner<MatchAssetId, AssetInspect, AccountId, AssetId, L = Location>(
65	core::marker::PhantomData<(MatchAssetId, AssetInspect, AccountId, AssetId, L)>,
66);
67impl<
68		MatchAssetId: MaybeEquivalence<L, AssetId>,
69		AssetInspect: frame_support::traits::fungibles::roles::Inspect<AccountId>,
70		AccountId: Eq + Clone + Into<L>,
71		AssetId: Eq + Clone,
72		RuntimeOrigin: OriginTrait + Clone,
73		L: From<Location> + Into<Location> + Clone,
74	> EnsureOriginWithArg<RuntimeOrigin, L>
75	for LocalAssetOwner<MatchAssetId, AssetInspect, AccountId, AssetId, L>
76where
77	RuntimeOrigin: Into<Result<RawOrigin<AccountId>, RuntimeOrigin>> + From<RawOrigin<AccountId>>,
78	<AssetInspect as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId: From<AssetId>,
79{
80	type Success = L;
81
82	fn try_origin(
83		origin: RuntimeOrigin,
84		asset_location: &L,
85	) -> Result<Self::Success, RuntimeOrigin> {
86		let who = ensure_signed(origin.clone()).map_err(|_| origin.clone())?;
87		let asset_id = MatchAssetId::convert(asset_location).ok_or(origin.clone())?;
88		let owner = AssetInspect::owner(asset_id.into()).ok_or(origin.clone())?;
89		if who != owner {
90			return Err(origin)
91		}
92		Ok(who.into())
93	}
94
95	#[cfg(feature = "runtime-benchmarks")]
96	fn try_successful_origin(_: &L) -> Result<RuntimeOrigin, ()> {
97		Ok(RawOrigin::Root.into())
98	}
99}