mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
XCM v1 (#2815)
* MultiAsset TWO * Draft next MultiAsset API. * XCM core builds * XCM Executor builds * XCM Builder builds * API changes making their way throughout * Some TODOs * Further build fixes * Basic compile builds * First test fixed * All executor tests fixed * Typo * Optimize subsume_assets and add test * Optimize checked_sub * XCM Builder first test fixed * Fix builder tests * Fix doc test * fix some doc tests * spelling * named fields for AllOf * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Reformat * Move to XCM version 1 * Spelling * warnings * Replace some more v0->v1s * warnings * format * Add max_assets param * building * test fixes * tests * another test * final test * tests * Rename Null -> Here * Introduce * More ergonomics * More ergonomics * test fix * test fixes * docs * BuyExecution includes * Fix XCM extrinsics * fmt * Make Vec<MultiAsset>/MultiAssets conversions safe * More MultiAssets conversion safety * spelling * fix doc test * Apply suggestions from code review Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * Apply suggestions from code review Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * fmt * Add v0, remove VersionedMultiAsset * Remove VersionedMultiLocation * Update xcm/src/v1/order.rs Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * Update xcm/src/v1/mod.rs Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * XCM v0 backwards compatibility * Full compatibility * fmt * Update xcm/pallet-xcm/src/lib.rs * Update xcm/src/v0/order.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Tweaks to versioning system * Fixes * fmt * Update xcm/xcm-executor/src/assets.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update xcm/xcm-executor/src/assets.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Grumbles * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * fmt * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Fixes * Formatting Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Amar Singh <asinghchrony@protonmail.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
use frame_support::{ensure, traits::Contains, weights::Weight};
|
||||
use polkadot_parachain::primitives::IsSystem;
|
||||
use sp_std::{marker::PhantomData, result::Result};
|
||||
use xcm::v0::{Junction, MultiLocation, Order, Xcm};
|
||||
use xcm::latest::{Junction, MultiLocation, Order, Xcm};
|
||||
use xcm_executor::traits::{OnResponse, ShouldExecute};
|
||||
|
||||
/// Execution barrier that just takes `shallow_weight` from `weight_credit`.
|
||||
@@ -51,9 +51,9 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowTopLevelPaidExecutionFro
|
||||
ensure!(T::contains(origin), ());
|
||||
ensure!(top_level, ());
|
||||
match message {
|
||||
Xcm::TeleportAsset { effects, .. } |
|
||||
Xcm::ReceiveTeleportedAsset { effects, .. } |
|
||||
Xcm::WithdrawAsset { effects, .. } |
|
||||
Xcm::ReserveAssetDeposit { effects, .. }
|
||||
Xcm::ReserveAssetDeposited { effects, .. }
|
||||
if matches!(
|
||||
effects.first(),
|
||||
Some(Order::BuyExecution { debt, ..}) if *debt >= shallow_weight
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use frame_support::traits::{ExistenceRequirement::AllowDeath, Get, WithdrawReasons};
|
||||
use sp_runtime::traits::{CheckedSub, SaturatedConversion};
|
||||
use sp_std::{convert::TryInto, marker::PhantomData, result};
|
||||
use xcm::v0::{Error as XcmError, MultiAsset, MultiLocation, Result};
|
||||
use xcm::latest::{Error as XcmError, MultiAsset, MultiLocation, Result};
|
||||
use xcm_executor::{
|
||||
traits::{Convert, MatchesFungible, TransactAsset},
|
||||
Assets,
|
||||
@@ -53,7 +53,7 @@ impl From<Error> for XcmError {
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use frame_support::parameter_types;
|
||||
/// use xcm::v0::{MultiLocation, Junction};
|
||||
/// use xcm::latest::{MultiLocation, Junction};
|
||||
/// use xcm_builder::{ParentIsDefault, CurrencyAdapter, IsConcrete};
|
||||
///
|
||||
/// /// Our chain's account id.
|
||||
|
||||
@@ -18,20 +18,20 @@
|
||||
|
||||
use frame_support::traits::Get;
|
||||
use sp_std::marker::PhantomData;
|
||||
use xcm::v0::{MultiAsset, MultiLocation};
|
||||
use xcm::latest::{AssetId::Concrete, MultiAsset, MultiAssetFilter, MultiLocation};
|
||||
use xcm_executor::traits::FilterAssetLocation;
|
||||
|
||||
/// Accepts an asset iff it is a native asset.
|
||||
pub struct NativeAsset;
|
||||
impl FilterAssetLocation for NativeAsset {
|
||||
fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
matches!(asset, MultiAsset::ConcreteFungible { ref id, .. } if id == origin)
|
||||
matches!(asset.id, Concrete(ref id) if id == origin)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is contained in the given `T`'s `Get` implementation.
|
||||
pub struct Case<T>(PhantomData<T>);
|
||||
impl<T: Get<(MultiAsset, MultiLocation)>> FilterAssetLocation for Case<T> {
|
||||
impl<T: Get<(MultiAssetFilter, MultiLocation)>> FilterAssetLocation for Case<T> {
|
||||
fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
let (a, o) = T::get();
|
||||
a.contains(asset) && &o == origin
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
use frame_support::traits::{tokens::fungibles, Contains, Get};
|
||||
use sp_std::{borrow::Borrow, marker::PhantomData, prelude::*, result};
|
||||
use xcm::v0::{Error as XcmError, Junction, MultiAsset, MultiLocation, Result};
|
||||
use xcm::latest::{
|
||||
AssetId::{Abstract, Concrete},
|
||||
Error as XcmError,
|
||||
Fungibility::Fungible,
|
||||
Junction, MultiAsset, MultiLocation, Result,
|
||||
};
|
||||
use xcm_executor::traits::{Convert, Error as MatchError, MatchesFungibles, TransactAsset};
|
||||
|
||||
/// Converter struct implementing `AssetIdConversion` converting a numeric asset ID (must be `TryFrom/TryInto<u128>`) into
|
||||
@@ -61,8 +66,8 @@ impl<
|
||||
for ConvertedConcreteAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
let (id, amount) = match a {
|
||||
MultiAsset::ConcreteFungible { id, amount } => (id, amount),
|
||||
let (amount, id) = match (&a.fun, &a.id) {
|
||||
(Fungible(ref amount), Concrete(ref id)) => (amount, id),
|
||||
_ => return Err(MatchError::AssetNotFound),
|
||||
};
|
||||
let what =
|
||||
@@ -85,8 +90,8 @@ impl<
|
||||
for ConvertedAbstractAssetId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
let (id, amount) = match a {
|
||||
MultiAsset::AbstractFungible { id, amount } => (id, amount),
|
||||
let (amount, id) = match (&a.fun, &a.id) {
|
||||
(Fungible(ref amount), Abstract(ref id)) => (amount, id),
|
||||
_ => return Err(MatchError::AssetNotFound),
|
||||
};
|
||||
let what =
|
||||
|
||||
@@ -55,7 +55,9 @@ pub use fungibles_adapter::{
|
||||
};
|
||||
|
||||
mod weight;
|
||||
pub use weight::{FixedRateOfConcreteFungible, FixedWeightBounds, TakeRevenue, UsingComponents};
|
||||
#[allow(deprecated)]
|
||||
pub use weight::FixedRateOfConcreteFungible;
|
||||
pub use weight::{FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents};
|
||||
|
||||
mod matches_fungible;
|
||||
pub use matches_fungible::{IsAbstract, IsConcrete};
|
||||
|
||||
@@ -19,7 +19,7 @@ use parity_scale_codec::Encode;
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_runtime::traits::AccountIdConversion;
|
||||
use sp_std::{borrow::Borrow, marker::PhantomData};
|
||||
use xcm::v0::{Junction, MultiLocation, NetworkId};
|
||||
use xcm::latest::{Junction, MultiLocation, NetworkId};
|
||||
use xcm_executor::traits::{Convert, InvertLocation};
|
||||
|
||||
pub struct Account32Hash<Network, AccountId>(PhantomData<(Network, AccountId)>);
|
||||
@@ -155,7 +155,7 @@ impl<Network: Get<NetworkId>, AccountId: From<[u8; 20]> + Into<[u8; 20]> + Clone
|
||||
/// ```
|
||||
/// ```rust
|
||||
/// # use frame_support::parameter_types;
|
||||
/// # use xcm::v0::{MultiLocation::{self, *}, Junction::*, NetworkId::Any};
|
||||
/// # use xcm::latest::{MultiLocation::{self, *}, Junction::*, NetworkId::Any};
|
||||
/// # use xcm_builder::LocationInverter;
|
||||
/// # use xcm_executor::traits::InvertLocation;
|
||||
/// # fn main() {
|
||||
@@ -200,7 +200,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
use frame_support::parameter_types;
|
||||
use xcm::v0::{Junction::*, MultiLocation::*, NetworkId::Any};
|
||||
use xcm::latest::{Junction::*, MultiLocation::*, NetworkId::Any};
|
||||
|
||||
fn account20() -> Junction {
|
||||
AccountKey20 { network: Any, key: Default::default() }
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
use frame_support::traits::Get;
|
||||
use sp_runtime::traits::CheckedConversion;
|
||||
use sp_std::{convert::TryFrom, marker::PhantomData};
|
||||
use xcm::v0::{MultiAsset, MultiLocation};
|
||||
use xcm::latest::{
|
||||
AssetId::{Abstract, Concrete},
|
||||
Fungibility::Fungible,
|
||||
MultiAsset, MultiLocation,
|
||||
};
|
||||
use xcm_executor::traits::MatchesFungible;
|
||||
|
||||
/// Converts a `MultiAsset` into balance `B` if it is a concrete fungible with an id equal to that
|
||||
@@ -28,17 +32,16 @@ use xcm_executor::traits::MatchesFungible;
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use xcm::v0::{MultiAsset, MultiLocation, Junction};
|
||||
/// use xcm::latest::prelude::*;
|
||||
/// use xcm_builder::IsConcrete;
|
||||
/// use xcm_executor::traits::MatchesFungible;
|
||||
///
|
||||
/// frame_support::parameter_types! {
|
||||
/// pub TargetLocation: MultiLocation = MultiLocation::X1(Junction::Parent);
|
||||
/// pub TargetLocation: MultiLocation = X1(Parent);
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let id = MultiLocation::X1(Junction::Parent);
|
||||
/// let asset = MultiAsset::ConcreteFungible { id, amount: 999u128 };
|
||||
/// let asset = (X1(Parent), 999).into();
|
||||
/// // match `asset` if it is a concrete asset in `TargetLocation`.
|
||||
/// assert_eq!(<IsConcrete<TargetLocation> as MatchesFungible<u128>>::matches_fungible(&asset), Some(999));
|
||||
/// # }
|
||||
@@ -46,8 +49,8 @@ use xcm_executor::traits::MatchesFungible;
|
||||
pub struct IsConcrete<T>(PhantomData<T>);
|
||||
impl<T: Get<MultiLocation>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<T> {
|
||||
fn matches_fungible(a: &MultiAsset) -> Option<B> {
|
||||
match a {
|
||||
MultiAsset::ConcreteFungible { id, amount } if id == &T::get() =>
|
||||
match (&a.id, &a.fun) {
|
||||
(Concrete(ref id), Fungible(ref amount)) if id == &T::get() =>
|
||||
CheckedConversion::checked_from(*amount),
|
||||
_ => None,
|
||||
}
|
||||
@@ -59,7 +62,7 @@ impl<T: Get<MultiLocation>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use xcm::v0::{MultiAsset};
|
||||
/// use xcm::latest::prelude::*;
|
||||
/// use xcm_builder::IsAbstract;
|
||||
/// use xcm_executor::traits::MatchesFungible;
|
||||
///
|
||||
@@ -68,7 +71,7 @@ impl<T: Get<MultiLocation>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let asset = MultiAsset::AbstractFungible { id: vec![7u8], amount: 999u128 };
|
||||
/// let asset = (vec![7u8], 999).into();
|
||||
/// // match `asset` if it is a concrete asset in `TargetLocation`.
|
||||
/// assert_eq!(<IsAbstract<TargetLocation> as MatchesFungible<u128>>::matches_fungible(&asset), Some(999));
|
||||
/// # }
|
||||
@@ -76,8 +79,8 @@ impl<T: Get<MultiLocation>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<
|
||||
pub struct IsAbstract<T>(PhantomData<T>);
|
||||
impl<T: Get<&'static [u8]>, B: TryFrom<u128>> MatchesFungible<B> for IsAbstract<T> {
|
||||
fn matches_fungible(a: &MultiAsset) -> Option<B> {
|
||||
match a {
|
||||
MultiAsset::AbstractFungible { id, amount } if &id[..] == T::get() =>
|
||||
match (&a.id, &a.fun) {
|
||||
(Abstract(ref id), Fungible(ref amount)) if id == &T::get() =>
|
||||
CheckedConversion::checked_from(*amount),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
pub use crate::{
|
||||
AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
|
||||
FixedRateOfConcreteFungible, FixedWeightBounds, LocationInverter, TakeWeightCredit,
|
||||
FixedRateOfFungible, FixedWeightBounds, LocationInverter, TakeWeightCredit,
|
||||
};
|
||||
pub use frame_support::{
|
||||
dispatch::{
|
||||
@@ -34,10 +34,7 @@ pub use sp_std::{
|
||||
fmt::Debug,
|
||||
marker::PhantomData,
|
||||
};
|
||||
pub use xcm::v0::{
|
||||
opaque, Error as XcmError, Junction, Junction::*, MultiAsset, MultiLocation, MultiLocation::*,
|
||||
Order, OriginKind, Result as XcmResult, SendXcm, Xcm,
|
||||
};
|
||||
pub use xcm::latest::prelude::*;
|
||||
pub use xcm_executor::{
|
||||
traits::{ConvertOrigin, FilterAssetLocation, InvertLocation, OnResponse, TransactAsset},
|
||||
Assets, Config,
|
||||
@@ -123,7 +120,7 @@ pub fn assets(who: u64) -> Vec<MultiAsset> {
|
||||
ASSETS.with(|a| a.borrow().get(&who).map_or(vec![], |a| a.clone().into()))
|
||||
}
|
||||
pub fn add_asset(who: u64, what: MultiAsset) {
|
||||
ASSETS.with(|a| a.borrow_mut().entry(who).or_insert(Assets::new()).saturating_subsume(what));
|
||||
ASSETS.with(|a| a.borrow_mut().entry(who).or_insert(Assets::new()).subsume(what));
|
||||
}
|
||||
|
||||
pub struct TestAssetTransactor;
|
||||
@@ -140,8 +137,8 @@ impl TransactAsset for TestAssetTransactor {
|
||||
a.borrow_mut()
|
||||
.get_mut(&who)
|
||||
.ok_or(XcmError::NotWithdrawable)?
|
||||
.try_take(what.clone())
|
||||
.map_err(|()| XcmError::NotWithdrawable)
|
||||
.try_take(what.clone().into())
|
||||
.map_err(|_| XcmError::NotWithdrawable)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -155,7 +152,7 @@ pub fn to_account(l: MultiLocation) -> Result<u64, MultiLocation> {
|
||||
// Children at 1000+id
|
||||
X1(Parachain(id)) => 1000 + id as u64,
|
||||
// Self at 3000
|
||||
Null => 3000,
|
||||
Here => 3000,
|
||||
// Parent at 3001
|
||||
X1(Parent) => 3001,
|
||||
l => return Err(l),
|
||||
@@ -181,14 +178,14 @@ impl ConvertOrigin<TestOrigin> for TestOriginConverter {
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static IS_RESERVE: RefCell<BTreeMap<MultiLocation, Vec<MultiAsset>>> = RefCell::new(BTreeMap::new());
|
||||
pub static IS_TELEPORTER: RefCell<BTreeMap<MultiLocation, Vec<MultiAsset>>> = RefCell::new(BTreeMap::new());
|
||||
pub static IS_RESERVE: RefCell<BTreeMap<MultiLocation, Vec<MultiAssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
pub static IS_TELEPORTER: RefCell<BTreeMap<MultiLocation, Vec<MultiAssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
}
|
||||
pub fn add_reserve(from: MultiLocation, asset: MultiAsset) {
|
||||
pub fn add_reserve(from: MultiLocation, asset: MultiAssetFilter) {
|
||||
IS_RESERVE.with(|r| r.borrow_mut().entry(from).or_default().push(asset));
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn add_teleporter(from: MultiLocation, asset: MultiAsset) {
|
||||
pub fn add_teleporter(from: MultiLocation, asset: MultiAssetFilter) {
|
||||
IS_TELEPORTER.with(|r| r.borrow_mut().entry(from).or_default().push(asset));
|
||||
}
|
||||
pub struct TestIsReserve;
|
||||
@@ -206,7 +203,7 @@ impl FilterAssetLocation for TestIsTeleporter {
|
||||
}
|
||||
}
|
||||
|
||||
use xcm::v0::Response;
|
||||
use xcm::latest::Response;
|
||||
pub enum ResponseSlot {
|
||||
Expecting(MultiLocation),
|
||||
Received(Response),
|
||||
@@ -222,7 +219,11 @@ impl OnResponse for TestResponseHandler {
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
fn on_response(_origin: MultiLocation, query_id: u64, response: xcm::v0::Response) -> Weight {
|
||||
fn on_response(
|
||||
_origin: MultiLocation,
|
||||
query_id: u64,
|
||||
response: xcm::latest::Response,
|
||||
) -> Weight {
|
||||
QUERIES.with(|q| {
|
||||
q.borrow_mut().entry(query_id).and_modify(|v| {
|
||||
if matches!(*v, ResponseSlot::Expecting(..)) {
|
||||
@@ -254,7 +255,7 @@ parameter_types! {
|
||||
pub static AllowUnpaidFrom: Vec<MultiLocation> = vec![];
|
||||
pub static AllowPaidFrom: Vec<MultiLocation> = vec![];
|
||||
// 1_000_000_000_000 => 1 unit of asset for 1 unit of Weight.
|
||||
pub static WeightPrice: (MultiLocation, u128) = (Null, 1_000_000_000_000);
|
||||
pub static WeightPrice: (AssetId, u128) = (Here.into(), 1_000_000_000_000);
|
||||
}
|
||||
|
||||
pub type TestBarrier = (
|
||||
@@ -275,6 +276,6 @@ impl Config for TestConfig {
|
||||
type LocationInverter = LocationInverter<TestAncestry>;
|
||||
type Barrier = TestBarrier;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, TestCall>;
|
||||
type Trader = FixedRateOfConcreteFungible<WeightPrice, ()>;
|
||||
type Trader = FixedRateOfFungible<WeightPrice, ()>;
|
||||
type ResponseHandler = TestResponseHandler;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use frame_support::traits::{EnsureOrigin, Get, GetBacking, OriginTrait};
|
||||
use frame_system::RawOrigin as SystemRawOrigin;
|
||||
use polkadot_parachain::primitives::IsSystem;
|
||||
use sp_std::{convert::TryInto, marker::PhantomData};
|
||||
use xcm::v0::{BodyId, BodyPart, Junction, MultiLocation, NetworkId, OriginKind};
|
||||
use xcm::latest::{BodyId, BodyPart, Junction, MultiLocation, NetworkId, OriginKind};
|
||||
use xcm_executor::traits::{Convert, ConvertOrigin};
|
||||
|
||||
/// Sovereign accounts use the system's `Signed` origin with an account ID derived from the `LocationConverter`.
|
||||
@@ -170,7 +170,7 @@ where
|
||||
// We institute a root fallback so root can always represent the context. This
|
||||
// guarantees that `successful_origin` will work.
|
||||
if o.caller() == Origin::root().caller() {
|
||||
Ok(MultiLocation::Null)
|
||||
Ok(MultiLocation::Here)
|
||||
} else {
|
||||
Err(o)
|
||||
}
|
||||
|
||||
@@ -15,16 +15,14 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{mock::*, *};
|
||||
use xcm::v0::{ExecuteXcm, NetworkId::Any, Order, Outcome, Response};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::{traits::*, Config, XcmExecutor};
|
||||
use MultiAsset::*;
|
||||
use Option::None;
|
||||
|
||||
#[test]
|
||||
fn basic_setup_works() {
|
||||
add_reserve(X1(Parent), AllConcreteFungible { id: X1(Parent) });
|
||||
add_reserve(X1(Parent), Wild((X1(Parent), WildFungible).into()));
|
||||
assert!(<TestConfig as Config>::IsReserve::filter_asset_location(
|
||||
&ConcreteFungible { id: X1(Parent), amount: 100 },
|
||||
&(X1(Parent), 100).into(),
|
||||
&X1(Parent),
|
||||
));
|
||||
|
||||
@@ -34,22 +32,23 @@ fn basic_setup_works() {
|
||||
assert_eq!(to_account(X2(Parent, Parachain(50))), Ok(2050));
|
||||
assert_eq!(to_account(X1(AccountIndex64 { index: 1, network: Any })), Ok(1));
|
||||
assert_eq!(to_account(X1(AccountIndex64 { index: 42, network: Any })), Ok(42));
|
||||
assert_eq!(to_account(Null), Ok(3000));
|
||||
assert_eq!(to_account(Here), Ok(3000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weigher_should_work() {
|
||||
let mut message = opaque::Xcm::ReserveAssetDeposit {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
let mut message = opaque::Xcm::ReserveAssetDeposited {
|
||||
assets: (X1(Parent), 100).into(),
|
||||
effects: vec![
|
||||
Order::BuyExecution {
|
||||
fees: All,
|
||||
fees: (X1(Parent), 1).into(),
|
||||
weight: 0,
|
||||
debt: 30,
|
||||
halt_on_error: true,
|
||||
xcm: vec![],
|
||||
orders: vec![],
|
||||
instructions: vec![],
|
||||
},
|
||||
Order::DepositAsset { assets: vec![All], dest: Null },
|
||||
Order::DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here },
|
||||
],
|
||||
}
|
||||
.into();
|
||||
@@ -58,10 +57,8 @@ fn weigher_should_work() {
|
||||
|
||||
#[test]
|
||||
fn take_weight_credit_barrier_should_work() {
|
||||
let mut message = opaque::Xcm::TransferAsset {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
dest: Null,
|
||||
};
|
||||
let mut message =
|
||||
opaque::Xcm::TransferAsset { assets: (X1(Parent), 100).into(), beneficiary: Here };
|
||||
|
||||
let mut weight_credit = 10;
|
||||
let r =
|
||||
@@ -77,10 +74,8 @@ fn take_weight_credit_barrier_should_work() {
|
||||
|
||||
#[test]
|
||||
fn allow_unpaid_should_work() {
|
||||
let mut message = opaque::Xcm::TransferAsset {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
dest: Null,
|
||||
};
|
||||
let mut message =
|
||||
opaque::Xcm::TransferAsset { assets: (X1(Parent), 100).into(), beneficiary: Here };
|
||||
|
||||
AllowUnpaidFrom::set(vec![X1(Parent)]);
|
||||
|
||||
@@ -107,10 +102,8 @@ fn allow_unpaid_should_work() {
|
||||
fn allow_paid_should_work() {
|
||||
AllowPaidFrom::set(vec![X1(Parent)]);
|
||||
|
||||
let mut message = opaque::Xcm::TransferAsset {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
dest: Null,
|
||||
};
|
||||
let mut message =
|
||||
opaque::Xcm::TransferAsset { assets: (X1(Parent), 100).into(), beneficiary: Here };
|
||||
|
||||
let r = AllowTopLevelPaidExecutionFrom::<IsInVec<AllowPaidFrom>>::should_execute(
|
||||
&X1(Parachain(1)),
|
||||
@@ -121,17 +114,19 @@ fn allow_paid_should_work() {
|
||||
);
|
||||
assert_eq!(r, Err(()));
|
||||
|
||||
let mut underpaying_message = opaque::Xcm::ReserveAssetDeposit {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
let fees = (X1(Parent), 1).into();
|
||||
let mut underpaying_message = opaque::Xcm::ReserveAssetDeposited {
|
||||
assets: (X1(Parent), 100).into(),
|
||||
effects: vec![
|
||||
Order::BuyExecution {
|
||||
fees: All,
|
||||
fees,
|
||||
weight: 0,
|
||||
debt: 20,
|
||||
halt_on_error: true,
|
||||
xcm: vec![],
|
||||
orders: vec![],
|
||||
instructions: vec![],
|
||||
},
|
||||
Order::DepositAsset { assets: vec![All], dest: Null },
|
||||
Order::DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -144,17 +139,19 @@ fn allow_paid_should_work() {
|
||||
);
|
||||
assert_eq!(r, Err(()));
|
||||
|
||||
let mut paying_message = opaque::Xcm::ReserveAssetDeposit {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
let fees = (X1(Parent), 1).into();
|
||||
let mut paying_message = opaque::Xcm::ReserveAssetDeposited {
|
||||
assets: (X1(Parent), 100).into(),
|
||||
effects: vec![
|
||||
Order::BuyExecution {
|
||||
fees: All,
|
||||
fees,
|
||||
weight: 0,
|
||||
debt: 30,
|
||||
halt_on_error: true,
|
||||
xcm: vec![],
|
||||
orders: vec![],
|
||||
instructions: vec![],
|
||||
},
|
||||
Order::DepositAsset { assets: vec![All], dest: Null },
|
||||
Order::DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -180,27 +177,33 @@ fn allow_paid_should_work() {
|
||||
#[test]
|
||||
fn paying_reserve_deposit_should_work() {
|
||||
AllowPaidFrom::set(vec![X1(Parent)]);
|
||||
add_reserve(X1(Parent), AllConcreteFungible { id: X1(Parent) });
|
||||
WeightPrice::set((X1(Parent), 1_000_000_000_000));
|
||||
add_reserve(X1(Parent), (Parent, WildFungible).into());
|
||||
WeightPrice::set((Parent.into(), 1_000_000_000_000));
|
||||
|
||||
let origin = X1(Parent);
|
||||
let message = Xcm::<TestCall>::ReserveAssetDeposit {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
let fees = (X1(Parent), 30).into();
|
||||
let message = Xcm::<TestCall>::ReserveAssetDeposited {
|
||||
assets: (X1(Parent), 100).into(),
|
||||
effects: vec![
|
||||
Order::<TestCall>::BuyExecution {
|
||||
fees: All,
|
||||
fees,
|
||||
weight: 0,
|
||||
debt: 30,
|
||||
halt_on_error: true,
|
||||
xcm: vec![],
|
||||
orders: vec![],
|
||||
instructions: vec![],
|
||||
},
|
||||
Order::<TestCall>::DepositAsset {
|
||||
assets: All.into(),
|
||||
max_assets: 1,
|
||||
beneficiary: Here,
|
||||
},
|
||||
Order::<TestCall>::DepositAsset { assets: vec![All], dest: Null },
|
||||
],
|
||||
};
|
||||
let weight_limit = 50;
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(30));
|
||||
assert_eq!(assets(3000), vec![ConcreteFungible { id: X1(Parent), amount: 70 }]);
|
||||
assert_eq!(assets(3000), vec![(X1(Parent), 70).into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -208,19 +211,19 @@ fn transfer_should_work() {
|
||||
// we'll let them have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1))]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(1001, ConcreteFungible { id: Null, amount: 1000 });
|
||||
add_asset(1001, (Here, 1000).into());
|
||||
// They want to transfer 100 of them to their sibling parachain #2
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
X1(Parachain(1)),
|
||||
Xcm::TransferAsset {
|
||||
assets: vec![ConcreteFungible { id: Null, amount: 100 }],
|
||||
dest: X1(AccountIndex64 { index: 3, network: Any }),
|
||||
assets: (Here, 100).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: Any }),
|
||||
},
|
||||
50,
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(10));
|
||||
assert_eq!(assets(3), vec![ConcreteFungible { id: Null, amount: 100 }]);
|
||||
assert_eq!(assets(1001), vec![ConcreteFungible { id: Null, amount: 900 }]);
|
||||
assert_eq!(assets(3), vec![(Here, 100).into()]);
|
||||
assert_eq!(assets(1001), vec![(Here, 900).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
}
|
||||
|
||||
@@ -228,7 +231,7 @@ fn transfer_should_work() {
|
||||
fn reserve_transfer_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1))]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(1001, ConcreteFungible { id: Null, amount: 1000 });
|
||||
add_asset(1001, (Here, 1000).into());
|
||||
// The remote account owned by gav.
|
||||
let three = X1(AccountIndex64 { index: 3, network: Any });
|
||||
|
||||
@@ -237,22 +240,30 @@ fn reserve_transfer_should_work() {
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
X1(Parachain(1)),
|
||||
Xcm::TransferReserveAsset {
|
||||
assets: vec![ConcreteFungible { id: Null, amount: 100 }],
|
||||
assets: (Here, 100).into(),
|
||||
dest: X1(Parachain(2)),
|
||||
effects: vec![Order::DepositAsset { assets: vec![All], dest: three.clone() }],
|
||||
effects: vec![Order::DepositAsset {
|
||||
assets: All.into(),
|
||||
max_assets: 1,
|
||||
beneficiary: three.clone(),
|
||||
}],
|
||||
},
|
||||
50,
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(10));
|
||||
|
||||
assert_eq!(assets(1002), vec![ConcreteFungible { id: Null, amount: 100 }]);
|
||||
assert_eq!(assets(1002), vec![(Here, 100).into()]);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
X1(Parachain(2)),
|
||||
Xcm::ReserveAssetDeposit {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }],
|
||||
effects: vec![Order::DepositAsset { assets: vec![All], dest: three }],
|
||||
Xcm::ReserveAssetDeposited {
|
||||
assets: (X1(Parent), 100).into(),
|
||||
effects: vec![Order::DepositAsset {
|
||||
assets: All.into(),
|
||||
max_assets: 1,
|
||||
beneficiary: three
|
||||
}],
|
||||
}
|
||||
)]
|
||||
);
|
||||
@@ -307,32 +318,38 @@ fn transacting_should_refund_weight() {
|
||||
fn paid_transacting_should_refund_payment_for_unused_weight() {
|
||||
let one = X1(AccountIndex64 { index: 1, network: Any });
|
||||
AllowPaidFrom::set(vec![one.clone()]);
|
||||
add_asset(1, ConcreteFungible { id: X1(Parent), amount: 100 });
|
||||
WeightPrice::set((X1(Parent), 1_000_000_000_000));
|
||||
add_asset(1, (Parent, 100).into());
|
||||
WeightPrice::set((Parent.into(), 1_000_000_000_000));
|
||||
|
||||
let origin = one.clone();
|
||||
let fees = (X1(Parent), 100).into();
|
||||
let message = Xcm::<TestCall>::WithdrawAsset {
|
||||
assets: vec![ConcreteFungible { id: X1(Parent), amount: 100 }], // enough for 100 units of weight.
|
||||
assets: (X1(Parent), 100).into(), // enough for 100 units of weight.
|
||||
effects: vec![
|
||||
Order::<TestCall>::BuyExecution {
|
||||
fees: All,
|
||||
fees,
|
||||
weight: 70,
|
||||
debt: 30,
|
||||
halt_on_error: true,
|
||||
xcm: vec![Xcm::<TestCall>::Transact {
|
||||
orders: vec![],
|
||||
instructions: vec![Xcm::<TestCall>::Transact {
|
||||
origin_type: OriginKind::Native,
|
||||
require_weight_at_most: 60,
|
||||
// call estimated at 70 but only takes 10.
|
||||
call: TestCall::Any(60, Some(10)).encode().into(),
|
||||
}],
|
||||
},
|
||||
Order::<TestCall>::DepositAsset { assets: vec![All], dest: one.clone() },
|
||||
Order::<TestCall>::DepositAsset {
|
||||
assets: All.into(),
|
||||
max_assets: 1,
|
||||
beneficiary: one.clone(),
|
||||
},
|
||||
],
|
||||
};
|
||||
let weight_limit = 100;
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(50));
|
||||
assert_eq!(assets(1), vec![ConcreteFungible { id: X1(Parent), amount: 50 }]);
|
||||
assert_eq!(assets(1), vec![(X1(Parent), 50).into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -342,7 +359,7 @@ fn prepaid_result_of_query_should_get_free_execution() {
|
||||
// We put this in manually here, but normally this would be done at the point of crafting the message.
|
||||
expect_response(query_id, origin.clone());
|
||||
|
||||
let the_response = Response::Assets(vec![ConcreteFungible { id: X1(Parent), amount: 100 }]);
|
||||
let the_response = Response::Assets((X1(Parent), 100).into());
|
||||
let message = Xcm::<TestCall>::QueryResponse { query_id, response: the_response.clone() };
|
||||
let weight_limit = 10;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use frame_support::{
|
||||
use parity_scale_codec::Decode;
|
||||
use sp_runtime::traits::{SaturatedConversion, Saturating, Zero};
|
||||
use sp_std::{convert::TryInto, marker::PhantomData, result::Result};
|
||||
use xcm::v0::{Error, MultiAsset, MultiLocation, Order, Xcm};
|
||||
use xcm::latest::{AssetId, AssetId::Concrete, Error, MultiAsset, MultiLocation, Order, Xcm};
|
||||
use xcm_executor::{
|
||||
traits::{WeightBounds, WeightTrader},
|
||||
Assets,
|
||||
@@ -36,23 +36,13 @@ impl<T: Get<Weight>, C: Decode + GetDispatchInfo> WeightBounds<C> for FixedWeigh
|
||||
Xcm::RelayedFrom { ref mut message, .. } =>
|
||||
T::get().saturating_add(Self::shallow(message.as_mut())?),
|
||||
Xcm::WithdrawAsset { effects, .. } |
|
||||
Xcm::ReserveAssetDeposit { effects, .. } |
|
||||
Xcm::TeleportAsset { effects, .. } => {
|
||||
let inner: Weight = effects
|
||||
.iter_mut()
|
||||
.map(|effect| match effect {
|
||||
Order::BuyExecution { .. } => {
|
||||
// On success, execution of this will result in more weight being consumed but
|
||||
// we don't count it here since this is only the *shallow*, non-negotiable weight
|
||||
// spend and doesn't count weight placed behind a `BuyExecution` since it will not
|
||||
// be definitely consumed from any existing weight credit if execution of the message
|
||||
// is attempted.
|
||||
T::get()
|
||||
},
|
||||
_ => T::get(),
|
||||
})
|
||||
.sum();
|
||||
T::get().saturating_add(inner)
|
||||
Xcm::ReserveAssetDeposited { effects, .. } |
|
||||
Xcm::ReceiveTeleportedAsset { effects, .. } => {
|
||||
let mut extra = T::get();
|
||||
for order in effects.iter_mut() {
|
||||
extra.saturating_accrue(Self::shallow_order(order)?);
|
||||
}
|
||||
extra
|
||||
},
|
||||
_ => T::get(),
|
||||
})
|
||||
@@ -61,19 +51,46 @@ impl<T: Get<Weight>, C: Decode + GetDispatchInfo> WeightBounds<C> for FixedWeigh
|
||||
Ok(match message {
|
||||
Xcm::RelayedFrom { ref mut message, .. } => Self::deep(message.as_mut())?,
|
||||
Xcm::WithdrawAsset { effects, .. } |
|
||||
Xcm::ReserveAssetDeposit { effects, .. } |
|
||||
Xcm::TeleportAsset { effects, .. } => {
|
||||
Xcm::ReserveAssetDeposited { effects, .. } |
|
||||
Xcm::ReceiveTeleportedAsset { effects, .. } => {
|
||||
let mut extra = 0;
|
||||
for effect in effects.iter_mut() {
|
||||
match effect {
|
||||
Order::BuyExecution { xcm, .. } =>
|
||||
for message in xcm.iter_mut() {
|
||||
extra.saturating_accrue(
|
||||
Self::shallow(message)?.saturating_add(Self::deep(message)?),
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
for order in effects.iter_mut() {
|
||||
extra.saturating_accrue(Self::deep_order(order)?);
|
||||
}
|
||||
extra
|
||||
},
|
||||
_ => 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Get<Weight>, C: Decode + GetDispatchInfo> FixedWeightBounds<T, C> {
|
||||
fn shallow_order(order: &mut Order<C>) -> Result<Weight, ()> {
|
||||
Ok(match order {
|
||||
Order::BuyExecution { .. } => {
|
||||
// On success, execution of this will result in more weight being consumed but
|
||||
// we don't count it here since this is only the *shallow*, non-negotiable weight
|
||||
// spend and doesn't count weight placed behind a `BuyExecution` since it will not
|
||||
// be definitely consumed from any existing weight credit if execution of the message
|
||||
// is attempted.
|
||||
T::get()
|
||||
},
|
||||
_ => T::get(),
|
||||
})
|
||||
}
|
||||
fn deep_order(order: &mut Order<C>) -> Result<Weight, ()> {
|
||||
Ok(match order {
|
||||
Order::BuyExecution { orders, instructions, .. } => {
|
||||
let mut extra = 0;
|
||||
for instruction in instructions.iter_mut() {
|
||||
extra.saturating_accrue(
|
||||
Self::shallow(instruction)?.saturating_add(Self::deep(instruction)?),
|
||||
);
|
||||
}
|
||||
for order in orders.iter_mut() {
|
||||
extra.saturating_accrue(
|
||||
Self::shallow_order(order)?.saturating_add(Self::deep_order(order)?),
|
||||
);
|
||||
}
|
||||
extra
|
||||
},
|
||||
@@ -98,11 +115,13 @@ impl TakeRevenue for () {
|
||||
///
|
||||
/// The constant `Get` type parameter should be the concrete fungible ID and the amount of it required for
|
||||
/// one second of weight.
|
||||
#[deprecated = "Use `FixedRateOfFungible` instead"]
|
||||
pub struct FixedRateOfConcreteFungible<T: Get<(MultiLocation, u128)>, R: TakeRevenue>(
|
||||
Weight,
|
||||
u128,
|
||||
PhantomData<(T, R)>,
|
||||
);
|
||||
#[allow(deprecated)]
|
||||
impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> WeightTrader
|
||||
for FixedRateOfConcreteFungible<T, R>
|
||||
{
|
||||
@@ -114,28 +133,80 @@ impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> WeightTrader
|
||||
let (id, units_per_second) = T::get();
|
||||
use frame_support::weights::constants::WEIGHT_PER_SECOND;
|
||||
let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128);
|
||||
let required = MultiAsset::ConcreteFungible { amount, id };
|
||||
let (unused, _) = payment.less(required).map_err(|_| Error::TooExpensive)?;
|
||||
let unused = payment.checked_sub((id, amount).into()).map_err(|_| Error::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight) -> MultiAsset {
|
||||
fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
|
||||
let (id, units_per_second) = T::get();
|
||||
let weight = weight.min(self.0);
|
||||
let amount = units_per_second * (weight as u128) / 1_000_000_000_000u128;
|
||||
self.0 -= weight;
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
let result = MultiAsset::ConcreteFungible { amount, id };
|
||||
result
|
||||
if amount > 0 {
|
||||
Some((Concrete(id), amount).into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
#[allow(deprecated)]
|
||||
impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> Drop for FixedRateOfConcreteFungible<T, R> {
|
||||
fn drop(&mut self) {
|
||||
if self.1 > 0 {
|
||||
R::take_revenue((Concrete(T::get().0), self.1).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> Drop for FixedRateOfConcreteFungible<T, R> {
|
||||
/// Simple fee calculator that requires payment in a single fungible at a fixed rate.
|
||||
///
|
||||
/// The constant `Get` type parameter should be the fungible ID and the amount of it required for
|
||||
/// one second of weight.
|
||||
pub struct FixedRateOfFungible<T: Get<(AssetId, u128)>, R: TakeRevenue>(
|
||||
Weight,
|
||||
u128,
|
||||
PhantomData<(T, R)>,
|
||||
);
|
||||
impl<T: Get<(AssetId, u128)>, R: TakeRevenue> WeightTrader for FixedRateOfFungible<T, R> {
|
||||
fn new() -> Self {
|
||||
Self(0, 0, PhantomData)
|
||||
}
|
||||
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error> {
|
||||
let (id, units_per_second) = T::get();
|
||||
use frame_support::weights::constants::WEIGHT_PER_SECOND;
|
||||
let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128);
|
||||
if amount == 0 {
|
||||
return Ok(payment)
|
||||
}
|
||||
let unused = payment.checked_sub((id, amount).into()).map_err(|_| Error::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
|
||||
let (id, units_per_second) = T::get();
|
||||
let weight = weight.min(self.0);
|
||||
let amount = units_per_second * (weight as u128) / 1_000_000_000_000u128;
|
||||
self.0 -= weight;
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
if amount > 0 {
|
||||
Some((id, amount).into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Get<(AssetId, u128)>, R: TakeRevenue> Drop for FixedRateOfFungible<T, R> {
|
||||
fn drop(&mut self) {
|
||||
let revenue = MultiAsset::ConcreteFungible { amount: self.1, id: T::get().0 };
|
||||
R::take_revenue(revenue);
|
||||
if self.1 > 0 {
|
||||
R::take_revenue((T::get().0, self.1).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,24 +237,25 @@ impl<
|
||||
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error> {
|
||||
let amount = WeightToFee::calc(&weight);
|
||||
let required = MultiAsset::ConcreteFungible {
|
||||
amount: amount.try_into().map_err(|_| Error::Overflow)?,
|
||||
id: AssetId::get(),
|
||||
};
|
||||
let (unused, _) = payment.less(required).map_err(|_| Error::TooExpensive)?;
|
||||
let u128_amount: u128 = amount.try_into().map_err(|_| Error::Overflow)?;
|
||||
let required = (Concrete(AssetId::get()), u128_amount).into();
|
||||
let unused = payment.checked_sub(required).map_err(|_| Error::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight) -> MultiAsset {
|
||||
fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
|
||||
let weight = weight.min(self.0);
|
||||
let amount = WeightToFee::calc(&weight);
|
||||
self.0 -= weight;
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
let result =
|
||||
MultiAsset::ConcreteFungible { amount: amount.saturated_into(), id: AssetId::get() };
|
||||
result
|
||||
let amount: u128 = amount.saturated_into();
|
||||
if amount > 0 {
|
||||
Some((AssetId::get(), amount).into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<
|
||||
|
||||
Reference in New Issue
Block a user