Adds syntax for marking calls feeless (#1926)

Fixes https://github.com/paritytech/polkadot-sdk/issues/1725

This PR adds the following changes:
1. An attribute `pallet::feeless_if` that can be optionally attached to
a call like so:
```rust
#[pallet::feeless_if(|_origin: &OriginFor<T>, something: &u32| -> bool {
	*something == 0
})]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
     ....
}
```
The closure passed accepts references to arguments as specified in the
call fn. It returns a boolean that denotes the conditions required for
this call to be "feeless".

2. A signed extension `SkipCheckIfFeeless<T: SignedExtension>` that
wraps a transaction payment processor such as
`pallet_transaction_payment::ChargeTransactionPayment`. It checks for
all calls annotated with `pallet::feeless_if` to see if the conditions
are met. If so, the wrapped signed extension is not called, essentially
making the call feeless.

In order to use this, you can simply replace your existing signed
extension that manages transaction payment like so:
```diff
- pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+ pallet_skip_feeless_payment::SkipCheckIfFeeless<
+	Runtime,
+	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
+ >,
```

### Todo
- [x] Tests
- [x] Docs
- [x] Prdoc

---------

Co-authored-by: Nikhil Gupta <>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
gupnik
2023-11-13 19:14:41 +05:30
committed by GitHub
parent ebcf0a0f1c
commit 60c77a2e9a
33 changed files with 874 additions and 54 deletions
+14
View File
@@ -54,6 +54,20 @@ pub trait Callable<T> {
// https://github.com/rust-lang/rust/issues/51331
pub type CallableCallFor<A, R> = <A as Callable<R>>::RuntimeCall;
/// Means to checks if the dispatchable is feeless.
///
/// This is automatically implemented for all dispatchables during pallet expansion.
/// If a call is marked by [`#[pallet::feeless_if]`](`macro@frame_support_procedural::feeless_if`)
/// attribute, the corresponding closure is checked.
pub trait CheckIfFeeless {
/// The Origin type of the runtime.
type Origin;
/// Checks if the dispatchable satisfies the feeless condition as defined by
/// [`#[pallet::feeless_if]`](`macro@frame_support_procedural::feeless_if`)
fn is_feeless(&self, origin: &Self::Origin) -> bool;
}
/// Origin for the System pallet.
#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
pub enum RawOrigin<AccountId> {
+4 -3
View File
@@ -2227,9 +2227,10 @@ pub use frame_support_procedural::pallet;
pub mod pallet_macros {
pub use frame_support_procedural::{
call_index, compact, composite_enum, config, disable_frame_system_supertrait_check, error,
event, extra_constants, generate_deposit, generate_store, getter, hooks, import_section,
inherent, no_default, no_default_bounds, origin, pallet_section, storage_prefix,
storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage,
event, extra_constants, feeless_if, generate_deposit, generate_store, getter, hooks,
import_section, inherent, no_default, no_default_bounds, origin, pallet_section,
storage_prefix, storage_version, type_value, unbounded, validate_unsigned, weight,
whitelist_storage,
};
/// Allows you to define the genesis configuration for the pallet.