diff --git a/traits/src/xcm_transfer.rs b/traits/src/xcm_transfer.rs index a86642c12..cb6d2443b 100644 --- a/traits/src/xcm_transfer.rs +++ b/traits/src/xcm_transfer.rs @@ -1,31 +1,67 @@ -use frame_support::dispatch::DispatchResult; +use frame_support::dispatch::DispatchError; +use sp_std::vec::Vec; use xcm::v3::prelude::*; +pub struct Transferred { + pub sender: AccountId, + pub assets: MultiAssets, + pub fee: MultiAsset, + pub dest: MultiLocation, +} + /// Abstraction over cross-chain token transfers. pub trait XcmTransfer { - /// Transfer native currencies. + /// Transfer local assets with given `CurrencyId` and `Amount`. fn transfer( who: AccountId, currency_id: CurrencyId, amount: Balance, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult; + ) -> Result, DispatchError>; - /// Transfer `MultiAsset` - fn transfer_multi_asset( + /// Transfer `MultiAsset` assets. + fn transfer_multiasset( who: AccountId, asset: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult; + ) -> Result, DispatchError>; - /// Transfer `MultiAssetWithFee` + /// Transfer native currencies specifying the fee and amount as separate. + fn transfer_with_fee( + who: AccountId, + currency_id: CurrencyId, + amount: Balance, + fee: Balance, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError>; + + /// Transfer `MultiAsset` specifying the fee and amount as separate. fn transfer_multiasset_with_fee( who: AccountId, asset: MultiAsset, fee: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult; + ) -> Result, DispatchError>; + + /// Transfer several currencies specifying the item to be used as fee. + fn transfer_multicurrencies( + who: AccountId, + currencies: Vec<(CurrencyId, Balance)>, + fee_item: u32, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError>; + + /// Transfer several `MultiAsset` specifying the item to be used as fee. + fn transfer_multiassets( + who: AccountId, + assets: MultiAssets, + fee: MultiAsset, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError>; } diff --git a/xtokens/src/lib.rs b/xtokens/src/lib.rs index 73e5f0040..acac5520a 100644 --- a/xtokens/src/lib.rs +++ b/xtokens/src/lib.rs @@ -55,6 +55,7 @@ use xcm_executor::traits::WeightBounds; pub use module::*; use orml_traits::{ location::{Parse, Reserve}, + xcm_transfer::Transferred, GetByKey, XcmTransfer, }; @@ -220,7 +221,7 @@ pub mod module { ) -> 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_limit) + Self::do_transfer(who, currency_id, amount, dest, dest_weight_limit).map(|_| ()) } /// Transfer `MultiAsset`. @@ -246,7 +247,7 @@ pub mod module { let who = ensure_signed(origin)?; let asset: MultiAsset = (*asset).try_into().map_err(|()| Error::::BadVersion)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer_multiasset(who, asset, dest, dest_weight_limit) + Self::do_transfer_multiasset(who, asset, dest, dest_weight_limit).map(|_| ()) } /// Transfer native currencies specifying the fee and amount as @@ -283,7 +284,7 @@ pub mod module { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer_with_fee(who, currency_id, amount, fee, dest, dest_weight_limit) + Self::do_transfer_with_fee(who, currency_id, amount, fee, dest, dest_weight_limit).map(|_| ()) } /// Transfer `MultiAsset` specifying the fee and amount as separate. @@ -321,7 +322,7 @@ pub mod module { let fee: MultiAsset = (*fee).try_into().map_err(|()| Error::::BadVersion)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer_multiasset_with_fee(who, asset, fee, dest, dest_weight_limit) + Self::do_transfer_multiasset_with_fee(who, asset, fee, dest, dest_weight_limit).map(|_| ()) } /// Transfer several currencies specifying the item to be used as fee @@ -351,7 +352,7 @@ pub mod module { let who = ensure_signed(origin)?; let dest: MultiLocation = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - Self::do_transfer_multicurrencies(who, currencies, fee_item, dest, dest_weight_limit) + Self::do_transfer_multicurrencies(who, currencies, fee_item, dest, dest_weight_limit).map(|_| ()) } /// Transfer several `MultiAsset` specifying the item to be used as fee @@ -385,7 +386,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_limit) + Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight_limit).map(|_| ()) } } @@ -396,7 +397,7 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -417,7 +418,7 @@ pub mod module { fee: T::Balance, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { let location: MultiLocation = T::CurrencyIdConvert::convert(currency_id).ok_or(Error::::NotCrossChainTransferableCurrency)?; @@ -444,7 +445,7 @@ pub mod module { asset: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { Self::do_transfer_multiassets(who, vec![asset.clone()].into(), asset, dest, dest_weight_limit) } @@ -454,15 +455,13 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { // Push contains saturated addition, so we should be able to use it safely let mut assets = MultiAssets::new(); assets.push(asset); assets.push(fee.clone()); - Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight_limit)?; - - Ok(()) + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight_limit) } fn do_transfer_multicurrencies( @@ -471,7 +470,7 @@ pub mod module { fee_item: u32, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { ensure!( currencies.len() <= T::MaxAssetsForTransfer::get(), Error::::TooManyAssetsBeingSent @@ -513,7 +512,7 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { ensure!( assets.len() <= T::MaxAssetsForTransfer::get(), Error::::TooManyAssetsBeingSent @@ -621,13 +620,18 @@ pub mod module { } Self::deposit_event(Event::::TransferredMultiAssets { + sender: who.clone(), + assets: assets.clone(), + fee: fee.clone(), + dest, + }); + + Ok(Transferred { sender: who, assets, fee, dest, - }); - - Ok(()) + }) } /// Execute and send xcm with given assets and fee to dest chain or @@ -947,20 +951,32 @@ pub mod module { amount: T::Balance, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { Self::do_transfer(who, currency_id, amount, dest, dest_weight_limit) } #[require_transactional] - fn transfer_multi_asset( + fn transfer_multiasset( who: T::AccountId, asset: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { Self::do_transfer_multiasset(who, asset, dest, dest_weight_limit) } + #[require_transactional] + fn transfer_with_fee( + who: T::AccountId, + currency_id: T::CurrencyId, + amount: T::Balance, + fee: T::Balance, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError> { + Self::do_transfer_with_fee(who, currency_id, amount, fee, dest, dest_weight_limit) + } + #[require_transactional] fn transfer_multiasset_with_fee( who: T::AccountId, @@ -968,9 +984,31 @@ pub mod module { fee: MultiAsset, dest: MultiLocation, dest_weight_limit: WeightLimit, - ) -> DispatchResult { + ) -> Result, DispatchError> { Self::do_transfer_multiasset_with_fee(who, asset, fee, dest, dest_weight_limit) } + + #[require_transactional] + fn transfer_multicurrencies( + who: T::AccountId, + currencies: Vec<(T::CurrencyId, T::Balance)>, + fee_item: u32, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError> { + Self::do_transfer_multicurrencies(who, currencies, fee_item, dest, dest_weight_limit) + } + + #[require_transactional] + fn transfer_multiassets( + who: T::AccountId, + assets: MultiAssets, + fee: MultiAsset, + dest: MultiLocation, + dest_weight_limit: WeightLimit, + ) -> Result, DispatchError> { + Self::do_transfer_multiassets(who, assets, fee, dest, dest_weight_limit) + } } }