diff --git a/runtime/test-runtime/src/xcm_config.rs b/runtime/test-runtime/src/xcm_config.rs index 45e7956d45ba..21ce8c877dc3 100644 --- a/runtime/test-runtime/src/xcm_config.rs +++ b/runtime/test-runtime/src/xcm_config.rs @@ -80,7 +80,12 @@ impl WeightTrader for DummyWeightTrader { DummyWeightTrader } - fn buy_weight(&mut self, _weight: Weight, _payment: Assets) -> Result { + fn buy_weight( + &mut self, + _weight: Weight, + _payment: Assets, + _context: &XcmContext, + ) -> Result { Ok(Assets::default()) } } diff --git a/xcm/xcm-builder/src/tests/weight.rs b/xcm/xcm-builder/src/tests/weight.rs index 99ef029196ff..a2fb265413f5 100644 --- a/xcm/xcm-builder/src/tests/weight.rs +++ b/xcm/xcm-builder/src/tests/weight.rs @@ -24,25 +24,42 @@ fn fixed_rate_of_fungible_should_work() { } let mut trader = FixedRateOfFungible::::new(); + let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; + // supplies 100 unit of asset, 80 still remains after purchasing weight assert_eq!( - trader - .buy_weight(Weight::from_parts(10, 10), fungible_multi_asset(Here.into(), 100).into()), + trader.buy_weight( + Weight::from_parts(10, 10), + fungible_multi_asset(Here.into(), 100).into(), + &ctx, + ), Ok(fungible_multi_asset(Here.into(), 80).into()), ); // should have nothing left, as 5 + 5 = 10, and we supplied 10 units of asset. assert_eq!( - trader.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(Here.into(), 10).into()), + trader.buy_weight( + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 10).into(), + &ctx, + ), Ok(vec![].into()), ); // should have 5 left, as there are no proof size components assert_eq!( - trader.buy_weight(Weight::from_parts(5, 0), fungible_multi_asset(Here.into(), 10).into()), + trader.buy_weight( + Weight::from_parts(5, 0), + fungible_multi_asset(Here.into(), 10).into(), + &ctx, + ), Ok(fungible_multi_asset(Here.into(), 5).into()), ); // not enough to purchase the combined weights assert_err!( - trader.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(Here.into(), 5).into()), + trader.buy_weight( + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 5).into(), + &ctx, + ), XcmError::TooExpensive, ); } @@ -149,35 +166,41 @@ fn weight_trader_tuple_should_work() { ); let mut traders = Traders::new(); + let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; + // trader one buys weight assert_eq!( - traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(Here.into(), 10).into()), + traders.buy_weight( + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 10).into(), + &ctx + ), Ok(vec![].into()), ); // trader one refunds assert_eq!( - traders.refund_weight(Weight::from_parts(2, 2)), + traders.refund_weight(Weight::from_parts(2, 2), &ctx), Some(fungible_multi_asset(Here.into(), 4)) ); let mut traders = Traders::new(); // trader one failed; trader two buys weight assert_eq!( - traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_1, 10).into()), + traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_1, 10).into(), &ctx), Ok(vec![].into()), ); // trader two refunds assert_eq!( - traders.refund_weight(Weight::from_parts(2, 2)), + traders.refund_weight(Weight::from_parts(2, 2), &ctx), Some(fungible_multi_asset(para_1, 4)) ); let mut traders = Traders::new(); // all traders fails assert_err!( - traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_2, 10).into()), + traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_2, 10).into(), &ctx), XcmError::TooExpensive, ); // and no refund - assert_eq!(traders.refund_weight(Weight::from_parts(2, 2)), None); + assert_eq!(traders.refund_weight(Weight::from_parts(2, 2), &ctx), None); } diff --git a/xcm/xcm-builder/src/weight.rs b/xcm/xcm-builder/src/weight.rs index 1473775eccd8..73cba6cb557b 100644 --- a/xcm/xcm-builder/src/weight.rs +++ b/xcm/xcm-builder/src/weight.rs @@ -140,11 +140,16 @@ impl, R: TakeRevenue> WeightTrader for FixedRateOf Self(Weight::zero(), 0, PhantomData) } - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + fn buy_weight( + &mut self, + weight: Weight, + payment: Assets, + context: &XcmContext, + ) -> Result { log::trace!( target: "xcm::weight", - "FixedRateOfFungible::buy_weight weight: {:?}, payment: {:?}", - weight, payment, + "FixedRateOfFungible::buy_weight weight: {:?}, payment: {:?}, context: {:?}", + weight, payment, context, ); let (id, units_per_second, units_per_mb) = T::get(); let amount = (units_per_second * (weight.ref_time() as u128) / @@ -160,8 +165,8 @@ impl, R: TakeRevenue> WeightTrader for FixedRateOf Ok(unused) } - fn refund_weight(&mut self, weight: Weight) -> Option { - log::trace!(target: "xcm::weight", "FixedRateOfFungible::refund_weight weight: {:?}", weight); + fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { + log::trace!(target: "xcm::weight", "FixedRateOfFungible::refund_weight weight: {:?}, context: {:?}", weight, context); let (id, units_per_second, units_per_mb) = T::get(); let weight = weight.min(self.0); let amount = (units_per_second * (weight.ref_time() as u128) / @@ -210,8 +215,13 @@ impl< Self(Weight::zero(), Zero::zero(), PhantomData) } - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { - log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}", weight, payment); + fn buy_weight( + &mut self, + weight: Weight, + payment: Assets, + context: &XcmContext, + ) -> Result { + log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}, context: {:?}", weight, payment, context); let amount = WeightToFee::weight_to_fee(&weight); let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?; let required = (Concrete(AssetId::get()), u128_amount).into(); @@ -221,8 +231,8 @@ impl< Ok(unused) } - fn refund_weight(&mut self, weight: Weight) -> Option { - log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}", weight); + fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { + log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}", weight, context); let weight = weight.min(self.0); let amount = WeightToFee::weight_to_fee(&weight); self.0 -= weight; diff --git a/xcm/xcm-executor/src/lib.rs b/xcm/xcm-executor/src/lib.rs index 050d73837085..57ddc4322923 100644 --- a/xcm/xcm-executor/src/lib.rs +++ b/xcm/xcm-executor/src/lib.rs @@ -457,7 +457,7 @@ impl XcmExecutor { let current_surplus = self.total_surplus.saturating_sub(self.total_refunded); if current_surplus.any_gt(Weight::zero()) { self.total_refunded.saturating_accrue(current_surplus); - if let Some(w) = self.trader.refund_weight(current_surplus) { + if let Some(w) = self.trader.refund_weight(current_surplus, &self.context) { self.subsume_asset(w)?; } } @@ -689,7 +689,7 @@ impl XcmExecutor { // pay for `weight` using up to `fees` of the holding register. let max_fee = self.holding.try_take(fees.into()).map_err(|_| XcmError::NotHoldingFees)?; - let unspent = self.trader.buy_weight(weight, max_fee)?; + let unspent = self.trader.buy_weight(weight, max_fee, &self.context)?; self.subsume_assets(unspent)?; } Ok(()) diff --git a/xcm/xcm-executor/src/traits/weight.rs b/xcm/xcm-executor/src/traits/weight.rs index 033614d4bf61..06e6b5f55bce 100644 --- a/xcm/xcm-executor/src/traits/weight.rs +++ b/xcm/xcm-executor/src/traits/weight.rs @@ -49,13 +49,18 @@ pub trait WeightTrader: Sized { /// Purchase execution weight credit in return for up to a given `payment`. If less of the /// payment is required then the surplus is returned. If the `payment` cannot be used to pay /// for the `weight`, then an error is returned. - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result; + fn buy_weight( + &mut self, + weight: Weight, + payment: Assets, + context: &XcmContext, + ) -> Result; /// Attempt a refund of `weight` into some asset. The caller does not guarantee that the weight was /// purchased using `buy_weight`. /// /// Default implementation refunds nothing. - fn refund_weight(&mut self, _weight: Weight) -> Option { + fn refund_weight(&mut self, _weight: Weight, _context: &XcmContext) -> Option { None } } @@ -66,11 +71,16 @@ impl WeightTrader for Tuple { for_tuples!( ( #( Tuple::new() ),* ) ) } - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + fn buy_weight( + &mut self, + weight: Weight, + payment: Assets, + context: &XcmContext, + ) -> Result { let mut too_expensive_error_found = false; let mut last_error = None; for_tuples!( #( - match Tuple.buy_weight(weight, payment.clone()) { + match Tuple.buy_weight(weight, payment.clone(), context) { Ok(assets) => return Ok(assets), Err(e) => { if let XcmError::TooExpensive = e { @@ -92,9 +102,9 @@ impl WeightTrader for Tuple { }) } - fn refund_weight(&mut self, weight: Weight) -> Option { + fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { for_tuples!( #( - if let Some(asset) = Tuple.refund_weight(weight) { + if let Some(asset) = Tuple.refund_weight(weight, context) { return Some(asset); } )* );