Skip to content

Commit e4091cd

Browse files
authored
Update currency adapter to work with new xtokens impl (#436)
* Xcm support implementations rework. * Update xtokens mock.
1 parent 3a77e1a commit e4091cd

File tree

4 files changed

+132
-246
lines changed

4 files changed

+132
-246
lines changed

xcm-support/src/currency_adapter.rs

+11-26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use codec::FullCodec;
22
use sp_runtime::traits::{MaybeSerializeDeserialize, SaturatedConversion};
33
use sp_std::{
44
cmp::{Eq, PartialEq},
5+
convert::{TryFrom, TryInto},
56
fmt::Debug,
67
marker::PhantomData,
78
prelude::*,
@@ -11,7 +12,7 @@ use sp_std::{
1112
use xcm::v0::{Error as XcmError, MultiAsset, MultiLocation, Result};
1213
use xcm_executor::traits::{LocationConversion, MatchesFungible, TransactAsset};
1314

14-
use crate::{CurrencyIdConversion, UnknownAsset as UnknownAssetT};
15+
use crate::UnknownAsset as UnknownAssetT;
1516

1617
/// Asset transaction errors.
1718
enum Error {
@@ -37,22 +38,13 @@ impl From<Error> for XcmError {
3738
///
3839
/// If the asset is known, deposit/withdraw will be handled by `MultiCurrency`,
3940
/// else by `UnknownAsset` if unknown.
40-
pub struct MultiCurrencyAdapter<
41-
MultiCurrency,
42-
UnknownAsset,
43-
Matcher,
44-
AccountIdConverter,
45-
AccountId,
46-
CurrencyIdConverter,
47-
CurrencyId,
48-
>(
41+
pub struct MultiCurrencyAdapter<MultiCurrency, UnknownAsset, Matcher, AccountIdConverter, AccountId, CurrencyId>(
4942
PhantomData<(
5043
MultiCurrency,
5144
UnknownAsset,
5245
Matcher,
5346
AccountIdConverter,
5447
AccountId,
55-
CurrencyIdConverter,
5648
CurrencyId,
5749
)>,
5850
);
@@ -63,27 +55,18 @@ impl<
6355
Matcher: MatchesFungible<MultiCurrency::Balance>,
6456
AccountIdConverter: LocationConversion<AccountId>,
6557
AccountId: sp_std::fmt::Debug,
66-
CurrencyIdConverter: CurrencyIdConversion<CurrencyId>,
67-
CurrencyId: FullCodec + Eq + PartialEq + Copy + MaybeSerializeDeserialize + Debug,
58+
CurrencyId: FullCodec + Eq + PartialEq + Copy + MaybeSerializeDeserialize + Debug + TryFrom<MultiAsset>,
6859
> TransactAsset
69-
for MultiCurrencyAdapter<
70-
MultiCurrency,
71-
UnknownAsset,
72-
Matcher,
73-
AccountIdConverter,
74-
AccountId,
75-
CurrencyIdConverter,
76-
CurrencyId,
77-
>
60+
for MultiCurrencyAdapter<MultiCurrency, UnknownAsset, Matcher, AccountIdConverter, AccountId, CurrencyId>
7861
{
7962
fn deposit_asset(asset: &MultiAsset, location: &MultiLocation) -> Result {
8063
match (
8164
AccountIdConverter::from_location(location),
82-
CurrencyIdConverter::from_asset(asset),
65+
asset.clone().try_into(),
8366
Matcher::matches_fungible(&asset),
8467
) {
8568
// known asset
86-
(Some(who), Some(currency_id), Some(amount)) => {
69+
(Some(who), Ok(currency_id), Some(amount)) => {
8770
MultiCurrency::deposit(currency_id, &who, amount).map_err(|e| XcmError::FailedToTransactAsset(e.into()))
8871
}
8972
// unknown asset
@@ -95,8 +78,10 @@ impl<
9578
UnknownAsset::withdraw(asset, location).or_else(|_| {
9679
let who = AccountIdConverter::from_location(location)
9780
.ok_or_else(|| XcmError::from(Error::AccountIdConversionFailed))?;
98-
let currency_id = CurrencyIdConverter::from_asset(asset)
99-
.ok_or_else(|| XcmError::from(Error::CurrencyIdConversionFailed))?;
81+
let currency_id = asset
82+
.clone()
83+
.try_into()
84+
.map_err(|_| XcmError::from(Error::CurrencyIdConversionFailed))?;
10085
let amount: MultiCurrency::Balance = Matcher::matches_fungible(&asset)
10186
.ok_or_else(|| XcmError::from(Error::FailedToMatchFungible))?
10287
.saturated_into();

xcm-support/src/lib.rs

+14-84
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,12 @@
99
#![cfg_attr(not(feature = "std"), no_std)]
1010
#![allow(clippy::unused_unit)]
1111

12-
use frame_support::{
13-
dispatch::{DispatchError, DispatchResult},
14-
traits::Get,
15-
};
16-
use sp_runtime::traits::{CheckedConversion, Convert};
17-
use sp_std::{
18-
collections::btree_set::BTreeSet,
19-
convert::{TryFrom, TryInto},
20-
marker::PhantomData,
21-
prelude::*,
22-
};
12+
use frame_support::dispatch::{DispatchError, DispatchResult};
13+
use sp_runtime::traits::CheckedConversion;
14+
use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*};
2315

24-
use xcm::v0::{Junction, MultiAsset, MultiLocation, Xcm};
25-
use xcm_executor::traits::{FilterAssetLocation, MatchesFungible, NativeAsset};
16+
use xcm::v0::{MultiAsset, MultiLocation, Xcm};
17+
use xcm_executor::traits::{FilterAssetLocation, MatchesFungible};
2618

2719
use orml_traits::location::Reserve;
2820

@@ -37,61 +29,24 @@ pub trait XcmHandler<AccountId> {
3729
fn execute_xcm(origin: AccountId, xcm: Xcm) -> DispatchResult;
3830
}
3931

40-
/// Convert `MultiAsset` to `CurrencyId`.
41-
pub trait CurrencyIdConversion<CurrencyId> {
42-
/// Get `CurrencyId` from `MultiAsset`. Returns `None` if conversion failed.
43-
fn from_asset(asset: &MultiAsset) -> Option<CurrencyId>;
44-
}
45-
46-
/// A `MatchesFungible` implementation. It matches relay chain tokens or
47-
/// parachain tokens that could be decoded from a general key.
48-
pub struct IsConcreteWithGeneralKey<CurrencyId, FromRelayChainBalance>(
49-
PhantomData<(CurrencyId, FromRelayChainBalance)>,
50-
);
51-
impl<CurrencyId, B, FromRelayChainBalance> MatchesFungible<B>
52-
for IsConcreteWithGeneralKey<CurrencyId, FromRelayChainBalance>
32+
/// A `MatchesFungible` implementation. It matches concrete fungible assets
33+
/// whose `id` could be converted into `CurrencyId`.
34+
pub struct IsNativeConcrete<CurrencyId>(PhantomData<CurrencyId>);
35+
impl<CurrencyId, Amount> MatchesFungible<Amount> for IsNativeConcrete<CurrencyId>
5336
where
54-
CurrencyId: TryFrom<Vec<u8>>,
55-
B: TryFrom<u128>,
56-
FromRelayChainBalance: Convert<u128, u128>,
37+
CurrencyId: TryFrom<MultiLocation>,
38+
Amount: TryFrom<u128>,
5739
{
58-
fn matches_fungible(a: &MultiAsset) -> Option<B> {
40+
fn matches_fungible(a: &MultiAsset) -> Option<Amount> {
5941
if let MultiAsset::ConcreteFungible { id, amount } = a {
60-
if id == &MultiLocation::X1(Junction::Parent) {
61-
// Convert relay chain decimals to local chain
62-
let local_amount = FromRelayChainBalance::convert(*amount);
63-
return CheckedConversion::checked_from(local_amount);
64-
}
65-
if let Some(Junction::GeneralKey(key)) = id.last() {
66-
if TryInto::<CurrencyId>::try_into(key.clone()).is_ok() {
67-
return CheckedConversion::checked_from(*amount);
68-
}
42+
if CurrencyId::try_from(id.clone()).is_ok() {
43+
return CheckedConversion::checked_from(*amount);
6944
}
7045
}
7146
None
7247
}
7348
}
7449

75-
/// A `FilterAssetLocation` implementation. Filters native assets and ORML
76-
/// tokens via provided general key to `MultiLocation` pairs.
77-
pub struct NativePalletAssetOr<Pairs>(PhantomData<Pairs>);
78-
impl<Pairs: Get<BTreeSet<(Vec<u8>, MultiLocation)>>> FilterAssetLocation for NativePalletAssetOr<Pairs> {
79-
fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {
80-
if NativeAsset::filter_asset_location(asset, origin) {
81-
return true;
82-
}
83-
84-
// native orml-tokens with a general key
85-
if let MultiAsset::ConcreteFungible { ref id, .. } = asset {
86-
if let Some(Junction::GeneralKey(key)) = id.last() {
87-
return Pairs::get().contains(&(key.clone(), origin.clone()));
88-
}
89-
}
90-
91-
false
92-
}
93-
}
94-
9550
/// A `FilterAssetLocation` implementation. Filters multi native assets whose
9651
/// reserve is same with `origin`.
9752
pub struct MultiNativeAsset;
@@ -106,31 +61,6 @@ impl FilterAssetLocation for MultiNativeAsset {
10661
}
10762
}
10863

109-
/// `CurrencyIdConversion` implementation. Converts relay chain tokens, or
110-
/// parachain tokens that could be decoded from a general key.
111-
pub struct CurrencyIdConverter<CurrencyId, RelayChainCurrencyId>(
112-
PhantomData<CurrencyId>,
113-
PhantomData<RelayChainCurrencyId>,
114-
);
115-
impl<CurrencyId, RelayChainCurrencyId> CurrencyIdConversion<CurrencyId>
116-
for CurrencyIdConverter<CurrencyId, RelayChainCurrencyId>
117-
where
118-
CurrencyId: TryFrom<Vec<u8>>,
119-
RelayChainCurrencyId: Get<CurrencyId>,
120-
{
121-
fn from_asset(asset: &MultiAsset) -> Option<CurrencyId> {
122-
if let MultiAsset::ConcreteFungible { id: location, .. } = asset {
123-
if location == &MultiLocation::X1(Junction::Parent) {
124-
return Some(RelayChainCurrencyId::get());
125-
}
126-
if let Some(Junction::GeneralKey(key)) = location.last() {
127-
return CurrencyId::try_from(key.clone()).ok();
128-
}
129-
}
130-
None
131-
}
132-
}
133-
13464
/// Handlers unknown asset deposit and withdraw.
13565
pub trait UnknownAsset {
13666
/// Deposit unknown asset.

0 commit comments

Comments
 (0)