diff --git a/runtime/test-runtime/src/xcm_config.rs b/runtime/test-runtime/src/xcm_config.rs index 45e7956d45ba..c6891c349d64 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, + _ctx: Option<&XcmContext>, + _weight: Weight, + _payment: Assets, + ) -> Result { Ok(Assets::default()) } } diff --git a/xcm/xcm-builder/src/tests/weight.rs b/xcm/xcm-builder/src/tests/weight.rs index 99ef029196ff..15a3c9d2a62a 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( + Some(&ctx), + Weight::from_parts(10, 10), + fungible_multi_asset(Here.into(), 100).into() + ), 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( + Some(&ctx), + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 10).into() + ), 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( + Some(&ctx), + Weight::from_parts(5, 0), + fungible_multi_asset(Here.into(), 10).into() + ), 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( + Some(&ctx), + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 5).into() + ), XcmError::TooExpensive, ); } @@ -151,33 +168,37 @@ fn weight_trader_tuple_should_work() { let mut traders = Traders::new(); // trader one buys weight assert_eq!( - traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(Here.into(), 10).into()), + traders.buy_weight( + None, + Weight::from_parts(5, 5), + fungible_multi_asset(Here.into(), 10).into() + ), Ok(vec![].into()), ); // trader one refunds assert_eq!( - traders.refund_weight(Weight::from_parts(2, 2)), + traders.refund_weight(None, Weight::from_parts(2, 2)), 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(None, Weight::from_parts(5, 5), fungible_multi_asset(para_1, 10).into()), Ok(vec![].into()), ); // trader two refunds assert_eq!( - traders.refund_weight(Weight::from_parts(2, 2)), + traders.refund_weight(None, Weight::from_parts(2, 2)), 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(None, Weight::from_parts(5, 5), fungible_multi_asset(para_2, 10).into()), XcmError::TooExpensive, ); // and no refund - assert_eq!(traders.refund_weight(Weight::from_parts(2, 2)), None); + assert_eq!(traders.refund_weight(None, Weight::from_parts(2, 2)), None); } diff --git a/xcm/xcm-builder/src/weight.rs b/xcm/xcm-builder/src/weight.rs index 1473775eccd8..de7fb6daafa9 100644 --- a/xcm/xcm-builder/src/weight.rs +++ b/xcm/xcm-builder/src/weight.rs @@ -140,7 +140,12 @@ 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, + _ctx: Option<&XcmContext>, + weight: Weight, + payment: Assets, + ) -> Result { log::trace!( target: "xcm::weight", "FixedRateOfFungible::buy_weight weight: {:?}, payment: {:?}", @@ -160,7 +165,7 @@ impl, R: TakeRevenue> WeightTrader for FixedRateOf Ok(unused) } - fn refund_weight(&mut self, weight: Weight) -> Option { + fn refund_weight(&mut self, _ctx: Option<&XcmContext>, weight: Weight) -> Option { log::trace!(target: "xcm::weight", "FixedRateOfFungible::refund_weight weight: {:?}", weight); let (id, units_per_second, units_per_mb) = T::get(); let weight = weight.min(self.0); @@ -210,7 +215,12 @@ impl< Self(Weight::zero(), Zero::zero(), PhantomData) } - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + fn buy_weight( + &mut self, + _ctx: Option<&XcmContext>, + weight: Weight, + payment: Assets, + ) -> Result { log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}", weight, payment); let amount = WeightToFee::weight_to_fee(&weight); let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?; @@ -221,7 +231,7 @@ impl< Ok(unused) } - fn refund_weight(&mut self, weight: Weight) -> Option { + fn refund_weight(&mut self, _ctx: Option<&XcmContext>, weight: Weight) -> Option { log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}", weight); let weight = weight.min(self.0); let amount = WeightToFee::weight_to_fee(&weight); diff --git a/xcm/xcm-executor/src/lib.rs b/xcm/xcm-executor/src/lib.rs index 050d73837085..24f38cc00e0c 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(Some(&self.context), current_surplus) { 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(Some(&self.context), weight, max_fee)?; 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..273d728db560 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, + ctx: Option<&XcmContext>, + weight: Weight, + payment: Assets, + ) -> 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, _ctx: Option<&XcmContext>, _weight: Weight) -> 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, + ctx: Option<&XcmContext>, + weight: Weight, + payment: Assets, + ) -> 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(ctx, weight, payment.clone()) { 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, ctx: Option<&XcmContext>, weight: Weight) -> Option { for_tuples!( #( - if let Some(asset) = Tuple.refund_weight(weight) { + if let Some(asset) = Tuple.refund_weight(ctx, weight) { return Some(asset); } )* );