Skip to content

Commit

Permalink
feat(system-parachains/asset-hubs): Configure AH Polkadot
Browse files Browse the repository at this point in the history
- [Assets] Call implementation for `transfer_all` (SDK #4527)
- [bridges-v2] Permissionless lanes (SDK #4949)
- add possibility to inject non-authorities session-keys in genesis (SDK #5078)
- Tx Payment: drop ED requirements for tx payments with exchangeable asset (SDK #4488)
- relax XcmFeeToAccount trait bound on AccountId (SDK #4959)
  • Loading branch information
pandres95 committed Oct 20, 2024
1 parent 548308c commit c926aa6
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 249 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub fn genesis() -> Storage {
)
})
.collect(),
// TODO: Any keys to add here?
non_authority_keys: vec![],
},
polkadot_xcm: asset_hub_polkadot_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ fn asset_hub_polkadot_genesis(
)
})
.collect(),
// TODO: Any keys to add here?
non_authority_keys: vec![],
},
"polkadotXcm": {
"safeXcmVersion": Some(SAFE_XCM_VERSION),
Expand Down
179 changes: 0 additions & 179 deletions system-parachains/asset-hubs/asset-hub-polkadot/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,10 @@ pub mod tx_payment {
ensure,
pallet_prelude::{InvalidTransaction, TransactionValidityError},
traits::{
fungibles::{Balanced as FungiblesBalanced, Inspect as FungiblesInspect},
tokens::{Fortitude, Precision, Preservation},
Defensive, OnUnbalanced, SameOrOther,
},
};
use pallet_asset_conversion::{Pallet as AssetConversion, SwapCredit};
use pallet_asset_conversion_tx_payment::OnChargeAssetTransaction;
use pallet_transaction_payment::OnChargeTransaction;
use sp_core::Get;
use sp_runtime::{
Expand Down Expand Up @@ -124,180 +121,4 @@ pub mod tx_payment {
Ok(())
}
}

type LiquidityInfoOf<T> =
<<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<
T,
>>::LiquidityInfo;

/// Implements [`OnChargeAssetTransaction`] for [`pallet_asset_conversion_tx_payment`], where
/// the asset class used to pay the fee is defined with the `A` type parameter (eg. DOT
/// location) and accessed via the type implementing the [`frame_support::traits::fungibles`]
/// trait.
pub struct SwapCreditAdapter<A, S>(PhantomData<(A, S)>);
impl<A, S, T> OnChargeAssetTransaction<T> for SwapCreditAdapter<A, S>
where
A: Get<S::AssetKind>,
S: SwapCredit<
T::AccountId,
Balance = T::Balance,
AssetKind = T::AssetKind,
Credit = fungibles::Credit<T::AccountId, T::Assets>,
>,

T: pallet_asset_conversion_tx_payment::Config,
T::Fungibles:
fungibles::Inspect<T::AccountId, Balance = T::Balance, AssetId = T::AssetKind>,
T::OnChargeTransaction:
OnChargeTransaction<T, Balance = T::Balance, LiquidityInfo = Option<S::Credit>>,
{
type AssetId = T::AssetKind;
type Balance = T::Balance;
type LiquidityInfo = T::Balance;

fn withdraw_fee(
who: &<T>::AccountId,
_call: &<T>::RuntimeCall,
_dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
asset_id: Self::AssetId,
fee: Self::Balance,
_tip: Self::Balance,
) -> Result<(LiquidityInfoOf<T>, Self::LiquidityInfo, T::Balance), TransactionValidityError>
{
let asset_fee = AssetConversion::<T>::quote_price_tokens_for_exact_tokens(
asset_id.clone(),
A::get(),
fee,
true,
)
.ok_or(InvalidTransaction::Payment)?;

let asset_fee_credit = T::Assets::withdraw(
asset_id.clone(),
who,
asset_fee,
Precision::Exact,
Preservation::Preserve,
Fortitude::Polite,
)
.map_err(|_| TransactionValidityError::from(InvalidTransaction::Payment))?;

let (fee_credit, change) = match S::swap_tokens_for_exact_tokens(
vec![asset_id, A::get()],
asset_fee_credit,
fee,
) {
Ok((fee_credit, change)) => (fee_credit, change),
Err((credit_in, _)) => {
// The swap should not error since the price quote was successful.
let _ = T::Assets::resolve(who, credit_in).defensive();
return Err(InvalidTransaction::Payment.into())
},
};

// Should be always zero since the exact price was quoted before.
ensure!(change.peek().is_zero(), InvalidTransaction::Payment);

Ok((Some(fee_credit), fee, asset_fee))
}
fn correct_and_deposit_fee(
who: &<T>::AccountId,
dispatch_info: &DispatchInfoOf<<T>::RuntimeCall>,
post_info: &PostDispatchInfoOf<<T>::RuntimeCall>,
corrected_fee: Self::Balance,
tip: Self::Balance,
fee_paid: LiquidityInfoOf<T>,
_received_exchanged: Self::LiquidityInfo,
asset_id: Self::AssetId,
initial_asset_consumed: T::Balance,
) -> Result<T::Balance, TransactionValidityError> {
let Some(fee_paid) = fee_paid else {
return Ok(Zero::zero());
};
// Try to refund if the fee paid is more than the corrected fee and the account was not
// removed by the dispatched function.
let (fee, fee_in_asset) = if fee_paid.peek() > corrected_fee &&
!T::Assets::total_balance(asset_id.clone(), who).is_zero()
{
let refund_amount = fee_paid.peek().saturating_sub(corrected_fee);
// Check if the refund amount can be swapped back into the asset used by `who` for
// fee payment.
let refund_asset_amount =
AssetConversion::<T>::quote_price_exact_tokens_for_tokens(
A::get(),
asset_id.clone(),
refund_amount,
true,
)
// No refund given if it cannot be swapped back.
.unwrap_or(Zero::zero());

// Deposit the refund before the swap to ensure it can be processed.
let debt = match T::Assets::deposit(
asset_id.clone(),
who,
refund_asset_amount,
Precision::BestEffort,
) {
Ok(debt) => debt,
// No refund given since it cannot be deposited.
Err(_) => fungibles::Debt::<T::AccountId, T::Assets>::zero(asset_id.clone()),
};

if debt.peek().is_zero() {
// No refund given.
(fee_paid, initial_asset_consumed)
} else {
let (refund, fee_paid) = fee_paid.split(refund_amount);
match S::swap_exact_tokens_for_tokens(
vec![A::get(), asset_id],
refund,
Some(refund_asset_amount),
) {
Ok(refund_asset) => {
match refund_asset.offset(debt) {
Ok(SameOrOther::None) => {},
// This arm should never be reached, as the amount of `debt` is
// expected to be exactly equal to the amount of `refund_asset`
// credit.
_ => return Err(InvalidTransaction::Payment.into()),
};
(fee_paid, initial_asset_consumed.saturating_sub(refund_asset_amount))
},
// The error should not occur since swap was quoted before.
Err((refund, _)) => {
match T::Assets::settle(who, debt, Preservation::Expendable) {
Ok(dust) =>
ensure!(dust.peek().is_zero(), InvalidTransaction::Payment),
// The error should not occur as the `debt` was just withdrawn
// above.
Err(_) => return Err(InvalidTransaction::Payment.into()),
};
let fee_paid = fee_paid.merge(refund).map_err(|_| {
// The error should never occur since `fee_paid` and `refund` are
// credits of the same asset.
TransactionValidityError::from(InvalidTransaction::Payment)
})?;
(fee_paid, initial_asset_consumed)
},
}
}
} else {
(fee_paid, initial_asset_consumed)
};

// Refund is already processed.
let corrected_fee = fee.peek();
// Deposit fee.
T::OnChargeTransaction::correct_and_deposit_fee(
who,
dispatch_info,
post_info,
corrected_fee,
tip,
Some(fee),
)
.map(|_| fee_in_asset)
}
}
}
30 changes: 12 additions & 18 deletions system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ use frame_support::{
parameter_types,
traits::{
fungible, fungibles, tokens::imbalance::ResolveAssetTo, AsEnsureOriginWithArg, ConstBool,
ConstU32, ConstU64, ConstU8, EitherOfDiverse, Equals, InstanceFilter, NeverEnsureOrigin,
ConstU32, ConstU64, ConstU8, EitherOfDiverse, InstanceFilter, NeverEnsureOrigin,
TransformOrigin, WithdrawReasons,
},
weights::{ConstantMultiplier, Weight, WeightToFee as _},
Expand Down Expand Up @@ -764,9 +764,13 @@ impl pallet_collator_selection::Config for Runtime {

impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = LocalAndForeignAssets;
type OnChargeAssetTransaction =
impls::tx_payment::SwapCreditAdapter<DotLocationV3, AssetConversion>;
type AssetId = xcm::v3::Location;
type OnChargeAssetTransaction = pallet_asset_conversion_tx_payment::SwapAssetAdapter<
DotLocationV3,
NativeAndAssets,
AssetConversion,
ResolveAssetTo<StakingPot, NativeAndAssets>,
>;
}

parameter_types! {
Expand Down Expand Up @@ -842,32 +846,22 @@ impl pallet_nfts::Config for Runtime {
/// consensus with dynamic fees and back-pressure.
pub type ToKusamaXcmRouterInstance = pallet_xcm_bridge_hub_router::Instance1;
impl pallet_xcm_bridge_hub_router::Config<ToKusamaXcmRouterInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo<Runtime>;

type UniversalLocation = xcm_config::UniversalLocation;
type BridgedNetworkId = xcm_config::bridging::to_kusama::KusamaNetwork;
type Bridges = xcm_config::bridging::NetworkExportTable;
type DestinationVersion = PolkadotXcm;

#[cfg(not(feature = "runtime-benchmarks"))]
type BridgeHubOrigin = EnsureXcm<Equals<xcm_config::bridging::SiblingBridgeHub>>;
#[cfg(feature = "runtime-benchmarks")]
type BridgeHubOrigin = frame_support::traits::EitherOfDiverse<
// for running benchmarks
EnsureRoot<AccountId>,
// for running tests with `--feature runtime-benchmarks`
EnsureXcm<Equals<xcm_config::bridging::SiblingBridgeHub>>,
>;
type SiblingBridgeHubLocation = xcm_config::bridging::SiblingBridgeHub;

type ToBridgeHubSender = XcmpQueue;
type WithBridgeHubChannel =
cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider<
xcm_config::bridging::SiblingBridgeHubParaId,
Runtime,
>;

type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee;
type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId;
type LocalXcmChannelManager =
cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider<Runtime>;
}

pub type PoolAssetsInstance = pallet_assets::Instance3;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ use xcm_builder::{
DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor,
FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
IsConcrete, LocalMint, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith,
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignPaidRemoteExporter,
SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeeManagerFromComponents,
};
use xcm_executor::{traits::ConvertLocation, XcmExecutor};

Expand Down Expand Up @@ -449,7 +449,7 @@ impl xcm_executor::Config for XcmConfig {
type AssetExchanger = ();
type FeeManager = XcmFeeManagerFromComponents<
WaivedLocations,
XcmFeeToAccount<Self::AssetTransactor, AccountId, RelayTreasuryPalletAccount>,
SendXcmFeeToAccount<Self::AssetTransactor, RelayTreasuryPalletAccount>,
>;
type MessageExporter = ();
type UniversalAliases =
Expand Down

0 comments on commit c926aa6

Please sign in to comment.