Substrate Developer Hub

Substrate Developer Hub

  • Tutorials
  • Knowledge Base
  • Recipes
  • API Reference
  • Languages iconEnglish
    • 简体中文
    • Help Translate

›Runtime

Getting Started

  • Overview
  • Architecture
  • Installation
  • Getting Started on Windows
  • Glossary

Learn Substrate

  • Extrinsics
  • Transaction Pool
  • Account Abstractions
  • Session Keys
  • Transaction Weight
  • Off-Chain Features

Runtime

  • Runtime Overview
  • Runtime Primitives
  • FRAME
  • Pallets
  • Runtime Macros
  • Runtime Metadata
  • Runtime Storage
  • Runtime Origin
  • Runtime Execution
  • Runtime Events
  • Runtime Errors
  • Transaction Fees
  • Debugging
  • Runtime Tests
  • Runtime Benchmarking
  • On-Chain Randomness
  • Runtime Upgrades

Smart Contracts

  • Overview
  • ink! Smart Contracts
  • ink! Concepts
  • ink! Development
  • Contracts Pallet
  • EVM Pallet
  • ink! F.A.Q.

Integrate

  • Polkadot-JS
  • Client Libraries
  • Chain Specification
  • The Subkey Tool
  • Memory Profiling

Advanced

  • SCALE Codec
  • Consensus
  • The Block Import Pipeline
  • Runtime Executor
  • Cryptography
  • Storage
  • SS58 Address Format
  • Why are there no Hash collections in sp_std?

Contribute

  • Help Translate
Edit

Runtime Events

A Substrate runtime module can emit events when it wants to notify external entities about changes or conditions in the runtime to external entities like users, chain explorers, or dApps.

You can define what events your module emits, what information is contained within those events, and when those events are emitted.

Declaring an Event

Runtime events are created with the decl_event! macro.

decl_event!(
    pub enum Event<T> where AccountId = <T as Config>::AccountId {
        /// Set a value.
        ValueSet(u32, AccountId),
    }
);

The Event enum needs to be declared in your runtime's configuration trait.

pub trait Config: system::Config {
    type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;
}

Exposing Events to Your Runtime

The events for your module need to be exposed to your Substrate's runtime (/runtime/src/lib.rs).

First you need to implement the Event type in your module's configuration trait:

// runtime/src/lib.rs
impl template::Config for Runtime {
    type Event = Event;
}

Then you need to add the Event type to your construct_runtime! macro:

// runtime/src/lib.rs
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        // --snip--
        TemplateModule: template::{Module, Call, Storage, Event<T>},
        //--add-this------------------------------------->^^^^^^^^
    }
);

Note: You may or may not need the <T> parameter depending on whether your events use generic types. In our example it does, and is included above.

Depositing an Event

Substrate provides a default implementation of how to deposit an event that is defined in the decl_module! macro.

decl_module! {
    pub struct Module<T: Config> for enum Call where origin: T::Origin {
        // Default implementation of `deposit_event`
        fn deposit_event() = default;

        fn set_value(origin, value: u64) {
            let sender = ensure_signed(origin)?;
            // --snip--
            Self::deposit_event(RawEvent::ValueSet(value, sender));
        }
    }
}

The default behavior of this function is to call deposit_event from the FRAME system, which writes the event to storage.

This function places the event in the System module's runtime storage for that block. At the beginning of a new block, the System module automatically removes all events that were stored from the previous block.

Events deposited using the default implementation will be directly supported by downstream libraries like the Polkadot-JS api, however you can implement your own deposit_event function if you want to handle events differently.

Supported Types

Events can emit any type which supports the Parity SCALE codec.

In the case where you want to use Runtime generic types like AccountId or Balances, you need to include a where clause to define those types as shown in the example above.

Listening To Events

The Substrate RPC does not directly expose an endpoint for querying events. If you used the default implementation, you can see the list of events for the current block by querying the storage of the System module. Otherwise, the Polkadot-JS api supports a WebSocket subscription on runtime events.

Next Steps

Learn More

  • Learn more about the macros used in Substrate runtime development.
  • Learn more about using the Polkadot JS api.

Examples

These Substrate Recipes offer examples of how runtime events are used:

  • A pallet that implements standard events

References

  • decl_event! macro
  • decl_module! macro
  • construct_runtime! macro
Last updated on 2/24/2021 by Dan Forbes
← Runtime ExecutionRuntime Errors →
  • Declaring an Event
  • Exposing Events to Your Runtime
  • Depositing an Event
  • Supported Types
  • Listening To Events
  • Next Steps
    • Learn More
    • Examples
    • References
Substrate Developer Hub
Developer Hub
TutorialsKnowledge BaseRecipesAPI Reference
Community
Community HomeNewsletterSubstrate Technical ChatSubstrate SeminarStack OverflowTwitterEvents
More
Substrate Builders ProgramBlogSubstrate GitHubDeveloper Hub GitHubPrivacy PolicyTerms of UseCookie Settings
Copyright © 2021 Parity Technologies