Skip to main content

Conditional weighting struct

There's always more than one way—but those can wait.

Goal#

Create and use a custom weighting struct.

Use cases#

Calculate transaction fees by computing correct weights based on the data within a function.

Overview#

Substrate provides a mechanism known as transaction weighting to quantify the resources consumed while executing a transaction. This approach to a custom weight function establishes a weight value based on some condition. Once defined, it can be used directly in your pallet, written as such:

#[weight = Conditional(200)]

Here are the different traits we'll be implementing:

  • WeighData: Weigh the data in a function.
  • PaysFee: Designate whether the dispatch pays a fee or not.
  • ClassifyDispatch: A way to tell the runtime about the type of dispatch being made.

Steps#

1. Write the WeighData struct#

Write an implementation of WeighData for Conditional, where the first parameter is a boolean value:

pub struct Conditional(u32);
impl WeighData<(&bool, &u32)> for Conditional {
fn weigh_data(&self, (switch, val): (&bool, &u32)) -> Weight {
// If the first parameter is true, then the weight is linear in the second parameter.
if *switch {
val.saturating_mul(self.0)
}
// Otherwise the weight is constant.
else {
self.0
}
}
}

2. Classify dispatch calls#

Since this implementation of WeighData requires a DispatchClass, use default to classify all calls as normal:

// Implement ClassifyDispatch
impl<T> ClassifyDispatch<T> for Conditional {
fn classify_dispatch(&self, _: T) -> DispatchClass {
Default::default()
}
}

3. Implement PaysFee#

Last, specify how PaysFee is used for the custom WeighData struct:

// Implement PaysFee
impl PaysFee for Conditional {
fn pays_fee(&self) -> bool {
true
}
}

Examples#

  • pallet-weights
  • pallet-feeless

Related material#

How-to guides#

Knowledgebase#

Other#

Was this guide useful?