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
@@ -1157,6 +1157,36 @@ pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
}
/// Each dispatchable may be annotated with the `#[pallet::feeless_if($closure)]` attribute,
/// which explicitly defines the condition for the dispatchable to be feeless.
///
/// The arguments for the closure must be the referenced arguments of the dispatchable function.
///
/// The closure must return `bool`.
///
/// ### Example
/// ```ignore
/// #[pallet::feeless_if(|_origin: &OriginFor<T>, something: &u32| -> bool {
/// *something == 0
/// })]
/// pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
/// ....
/// }
/// ```
///
/// Please note that this only works for signed dispatchables and requires a signed extension
/// such as `SkipCheckIfFeeless` as defined in `pallet-skip-feeless-payment` to wrap the existing
/// payment extension. Else, this is completely ignored and the dispatchable is still charged.
///
/// ### Macro expansion
///
/// The macro implements the `CheckIfFeeless` trait on the dispatchable and calls the corresponding
/// closure in the implementation.
#[proc_macro_attribute]
pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
}
/// Allows you to define some extra constants to be added into constant metadata.
///
/// Item must be defined as: