Unverified Commit f3f83e3f authored by Shaun Wang's avatar Shaun Wang Committed by GitHub
Browse files

Impl WeightTrader for tuple (#3601)



* Impl WeightTrader for tuple.

* fmt

* Renaming.

* add tracing for buy_weight

* Add comment clarifying the default behavior of a WeightTrader tuple
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>
Co-authored-by: Keith Yeung's avatarKeith Yeung <kungfukeith11@gmail.com>
parent 3d0ee437
Pipeline #153211 failed with stages
in 19 minutes and 30 seconds
......@@ -15,6 +15,7 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use super::{mock::*, *};
use frame_support::{assert_err, weights::constants::WEIGHT_PER_SECOND};
use xcm::latest::prelude::*;
use xcm_executor::{traits::*, Config, XcmExecutor};
......@@ -383,3 +384,52 @@ fn prepaid_result_of_query_should_get_free_execution() {
let r = XcmExecutor::<TestConfig>::execute_xcm(origin.clone(), message.clone(), weight_limit);
assert_eq!(r, Outcome::Incomplete(10, XcmError::Barrier));
}
fn fungible_multi_asset(location: MultiLocation, amount: u128) -> MultiAsset {
(AssetId::from(location), Fungibility::Fungible(amount)).into()
}
#[test]
fn weight_trader_tuple_should_work() {
pub const PARA_1: MultiLocation = X1(Parachain(1));
pub const PARA_2: MultiLocation = X1(Parachain(2));
parameter_types! {
pub static HereWeightPrice: (AssetId, u128) = (Here.into(), WEIGHT_PER_SECOND.into());
pub static PARA1WeightPrice: (AssetId, u128) = (PARA_1.into(), WEIGHT_PER_SECOND.into());
}
type Traders = (
// trader one
FixedRateOfFungible<HereWeightPrice, ()>,
// trader two
FixedRateOfFungible<PARA1WeightPrice, ()>,
);
let mut traders = Traders::new();
// trader one buys weight
assert_eq!(
traders.buy_weight(5, fungible_multi_asset(Here, 10).into()),
Ok(fungible_multi_asset(Here, 5).into()),
);
// trader one refunds
assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(Here, 2)));
let mut traders = Traders::new();
// trader one failed; trader two buys weight
assert_eq!(
traders.buy_weight(5, fungible_multi_asset(PARA_1, 10).into()),
Ok(fungible_multi_asset(PARA_1, 5).into()),
);
// trader two refunds
assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(PARA_1, 2)));
let mut traders = Traders::new();
// all traders fails
assert_err!(
traders.buy_weight(5, fungible_multi_asset(PARA_2, 10).into()),
XcmError::TooExpensive,
);
// and no refund
assert_eq!(traders.refund_weight(2), None);
}
......@@ -58,6 +58,11 @@ pub trait UniversalWeigher {
}
/// Charge for weight in order to execute XCM.
///
/// A `WeightTrader` may also be put into a tuple, in which case the default behavior of
/// `buy_weight` and `refund_weight` would be to attempt to call each tuple element's own
/// implementation of these two functions, in the order of which they appear in the tuple,
/// returning early when a successful result is returned.
pub trait WeightTrader: Sized {
/// Create a new trader instance.
fn new() -> Self;
......@@ -76,11 +81,31 @@ pub trait WeightTrader: Sized {
}
}
impl WeightTrader for () {
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl WeightTrader for Tuple {
fn new() -> Self {
()
for_tuples!( ( #( Tuple::new() ),* ) )
}
fn buy_weight(&mut self, _: Weight, _: Assets) -> Result<Assets, Error> {
Err(Error::Unimplemented)
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error> {
let mut last_error = None;
for_tuples!( #(
match Tuple.buy_weight(weight, payment.clone()) {
Ok(assets) => return Ok(assets),
Err(e) => { last_error = Some(e) }
}
)* );
let last_error = last_error.unwrap_or(Error::TooExpensive);
log::trace!(target: "xcm::buy_weight", "last_error: {:?}", last_error);
Err(last_error)
}
fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
for_tuples!( #(
if let Some(asset) = Tuple.refund_weight(weight) {
return Some(asset);
}
)* );
None
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment