XCM docs and tests (#2948)

* WIP

* add tests and docs for DoubleEncoded

* reformat parent_count

* add test for match_and_split

* fix append_with docs and add tests

* move Parachain enum variant to tuple

* Fix stuff

* add to append test

* simplify match

* formatting

* format and extend doc comments (including examples)

* fix typo

* add some doc comments

* add test for location inverter

* Add more tests/docs

* Fix build

* matches fungibles

* currency adapter.

* add more tests for location inverter

* extract max length magic number into constant

* adapters.

* Apply suggestions from code review

* Final touches.

* Repot and fixes

* Remove last todo

* Apply suggestions from code review

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-builder/src/barriers.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-builder/src/barriers.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-builder/src/currency_adapter.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-builder/src/filter_asset_location.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-builder/src/matches_fungible.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-executor/src/traits/conversion.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-executor/src/traits/conversion.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-executor/src/traits/transact_asset.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update xcm/xcm-executor/src/traits/should_execute.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

Co-authored-by: kianenigma <kian@parity.io>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Alexander Popiak
2021-06-03 04:01:25 +02:00
committed by GitHub
parent 512b366280
commit a28d4a5c5d
22 changed files with 715 additions and 200 deletions
@@ -14,40 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Adapters to work with `frame_support::traits::tokens::fungibles` through XCM.
use sp_std::{prelude::*, result, marker::PhantomData, borrow::Borrow};
use xcm::v0::{Error as XcmError, Result, MultiAsset, MultiLocation, Junction};
use frame_support::traits::{Get, tokens::fungibles, Contains};
use xcm_executor::traits::{TransactAsset, Convert};
use xcm_executor::traits::{TransactAsset, Convert, MatchesFungibles, Error as MatchError};
/// Asset transaction errors.
pub enum Error {
/// Asset not found.
AssetNotFound,
/// `MultiLocation` to `AccountId` conversion failed.
AccountIdConversionFailed,
/// `u128` amount to currency `Balance` conversion failed.
AmountToBalanceConversionFailed,
/// `MultiLocation` to `AssetId` conversion failed.
AssetIdConversionFailed,
}
impl From<Error> for XcmError {
fn from(e: Error) -> Self {
match e {
Error::AssetNotFound => XcmError::FailedToTransactAsset("AssetNotFound"),
Error::AccountIdConversionFailed =>
XcmError::FailedToTransactAsset("AccountIdConversionFailed"),
Error::AmountToBalanceConversionFailed =>
XcmError::FailedToTransactAsset("AmountToBalanceConversionFailed"),
Error::AssetIdConversionFailed =>
XcmError::FailedToTransactAsset("AssetIdConversionFailed"),
}
}
}
/// Converter struct implementing `AssetIdConversion` converting a numeric asset ID (must be TryFrom/TryInto<u128>)
/// into a `GeneralIndex` junction, prefixed by some `MultiLocation` value. The `MultiLocation` value will
/// typically be a `PalletInstance` junction.
/// Converter struct implementing `AssetIdConversion` converting a numeric asset ID (must be TryFrom/TryInto<u128>) into
/// a `GeneralIndex` junction, prefixed by some `MultiLocation` value. The `MultiLocation` value will typically be a
/// `PalletInstance` junction.
pub struct AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId>(PhantomData<(Prefix, AssetId, ConvertAssetId)>);
impl<
Prefix: Get<MultiLocation>,
@@ -73,23 +49,6 @@ impl<
}
}
pub trait MatchesFungibles<AssetId, Balance> {
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error>;
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<
AssetId: Clone,
Balance: Clone,
> MatchesFungibles<AssetId, Balance> for Tuple {
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
for_tuples!( #(
match Tuple::matches_fungibles(a) { o @ Ok(_) => return o, _ => () }
)* );
Err(Error::AssetNotFound)
}
}
pub struct ConvertedConcreteAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>(
PhantomData<(AssetId, Balance, ConvertAssetId, ConvertBalance)>
);
@@ -101,13 +60,13 @@ impl<
> MatchesFungibles<AssetId, Balance> for
ConvertedConcreteAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
{
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
let (id, amount) = match a {
MultiAsset::ConcreteFungible { id, amount } => (id, amount),
_ => return Err(Error::AssetNotFound),
_ => return Err(MatchError::AssetNotFound),
};
let what = ConvertAssetId::convert_ref(id).map_err(|_| Error::AssetIdConversionFailed)?;
let amount = ConvertBalance::convert_ref(amount).map_err(|_| Error::AmountToBalanceConversionFailed)?;
let what = ConvertAssetId::convert_ref(id).map_err(|_| MatchError::AssetIdConversionFailed)?;
let amount = ConvertBalance::convert_ref(amount).map_err(|_| MatchError::AmountToBalanceConversionFailed)?;
Ok((what, amount))
}
}
@@ -123,13 +82,13 @@ impl<
> MatchesFungibles<AssetId, Balance> for
ConvertedAbstractAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
{
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
let (id, amount) = match a {
MultiAsset::AbstractFungible { id, amount } => (id, amount),
_ => return Err(Error::AssetNotFound),
_ => return Err(MatchError::AssetNotFound),
};
let what = ConvertAssetId::convert_ref(id).map_err(|_| Error::AssetIdConversionFailed)?;
let amount = ConvertBalance::convert_ref(amount).map_err(|_| Error::AmountToBalanceConversionFailed)?;
let what = ConvertAssetId::convert_ref(id).map_err(|_| MatchError::AssetIdConversionFailed)?;
let amount = ConvertBalance::convert_ref(amount).map_err(|_| MatchError::AmountToBalanceConversionFailed)?;
Ok((what, amount))
}
}
@@ -151,9 +110,9 @@ impl<
// Check we handle this asset.
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
let source = AccountIdConverter::convert_ref(from)
.map_err(|()| Error::AccountIdConversionFailed)?;
.map_err(|()| MatchError::AccountIdConversionFailed)?;
let dest = AccountIdConverter::convert_ref(to)
.map_err(|()| Error::AccountIdConversionFailed)?;
.map_err(|()| MatchError::AccountIdConversionFailed)?;
Assets::transfer(asset_id, &source, &dest, amount, true)
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
Ok(what.clone().into())
@@ -208,7 +167,7 @@ impl<
// Check we handle this asset.
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
let who = AccountIdConverter::convert_ref(who)
.map_err(|()| Error::AccountIdConversionFailed)?;
.map_err(|()| MatchError::AccountIdConversionFailed)?;
Assets::mint_into(asset_id, &who, amount)
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))
}
@@ -220,7 +179,7 @@ impl<
// Check we handle this asset.
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
let who = AccountIdConverter::convert_ref(who)
.map_err(|()| Error::AccountIdConversionFailed)?;
.map_err(|()| MatchError::AccountIdConversionFailed)?;
Assets::burn_from(asset_id, &who, amount)
.map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
Ok(what.clone().into())