From 1c8c05f4530859e4daaddfbee86c9f956e049bbf Mon Sep 17 00:00:00 2001 From: str-mv Date: Wed, 26 Jan 2022 09:53:03 +0000 Subject: [PATCH] From Karura transfers --- --- a/README.md +++ b/README.md @@ -340,6 +340,7 @@ To get started, you need to open the hrmr channel. Next, we need to register our asset in Karura. +``` assetRegistry -> registerForeignAsset(location, metadata) location: V0(X2(Parent, Parachain(PARA_ID))) @@ -348,20 +349,46 @@ symbol OPL decimals 15 minimalBalance 1 +``` Next, we can send tokens of our chain: +``` polkadotXcm -> reserveTransferAssets dest: - V0(X2(Parent, Parachain(KARURA_PARA_ID))) + V0(X2(Parent, Parachain())) beneficiary: - X1(AccountId(Any, ACCOUNT)) + X1(AccountId(Any, )) assets: - V1(Concrete(0,Here), Fungible(AMOUNT)) + V1(Concrete(0,Here), Fungible()) feeAssetItem: 0 weightLimit: - Limit - + +``` The result will be displayed in ChainState tokens -> accounts + + +To send tokens from karura: + +``` +xtokens -> transfer + +currencyId: + ForeingAsset + + +amount: + +dest: + V1 + ( + Parents:1, + X2(Parachain(), AccountId(Any, ) + ) +destWeight: + + + +``` \ No newline at end of file --- 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(PhantomData<(ParaId, AccountId)>); -impl + Into + AccountIdConversion, AccountId: Clone + core::fmt::Debug> - Convert for SiblingParachainConvertsVia2 -{ - fn convert_ref(location: impl Borrow) -> Result { - - - 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) -> Result { - 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, // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia2, + SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, ); - pub struct OnlySelfCurrency; impl> MatchesFungible for OnlySelfCurrency { fn matches_fungible(a: &MultiAsset) -> Option { 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, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, +>( + Weight, + Currency::Balance, + PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, +); +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > WeightTrader + for UsingOnlySelfCurrencyComponents +{ + fn new() -> Self { + Self(0, Zero::zero(), PhantomData) + } + + fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + 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 { + 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, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > Drop + for UsingOnlySelfCurrencyComponents +{ + 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; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; + type Trader = UsingOnlySelfCurrencyComponents< + IdentityFee, + RelayLocation, + AccountId, + Balances, + (), + >; type ResponseHandler = (); // Don't handle responses for now. type SubscriptionService = PolkadotXcm; -- gitstuff