Skip to content

Commit

Permalink
The return of the xcm (open-web3-stack#518)
Browse files Browse the repository at this point in the history
* Update xcm support.

* Fix unit tests.

* fmt

* Add patches.

* Update xtokens.

* fmt

* Clean up.

* Cross-chain transfer weight.

* Weight for xcm execution.

* Keep clippy happy.

* Clean up.

* Buy execution on dest location.

* Better transfer error handling.

* Update deps.

* fmt

* fix fmt

* Update events in unit tests.
  • Loading branch information
shaunxw authored Jun 21, 2021
1 parent 2ff4dbb commit 5505324
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 136 deletions.
31 changes: 15 additions & 16 deletions Cargo.dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ members = [
"vesting",
"rewards",
"nft",
# "xtokens",
# "xcm-support",
# "unknown-tokens",
"xtokens",
"xcm-support",
"unknown-tokens",
"build-script-utils",
"weight-gen",
"weight-meter",
Expand Down Expand Up @@ -82,20 +82,19 @@ sp-trie = { git = "https://github.com/paritytech//substrate", rev = "9c572625f65
sp-version = { git = "https://github.com/paritytech//substrate", rev = "9c572625f6557dfdb19f47474369a0327d51dfbc" }
sp-wasm-interface = { git = "https://github.com/paritytech//substrate", rev = "9c572625f6557dfdb19f47474369a0327d51dfbc" }

# [patch.'https://github.com/paritytech/cumulus']
# cumulus-primitives-core = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
# cumulus-pallet-parachain-system = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
# parachain-info = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
# cumulus-pallet-xcm-handler = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
[patch.'https://github.com/paritytech/cumulus']
cumulus-primitives-core = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
cumulus-pallet-parachain-system = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }
parachain-info = { git = "https://github.com/paritytech//cumulus", rev = "05ab7a377d2c3b73566c0c3bd41b003486d6913b" }

# [patch.'https://github.com/paritytech/polkadot']
# xcm = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# xcm-executor = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# xcm-builder = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# polkadot-core-primitives = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# polkadot-runtime-parachains = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# polkadot-parachain = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
# polkadot-primitives = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
[patch.'https://github.com/paritytech/polkadot']
xcm = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
xcm-executor = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
xcm-builder = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
polkadot-core-primitives = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
polkadot-parachain = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }
polkadot-primitives = { git = "https://github.com/paritytech//polkadot", rev = "3ce09da502dd74d88f24d76f579d19fd4e6c5624" }

# [patch.'https://github.com/shaunxw/xcm-simulator']
# xcm-simulator = { git = "https://github.com/shaunxw//xcm-simulator", rev = "c52bd64a41a51d08bd5a1e27f32c47419b41f3e5" }
2 changes: 1 addition & 1 deletion tokens/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-
pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5" }
# Patch doesn't work as `pallet-elections-phragmen` is now 4.0.0 version. Revert `rev` to `statemint` branch after
# other `statemint` dependencies upgraded.
pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", rev = "85fa0ab80c3ceccf4bb98380d7833578aaf8815e" }
pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }

[features]
default = ["std"]
Expand Down
4 changes: 2 additions & 2 deletions traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ num-traits = { version = "0.2.14", default-features = false }
impl-trait-for-tuples = "0.2.1"
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5", default-features = false }
orml-utilities = { path = "../utilities", version = "0.4.1-dev", default-features = false }
# xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5", default-features = false }
xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5", default-features = false }

[features]
default = ["std"]
Expand All @@ -30,5 +30,5 @@ std = [
"num-traits/std",
"frame-support/std",
"orml-utilities/std",
# "xcm/std",
"xcm/std",
]
2 changes: 1 addition & 1 deletion traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod auction;
pub mod currency;
pub mod data_provider;
pub mod get_by_key;
// pub mod location;
pub mod location;
pub mod nft;
pub mod price;
pub mod rewards;
Expand Down
8 changes: 4 additions & 4 deletions traits/src/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ pub trait Parse {
}

fn is_chain_junction(junction: Option<&Junction>) -> bool {
matches!(junction, Some(Parent) | Some(Parachain { id: _ }))
matches!(junction, Some(Parent) | Some(Parachain(_)))
}

