From a3753aa7c1bbd9d5497421ea74fedee97350b15b Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Sat, 4 Jun 2022 21:18:37 +0300 Subject: [PATCH 1/7] try-2: works Signed-off-by: Georgi Zlatarev --- traits/src/xcm_transfer.rs | 25 ++++ xtokens/src/lib.rs | 292 ++++++++++++++++++++++++++++++++++--- 2 files changed, 297 insertions(+), 20 deletions(-) diff --git a/traits/src/xcm_transfer.rs b/traits/src/xcm_transfer.rs index 18913cb00..2e9b07457 100644 --- a/traits/src/xcm_transfer.rs +++ b/traits/src/xcm_transfer.rs @@ -1,5 +1,6 @@ use frame_support::dispatch::DispatchResult; use frame_support::weights::Weight; +use sp_std::vec::Vec; use xcm::latest::prelude::*; /// Abstraction over cross-chain token transfers. @@ -11,6 +12,8 @@ pub trait XcmTransfer { amount: Balance, dest: MultiLocation, dest_weight: Weight, + maybe_call: Option>, + maybe_transact_fee: Balance, ) -> DispatchResult; /// Transfer `MultiAsset` @@ -21,3 +24,25 @@ pub trait XcmTransfer { dest_weight: Weight, ) -> DispatchResult; } + +// /// Abstraction over cross-chain token transfers. +// pub trait XcmTransfer { +// /// Transfer native currencies. +// fn transfer( +// who: AccountId, +// currency_id: CurrencyId, +// amount: Balance, +// dest: MultiLocation, +// dest_weight: Weight, +// maybe_call: Option>, +// maybe_transact_fee: Balance, +// ) -> DispatchResult; + +// /// Transfer `MultiAsset` +// fn transfer_multi_asset( +// who: AccountId, +// asset: MultiAsset, +// dest: MultiLocation, +// dest_weight: Weight, +// ) -> DispatchResult; +// } diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 1d52a63c6..8dba78455 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -36,7 +36,7 @@ use sp_runtime::{ }; use sp_std::{prelude::*, result::Result}; -use xcm::prelude::*; +use xcm::{prelude::*, DoubleEncoded}; use xcm_executor::traits::{InvertLocation, WeightBounds}; pub use module::*; @@ -94,6 +94,8 @@ pub mod module { /// XCM executor. type XcmExecutor: ExecuteXcm; + type XcmSender: SendXcm; + /// MultiLocation filter type MultiLocationsFilter: Contains; @@ -195,6 +197,8 @@ pub mod module { /// received. Receiving depends on if the XCM message could be delivered /// by the network, and if the receiving chain would handle /// messages correctly. + //#[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), *amount, dest, maybe_call, + //#[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), dest_weight))] #[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), *amount, dest))] #[transactional] pub fn transfer( @@ -203,10 +207,20 @@ pub mod module { amount: T::Balance, dest: Box, dest_weight: Weight, + maybe_call: Option>, + maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer(who, currency_id, amount, dest, dest_weight) + Self::do_transfer( + who, + currency_id, + amount, + dest, + dest_weight, + maybe_call, + maybe_transact_fee, + ) } /// Transfer `MultiAsset`. @@ -371,7 +385,7 @@ pub mod module { // We first grab the fee let fee: &MultiAsset = assets.get(fee_item as usize).ok_or(Error::::AssetIndexNonExistent)?; - Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight) + Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight, None, None) } } @@ -382,6 +396,8 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, + maybe_call: Option>, + maybe_transact_fee: Option, ) -> DispatchResult { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -392,8 +408,28 @@ pub mod module { Error::::NotSupportedMultiLocation ); - let asset: MultiAsset = (location, amount.into()).into(); - Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight) + let asset: MultiAsset = (location.clone(), amount.into()).into(); + if let Some(transact_fee) = maybe_transact_fee { + return Self::do_transfer_multiassets( + who, + vec![asset.clone()].into(), + asset, + dest, + dest_weight, + maybe_call, + Some((location, transact_fee.into()).into()), + ); + }; + + Self::do_transfer_multiassets( + who, + vec![asset.clone()].into(), + asset, + dest, + dest_weight, + maybe_call, + None, + ) } fn do_transfer_with_fee( @@ -422,7 +458,7 @@ pub mod module { assets.push(asset); assets.push(fee_asset.clone()); - Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight) + Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight, None, None) } fn do_transfer_multiasset( @@ -431,7 +467,7 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, ) -> DispatchResult { - Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight) + Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight, None, None) } fn do_transfer_multiasset_with_fee( @@ -446,7 +482,7 @@ pub mod module { assets.push(asset); assets.push(fee.clone()); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight)?; + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None)?; Ok(()) } @@ -490,7 +526,7 @@ pub mod module { let fee: MultiAsset = (fee_location, (*fee_amount).into()).into(); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight) + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None) } fn do_transfer_multiassets( @@ -499,6 +535,8 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight: Weight, + maybe_call: Option>, + transact_fee_assets: Option, ) -> DispatchResult { ensure!( assets.len() <= T::MaxAssetsForTransfer::get(), @@ -567,6 +605,8 @@ pub mod module { &dest, Some(T::SelfLocation::get()), dest_weight, + None, + None, )?; // Second xcm send to dest chain. @@ -578,18 +618,109 @@ pub mod module { &dest, None, dest_weight, + // fee_reserve != non_fee_reserve + None, + None, )?; } else { Self::execute_and_send_reserve_kind_xcm( - origin_location, + origin_location.clone(), assets.clone(), fee.clone(), - non_fee_reserve, + non_fee_reserve.clone(), &dest, None, dest_weight, + maybe_call.clone(), + transact_fee_assets.clone(), )?; + + // if let Some(non_fee_reserve) = non_fee_reserve { + // if let Some(call) = maybe_call { + // let (transfer_kind, dest, reserve, recipient) = + // Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; + + // let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; + // let ancestry = T::LocationInverter::ancestry(); + // let fees = asset + // .clone() + // .reanchored(&reserve, &ancestry) + // .map_err(|_| Error::::CannotReanchor)?; + // let mut assets = MultiAssets::new(); + // assets.push(half(&fees.clone())); + // //non_fee_reserve = non_fee_reserve.unwrap(); + // let instructions = Xcm(vec![ + // WithdrawAsset(assets), + // // TODO: unwrap() !! + // Self::buy_execution(half(&fee.clone()), &reserve, dest_weight)?, + // Transact { + // origin_type: OriginKind::SovereignAccount, + // require_weight_at_most: dest_weight, + // call: call.into(), + // }, + // ]); + + // //let interior = origin_location.interior; + // //let dest = dest.into(); + // // if interior != Junctions::Here { + // // instructions.0.insert(0, DescendOrigin(interior)) + // // }; + // let _res = T::XcmSender::send_xcm(non_fee_reserve.clone(), instructions); + + // // pallet_xcm::Pallet::::send_xcm(Here, dest.clone(), + // // message.clone()).map_err(|e| match e { SendError:: + // // CannotReachDestination(..) => + // // Error::::Unreachable, _ => Error:::: + // // SendFailure, })?; + // } + // } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // TODO: can do another execute_and_send_reserve_kind_xcm() for the transact_fee + // instead of in the inner functions... + + if let Some(non_fee_reserve) = non_fee_reserve { + if let Some(call) = maybe_call { + if let Some(transact_fee_asset) = transact_fee_assets { + let (transfer_kind, dest, reserve, recipient) = + Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; + + //let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; + let ancestry = T::LocationInverter::ancestry(); + let transact_fee_asset = transact_fee_asset + .clone() + .reanchored(&reserve, &ancestry) + .map_err(|_| Error::::CannotReanchor)?; + let mut transact_fee_assets = MultiAssets::new(); + transact_fee_assets.push(transact_fee_asset.clone()); + //non_fee_reserve = non_fee_reserve.unwrap(); + let instructions = Xcm(vec![ + WithdrawAsset(transact_fee_assets), + // TODO: unwrap() !! + BuyExecution { + fees: transact_fee_asset, + weight_limit: WeightLimit::Limited(dest_weight), + }, + //Self::buy_execution(transact_fee_asset, &reserve, dest_weight)?, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: dest_weight, + call: call.into(), + }, + ]); + + let _res = T::XcmSender::send_xcm(non_fee_reserve.clone(), instructions); + } + } + } } + // TODO: + // if transact and fee exist + // if user has fee exists here + // if dest is reserve chain for fee (this does not necessarily have to be the + // case, any asset can be withdrawn into holding) withdraw fee (guaranteed to be + // ToReserve) Self::deposit_event(Event::::TransferredMultiAssets { sender: who, @@ -611,6 +742,8 @@ pub mod module { dest: &MultiLocation, maybe_recipient_override: Option, dest_weight: Weight, + call: Option>, + transact_fee_assets: Option, ) -> DispatchResult { let (transfer_kind, dest, reserve, recipient) = Self::transfer_kind(reserve, dest)?; let recipient = match maybe_recipient_override { @@ -620,7 +753,16 @@ pub mod module { let mut msg = match transfer_kind { SelfReserveAsset => Self::transfer_self_reserve_asset(assets, fee, dest, recipient, dest_weight)?, - ToReserve => Self::transfer_to_reserve(assets, fee, dest, recipient, dest_weight)?, + ToReserve => Self::transfer_to_reserve( + assets, + fee, + dest, + recipient, + dest_weight, + call, + origin_location.clone().interior, + transact_fee_assets, + )?, ToNonReserve => Self::transfer_to_non_reserve(assets, fee, reserve, dest, recipient, dest_weight)?, }; @@ -662,18 +804,110 @@ pub mod module { reserve: MultiLocation, recipient: MultiLocation, dest_weight: Weight, + call: Option>, + who: InteriorMultiLocation, + transact_fee_assets: Option, ) -> Result, DispatchError> { - Ok(Xcm(vec![ + // let dest_msg = match call { + // Some(call) => Xcm(vec![ + // Self::buy_execution(fee, &reserve, dest_weight)?, + // //ClearOrigin, + // //DescendOrigin(who), + // // Transact { + // // origin_type: OriginKind::Native, + // // require_weight_at_most: dest_weight, + // // call: call.into(), + // // }, + // Self::deposit_asset(recipient, assets.len() as u32), + // ]), + // None => Xcm(vec![ + // Self::buy_execution(fee, &reserve, dest_weight)?, + // Self::deposit_asset(recipient, assets.len() as u32), + // ]), + // }; + + // Ok(Xcm(vec![ + // WithdrawAsset(assets.clone()), + // InitiateReserveWithdraw { + // assets: All.into(), + // reserve: reserve.clone(), + // xcm: dest_msg, + // }, + // ])) + + /////////////////////////////////////////////////////////////////////////////////////// + + // let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; + // let mut assets1 = MultiAssets::new(); + // assets1.push(half(&asset.clone())); + + // let mut assets2 = MultiAssets::new(); + // assets2.push(half(&asset.clone())); + + // let dest_msg = Xcm(vec![ + // Self::buy_execution(half(&fee.clone()), &reserve, dest_weight)?, + // Self::deposit_asset(recipient, assets.len() as u32), + // ]); + // let self_location = T::SelfLocation::get(); + // let dest_msg_2 = Xcm(vec![ + // Self::buy_execution(half(&fee), &reserve, dest_weight)?, + // Self::deposit_asset(self_location, assets.len() as u32), + // ]); + + // Ok(Xcm(vec![ + // WithdrawAsset(assets1.clone()), + // InitiateReserveWithdraw { + // assets: All.into(), + // reserve: reserve.clone(), + // xcm: dest_msg, + // }, + // WithdrawAsset(assets2.clone()), + // InitiateReserveWithdraw { + // assets: All.into(), + // reserve: reserve.clone(), + // xcm: dest_msg_2, + // }, + // ])) + + /////////////////////////////////////////////////////////////////////////////////////// + + let dest_msg = Xcm(vec![ + Self::buy_execution(fee.clone(), &reserve, dest_weight)?, + Self::deposit_asset(recipient, assets.len() as u32), + ]); + + let full_xcm = Xcm(vec![ WithdrawAsset(assets.clone()), InitiateReserveWithdraw { assets: All.into(), reserve: reserve.clone(), - xcm: Xcm(vec![ - Self::buy_execution(fee, &reserve, dest_weight)?, - Self::deposit_asset(recipient, assets.len() as u32), - ]), + xcm: dest_msg, }, - ])) + ]); + + if let Some(transact_fee_asset) = transact_fee_assets { + let mut transact_fee_assets = MultiAssets::new(); + transact_fee_assets.push(transact_fee_asset.clone()); + + let self_location = T::SelfLocation::get(); + let dest_msg_2 = Xcm(vec![ + Self::buy_execution(transact_fee_asset, &reserve, dest_weight)?, + Self::deposit_asset(self_location, assets.len() as u32), + ]); + + let mut extension = vec![ + WithdrawAsset(transact_fee_assets.clone()), + InitiateReserveWithdraw { + assets: All.into(), + reserve: reserve.clone(), + xcm: dest_msg_2, + }, + ]; + extension.extend(full_xcm.0.into_iter()); + return Ok(Xcm(extension)); + } + + Ok(full_xcm) } fn transfer_to_non_reserve( @@ -784,6 +1018,8 @@ pub mod module { fn weight_of_transfer_multiasset(asset: &VersionedMultiAsset, dest: &VersionedMultiLocation) -> Weight { let asset: Result = asset.clone().try_into(); let dest = dest.clone().try_into(); + // TODO: + // if maybe_call, include Transact instruction with required_weight_at_most if let (Ok(asset), Ok(dest)) = (asset, dest) { if let Ok((transfer_kind, dest, _, reserve)) = Self::transfer_kind(T::ReserveProvider::reserve(&asset), &dest) @@ -816,7 +1052,13 @@ pub mod module { } /// Returns weight of `transfer` call. - fn weight_of_transfer(currency_id: T::CurrencyId, amount: T::Balance, dest: &VersionedMultiLocation) -> Weight { + fn weight_of_transfer( + currency_id: T::CurrencyId, + amount: T::Balance, + dest: &VersionedMultiLocation, + // maybe_call: Option>, + // dest_weight: Weight, + ) -> Weight { if let Some(location) = T::CurrencyIdConvert::convert(currency_id) { let asset = (location, amount.into()).into(); Self::weight_of_transfer_multiasset(&asset, dest) @@ -908,8 +1150,18 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, + maybe_call: Option>, + maybe_transact_fee: T::Balance, ) -> DispatchResult { - Self::do_transfer(who, currency_id, amount, dest, dest_weight) + Self::do_transfer( + who, + currency_id, + amount, + dest, + dest_weight, + maybe_call, + Some(maybe_transact_fee), + ) } #[require_transactional] From 2c1b6fcc9791318ce4029bd334aa6d2c69900780 Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Sat, 4 Jun 2022 21:27:33 +0300 Subject: [PATCH 2/7] try-2: works Signed-off-by: Georgi Zlatarev --- xtokens/src/lib.rs | 96 +--------------------------------------------- 1 file changed, 2 insertions(+), 94 deletions(-) diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 8dba78455..75547f92a 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -606,7 +606,6 @@ pub mod module { Some(T::SelfLocation::get()), dest_weight, None, - None, )?; // Second xcm send to dest chain. @@ -620,7 +619,6 @@ pub mod module { dest_weight, // fee_reserve != non_fee_reserve None, - None, )?; } else { Self::execute_and_send_reserve_kind_xcm( @@ -631,60 +629,16 @@ pub mod module { &dest, None, dest_weight, - maybe_call.clone(), transact_fee_assets.clone(), )?; - // if let Some(non_fee_reserve) = non_fee_reserve { - // if let Some(call) = maybe_call { - // let (transfer_kind, dest, reserve, recipient) = - // Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; - - // let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; - // let ancestry = T::LocationInverter::ancestry(); - // let fees = asset - // .clone() - // .reanchored(&reserve, &ancestry) - // .map_err(|_| Error::::CannotReanchor)?; - // let mut assets = MultiAssets::new(); - // assets.push(half(&fees.clone())); - // //non_fee_reserve = non_fee_reserve.unwrap(); - // let instructions = Xcm(vec![ - // WithdrawAsset(assets), - // // TODO: unwrap() !! - // Self::buy_execution(half(&fee.clone()), &reserve, dest_weight)?, - // Transact { - // origin_type: OriginKind::SovereignAccount, - // require_weight_at_most: dest_weight, - // call: call.into(), - // }, - // ]); - - // //let interior = origin_location.interior; - // //let dest = dest.into(); - // // if interior != Junctions::Here { - // // instructions.0.insert(0, DescendOrigin(interior)) - // // }; - // let _res = T::XcmSender::send_xcm(non_fee_reserve.clone(), instructions); - - // // pallet_xcm::Pallet::::send_xcm(Here, dest.clone(), - // // message.clone()).map_err(|e| match e { SendError:: - // // CannotReachDestination(..) => - // // Error::::Unreachable, _ => Error:::: - // // SendFailure, })?; - // } - // } - - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // TODO: can do another execute_and_send_reserve_kind_xcm() for the transact_fee // instead of in the inner functions... if let Some(non_fee_reserve) = non_fee_reserve { if let Some(call) = maybe_call { if let Some(transact_fee_asset) = transact_fee_assets { - let (transfer_kind, dest, reserve, recipient) = - Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; + let (_, _, reserve, _) = Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; //let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; let ancestry = T::LocationInverter::ancestry(); @@ -742,7 +696,6 @@ pub mod module { dest: &MultiLocation, maybe_recipient_override: Option, dest_weight: Weight, - call: Option>, transact_fee_assets: Option, ) -> DispatchResult { let (transfer_kind, dest, reserve, recipient) = Self::transfer_kind(reserve, dest)?; @@ -753,16 +706,7 @@ pub mod module { let mut msg = match transfer_kind { SelfReserveAsset => Self::transfer_self_reserve_asset(assets, fee, dest, recipient, dest_weight)?, - ToReserve => Self::transfer_to_reserve( - assets, - fee, - dest, - recipient, - dest_weight, - call, - origin_location.clone().interior, - transact_fee_assets, - )?, + ToReserve => Self::transfer_to_reserve(assets, fee, dest, recipient, dest_weight, transact_fee_assets)?, ToNonReserve => Self::transfer_to_non_reserve(assets, fee, reserve, dest, recipient, dest_weight)?, }; @@ -804,8 +748,6 @@ pub mod module { reserve: MultiLocation, recipient: MultiLocation, dest_weight: Weight, - call: Option>, - who: InteriorMultiLocation, transact_fee_assets: Option, ) -> Result, DispatchError> { // let dest_msg = match call { @@ -837,40 +779,6 @@ pub mod module { /////////////////////////////////////////////////////////////////////////////////////// - // let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; - // let mut assets1 = MultiAssets::new(); - // assets1.push(half(&asset.clone())); - - // let mut assets2 = MultiAssets::new(); - // assets2.push(half(&asset.clone())); - - // let dest_msg = Xcm(vec![ - // Self::buy_execution(half(&fee.clone()), &reserve, dest_weight)?, - // Self::deposit_asset(recipient, assets.len() as u32), - // ]); - // let self_location = T::SelfLocation::get(); - // let dest_msg_2 = Xcm(vec![ - // Self::buy_execution(half(&fee), &reserve, dest_weight)?, - // Self::deposit_asset(self_location, assets.len() as u32), - // ]); - - // Ok(Xcm(vec![ - // WithdrawAsset(assets1.clone()), - // InitiateReserveWithdraw { - // assets: All.into(), - // reserve: reserve.clone(), - // xcm: dest_msg, - // }, - // WithdrawAsset(assets2.clone()), - // InitiateReserveWithdraw { - // assets: All.into(), - // reserve: reserve.clone(), - // xcm: dest_msg_2, - // }, - // ])) - - /////////////////////////////////////////////////////////////////////////////////////// - let dest_msg = Xcm(vec![ Self::buy_execution(fee.clone(), &reserve, dest_weight)?, Self::deposit_asset(recipient, assets.len() as u32), From 0f742519c2ac2b15cb69a22154d32a1f67f0057f Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Sat, 4 Jun 2022 23:53:02 +0300 Subject: [PATCH 3/7] try-2: works, more general and simplified Signed-off-by: Georgi Zlatarev --- xtokens/src/lib.rs | 162 +++++++++++++++------------------------------ 1 file changed, 53 insertions(+), 109 deletions(-) diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 75547f92a..a1b11718f 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -605,12 +605,11 @@ pub mod module { &dest, Some(T::SelfLocation::get()), dest_weight, - None, )?; // Second xcm send to dest chain. Self::execute_and_send_reserve_kind_xcm( - origin_location, + origin_location.clone(), assets_to_dest, fee_to_dest, non_fee_reserve, @@ -618,7 +617,6 @@ pub mod module { None, dest_weight, // fee_reserve != non_fee_reserve - None, )?; } else { Self::execute_and_send_reserve_kind_xcm( @@ -629,52 +627,55 @@ pub mod module { &dest, None, dest_weight, - transact_fee_assets.clone(), )?; + } - // TODO: can do another execute_and_send_reserve_kind_xcm() for the transact_fee - // instead of in the inner functions... - - if let Some(non_fee_reserve) = non_fee_reserve { - if let Some(call) = maybe_call { - if let Some(transact_fee_asset) = transact_fee_assets { - let (_, _, reserve, _) = Self::transfer_kind(Some(non_fee_reserve.clone()), &dest)?; - - //let asset = assets.get(0).ok_or(Error::::AssetIndexNonExistent)?; - let ancestry = T::LocationInverter::ancestry(); - let transact_fee_asset = transact_fee_asset - .clone() - .reanchored(&reserve, &ancestry) - .map_err(|_| Error::::CannotReanchor)?; - let mut transact_fee_assets = MultiAssets::new(); - transact_fee_assets.push(transact_fee_asset.clone()); - //non_fee_reserve = non_fee_reserve.unwrap(); - let instructions = Xcm(vec![ - WithdrawAsset(transact_fee_assets), - // TODO: unwrap() !! - BuyExecution { - fees: transact_fee_asset, - weight_limit: WeightLimit::Limited(dest_weight), - }, - //Self::buy_execution(transact_fee_asset, &reserve, dest_weight)?, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: dest_weight, - call: call.into(), - }, - ]); - - let _res = T::XcmSender::send_xcm(non_fee_reserve.clone(), instructions); - } - } + if let Some(call) = maybe_call { + if let Some(transact_fee_asset) = transact_fee_assets { + let mut transact_fee_assets = MultiAssets::new(); + transact_fee_assets.push(transact_fee_asset.clone()); + // TODO: do i need this reserve() + let transact_fee_reserve = T::ReserveProvider::reserve(&transact_fee_asset); + Self::execute_and_send_reserve_kind_xcm( + origin_location.clone(), + transact_fee_assets.clone(), + transact_fee_asset.clone(), + transact_fee_reserve.clone(), + &dest, + // recipient has to be sovereign account of sender chain + Some(T::SelfLocation::get()), + dest_weight, + )?; + + // TODO: is this the best way to get dest location + let dest_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; + let ancestry = T::LocationInverter::ancestry(); + let transact_fee_asset = transact_fee_asset + .clone() + .reanchored(&dest_location, &ancestry) + .map_err(|_| Error::::CannotReanchor)?; + + let mut transact_fee_assets = MultiAssets::new(); + transact_fee_assets.push(transact_fee_asset.clone()); + let instructions = Xcm(vec![ + WithdrawAsset(transact_fee_assets), + BuyExecution { + fees: transact_fee_asset, + weight_limit: WeightLimit::Limited(dest_weight), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: dest_weight, + call: call.into(), + }, + // TODO: + // RefundSurplus + // DepositAsset(user_account) + ]); + + let _res = T::XcmSender::send_xcm(dest_location.clone(), instructions); } } - // TODO: - // if transact and fee exist - // if user has fee exists here - // if dest is reserve chain for fee (this does not necessarily have to be the - // case, any asset can be withdrawn into holding) withdraw fee (guaranteed to be - // ToReserve) Self::deposit_event(Event::::TransferredMultiAssets { sender: who, @@ -696,7 +697,6 @@ pub mod module { dest: &MultiLocation, maybe_recipient_override: Option, dest_weight: Weight, - transact_fee_assets: Option, ) -> DispatchResult { let (transfer_kind, dest, reserve, recipient) = Self::transfer_kind(reserve, dest)?; let recipient = match maybe_recipient_override { @@ -706,7 +706,7 @@ pub mod module { let mut msg = match transfer_kind { SelfReserveAsset => Self::transfer_self_reserve_asset(assets, fee, dest, recipient, dest_weight)?, - ToReserve => Self::transfer_to_reserve(assets, fee, dest, recipient, dest_weight, transact_fee_assets)?, + ToReserve => Self::transfer_to_reserve(assets, fee, dest, recipient, dest_weight)?, ToNonReserve => Self::transfer_to_non_reserve(assets, fee, reserve, dest, recipient, dest_weight)?, }; @@ -748,74 +748,18 @@ pub mod module { reserve: MultiLocation, recipient: MultiLocation, dest_weight: Weight, - transact_fee_assets: Option, ) -> Result, DispatchError> { - // let dest_msg = match call { - // Some(call) => Xcm(vec![ - // Self::buy_execution(fee, &reserve, dest_weight)?, - // //ClearOrigin, - // //DescendOrigin(who), - // // Transact { - // // origin_type: OriginKind::Native, - // // require_weight_at_most: dest_weight, - // // call: call.into(), - // // }, - // Self::deposit_asset(recipient, assets.len() as u32), - // ]), - // None => Xcm(vec![ - // Self::buy_execution(fee, &reserve, dest_weight)?, - // Self::deposit_asset(recipient, assets.len() as u32), - // ]), - // }; - - // Ok(Xcm(vec![ - // WithdrawAsset(assets.clone()), - // InitiateReserveWithdraw { - // assets: All.into(), - // reserve: reserve.clone(), - // xcm: dest_msg, - // }, - // ])) - - /////////////////////////////////////////////////////////////////////////////////////// - - let dest_msg = Xcm(vec![ - Self::buy_execution(fee.clone(), &reserve, dest_weight)?, - Self::deposit_asset(recipient, assets.len() as u32), - ]); - - let full_xcm = Xcm(vec![ + Ok(Xcm(vec![ WithdrawAsset(assets.clone()), InitiateReserveWithdraw { assets: All.into(), reserve: reserve.clone(), - xcm: dest_msg, + xcm: Xcm(vec![ + Self::buy_execution(fee, &reserve, dest_weight)?, + Self::deposit_asset(recipient, assets.len() as u32), + ]), }, - ]); - - if let Some(transact_fee_asset) = transact_fee_assets { - let mut transact_fee_assets = MultiAssets::new(); - transact_fee_assets.push(transact_fee_asset.clone()); - - let self_location = T::SelfLocation::get(); - let dest_msg_2 = Xcm(vec![ - Self::buy_execution(transact_fee_asset, &reserve, dest_weight)?, - Self::deposit_asset(self_location, assets.len() as u32), - ]); - - let mut extension = vec![ - WithdrawAsset(transact_fee_assets.clone()), - InitiateReserveWithdraw { - assets: All.into(), - reserve: reserve.clone(), - xcm: dest_msg_2, - }, - ]; - extension.extend(full_xcm.0.into_iter()); - return Ok(Xcm(extension)); - } - - Ok(full_xcm) + ])) } fn transfer_to_non_reserve( From c7860ee7e5d1dc46c377429edbf1fa1a0c16a16c Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Sun, 5 Jun 2022 14:34:19 +0300 Subject: [PATCH 4/7] try-2: works, cleanup Signed-off-by: Georgi Zlatarev --- xtokens/src/lib.rs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index a1b11718f..39c35924b 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -409,26 +409,19 @@ pub mod module { ); let asset: MultiAsset = (location.clone(), amount.into()).into(); - if let Some(transact_fee) = maybe_transact_fee { - return Self::do_transfer_multiassets( - who, - vec![asset.clone()].into(), - asset, - dest, - dest_weight, - maybe_call, - Some((location, transact_fee.into()).into()), - ); + let maybe_transact_fee_asset: Option = match maybe_transact_fee { + Some(transact_fee) => Some((location, transact_fee.into()).into()), + _ => None, }; Self::do_transfer_multiassets( - who, + who.clone(), vec![asset.clone()].into(), asset, - dest, + dest.clone(), dest_weight, - maybe_call, - None, + maybe_call.clone(), + maybe_transact_fee_asset, ) } @@ -536,7 +529,7 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, maybe_call: Option>, - transact_fee_assets: Option, + maybe_transact_fee_assets: Option, ) -> DispatchResult { ensure!( assets.len() <= T::MaxAssetsForTransfer::get(), @@ -631,7 +624,7 @@ pub mod module { } if let Some(call) = maybe_call { - if let Some(transact_fee_asset) = transact_fee_assets { + if let Some(transact_fee_asset) = maybe_transact_fee_assets { let mut transact_fee_assets = MultiAssets::new(); transact_fee_assets.push(transact_fee_asset.clone()); // TODO: do i need this reserve() @@ -648,11 +641,11 @@ pub mod module { )?; // TODO: is this the best way to get dest location - let dest_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; + let target_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; let ancestry = T::LocationInverter::ancestry(); let transact_fee_asset = transact_fee_asset .clone() - .reanchored(&dest_location, &ancestry) + .reanchored(&target_location, &ancestry) .map_err(|_| Error::::CannotReanchor)?; let mut transact_fee_assets = MultiAssets::new(); @@ -661,6 +654,7 @@ pub mod module { WithdrawAsset(transact_fee_assets), BuyExecution { fees: transact_fee_asset, + // TODO: pass separate dest_weight for transact_fee_asset weight_limit: WeightLimit::Limited(dest_weight), }, Transact { @@ -670,10 +664,10 @@ pub mod module { }, // TODO: // RefundSurplus - // DepositAsset(user_account) + // DepositAsset(user_account or back to sovereign_account) ]); - let _res = T::XcmSender::send_xcm(dest_location.clone(), instructions); + let _res = T::XcmSender::send_xcm(target_location.clone(), instructions); } } From d0786759995748dbcdffea787935d9ad2c1fa40a Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Sun, 5 Jun 2022 21:15:59 +0300 Subject: [PATCH 5/7] try-2: works, cleanup Signed-off-by: Georgi Zlatarev --- xtokens/src/lib.rs | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 39c35924b..488144754 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -197,7 +197,7 @@ pub mod module { /// received. Receiving depends on if the XCM message could be delivered /// by the network, and if the receiving chain would handle /// messages correctly. - //#[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), *amount, dest, maybe_call, + //#[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), *amount, dest, maybe_transact_call, //#[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), dest_weight))] #[pallet::weight(Pallet::::weight_of_transfer(currency_id.clone(), *amount, dest))] #[transactional] @@ -207,7 +207,7 @@ pub mod module { amount: T::Balance, dest: Box, dest_weight: Weight, - maybe_call: Option>, + maybe_transact_call: Option>, maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; @@ -218,7 +218,7 @@ pub mod module { amount, dest, dest_weight, - maybe_call, + maybe_transact_call, maybe_transact_fee, ) } @@ -242,6 +242,9 @@ pub mod module { asset: Box, dest: Box, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let asset: MultiAsset = (*asset).try_into().map_err(|()| Error::::BadVersion)?; @@ -279,6 +282,9 @@ pub mod module { fee: T::Balance, dest: Box, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -315,6 +321,9 @@ pub mod module { fee: Box, dest: Box, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let asset: MultiAsset = (*asset).try_into().map_err(|()| Error::::BadVersion)?; @@ -347,6 +356,9 @@ pub mod module { fee_item: u32, dest: Box, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -377,6 +389,9 @@ pub mod module { fee_item: u32, dest: Box, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; @@ -396,7 +411,7 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, - maybe_call: Option>, + maybe_transact_call: Option>, maybe_transact_fee: Option, ) -> DispatchResult { let location: MultiLocation = @@ -420,7 +435,7 @@ pub mod module { asset, dest.clone(), dest_weight, - maybe_call.clone(), + maybe_transact_call.clone(), maybe_transact_fee_asset, ) } @@ -432,6 +447,9 @@ pub mod module { fee: T::Balance, dest: MultiLocation, dest_weight: Weight, + // TODO: + // maybe_transact_call: Option>, + // maybe_transact_fee: Option, ) -> DispatchResult { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -528,8 +546,8 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight: Weight, - maybe_call: Option>, - maybe_transact_fee_assets: Option, + maybe_transact_call: Option>, + maybe_transact_fee_asset: Option, ) -> DispatchResult { ensure!( assets.len() <= T::MaxAssetsForTransfer::get(), @@ -623,8 +641,8 @@ pub mod module { )?; } - if let Some(call) = maybe_call { - if let Some(transact_fee_asset) = maybe_transact_fee_assets { + if let Some(call) = maybe_transact_call { + if let Some(transact_fee_asset) = maybe_transact_fee_asset { let mut transact_fee_assets = MultiAssets::new(); transact_fee_assets.push(transact_fee_asset.clone()); // TODO: do i need this reserve() @@ -865,7 +883,8 @@ pub mod module { let asset: Result = asset.clone().try_into(); let dest = dest.clone().try_into(); // TODO: - // if maybe_call, include Transact instruction with required_weight_at_most + // if maybe_transact_call, include Transact instruction with + // required_weight_at_most if let (Ok(asset), Ok(dest)) = (asset, dest) { if let Ok((transfer_kind, dest, _, reserve)) = Self::transfer_kind(T::ReserveProvider::reserve(&asset), &dest) @@ -902,7 +921,7 @@ pub mod module { currency_id: T::CurrencyId, amount: T::Balance, dest: &VersionedMultiLocation, - // maybe_call: Option>, + // maybe_transact_call: Option>, // dest_weight: Weight, ) -> Weight { if let Some(location) = T::CurrencyIdConvert::convert(currency_id) { @@ -996,7 +1015,7 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, - maybe_call: Option>, + maybe_transact_call: Option>, maybe_transact_fee: T::Balance, ) -> DispatchResult { Self::do_transfer( @@ -1005,7 +1024,7 @@ pub mod module { amount, dest, dest_weight, - maybe_call, + maybe_transact_call, Some(maybe_transact_fee), ) } From a9d0d409cb7b473424681b433b2bd04e7acff688 Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Thu, 9 Jun 2022 12:39:31 +0300 Subject: [PATCH 6/7] try-3: transact_with_fee initial Signed-off-by: Georgi Zlatarev --- traits/src/xcm_transfer.rs | 25 +------ xtokens/src/lib.rs | 134 +++++++++++++++++++++++++++++++------ 2 files changed, 115 insertions(+), 44 deletions(-) diff --git a/traits/src/xcm_transfer.rs b/traits/src/xcm_transfer.rs index 2e9b07457..20697d285 100644 --- a/traits/src/xcm_transfer.rs +++ b/traits/src/xcm_transfer.rs @@ -1,7 +1,7 @@ use frame_support::dispatch::DispatchResult; use frame_support::weights::Weight; use sp_std::vec::Vec; -use xcm::latest::prelude::*; +use xcm::{latest::prelude::*, DoubleEncoded}; /// Abstraction over cross-chain token transfers. pub trait XcmTransfer { @@ -13,6 +13,7 @@ pub trait XcmTransfer { dest: MultiLocation, dest_weight: Weight, maybe_call: Option>, + //maybe_transact_call: Option>, maybe_transact_fee: Balance, ) -> DispatchResult; @@ -24,25 +25,3 @@ pub trait XcmTransfer { dest_weight: Weight, ) -> DispatchResult; } - -// /// Abstraction over cross-chain token transfers. -// pub trait XcmTransfer { -// /// Transfer native currencies. -// fn transfer( -// who: AccountId, -// currency_id: CurrencyId, -// amount: Balance, -// dest: MultiLocation, -// dest_weight: Weight, -// maybe_call: Option>, -// maybe_transact_fee: Balance, -// ) -> DispatchResult; - -// /// Transfer `MultiAsset` -// fn transfer_multi_asset( -// who: AccountId, -// asset: MultiAsset, -// dest: MultiLocation, -// dest_weight: Weight, -// ) -> DispatchResult; -// } diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 488144754..2895020fa 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -208,6 +208,7 @@ pub mod module { dest: Box, dest_weight: Weight, maybe_transact_call: Option>, + //maybe_transact_call: Option>, maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; @@ -220,6 +221,42 @@ pub mod module { dest_weight, maybe_transact_call, maybe_transact_fee, + None, + ) + } + + #[pallet::weight(0)] + #[transactional] + pub fn transfer_with_transact( + origin: OriginFor, + currency_id: T::CurrencyId, + amount: T::Balance, + dest_id: u32, + dest_weight: Weight, + maybe_transact_call: Option>, + //maybe_transact_call: Option>, + maybe_transact_fee: Option, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + //let dest: MultiLocation = (*dest).try_into().map_err(|()| + // Error::::BadVersion)?; let ancestry = T::LocationInverter::ancestry(); + let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); + + let mut dest_loc: MultiLocation = (1, Parachain(dest_id)).into(); + dest_loc.append_with(origin_location.clone().interior); + + let mut dest = T::SelfLocation::get(); + dest.append_with(origin_location.clone().interior); + + Self::do_transfer( + who, + currency_id, + amount, + dest_loc.clone(), + dest_weight, + maybe_transact_call, + maybe_transact_fee, + Some(dest), ) } @@ -400,7 +437,7 @@ pub mod module { // We first grab the fee let fee: &MultiAsset = assets.get(fee_item as usize).ok_or(Error::::AssetIndexNonExistent)?; - Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight, None, None) + Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight, None, None, None) } } @@ -412,7 +449,9 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, maybe_transact_call: Option>, + //maybe_transact_call: Option>, maybe_transact_fee: Option, + maybe_recipient_override: Option, ) -> DispatchResult { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -429,6 +468,15 @@ pub mod module { _ => None, }; + // //let ancestry = T::LocationInverter::ancestry(); + // let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); + + // let mut dest_loc: MultiLocation = (1, Parachain(2)).into(); + // dest_loc.append_with(origin_location.clone().interior); + + // let mut dest = T::SelfLocation::get(); + // dest.append_with(origin_location.clone().interior); + Self::do_transfer_multiassets( who.clone(), vec![asset.clone()].into(), @@ -437,6 +485,7 @@ pub mod module { dest_weight, maybe_transact_call.clone(), maybe_transact_fee_asset, + maybe_recipient_override, ) } @@ -469,7 +518,7 @@ pub mod module { assets.push(asset); assets.push(fee_asset.clone()); - Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight, None, None) + Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight, None, None, None) } fn do_transfer_multiasset( @@ -478,7 +527,16 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, ) -> DispatchResult { - Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight, None, None) + Self::do_transfer_multiassets( + who, + vec![asset.clone()].into(), + asset, + dest, + dest_weight, + None, + None, + None, + ) } fn do_transfer_multiasset_with_fee( @@ -493,7 +551,7 @@ pub mod module { assets.push(asset); assets.push(fee.clone()); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None)?; + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None, None)?; Ok(()) } @@ -537,7 +595,7 @@ pub mod module { let fee: MultiAsset = (fee_location, (*fee_amount).into()).into(); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None) + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None, None) } fn do_transfer_multiassets( @@ -547,7 +605,9 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, maybe_transact_call: Option>, + //maybe_transact_call: Option>, maybe_transact_fee_asset: Option, + maybe_recipient_override: Option, ) -> DispatchResult { ensure!( assets.len() <= T::MaxAssetsForTransfer::get(), @@ -636,39 +696,67 @@ pub mod module { fee.clone(), non_fee_reserve.clone(), &dest, - None, + maybe_recipient_override, dest_weight, )?; } if let Some(call) = maybe_transact_call { if let Some(transact_fee_asset) = maybe_transact_fee_asset { + // TODO: is this the best way to get dest location + let target_chain_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; + let mut self_location_appended = T::SelfLocation::get(); + let ancestry = T::LocationInverter::ancestry(); + // let mut self_location_inverted = self_location.clone(); + // self_location_inverted + // .reanchor(&target_chain_location, &ancestry) + // .map_err(|_| Error::::CannotReanchor)?; + // self_location_inverted.append_with(origin_location.clone().interior); + self_location_appended.append_with(origin_location.clone().interior); + let mut transact_fee_assets = MultiAssets::new(); transact_fee_assets.push(transact_fee_asset.clone()); // TODO: do i need this reserve() let transact_fee_reserve = T::ReserveProvider::reserve(&transact_fee_asset); - Self::execute_and_send_reserve_kind_xcm( - origin_location.clone(), - transact_fee_assets.clone(), - transact_fee_asset.clone(), - transact_fee_reserve.clone(), - &dest, - // recipient has to be sovereign account of sender chain - Some(T::SelfLocation::get()), - dest_weight, - )?; + // Self::execute_and_send_reserve_kind_xcm( + // origin_location.clone(), + // transact_fee_assets.clone(), + // transact_fee_asset.clone(), + // transact_fee_reserve.clone(), + // &dest, + // // recipient has to be sovereign account of sender chain + // //Some(T::SelfLocation::get()), + // //Some(origin_location.clone()), + // //Some(self_location_inverted), + // Some(self_location_appended), + // dest_weight, + // )?; - // TODO: is this the best way to get dest location - let target_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; - let ancestry = T::LocationInverter::ancestry(); let transact_fee_asset = transact_fee_asset .clone() - .reanchored(&target_location, &ancestry) + .reanchored(&target_chain_location, &ancestry) .map_err(|_| Error::::CannotReanchor)?; + // MultiLocation { + // parents: 0, + // interior: X2( + // Parachain(origin_location.get_para_id()), + // AccountId32 { + // network: NetworkId::Any, + // id: account.into(), + // }, + // ), + // // X1(AccountId32 { + // // network: NetworkId::Any, + // // id: account.into(), + // // }), + // }; + + //let double_encoded: DoubleEncoded = call.into(); let mut transact_fee_assets = MultiAssets::new(); transact_fee_assets.push(transact_fee_asset.clone()); let instructions = Xcm(vec![ + DescendOrigin(origin_location.clone().interior), WithdrawAsset(transact_fee_assets), BuyExecution { fees: transact_fee_asset, @@ -679,13 +767,14 @@ pub mod module { origin_type: OriginKind::SovereignAccount, require_weight_at_most: dest_weight, call: call.into(), + //call, }, // TODO: // RefundSurplus // DepositAsset(user_account or back to sovereign_account) ]); - let _res = T::XcmSender::send_xcm(target_location.clone(), instructions); + let _res = T::XcmSender::send_xcm(target_chain_location.clone(), instructions); } } @@ -863,6 +952,7 @@ pub mod module { let (dest, recipient) = Self::ensure_valid_dest(dest)?; let self_location = T::SelfLocation::get(); + // TODO: skip check ensure!(dest != self_location, Error::::NotCrossChainTransfer); let reserve = reserve.ok_or(Error::::AssetHasNoReserve)?; let transfer_kind = if reserve == self_location { @@ -1016,6 +1106,7 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, maybe_transact_call: Option>, + //maybe_transact_call: Option>, maybe_transact_fee: T::Balance, ) -> DispatchResult { Self::do_transfer( @@ -1026,6 +1117,7 @@ pub mod module { dest_weight, maybe_transact_call, Some(maybe_transact_fee), + None, ) } From d1323e6ab38d26e013d84fc054099f6a40a7b6dc Mon Sep 17 00:00:00 2001 From: Georgi Zlatarev Date: Thu, 9 Jun 2022 14:01:18 +0300 Subject: [PATCH 7/7] try-3: transact_with_fee cleaned up Signed-off-by: Georgi Zlatarev --- traits/src/xcm_transfer.rs | 4 +- xtokens/src/lib.rs | 264 +++++++++++++------------------------ 2 files changed, 94 insertions(+), 174 deletions(-) diff --git a/traits/src/xcm_transfer.rs b/traits/src/xcm_transfer.rs index 20697d285..2a2e7104b 100644 --- a/traits/src/xcm_transfer.rs +++ b/traits/src/xcm_transfer.rs @@ -12,9 +12,9 @@ pub trait XcmTransfer { amount: Balance, dest: MultiLocation, dest_weight: Weight, - maybe_call: Option>, + //maybe_call: Option>, //maybe_transact_call: Option>, - maybe_transact_fee: Balance, + //maybe_transact_fee: Balance, ) -> DispatchResult; /// Transfer `MultiAsset` diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 2895020fa..88b2b351e 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -207,22 +207,10 @@ pub mod module { amount: T::Balance, dest: Box, dest_weight: Weight, - maybe_transact_call: Option>, - //maybe_transact_call: Option>, - maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer( - who, - currency_id, - amount, - dest, - dest_weight, - maybe_transact_call, - maybe_transact_fee, - None, - ) + Self::do_transfer(who, currency_id, amount, dest, dest_weight) } #[pallet::weight(0)] @@ -233,30 +221,20 @@ pub mod module { amount: T::Balance, dest_id: u32, dest_weight: Weight, - maybe_transact_call: Option>, + encoded_call_data: Vec, //maybe_transact_call: Option>, - maybe_transact_fee: Option, + transact_fee: T::Balance, ) -> DispatchResult { let who = ensure_signed(origin)?; - //let dest: MultiLocation = (*dest).try_into().map_err(|()| - // Error::::BadVersion)?; let ancestry = T::LocationInverter::ancestry(); - let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); - let mut dest_loc: MultiLocation = (1, Parachain(dest_id)).into(); - dest_loc.append_with(origin_location.clone().interior); - - let mut dest = T::SelfLocation::get(); - dest.append_with(origin_location.clone().interior); - - Self::do_transfer( + Self::do_transfer_with_transact( who, currency_id, amount, - dest_loc.clone(), + dest_id, dest_weight, - maybe_transact_call, - maybe_transact_fee, - Some(dest), + encoded_call_data, + transact_fee, ) } @@ -279,9 +257,6 @@ pub mod module { asset: Box, dest: Box, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let asset: MultiAsset = (*asset).try_into().map_err(|()| Error::::BadVersion)?; @@ -319,9 +294,6 @@ pub mod module { fee: T::Balance, dest: Box, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -358,9 +330,6 @@ pub mod module { fee: Box, dest: Box, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let asset: MultiAsset = (*asset).try_into().map_err(|()| Error::::BadVersion)?; @@ -393,9 +362,6 @@ pub mod module { fee_item: u32, dest: Box, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -426,9 +392,6 @@ pub mod module { fee_item: u32, dest: Box, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee_asset: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; @@ -437,7 +400,7 @@ pub mod module { // We first grab the fee let fee: &MultiAsset = assets.get(fee_item as usize).ok_or(Error::::AssetIndexNonExistent)?; - Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight, None, None, None) + Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight, None) } } @@ -448,10 +411,6 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, - maybe_transact_call: Option>, - //maybe_transact_call: Option>, - maybe_transact_fee: Option, - maybe_recipient_override: Option, ) -> DispatchResult { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -463,19 +422,6 @@ pub mod module { ); let asset: MultiAsset = (location.clone(), amount.into()).into(); - let maybe_transact_fee_asset: Option = match maybe_transact_fee { - Some(transact_fee) => Some((location, transact_fee.into()).into()), - _ => None, - }; - - // //let ancestry = T::LocationInverter::ancestry(); - // let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); - - // let mut dest_loc: MultiLocation = (1, Parachain(2)).into(); - // dest_loc.append_with(origin_location.clone().interior); - - // let mut dest = T::SelfLocation::get(); - // dest.append_with(origin_location.clone().interior); Self::do_transfer_multiassets( who.clone(), @@ -483,12 +429,84 @@ pub mod module { asset, dest.clone(), dest_weight, - maybe_transact_call.clone(), - maybe_transact_fee_asset, - maybe_recipient_override, + None, ) } + fn do_transfer_with_transact( + who: T::AccountId, + currency_id: T::CurrencyId, + amount: T::Balance, + dest_id: u32, + dest_weight: Weight, + encoded_call_data: Vec, + transact_fee: T::Balance, + ) -> DispatchResult { + let location: MultiLocation = + T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; + + let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); + + let mut dest_chain_location: MultiLocation = (1, Parachain(dest_id)).into(); + let _ = dest_chain_location.append_with(origin_location.clone().interior); + + ensure!(!amount.is_zero(), Error::::ZeroAmount); + ensure!( + T::MultiLocationsFilter::contains(&dest_chain_location), + Error::::NotSupportedMultiLocation + ); + + let asset: MultiAsset = (location.clone(), amount.into()).into(); + let transact_fee_asset: MultiAsset = (location, transact_fee.into()).into(); + + let mut override_dest = T::SelfLocation::get(); + let _ = override_dest.append_with(origin_location.clone().interior); + + let _ = Self::do_transfer_multiassets( + who.clone(), + vec![asset.clone()].into(), + asset, + dest_chain_location.clone(), + dest_weight, + // TODO: not a todo, but this part is important + Some(override_dest), + ); + + let origin_location = T::AccountIdToMultiLocation::convert(who.clone()); + // TODO: is this the best way to get dest location + let target_chain_location = dest_chain_location.chain_part().ok_or(Error::::AssetHasNoReserve)?; + let ancestry = T::LocationInverter::ancestry(); + + let transact_fee_asset = transact_fee_asset + .clone() + .reanchored(&target_chain_location, &ancestry) + .map_err(|_| Error::::CannotReanchor)?; + + //let double_encoded: DoubleEncoded = call.into(); + let mut transact_fee_assets = MultiAssets::new(); + transact_fee_assets.push(transact_fee_asset.clone()); + let instructions = Xcm(vec![ + DescendOrigin(origin_location.clone().interior), + WithdrawAsset(transact_fee_assets), + BuyExecution { + fees: transact_fee_asset, + weight_limit: WeightLimit::Limited(dest_weight), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: dest_weight, + call: encoded_call_data.into(), + //call, + }, + // TODO: + // RefundSurplus + // DepositAsset(user_account or back to sovereign_account) + ]); + + let _res = T::XcmSender::send_xcm(target_chain_location.clone(), instructions); + Ok(()) + } + fn do_transfer_with_fee( who: T::AccountId, currency_id: T::CurrencyId, @@ -496,9 +514,6 @@ pub mod module { fee: T::Balance, dest: MultiLocation, dest_weight: Weight, - // TODO: - // maybe_transact_call: Option>, - // maybe_transact_fee: Option, ) -> DispatchResult { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -518,7 +533,7 @@ pub mod module { assets.push(asset); assets.push(fee_asset.clone()); - Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight, None, None, None) + Self::do_transfer_multiassets(who, assets, fee_asset, dest, dest_weight, None) } fn do_transfer_multiasset( @@ -527,16 +542,7 @@ pub mod module { dest: MultiLocation, dest_weight: Weight, ) -> DispatchResult { - Self::do_transfer_multiassets( - who, - vec![asset.clone()].into(), - asset, - dest, - dest_weight, - None, - None, - None, - ) + Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight, None) } fn do_transfer_multiasset_with_fee( @@ -551,7 +557,7 @@ pub mod module { assets.push(asset); assets.push(fee.clone()); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None, None)?; + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None)?; Ok(()) } @@ -595,7 +601,7 @@ pub mod module { let fee: MultiAsset = (fee_location, (*fee_amount).into()).into(); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None, None, None) + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight, None) } fn do_transfer_multiassets( @@ -604,9 +610,9 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight: Weight, - maybe_transact_call: Option>, + //maybe_transact_call: Option>, //maybe_transact_call: Option>, - maybe_transact_fee_asset: Option, + //maybe_transact_fee_asset: Option, maybe_recipient_override: Option, ) -> DispatchResult { ensure!( @@ -701,83 +707,6 @@ pub mod module { )?; } - if let Some(call) = maybe_transact_call { - if let Some(transact_fee_asset) = maybe_transact_fee_asset { - // TODO: is this the best way to get dest location - let target_chain_location = dest.chain_part().ok_or(Error::::AssetHasNoReserve)?; - let mut self_location_appended = T::SelfLocation::get(); - let ancestry = T::LocationInverter::ancestry(); - // let mut self_location_inverted = self_location.clone(); - // self_location_inverted - // .reanchor(&target_chain_location, &ancestry) - // .map_err(|_| Error::::CannotReanchor)?; - // self_location_inverted.append_with(origin_location.clone().interior); - self_location_appended.append_with(origin_location.clone().interior); - - let mut transact_fee_assets = MultiAssets::new(); - transact_fee_assets.push(transact_fee_asset.clone()); - // TODO: do i need this reserve() - let transact_fee_reserve = T::ReserveProvider::reserve(&transact_fee_asset); - // Self::execute_and_send_reserve_kind_xcm( - // origin_location.clone(), - // transact_fee_assets.clone(), - // transact_fee_asset.clone(), - // transact_fee_reserve.clone(), - // &dest, - // // recipient has to be sovereign account of sender chain - // //Some(T::SelfLocation::get()), - // //Some(origin_location.clone()), - // //Some(self_location_inverted), - // Some(self_location_appended), - // dest_weight, - // )?; - - let transact_fee_asset = transact_fee_asset - .clone() - .reanchored(&target_chain_location, &ancestry) - .map_err(|_| Error::::CannotReanchor)?; - - // MultiLocation { - // parents: 0, - // interior: X2( - // Parachain(origin_location.get_para_id()), - // AccountId32 { - // network: NetworkId::Any, - // id: account.into(), - // }, - // ), - // // X1(AccountId32 { - // // network: NetworkId::Any, - // // id: account.into(), - // // }), - // }; - - //let double_encoded: DoubleEncoded = call.into(); - let mut transact_fee_assets = MultiAssets::new(); - transact_fee_assets.push(transact_fee_asset.clone()); - let instructions = Xcm(vec![ - DescendOrigin(origin_location.clone().interior), - WithdrawAsset(transact_fee_assets), - BuyExecution { - fees: transact_fee_asset, - // TODO: pass separate dest_weight for transact_fee_asset - weight_limit: WeightLimit::Limited(dest_weight), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: dest_weight, - call: call.into(), - //call, - }, - // TODO: - // RefundSurplus - // DepositAsset(user_account or back to sovereign_account) - ]); - - let _res = T::XcmSender::send_xcm(target_chain_location.clone(), instructions); - } - } - Self::deposit_event(Event::::TransferredMultiAssets { sender: who, assets, @@ -1105,20 +1034,11 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight: Weight, - maybe_transact_call: Option>, + //maybe_transact_call: Option>, //maybe_transact_call: Option>, - maybe_transact_fee: T::Balance, + //maybe_transact_fee: T::Balance, ) -> DispatchResult { - Self::do_transfer( - who, - currency_id, - amount, - dest, - dest_weight, - maybe_transact_call, - Some(maybe_transact_fee), - None, - ) + Self::do_transfer(who, currency_id, amount, dest, dest_weight) } #[require_transactional]