shiden_runtime/
xcm_config.rs

1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19use super::{
20    AccountId, AllPalletsWithSystem, AssetId, Assets, Balance, Balances, DealWithFees,
21    MessageQueue, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
22    RuntimeOrigin, ShidenAssetLocationIdConverter, TreasuryAccountId, XcAssetConfig,
23    XcmWeightToFee, XcmpQueue,
24};
25use crate::weights;
26use frame_support::{
27    parameter_types,
28    traits::{ConstU32, Contains, Everything, Nothing},
29    weights::Weight,
30};
31use frame_system::EnsureRoot;
32
33// Polkadot imports
34use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
35use frame_support::traits::{Disabled, TransformOrigin};
36use parachains_common::{
37    message_queue::ParaIdToSibling, xcm_config::ParentRelayOrSiblingParachains,
38};
39use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery;
40use xcm::latest::prelude::*;
41use xcm_builder::{
42    AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
43    AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, ConvertedConcreteId,
44    DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor,
45    FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete, NoChecking,
46    ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
47    SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
48    SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
49    WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
50};
51use xcm_executor::{
52    traits::{JustTry, WithOriginFilter},
53    XcmExecutor,
54};
55
56// Astar imports
57use astar_primitives::xcm::{FixedRateOfForeignAsset, ReserveAssetFilter, XcmFungibleFeeHandler};
58
59parameter_types! {
60    pub RelayNetwork: Option<NetworkId> = Some(NetworkId::Kusama);
61    pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
62    pub UniversalLocation: InteriorLocation =
63    [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into();
64    pub const ShidenLocation: Location = Here.into_location();
65    pub DummyCheckingAccount: AccountId = PolkadotXcm::check_account();
66}
67
68/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
69/// when determining ownership of accounts for asset transacting and when attempting to use XCM
70/// `Transact` in order to determine the dispatch Origin.
71pub type LocationToAccountId = (
72    // The parent (Relay-chain) origin converts to the default `AccountId`.
73    ParentIsPreset<AccountId>,
74    // Sibling parachain origins convert to AccountId via the `ParaId::into`.
75    SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>,
76    // Straight up local `AccountId32` origins just alias directly to `AccountId`.
77    AccountId32Aliases<RelayNetwork, AccountId>,
78    // Generates private `AccountId`s from `Location`s, in a stable & safe way.
79    // Replaces the old `Account32Hash` approach.
80    HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
81);
82
83/// Means for transacting the native currency on this chain.
84pub type CurrencyTransactor = FungibleAdapter<
85    // Use this currency:
86    Balances,
87    // Use this currency when it is a fungible asset matching the given location or name:
88    IsConcrete<ShidenLocation>,
89    // Convert an XCM Location into a local account id:
90    LocationToAccountId,
91    // Our chain's account ID type (we can't get away without mentioning it explicitly):
92    AccountId,
93    // We don't track any teleports of `Balances`.
94    (),
95>;
96
97/// Means for transacting assets besides the native currency on this chain.
98pub type FungiblesTransactor = FungiblesAdapter<
99    // Use this fungibles implementation:
100    Assets,
101    // Use this currency when it is a fungible asset matching the given location or name:
102    ConvertedConcreteId<AssetId, Balance, ShidenAssetLocationIdConverter, JustTry>,
103    // Convert an XCM Location into a local account id:
104    LocationToAccountId,
105    // Our chain's account ID type (we can't get away without mentioning it explicitly):
106    AccountId,
107    // We don't support teleport so no need to check any assets.
108    NoChecking,
109    // We don't track any teleports of `Assets`.
110    DummyCheckingAccount,
111>;
112
113/// Means for transacting assets on this chain.
114pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor);
115
116/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
117/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
118/// biases the kind of local `Origin` it will become.
119pub type XcmOriginToTransactDispatchOrigin = (
120    // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
121    // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
122    // foreign chains who want to have a local sovereign account on this chain which they control.
123    SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
124    // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
125    // recognised.
126    RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
127    // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
128    // recognised.
129    SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
130    // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
131    // transaction from the Root origin.
132    ParentAsSuperuser<RuntimeOrigin>,
133    // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
134    pallet_xcm::XcmPassthrough<RuntimeOrigin>,
135    // Native signed account converter; this just converts an `AccountId32` origin into a normal
136    // `Origin::Signed` origin of the same 32-byte value.
137    SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
138);
139
140parameter_types! {
141    // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
142    // For the PoV size, we estimate 4 kB per instruction. This will be changed when we benchmark the instructions.
143    pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 4 * 1024);
144    pub const MaxInstructions: u32 = 100;
145}
146
147pub struct ParentOrParentsPlurality;
148impl Contains<Location> for ParentOrParentsPlurality {
149    fn contains(location: &Location) -> bool {
150        matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
151    }
152}
153
154/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
155/// account for proof size weights.
156pub struct SafeCallFilter;
157impl SafeCallFilter {
158    // 1. RuntimeCall::EVM(..) & RuntimeCall::Ethereum(..) have to be prohibited since we cannot measure PoV size properly
159
160    /// Checks whether the base (non-composite) call is allowed to be executed via `Transact` XCM instruction.
161    pub fn allow_base_call(call: &RuntimeCall) -> bool {
162        match call {
163            RuntimeCall::System(..)
164            | RuntimeCall::Identity(..)
165            | RuntimeCall::Balances(..)
166            | RuntimeCall::Vesting(..)
167            | RuntimeCall::DappStaking(..)
168            | RuntimeCall::Assets(..)
169            | RuntimeCall::Session(..)
170            | RuntimeCall::Proxy(
171                pallet_proxy::Call::add_proxy { .. }
172                | pallet_proxy::Call::remove_proxy { .. }
173                | pallet_proxy::Call::remove_proxies { .. }
174                | pallet_proxy::Call::create_pure { .. }
175                | pallet_proxy::Call::kill_pure { .. }
176                | pallet_proxy::Call::announce { .. }
177                | pallet_proxy::Call::remove_announcement { .. }
178                | pallet_proxy::Call::reject_announcement { .. },
179            )
180            | RuntimeCall::Multisig(
181                pallet_multisig::Call::approve_as_multi { .. }
182                | pallet_multisig::Call::cancel_as_multi { .. },
183            ) => true,
184            RuntimeCall::PolkadotXcm(call) => !matches!(
185                call,
186                pallet_xcm::Call::send { .. } | pallet_xcm::Call::execute { .. }
187            ),
188            _ => false,
189        }
190    }
191    /// Checks whether composite call is allowed to be executed via `Transact` XCM instruction.
192    ///
193    /// Each composite call's subcalls are checked against base call filter. No nesting of composite calls is allowed.
194    pub fn allow_composite_call(call: &RuntimeCall) -> bool {
195        match call {
196            RuntimeCall::Proxy(pallet_proxy::Call::proxy { call, .. }) => {
197                Self::allow_base_call(call)
198            }
199            RuntimeCall::Proxy(pallet_proxy::Call::proxy_announced { call, .. }) => {
200                Self::allow_base_call(call)
201            }
202            RuntimeCall::Utility(pallet_utility::Call::batch { calls, .. }) => {
203                calls.iter().all(|call| Self::allow_base_call(call))
204            }
205            RuntimeCall::Utility(pallet_utility::Call::batch_all { calls, .. }) => {
206                calls.iter().all(|call| Self::allow_base_call(call))
207            }
208            RuntimeCall::Utility(pallet_utility::Call::as_derivative { call, .. }) => {
209                Self::allow_base_call(call)
210            }
211            RuntimeCall::Multisig(pallet_multisig::Call::as_multi_threshold_1 { call, .. }) => {
212                Self::allow_base_call(call)
213            }
214            RuntimeCall::Multisig(pallet_multisig::Call::as_multi { call, .. }) => {
215                Self::allow_base_call(call)
216            }
217            _ => false,
218        }
219    }
220}
221
222impl Contains<RuntimeCall> for SafeCallFilter {
223    fn contains(call: &RuntimeCall) -> bool {
224        Self::allow_base_call(call) || Self::allow_composite_call(call)
225    }
226}
227
228pub type XcmBarrier = TrailingSetTopicAsId<(
229    TakeWeightCredit,
230    // Expected responses are OK.
231    AllowKnownQueryResponses<PolkadotXcm>,
232    // Allow XCMs with some computed origins to pass through.
233    WithComputedOrigin<
234        (
235            // If the message is one that immediately attempts to pay for execution, then allow it.
236            AllowTopLevelPaidExecutionFrom<Everything>,
237            // Subscriptions for version tracking are OK.
238            AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
239        ),
240        UniversalLocation,
241        ConstU32<8>,
242    >,
243    // Parent and its plurality get free execution
244    AllowUnpaidExecutionFrom<ParentOrParentsPlurality>,
245)>;
246
247// Used to handle XCM fee deposit into treasury account
248pub type ShidenXcmFungibleFeeHandler = XcmFungibleFeeHandler<
249    AccountId,
250    ConvertedConcreteId<AssetId, Balance, ShidenAssetLocationIdConverter, JustTry>,
251    Assets,
252    TreasuryAccountId,
253>;
254
255pub struct XcmConfig;
256impl xcm_executor::Config for XcmConfig {
257    type RuntimeCall = RuntimeCall;
258    type XcmSender = XcmRouter;
259    type AssetTransactor = AssetTransactors;
260    type OriginConverter = XcmOriginToTransactDispatchOrigin;
261    type IsReserve = ReserveAssetFilter;
262    type IsTeleporter = ();
263    type UniversalLocation = UniversalLocation;
264    type Barrier = XcmBarrier;
265    type Weigher = Weigher;
266    type Trader = (
267        UsingComponents<XcmWeightToFee, ShidenLocation, AccountId, Balances, DealWithFees>,
268        FixedRateOfForeignAsset<XcAssetConfig, ShidenXcmFungibleFeeHandler>,
269    );
270    type ResponseHandler = PolkadotXcm;
271    type AssetTrap = PolkadotXcm;
272    type AssetClaims = PolkadotXcm;
273    type SubscriptionService = PolkadotXcm;
274
275    type PalletInstancesInfo = AllPalletsWithSystem;
276    type MaxAssetsIntoHolding = ConstU32<64>;
277    type AssetLocker = ();
278    type AssetExchanger = ();
279    type FeeManager = ();
280    type MessageExporter = ();
281    type UniversalAliases = Nothing;
282    type CallDispatcher = WithOriginFilter<SafeCallFilter>;
283    type SafeCallFilter = SafeCallFilter;
284    type Aliasers = Nothing;
285    type TransactionalProcessor = FrameTransactionalProcessor;
286
287    type HrmpNewChannelOpenRequestHandler = ();
288    type HrmpChannelAcceptedHandler = ();
289    type HrmpChannelClosingHandler = ();
290    type XcmRecorder = PolkadotXcm;
291    type XcmEventEmitter = PolkadotXcm;
292}
293
294/// Local origins on this chain are allowed to dispatch XCM sends/executions.
295pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
296
297/// The means for routing XCM messages which are not for local execution into the right message
298/// queues.
299pub type XcmRouter = WithUniqueTopic<(
300    // Two routers - use UMP to communicate with the relay chain:
301    cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, ()>,
302    // ..and XCMP to communicate with the sibling chains.
303    XcmpQueue,
304)>;
305
306pub type Weigher =
307    WeightInfoBounds<weights::xcm::XcmWeight<Runtime, RuntimeCall>, RuntimeCall, MaxInstructions>;
308
309impl pallet_xcm::Config for Runtime {
310    const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
311
312    type RuntimeEvent = RuntimeEvent;
313    type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
314    type XcmRouter = XcmRouter;
315    type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
316    type XcmExecuteFilter = Nothing;
317    type XcmExecutor = XcmExecutor<XcmConfig>;
318    type XcmTeleportFilter = Nothing;
319    type XcmReserveTransferFilter = Everything;
320    type Weigher = Weigher;
321    type UniversalLocation = UniversalLocation;
322    type RuntimeOrigin = RuntimeOrigin;
323    type RuntimeCall = RuntimeCall;
324    type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
325
326    type Currency = Balances;
327    type CurrencyMatcher = ();
328    type TrustedLockers = ();
329    type SovereignAccountOf = LocationToAccountId;
330    type MaxLockers = ConstU32<0>;
331    type WeightInfo = weights::pallet_xcm::SubstrateWeight<Runtime>;
332    type MaxRemoteLockConsumers = ConstU32<0>;
333    type RemoteLockConsumerIdentifier = ();
334    type AdminOrigin = EnsureRoot<AccountId>;
335    type AuthorizedAliasConsideration = Disabled;
336}
337
338impl cumulus_pallet_xcm::Config for Runtime {
339    type RuntimeEvent = RuntimeEvent;
340    type XcmExecutor = XcmExecutor<XcmConfig>;
341}
342
343impl cumulus_pallet_xcmp_queue::Config for Runtime {
344    type RuntimeEvent = RuntimeEvent;
345    type ChannelInfo = ParachainSystem;
346    type VersionWrapper = PolkadotXcm;
347    type XcmpQueue = TransformOrigin<MessageQueue, AggregateMessageOrigin, ParaId, ParaIdToSibling>;
348    type MaxInboundSuspended = ConstU32<1_000>;
349    type MaxActiveOutboundChannels = ConstU32<128>;
350    type MaxPageSize = ConstU32<{ 128 * 1024 }>;
351    type ControllerOrigin = EnsureRoot<AccountId>;
352    type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
353    type PriceForSiblingDelivery = NoPriceForMessageDelivery<ParaId>;
354    type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight<Runtime>;
355}