Reputation: 344
In reference to the Substrate Collectables Workshop, what does the <T>
actually do and refer to in fn deposit_event<T>() = default;
? Can I omit it when my Event
doesn't include for example AccountId
?
Upvotes: 0
Views: 488
Reputation: 12434
In the context of Substrate, there are a few things to answer here.
Each Substrate module has the ability to define the custom types needed for the module, all of which are required to implement some traits. Rather than strongly defining these types, using traits allows us to ensure that the types have certain properties, but are not limited in what the type can be. These generic type definitions live in trait Trait
, which must be defined in each module.
Here is an example of the custom types defined in the system
module, which is used in nearly all other modules:
pub trait Trait: 'static + Eq + Clone {
/// The aggregated `Origin` type used by dispatchable calls.
type Origin: ...
/// Account index (aka nonce) type. This stores the number of previous transactions associated with a sender
/// account.
type Index: ...
/// The block number type used by the runtime.
type BlockNumber: ...
/// The output of the `Hashing` function.
type Hash: ...
/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
type Hashing: Hash<Output = Self::Hash>;
/// Collection of (light-client-relevant) logs for a block to be included verbatim in the block header.
type Digest: ...
/// The user account identifier type for the runtime.
type AccountId: ...
/// Converting trait to take a source type and convert to `AccountId`.
///
/// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly
/// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules
/// (e.g. Indices module) may provide more functional/efficient alternatives.
type Lookup: StaticLookup<Target = Self::AccountId>;
/// The block header.
type Header: ...
/// The aggregated event type of the runtime.
type Event: Parameter + Member + From<Event>;
/// A piece of information that can be part of the digest (as a digest item).
type Log: From<Log<Self>> + Into<DigestItemOf<Self>>;
}
In your custom module, you will define something like:
/// The module's configuration trait.
pub trait Trait: system::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
Note here that we have defined our own Event
type, which our module can now use, but also we have inherited the traits from the system
module (system::Trait
), so we can also use all those types too!
Now that we have defined some custom types in our runtime module, we can start to use them throughout our module logic.
You will always see a line like the second line in this code snippet:
decl_storage! {
trait Store for Module<T: Trait> as Sudo {
/// The `AccountId` of the sudo key.
Key get(key) config(): T::AccountId;
}
}
Some of this line is macro magic, but importantly you see we define Module<T: Trait>
. This means we have assigned our module's trait Trait
as the generic parameter for Module
under the alias of T
.
Thus, we can then use T
to reference these special types like we did above:
T::AccountId
Going full circle, we can access this type because we have inherited it from the system::Trait
definition!
To finally answer your question, the decl_module!
function generates the function body of the deposit_event
to save you from writing the same code over and over.
We detect the pre-defined function name deposit_event
, and check for = default;
, and then replace that with a working deposit_event
function.
However, when generating this function, the macro does not know if it should use a function where the input event is generic, or the input event does not use generics. Thus, you need to "give it a hint" by saying deposit_event<T>()
or just deposit_event()
.
It will then produce the right version of the function which will work with the types in your module. If your module events uses any generic types, like T::AccountId
or T::Balance
, you will also need to define the generic version of deposit_event
.
Upvotes: 4