Attribute Macro frame_support::pallet_macros::call
source · #[call]Expand description
Allows a pallet to declare a set of functions as a dispatchable extrinsic. In slightly simplified terms, this macro declares the set of “transactions” of a pallet.
The exact definition of extrinsic can be found in
sp_runtime::generic::UncheckedExtrinsic.
A dispatchable is a common term in FRAME, referring to process of constructing a
function, and dispatching it with the correct inputs. This is commonly used with
extrinsics, for example “an extrinsic has been dispatched”. See
sp_runtime::traits::Dispatchable and crate::traits::UnfilteredDispatchable.
§Call Enum
The macro is called call (rather than #[pallet::extrinsics]) because of the
generation of a enum Call. This enum contains only the encoding of the function
arguments of the dispatchable, alongside the information needed to route it to the
correct function.
#[frame_support::pallet(dev_mode)]
pub mod custom_pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
pub fn some_dispatchable(_origin: OriginFor<T>, _input: u32) -> DispatchResult {
Ok(())
}
pub fn other(_origin: OriginFor<T>, _input: u64) -> DispatchResult {
Ok(())
}
}
// generates something like:
// enum Call<T: Config> {
// some_dispatchable { input: u32 }
// other { input: u64 }
// }
}
fn main() {
construct_runtime! {
pub enum Runtime {
System: frame_system,
Custom: custom_pallet
}
}
let origin: RuntimeOrigin = frame_system::RawOrigin::Signed(10).into();
// calling into a dispatchable from within the runtime is simply a function call.
let _ = custom_pallet::Pallet::<Runtime>::some_dispatchable(origin.clone(), 10);
// calling into a dispatchable from the outer world involves constructing the bytes of
let call = custom_pallet::Call::<Runtime>::some_dispatchable { input: 10 };
let _ = call.clone().dispatch_bypass_filter(origin);
// the routing of a dispatchable is simply done through encoding of the `Call` enum,
// which is the index of the variant, followed by the arguments.
assert_eq!(call.encode(), vec![0u8, 10, 0, 0, 0]);
// notice how in the encoding of the second function, the first byte is different and
// referring to the second variant of `enum Call`.
let call = custom_pallet::Call::<Runtime>::other { input: 10 };
assert_eq!(call.encode(), vec![1u8, 10, 0, 0, 0, 0, 0, 0, 0]);
}Further properties of dispatchable functions are as follows:
- Unless if annotated by
dev_mode, it must containweightto denote the pre-dispatch weight consumed. - The dispatchable must declare its index via
call_index, which can override the position of a function inenum Call. - The first argument is always an
OriginFor(orT::RuntimeOrigin). - The return type is always
crate::dispatch::DispatchResult(orcrate::dispatch::DispatchResultWithPostInfo).
WARNING: modifying dispatchables, changing their order (i.e. using call_index),
removing some, etc., must be done with care. This will change the encoding of the , and
the call can be stored on-chain (e.g. in pallet-scheduler). Thus, migration might be
needed. This is why the use of call_index is mandatory by default in FRAME.
§Default Behavior
If no #[pallet::call] exists, then a default implementation corresponding to the
following code is automatically generated:
#[pallet::call]
impl<T: Config> Pallet<T> {}Rust-Analyzer users: See the documentation of the Rust item in
frame_support::pallet_macros::call.