Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local Pluralities Get Free Xcm Execution #125

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Election provider: use a geometric deposit base calculation for EPM signed submissions in Polkadot and Kusama ([polkadot-fellows/runtimes#56](https://github.com/polkadot-fellows/runtimes/pull/56))
- Make `IdentityInfo` generic in `pallet-identity` ([polkadot-fellows/runtimes#87](https://github.com/polkadot-fellows/runtimes/pull/87)). Context: https://github.com/paritytech/polkadot-sdk/pull/1661
- Whitelist `force_default_xcm_version` in XCM call filter ([polkadot-fellows/runtimes#45](https://github.com/polkadot-fellows/runtimes/pull/45))
- Set up an account ID for the local root location on Polkadot Collectives ([polkadot-fellows/runtimes#125](https://github.com/polkadot-fellows/runtimes/pull/125))

### Added

Expand Down
12 changes: 10 additions & 2 deletions relay/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use super::{
};
use frame_support::{
match_types, parameter_types,
traits::{Contains, Everything, Nothing},
traits::{Contains, Equals, Everything, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
Expand All @@ -47,6 +47,7 @@ use xcm_builder::{
use xcm_executor::traits::WithOriginFilter;

parameter_types! {
pub const RootLocation: MultiLocation = Here.into_location();
/// The location of the KSM token, from the context of this chain. Since this token is native to this
/// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to
/// the context".
Expand Down Expand Up @@ -147,6 +148,9 @@ match_types! {
pub type OnlyParachains: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Parachain(_)) }
};
pub type LocalPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Plurality { .. }) }
};
}

/// The barriers one of which must be passed for an XCM message to be executed.
Expand Down Expand Up @@ -321,6 +325,10 @@ impl Contains<RuntimeCall> for SafeCallFilter {
}
}

/// Locations that will not be charged fees in the executor, neither for execution nor delivery.
/// We only waive fees for system functions, which these locations represent.
pub type WaivedLocations = (SystemParachains, Equals<RootLocation>, LocalPlurality);

pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
Expand All @@ -347,7 +355,7 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
// No bridges yet...
type MessageExporter = ();
type UniversalAliases = Nothing;
Expand Down
12 changes: 10 additions & 2 deletions relay/polkadot/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use super::{
};
use frame_support::{
match_types, parameter_types,
traits::{Contains, Everything, Nothing},
traits::{Contains, Equals, Everything, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
Expand Down Expand Up @@ -52,6 +52,7 @@ use xcm_builder::{
use xcm_executor::traits::WithOriginFilter;

parameter_types! {
pub const RootLocation: MultiLocation = Here.into_location();
/// The location of the DOT token, from the context of this chain. Since this token is native to this
/// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to
/// the context".
Expand Down Expand Up @@ -161,6 +162,9 @@ match_types! {
MultiLocation { parents: 0, interior: X1(Parachain(COLLECTIVES_ID)) } |
MultiLocation { parents: 0, interior: X2(Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }) }
};
pub type LocalPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Plurality { .. }) }
};
}

/// The barriers one of which must be passed for an XCM message to be executed.
Expand Down Expand Up @@ -324,6 +328,10 @@ impl Contains<RuntimeCall> for SafeCallFilter {
}
}

/// Locations that will not be charged fees in the executor, neither for execution nor delivery.
/// We only waive fees for system functions, which these locations represent.
pub type WaivedLocations = (SystemParachains, Equals<RootLocation>, LocalPlurality);

pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
Expand Down Expand Up @@ -351,7 +359,7 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeesToAccount<Self, SystemParachains, AccountId, TreasuryAccount>;
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
// No bridges yet...
type MessageExporter = ();
type UniversalAliases = Nothing;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
mod origins;
mod tracks;
use crate::{
impls::ToParentTreasury, weights, xcm_config::TreasurerBodyId, AccountId, AssetRate, Balance,
Balances, FellowshipReferenda, GovernanceLocation, PolkadotTreasuryAccount, Preimage, Runtime,
RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, DAYS,
impls::ToParentTreasury,
weights,
xcm_config::{LocationToAccountId, TreasurerBodyId},
AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation,
PolkadotTreasuryAccount, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
Scheduler, DAYS,
};
use cumulus_primitives_core::Junction::GeneralIndex;
use frame_support::{
Expand All @@ -38,16 +41,13 @@ pub use origins::{
};
use pallet_ranked_collective::EnsureOfRank;
use pallet_xcm::{EnsureXcm, IsVoiceOfBody};
use parachains_common::polkadot::account;
use polkadot_runtime_common::impls::{
LocatableAssetConverter, VersionedLocatableAsset, VersionedMultiLocationConverter,
};
use polkadot_runtime_constants::{currency::GRAND, time::HOURS, xcm::body::FELLOWSHIP_ADMIN_INDEX};
use sp_arithmetic::Permill;
use sp_core::{ConstU128, ConstU32};
use sp_runtime::traits::{
AccountIdConversion, ConstU16, ConvertToValue, IdentityLookup, Replace, TakeFirst,
};
use sp_runtime::traits::{ConstU16, ConvertToValue, IdentityLookup, Replace, TakeFirst};
use xcm::latest::BodyId;
use xcm_builder::{AliasesIntoAccountId32, LocatableAssetId, PayOverXcm};

Expand All @@ -70,8 +70,6 @@ pub mod ranks {
}

parameter_types! {
// Referenda pallet account, used to temporarily deposit slashed imbalance before teleporting.
pub ReferendaPalletAccount: AccountId = account::REFERENDA_PALLET_ID.into_account_truncating();
pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX);
}

Expand Down Expand Up @@ -101,7 +99,7 @@ impl pallet_referenda::Config<FellowshipReferendaInstance> for Runtime {
>;
type CancelOrigin = Architects;
type KillOrigin = Masters;
type Slash = ToParentTreasury<PolkadotTreasuryAccount, ReferendaPalletAccount, Runtime>;
type Slash = ToParentTreasury<PolkadotTreasuryAccount, LocationToAccountId, Runtime>;
type Votes = pallet_ranked_collective::Votes;
type Tally = pallet_ranked_collective::TallyOf<Runtime, FellowshipCollectiveInstance>;
type SubmissionDeposit = ConstU128<0>;
Expand Down
33 changes: 21 additions & 12 deletions system-parachains/collectives/collectives-polkadot/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use pallet_alliance::{ProposalIndex, ProposalProvider};
use parachains_common::impls::NegativeImbalance;
use sp_runtime::DispatchError;
use sp_std::{cmp::Ordering, marker::PhantomData, prelude::*};
use xcm::latest::{Fungibility, Junction, Parent, WeightLimit};
use xcm::latest::{Fungibility, Junction, Junctions::Here, MultiLocation, Parent, WeightLimit};
use xcm_executor::traits::ConvertLocation;

type AccountIdOf<T> = <T as frame_system::Config>::AccountId;

Expand All @@ -38,36 +39,44 @@ pub type BalanceOf<T> =

/// Implements `OnUnbalanced::on_unbalanced` to teleport slashed assets to relay chain treasury
/// account.
pub struct ToParentTreasury<TreasuryAccount, PalletAccount, T>(
PhantomData<(TreasuryAccount, PalletAccount, T)>,
pub struct ToParentTreasury<TreasuryAccount, AccountIdConverter, T>(
PhantomData<(TreasuryAccount, AccountIdConverter, T)>,
);

impl<TreasuryAccount, PalletAccount, T> OnUnbalanced<NegativeImbalance<T>>
for ToParentTreasury<TreasuryAccount, PalletAccount, T>
impl<TreasuryAccount, AccountIdConverter, T> OnUnbalanced<NegativeImbalance<T>>
for ToParentTreasury<TreasuryAccount, AccountIdConverter, T>
where
T: pallet_balances::Config + pallet_xcm::Config + frame_system::Config,
<<T as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId: From<AccountIdOf<T>>,
[u8; 32]: From<<T as frame_system::Config>::AccountId>,
TreasuryAccount: Get<AccountIdOf<T>>,
PalletAccount: Get<AccountIdOf<T>>,
BalanceOf<T>: Into<Fungibility>,
AccountIdConverter: ConvertLocation<AccountIdOf<T>>,
{
fn on_unbalanced(amount: NegativeImbalance<T>) {
let amount = match amount.drop_zero() {
Ok(..) => return,
Err(amount) => amount,
};
let imbalance = amount.peek();
let pallet_acc: AccountIdOf<T> = PalletAccount::get();
let treasury_acc: AccountIdOf<T> = TreasuryAccount::get();

<pallet_balances::Pallet<T>>::resolve_creating(&pallet_acc, amount);
let root_location: MultiLocation = Here.into();
Copy link
Contributor Author

@muharem muharem Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are few options,

  • (current) resolve funds into root account temporarily and teleport on behalf of the root
  • calculated an expected fee for the execution and delivery and keep that amount within the account to pay the fee
  • keep as it is, and grant free execution to the pallet's account id. where an account id has to be whitelisted as a location X1(AccountId32(some_bytes_of_pallet_account_id))

I think the current is the most optimal

let root_account: AccountIdOf<T> =
match AccountIdConverter::convert_location(&root_location) {
Some(a) => a,
None => {
log::warn!("Failed to convert root origin into account id");
return
},
};
let treasury_account: AccountIdOf<T> = TreasuryAccount::get();

<pallet_balances::Pallet<T>>::resolve_creating(&root_account, amount);

let result = <pallet_xcm::Pallet<T>>::limited_teleport_assets(
<<T as frame_system::Config>::RuntimeOrigin>::signed(pallet_acc.into()),
<<T as frame_system::Config>::RuntimeOrigin>::root(),
Box::new(Parent.into()),
Box::new(
Junction::AccountId32 { network: None, id: treasury_acc.into() }
Junction::AccountId32 { network: None, id: treasury_account.into() }
.into_location()
.into(),
),
Expand Down
8 changes: 3 additions & 5 deletions system-parachains/collectives/collectives-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ use parachains_common::{
};
use sp_runtime::RuntimeDebug;
use xcm_config::{
GovernanceLocation, TreasurerBodyId, XcmConfig, XcmOriginToTransactDispatchOrigin,
GovernanceLocation, LocationToAccountId, TreasurerBodyId, XcmConfig,
XcmOriginToTransactDispatchOrigin,
};

#[cfg(any(feature = "std", test))]
Expand Down Expand Up @@ -509,9 +510,6 @@ pub const MAX_ALLIES: u32 = 100;

parameter_types! {
pub const AllyDeposit: Balance = 1_000 * UNITS; // 1,000 DOT bond to join as an Ally
// The Alliance pallet account, used as a temporary place to deposit a slashed imbalance
// before the teleport to the Treasury.
pub AlliancePalletAccount: AccountId = ALLIANCE_PALLET_ID.into_account_truncating();
pub PolkadotTreasuryAccount: AccountId = POLKADOT_TREASURY_PALLET_ID.into_account_truncating();
// The number of blocks a member must wait between giving a retirement notice and retiring.
// Supposed to be greater than time required to `kick_member` with alliance motion.
Expand All @@ -525,7 +523,7 @@ impl pallet_alliance::Config for Runtime {
type MembershipManager = RootOrAllianceTwoThirdsMajority;
type AnnouncementOrigin = RootOrAllianceTwoThirdsMajority;
type Currency = Balances;
type Slashed = ToParentTreasury<PolkadotTreasuryAccount, AlliancePalletAccount, Runtime>;
type Slashed = ToParentTreasury<PolkadotTreasuryAccount, LocationToAccountId, Runtime>;
type InitializeMembers = AllianceMotion;
type MembershipChanged = AllianceMotion;
type RetirementPeriod = AllianceRetirementPeriod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter,
DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
EnsureXcmOrigin, FixedWeightBounds, HashedDescription, IsConcrete, OriginToPluralityVoice,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount,
DescribeTerminus, EnsureXcmOrigin, FixedWeightBounds, HashedDescription, IsConcrete,
OriginToPluralityVoice, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
UsingComponents, WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};

parameter_types! {
pub const RootLocation: MultiLocation = MultiLocation::here();
pub const DotLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: Option<NetworkId> = Some(NetworkId::Polkadot);
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
Expand All @@ -71,6 +72,8 @@ pub type LocationToAccountId = (
AccountId32Aliases<RelayNetwork, AccountId>,
// Foreign locations alias into accounts according to a hash of their standard description.
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
// Here/local root location to `AccountId`.
HashedDescription<AccountId, DescribeTerminus>,
);

/// Means for transacting the native currency on this chain.
Expand Down Expand Up @@ -132,6 +135,9 @@ match_types! {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(_) }
};
pub type LocalPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Plurality { .. }) }
};
}

/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
Expand Down Expand Up @@ -261,8 +267,12 @@ match_types! {
/// Locations that will not be charged fees in the executor,
/// either execution or delivery.
/// We only waive fees for system functions, which these locations represent.
pub type WaivedLocations =
(RelayOrOtherSystemParachains<SystemParachains, Runtime>, Equals<RelayTreasuryLocation>);
pub type WaivedLocations = (
RelayOrOtherSystemParachains<SystemParachains, Runtime>,
Equals<RelayTreasuryLocation>,
Equals<RootLocation>,
LocalPlurality,
);

/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
/// - DOT with the parent Relay Chain and sibling parachains.
Expand Down
Loading