impl Parse for MultiLocation {
fn chain_part(&self) -> Option<MultiLocation> {
match (self.first(), self.at(1)) {
(Some(Parent), Some(Parachain { id })) => Some((Parent, Parachain { id: *id }).into()),
(Some(Parent), Some(Parachain(id))) => Some((Parent, Parachain(*id)).into()),
(Some(Parent), _) => Some(Parent.into()),
(Some(Parachain { id }), _) => Some(Parachain { id: *id }.into()),
(Some(Parachain(id)), _) => Some(Parachain(*id).into()),
_ => None,
}
}
Expand Down Expand Up @@ -58,7 +58,7 @@ impl Reserve for MultiAsset {
mod tests {
use super::*;

const PARACHAIN: Junction = Parachain { id: 1 };
const PARACHAIN: Junction = Parachain(1);
const GENERAL_INDEX: Junction = GeneralIndex { id: 1 };

fn concrete_fungible(id: MultiLocation) -> MultiAsset {
Expand Down
14 changes: 10 additions & 4 deletions unknown-tokens/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn deposit_concrete_fungible_asset_works() {
UnknownTokens::concrete_fungible_balances(&MOCK_RECIPIENT, &MOCK_CONCRETE_FUNGIBLE_ID),
3
);
System::assert_last_event(Event::unknown_tokens(crate::Event::Deposited(asset, MOCK_RECIPIENT)));
System::assert_last_event(Event::UnknownTokens(crate::Event::Deposited(asset, MOCK_RECIPIENT)));

// overflow case
let max_asset = concrete_fungible(u128::max_value());
Expand All @@ -58,7 +58,7 @@ fn deposit_abstract_fungible_asset() {
UnknownTokens::abstract_fungible_balances(&MOCK_RECIPIENT, &mock_abstract_fungible_id()),
3
);
System::assert_last_event(Event::unknown_tokens(crate::Event::Deposited(asset, MOCK_RECIPIENT)));
System::assert_last_event(Event::UnknownTokens(crate::Event::Deposited(asset, MOCK_RECIPIENT)));

// overflow case
let max_asset = abstract_fungible(u128::max_value());
Expand Down Expand Up @@ -94,7 +94,10 @@ fn withdraw_concrete_fungible_asset_works() {
UnknownTokens::concrete_fungible_balances(&MOCK_RECIPIENT, &MOCK_CONCRETE_FUNGIBLE_ID),
0
);
System::assert_last_event(Event::unknown_tokens(crate::Event::Withdrawn(asset.clone(), MOCK_RECIPIENT)));
System::assert_last_event(Event::UnknownTokens(crate::Event::Withdrawn(
asset.clone(),
MOCK_RECIPIENT,
)));

// balance too low case
assert_err!(
Expand All @@ -115,7 +118,10 @@ fn withdraw_abstract_fungible_asset_works() {
UnknownTokens::abstract_fungible_balances(&MOCK_RECIPIENT, &mock_abstract_fungible_id()),
0
);
System::assert_last_event(Event::unknown_tokens(crate::Event::Withdrawn(asset.clone(), MOCK_RECIPIENT)));
System::assert_last_event(Event::UnknownTokens(crate::Event::Withdrawn(
asset.clone(),
MOCK_RECIPIENT,
)));

// balance too low case
assert_err!(
Expand Down
42 changes: 19 additions & 23 deletions xcm-support/src/currency_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use sp_std::{
};

use xcm::v0::{Error as XcmError, MultiAsset, MultiLocation, Result};
use xcm_executor::traits::{LocationConversion, MatchesFungible, TransactAsset};
use xcm_executor::{
traits::{Convert as MoreConvert, MatchesFungible, TransactAsset},
Assets,
};

use crate::UnknownAsset as UnknownAssetT;

Expand All @@ -34,13 +37,14 @@ impl From<Error> for XcmError {
}

/// The `TransactAsset` implementation, to handle `MultiAsset` deposit/withdraw.
/// Note that teleport related functions are unimplemented.
///
/// If the asset is known, deposit/withdraw will be handled by `MultiCurrency`,
/// else by `UnknownAsset` if unknown.
pub struct MultiCurrencyAdapter<
MultiCurrency,
UnknownAsset,
Matcher,
Match,
AccountId,
AccountIdConvert,
CurrencyId,
Expand All @@ -49,7 +53,7 @@ pub struct MultiCurrencyAdapter<
PhantomData<(
MultiCurrency,
UnknownAsset,
Matcher,
Match,
AccountId,
AccountIdConvert,
CurrencyId,
Expand All @@ -60,49 +64,41 @@ pub struct MultiCurrencyAdapter<
impl<
MultiCurrency: orml_traits::MultiCurrency<AccountId, CurrencyId = CurrencyId>,
UnknownAsset: UnknownAssetT,
Matcher: MatchesFungible<MultiCurrency::Balance>,
AccountId: sp_std::fmt::Debug,
AccountIdConvert: LocationConversion<AccountId>,
Match: MatchesFungible<MultiCurrency::Balance>,
AccountId: sp_std::fmt::Debug + Clone,
AccountIdConvert: MoreConvert<MultiLocation, AccountId>,
CurrencyId: FullCodec + Eq + PartialEq + Copy + MaybeSerializeDeserialize + Debug,
CurrencyIdConvert: Convert<MultiAsset, Option<CurrencyId>>,
> TransactAsset
for MultiCurrencyAdapter<
MultiCurrency,
UnknownAsset,
Matcher,
AccountId,
AccountIdConvert,
CurrencyId,
CurrencyIdConvert,
>
for MultiCurrencyAdapter<MultiCurrency, UnknownAsset, Match, AccountId, AccountIdConvert, CurrencyId, CurrencyIdConvert>
{
fn deposit_asset(asset: &MultiAsset, location: &MultiLocation) -> Result {
match (
AccountIdConvert::from_location(location),
AccountIdConvert::convert_ref(location),
CurrencyIdConvert::convert(asset.clone()),
Matcher::matches_fungible(&asset),
Match::matches_fungible(&asset),
) {
// known asset
(Some(who), Some(currency_id), Some(amount)) => {
(Ok(who), Some(currency_id), Some(amount)) => {
MultiCurrency::deposit(currency_id, &who, amount).map_err(|e| XcmError::FailedToTransactAsset(e.into()))
}
// unknown asset
_ => UnknownAsset::deposit(asset, location).map_err(|e| XcmError::FailedToTransactAsset(e.into())),
}
}

fn withdraw_asset(asset: &MultiAsset, location: &MultiLocation) -> result::Result<MultiAsset, XcmError> {
fn withdraw_asset(asset: &MultiAsset, location: &MultiLocation) -> result::Result<Assets, XcmError> {
UnknownAsset::withdraw(asset, location).or_else(|_| {
let who = AccountIdConvert::from_location(location)
.ok_or_else(|| XcmError::from(Error::AccountIdConversionFailed))?;
let who = AccountIdConvert::convert_ref(location)
.map_err(|_| XcmError::from(Error::AccountIdConversionFailed))?;
let currency_id = CurrencyIdConvert::convert(asset.clone())
.ok_or_else(|| XcmError::from(Error::CurrencyIdConversionFailed))?;
let amount: MultiCurrency::Balance = Matcher::matches_fungible(&asset)
let amount: MultiCurrency::Balance = Match::matches_fungible(&asset)
.ok_or_else(|| XcmError::from(Error::FailedToMatchFungible))?
.saturated_into();
MultiCurrency::withdraw(currency_id, &who, amount).map_err(|e| XcmError::FailedToTransactAsset(e.into()))
})?;

Ok(asset.clone())
Ok(asset.clone().into())
}
}
4 changes: 2 additions & 2 deletions xcm-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ mod currency_adapter;
mod tests;

/// The XCM handler to execute XCM locally.
pub trait XcmHandler<AccountId> {
fn execute_xcm(origin: AccountId, xcm: Xcm) -> DispatchResult;
pub trait ExecuteXcm<AccountId, Call> {
fn execute_xcm(origin: AccountId, xcm: Xcm<Call>) -> DispatchResult;
}

/// A `MatchesFungible` implementation. It matches concrete fungible assets
Expand Down
18 changes: 9 additions & 9 deletions xcm-support/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ impl Convert<MultiLocation, Option<TestCurrencyId>> for CurrencyIdConvert {
let token_b: Vec<u8> = "TokenB".into();
match l {
X1(Parent) => Some(RelayChainToken),
X3(Parent, Parachain { id: 1 }, GeneralKey(k)) if k == token_a => Some(TokenA),
X3(Parent, Parachain { id: 2 }, GeneralKey(k)) if k == token_b => Some(TokenB),
X3(Parent, Parachain(1), GeneralKey(k)) if k == token_a => Some(TokenA),
X3(Parent, Parachain(2), GeneralKey(k)) if k == token_b => Some(TokenB),
_ => None,
}
}
Expand All @@ -41,14 +41,14 @@ fn is_native_concrete_matches_native_currencies() {
);
assert_eq!(
MatchesCurrencyId::matches_fungible(&ConcreteFungible {
id: X3(Parent, Parachain { id: 1 }, GeneralKey("TokenA".into())),
id: X3(Parent, Parachain(1), GeneralKey("TokenA".into())),
amount: 100
}),
Some(100),
);
assert_eq!(
MatchesCurrencyId::matches_fungible(&ConcreteFungible {
id: X3(Parent, Parachain { id: 2 }, GeneralKey("TokenB".into())),
id: X3(Parent, Parachain(2), GeneralKey("TokenB".into())),
amount: 100
}),
Some(100),
Expand All @@ -59,14 +59,14 @@ fn is_native_concrete_matches_native_currencies() {
fn is_native_concrete_does_not_matches_non_native_currencies() {
assert!(
<MatchesCurrencyId as MatchesFungible<u128>>::matches_fungible(&ConcreteFungible {
id: X3(Parent, Parachain { id: 2 }, GeneralKey("TokenC".into())),
id: X3(Parent, Parachain(2), GeneralKey("TokenC".into())),
amount: 100
})
.is_none()
);
assert!(
<MatchesCurrencyId as MatchesFungible<u128>>::matches_fungible(&ConcreteFungible {
id: X3(Parent, Parachain { id: 1 }, GeneralKey("TokenB".into())),
id: X3(Parent, Parachain(1), GeneralKey("TokenB".into())),
amount: 100
})
.is_none()
Expand All @@ -91,15 +91,15 @@ fn multi_native_asset() {
));
assert!(MultiNativeAsset::filter_asset_location(
&ConcreteFungible {
id: X3(Parent, Parachain { id: 1 }, GeneralKey("TokenA".into())),
id: X3(Parent, Parachain(1), GeneralKey("TokenA".into())),
amount: 10,
},
&X2(Parent, Parachain { id: 1 }),
&X2(Parent, Parachain(1)),
));
assert_eq!(
MultiNativeAsset::filter_asset_location(
&ConcreteFungible {
id: X3(Parent, Parachain { id: 1 }, GeneralKey("TokenA".into())),
id: X3(Parent, Parachain(1), GeneralKey("TokenA".into())),
amount: 10,
},
&X1(Parent),
Expand Down
25 changes: 13 additions & 12 deletions xtokens/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "polk
cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.5", default-features = false }

xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5", default-features = false }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5", default-features = false }

orml-xcm-support = { path = "../xcm-support", default-features = false }
orml-traits = { path = "../traits", default-features = false}

[dev-dependencies]
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5" }
polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5" }
xcm-simulator = { git = "https://github.com/shaunxw/xcm-simulator", branch = "master" }
cumulus-pallet-xcm-handler = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.5" }
parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.5" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }

orml-tokens = { path = "../tokens", version = "0.4.1-dev" }
orml-traits = { path = "../traits", version = "0.4.1-dev" }
# sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5" }
# polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
# polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
# pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.5" }
# xcm-simulator = { git = "https://github.com/shaunxw/xcm-simulator", branch = "master" }
# parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.5" }
# xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }
# xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.5" }

# orml-tokens = { path = "../tokens" }
# orml-traits = { path = "../traits" }

[features]
default = ["std"]
Expand All @@ -50,6 +50,7 @@ std = [
"frame-system/std",
"cumulus-primitives-core/std",
"xcm/std",
"xcm-executor/std",
"orml-xcm-support/std",
"orml-traits/std",
]
Expand Down
Loading

0 comments on commit 5505324

Please sign in to comment.