1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
// KILT Blockchain – https://botlabs.org
// Copyright (C) 2019-2024 BOTLabs GmbH
// 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 <https://www.gnu.org/licenses/>.
// If you feel like getting in touch with us, you can do so at info@botlabs.org
use core::{marker::PhantomData, ops::ControlFlow};
use cumulus_primitives_core::AggregateMessageOrigin;
use frame_support::{match_types, parameter_types, traits::ProcessMessageError, weights::Weight};
use polkadot_parachain::primitives::Sibling;
use sp_runtime::Perbill;
use xcm::v4::prelude::*;
use xcm_builder::{AccountId32Aliases, FungibleAdapter, IsConcrete, ParentIsPreset, SiblingParachainConvertsVia};
use xcm_executor::traits::{Properties, ShouldExecute};
use crate::{AccountId, BlockWeights};
parameter_types! {
// One XCM operation is 200_000_000 weight, cross-chain transfer ~= 2x of transfer.
pub UnitWeightCost: Weight = Weight::from_parts(200_000_000, 0);
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
pub const MaxStale: u32 = 8;
pub const HeapSize: u32 = 64 * 1024;
pub ServiceWeight: Weight = Perbill::from_percent(35) * BlockWeights::get().max_block;
pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
}
match_types! {
pub type ParentLocation: impl Contains<Location> = {
Location { parents: 1, interior: Here}
};
pub type ParentOrSiblings: impl Contains<Location> = {
Location { parents: 1, interior: Here } |
Location { parents: 1, interior: Junctions::X1(_) }
};
}
// Note: This might move to polkadot's xcm module.
/// Deny executing the xcm message if it matches any of the Deny filter
/// regardless of anything else. If it passes the Deny and matches one of the
/// Allow cases, then it is let through.
pub struct DenyThenTry<Deny, Allow>(PhantomData<(Deny, Allow)>);
impl<Deny, Allow> ShouldExecute for DenyThenTry<Deny, Allow>
where
Deny: ShouldExecute,
Allow: ShouldExecute,
{
fn should_execute<Call>(
origin: &Location,
instructions: &mut [Instruction<Call>],
max_weight: Weight,
properties: &mut Properties,
) -> Result<(), ProcessMessageError> {
Deny::should_execute(origin, instructions, max_weight, properties)?;
Allow::should_execute(origin, instructions, max_weight, properties)
}
}
/// Reserved funds to the relay chain can't return. See <https://github.com/paritytech/polkadot/issues/5233>
/// Usage of the new xcm matcher. See <https://github.com/paritytech/polkadot/pull/7098>
pub struct DenyReserveTransferToRelayChain;
impl ShouldExecute for DenyReserveTransferToRelayChain {
fn should_execute<RuntimeCall>(
origin: &Location,
message: &mut [Instruction<RuntimeCall>],
_max_weight: Weight,
_properties: &mut Properties,
) -> Result<(), ProcessMessageError> {
xcm_builder::MatchXcm::match_next_inst_while(
xcm_builder::CreateMatcher::matcher(message),
|_| true,
|inst| match inst {
InitiateReserveWithdraw {
reserve: Location {
parents: 1,
interior: Here,
},
..
}
| DepositReserveAsset {
dest: Location {
parents: 1,
interior: Here,
},
..
}
| TransferReserveAsset {
dest: Location {
parents: 1,
interior: Here,
},
..
}
| TransferAsset {
beneficiary: Location {
parents: 1,
interior: Here,
},
..
} => {
Err(ProcessMessageError::Unsupported) // Deny
}
// We don't accept DOTs from the relay chain for the moment. Only AH should pass.
ReserveAssetDeposited { .. }
if matches!(
origin,
Location {
parents: 1,
interior: Here
}
) =>
{
Err(ProcessMessageError::Unsupported) // Deny
}
_ => Ok(ControlFlow::Continue(())),
},
)?;
// Permit everything else
Ok(())
}
}
parameter_types! {
pub const RelayLocation: Location = Location::parent();
pub const HereLocation: Location = Location::here();
}
/// Type for specifying how a `Location` can be converted into an
/// `AccountId`. This is used when determining ownership of accounts for asset
/// transacting and when attempting to use XCM `Transact` in order to determine
/// the dispatch Origin.
pub type LocationToAccountId<NetworkId> = (
// The parent (Relay-chain) origin converts to the b"parent" `AccountId`.
ParentIsPreset<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<NetworkId, AccountId>,
);
/// Means for transacting assets on this chain.
pub type LocalAssetTransactor<Currency, NetworkId> = FungibleAdapter<
// Use this currency:
Currency,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<HereLocation>,
// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
LocationToAccountId<NetworkId>,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
(),
>;