-
Notifications
You must be signed in to change notification settings - Fork 742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Too permissive XCM token matching inside tuples #4841
Comments
@mrshiposha Long time ago, I was fixing also something around this "fungible matching" stuff. I got your points, but let's find a better/simpler/generic solution here. Just few of my thoughts for the beginning:
So before we start aligning/changing api/signatures, let's think about first if we really need both XCM traits ( I am (almost) sure, that just one trait (as a combination of both) should be enough:
@mrshiposha Thank you for raising this issue. Feel free to continue/contribute with a PR. I am happy to help you, but let's discuss and make a "plan" first. :) |
I think so, too. However, I think it'd be confusing if the adapter could ignore the
Maybe we could define that single trait more generally? pub trait MatchesAsset<Id> {
fn matches_asset(a: &Asset) -> Result<Id, Error>;
} It seems to me to be more general since we can always define the The adapters could use the trait like this:
For non-fungibles, it will be similar. This would require changing the matcher trait implementations since they are generic, and we can't have several generic implementations of the same trait for the same type. This way, we can cover fungibles and non-fungibles with a uniform matcher trait. For example: // Wrapper types - they will be plugged into the adapters in the Runtime config.
pub struct MatchFungible<MatcherSettings>(PhantomData<MatcherSettings>);
pub struct MatchNonFungible<MatcherSettings>(PhantomData<MatcherSettings>);
// impl: IsConcrete
pub struct IsConcrete<T>(PhantomData<T>);
impl<T: Get<Location>, B: TryFrom<u128>> MatchesAsset<B> for MatchFungible<IsConcrete<B>> {
fn matches_asset(a: &Asset) -> Result<B, Error> {
match (&a.id, &a.fun) {
(AssetId(ref id), Fungible(ref amount)) if id == &T::get() => {
(*amount).try_into().map_err(|_| MatchError::AssetNotHandled)
},
_ => Err(Error::AssetNotHandled),
}
}
}
impl<T: Get<Location>, I: TryFrom<AssetInstance>> MatchesAsset<I> for MatchNonFungible<IsConcrete<I>> {
fn matches_asset(a: &Asset) -> Result<I, Error> {
match (&a.id, &a.fun) {
(AssetId(id), NonFungible(instance)) if id == &T::get() => {
(*instance).try_into().map_err(|_| MatchError::AssetNotHandled)
},
_ => Err(Error::AssetNotHandled),
}
}
}
// impl: ConvertedConcreteId
impl<
AssetId: Clone,
Balance: Clone,
ConvertAssetId: MaybeEquivalence<Location, AssetId>,
ConvertBalance: MaybeEquivalence<u128, Balance>,
> MatchesAsset<(AssetId, Balance)> for MatchFungible<ConvertedConcreteId<AssetId, Balance, ConvertAssetId, ConvertBalance>> {
/* ...match fungibles... */
}
impl<
ClassId: Clone,
InstanceId: Clone,
ConvertClassId: MaybeEquivalence<Location, ClassId>,
ConvertInstanceId: MaybeEquivalence<AssetInstance, InstanceId>,
> MatchesAsset<(ClassId, InstanceId)>
for MatchNonFungible<ConvertedConcreteId<ClassId, InstanceId, ConvertClassId, ConvertInstanceId>> {
/* ...match non-fungibles... */
} |
The current implementation of token matchers for tuples seems too permissive. When bundled in a tuple, the matchers should let the next matcher execute only on
AssetNotFound
orUnimplemented
errors, as the Asset Transactors do, not on every error.Otherwise, there could be a situation where some of the matchers fail with a prohibiting error, potentially polluting the storage in the process. However, the matching process won't halt and will fall through the rest of the matchers. Some of the remaining matchers could succeed, consequently triggering the Asset Transactor to do something. Yet, we have additional changes on-chain because of the first failed matcher.
This could lead to hard-to-debug errors.
Suggested change
I suggest changing the following implementations:
To something similar to this:
Inconsistent return types
Also, it feels inconsistent that
Matches<Singular>
(Fungible / NonFungible) andMatches<Plural>
(Fungibles / NonFungibles) have different return types. The<Singular>
matchers return anOption
, while the<Plural>
ones return aResult
.Maybe a
Result
return type for every matcher would be better?The text was updated successfully, but these errors were encountered: