difftreelog
From Karura transfers
in: master
2 files changed
README.mddiffbeforeafterboth340To get started, you need to open the hrmr channel.340To get started, you need to open the hrmr channel.341Next, we need to register our asset in Karura.341Next, we need to register our asset in Karura.342342343```343assetRegistry -> registerForeignAsset(location, metadata)344assetRegistry -> registerForeignAsset(location, metadata)344location:345location:345 V0(X2(Parent, Parachain(PARA_ID))) 346 V0(X2(Parent, Parachain(PARA_ID))) 348 symbol OPL349 symbol OPL349 decimals 15350 decimals 15350minimalBalance 1351minimalBalance 1352```351353352Next, we can send tokens of our chain:354Next, we can send tokens of our chain:355```353polkadotXcm -> reserveTransferAssets356polkadotXcm -> reserveTransferAssets354dest:357dest:355 V0(X2(Parent, Parachain(KARURA_PARA_ID))) 358 V0(X2(Parent, Parachain(<KARURA_PARA_ID>))) 356beneficiary:359beneficiary:357 X1(AccountId(Any, ACCOUNT))360 X1(AccountId(Any, <ACCOUNT>))358assets:361assets:359 V1(Concrete(0,Here), Fungible(AMOUNT))362 V1(Concrete(0,Here), Fungible(<AMOUNT>))360feeAssetItem: 363feeAssetItem: 361 0 364 0 362weightLimit:365weightLimit:363 Limit366 <LIMIT>364 367``` 365368366The result will be displayed in ChainState 369The result will be displayed in ChainState 367tokens -> accounts 370tokens -> accounts 368371372373To send tokens from karura:374375```376xtokens -> transfer377378currencyId:379 ForeingAsset380 <TOKEN_ID>381382amount:383 <AMOUNT>384dest:385 V1386 (387 Parents:1, 388 X2(Parachain(<KARURA_PARA_ID>), AccountId(Any, <ACCOUNT>)389 )390destWeight:391 <WEIGHT>392 393394```runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -23,7 +23,8 @@
use sp_runtime::{
Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
traits::{
- AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion,
+ AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify,
+ AccountIdConversion, Zero,
},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature, RuntimeAppPublic,
@@ -45,8 +46,9 @@
dispatch::DispatchResult,
PalletId, parameter_types, StorageValue, ConsensusEngineId,
traits::{
- Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem,
- LockIdentifier, OnUnbalanced, Randomness, FindAuthor,
+ tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
+ Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
+ OnUnbalanced, Randomness, FindAuthor,
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
@@ -69,8 +71,9 @@
use pallet_evm::{Account as EVMAccount, FeeCalculator, GasWeightMapping, OnMethodCall};
use fp_rpc::TransactionStatus;
use sp_runtime::{
- traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf},
+ traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf, Saturating},
transaction_validity::TransactionValidityError,
+ SaturatedConversion,
};
// pub use pallet_timestamp::Call as TimestampCall;
@@ -82,23 +85,21 @@
use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
- EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset,
- ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
- SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
- SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
+ EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
+ ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
+ SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
};
-use xcm_executor::{Config, XcmExecutor};
+use xcm_executor::{Config, XcmExecutor, Assets};
+use sp_std::{marker::PhantomData};
-use log::{debug};
-use sp_std::{borrow::Borrow, marker::PhantomData};
-
use xcm::latest::{
-// Xcm,
+ // Xcm,
AssetId::{Concrete},
Fungibility::Fungible as XcmFungible,
- MultiAsset
+ MultiAsset,
+ Error as XcmError,
};
-use xcm_executor::traits::{ShouldExecute, WeightBounds, MatchesFungible, WeightTrader, Convert};
+use xcm_executor::traits::{MatchesFungible, WeightTrader};
//use xcm_executor::traits::MatchesFungible;
use sp_runtime::traits::CheckedConversion;
@@ -605,38 +606,7 @@
type ReservedXcmpWeight = ReservedXcmpWeight;
type XcmpMessageHandler = XcmpQueue;
}
-
-pub struct SiblingParachainConvertsVia2<ParaId, AccountId>(PhantomData<(ParaId, AccountId)>);
-impl<ParaId: From<u32> + Into<u32> + AccountIdConversion<AccountId>, AccountId: Clone + core::fmt::Debug>
- Convert<MultiLocation, AccountId> for SiblingParachainConvertsVia2<ParaId, AccountId>
-{
- fn convert_ref(location: impl Borrow<MultiLocation>) -> Result<AccountId, ()> {
-
-
- match location.borrow() {
- MultiLocation { parents: 1, interior: X1(Parachain(id)) } => {
- log::debug!(
- target: "xcm::converter",
- "SiblingParachainConvertsVia2 accountId: {:?}",
- ParaId::from(*id).into_account(),
- );
- Ok(ParaId::from(*id).into_account())
- }
- _ => Err(()),
- }
- }
-
- fn reverse_ref(who: impl Borrow<AccountId>) -> Result<MultiLocation, ()> {
- if let Some(id) = ParaId::try_from_account(who.borrow()) {
- Ok(MultiLocation::new(1, X1(Parachain(id.into()))))
- } else {
- Err(())
- }
- }
-}
-
-
impl parachain_info::Config for Runtime {}
impl cumulus_pallet_aura_ext::Config for Runtime {}
@@ -655,18 +625,16 @@
// The parent (Relay-chain) origin converts to the default `AccountId`.
ParentIsDefault<AccountId>,
// Sibling parachain origins convert to AccountId via the `ParaId::into`.
- SiblingParachainConvertsVia2<Sibling, AccountId>,
+ SiblingParachainConvertsVia<Sibling, AccountId>,
// Straight up local `AccountId32` origins just alias directly to `AccountId`.
AccountId32Aliases<RelayNetwork, AccountId>,
);
-
pub struct OnlySelfCurrency;
impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
fn matches_fungible(a: &MultiAsset) -> Option<B> {
match (&a.id, &a.fun) {
- (Concrete(_), XcmFungible(ref amount)) =>
- CheckedConversion::checked_from(*amount),
+ (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
_ => None,
}
}
@@ -733,6 +701,88 @@
// ^^^ Parent & its unit plurality gets free execution
);
+pub struct UsingOnlySelfCurrencyComponents<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+>(
+ Weight,
+ Currency::Balance,
+ PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
+);
+impl<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+ > WeightTrader
+ for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
+{
+ fn new() -> Self {
+ Self(0, Zero::zero(), PhantomData)
+ }
+
+ fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
+ let amount = WeightToFee::calc(&weight);
+ let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
+
+ // location to this parachain through relay chain
+ let option1: xcm::v1::AssetId = Concrete(MultiLocation {
+ parents: 1,
+ interior: X1(Parachain(ParachainInfo::parachain_id().into())),
+ });
+ // direct location
+ let option2: xcm::v1::AssetId = Concrete(MultiLocation {
+ parents: 0,
+ interior: Here,
+ });
+
+ let required = if payment.fungible.contains_key(&option1) {
+ (option1, u128_amount).into()
+ } else if payment.fungible.contains_key(&option2) {
+ (option2, u128_amount).into()
+ } else {
+ (Concrete(MultiLocation::default()), u128_amount).into()
+ };
+
+ let unused = payment
+ .checked_sub(required)
+ .map_err(|_| XcmError::TooExpensive)?;
+ self.0 = self.0.saturating_add(weight);
+ self.1 = self.1.saturating_add(amount);
+ Ok(unused)
+ }
+
+ fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
+ let weight = weight.min(self.0);
+ let amount = WeightToFee::calc(&weight);
+ self.0 -= weight;
+ self.1 = self.1.saturating_sub(amount);
+ let amount: u128 = amount.saturated_into();
+ if amount > 0 {
+ Some((AssetId::get(), amount).into())
+ } else {
+ None
+ }
+ }
+}
+impl<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+ > Drop
+ for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
+{
+ fn drop(&mut self) {
+ OnUnbalanced::on_unbalanced(Currency::issue(self.1));
+ }
+}
+
pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
@@ -745,7 +795,13 @@
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;
+ type Trader = UsingOnlySelfCurrencyComponents<
+ IdentityFee<Balance>,
+ RelayLocation,
+ AccountId,
+ Balances,
+ (),
+ >;
type ResponseHandler = (); // Don't handle responses for now.
type SubscriptionService = PolkadotXcm;