infrablockchain-docs
en
en
  • InfraBlockchain
    • Learn
      • Architecture
        • Architecture
        • Network Participants
        • Parachain
          • System Parachains
      • Protocol
        • System Token
        • Transaction Fee
        • Proof of Transaction
      • Substrate
        • Learn
          • Basic
            • Cryptography
            • Blockchain Basics
            • Consensus
            • Networks and Nodes
            • Blockchain Transaction
            • Transaction Life Cycle
            • Offchain Operations
            • Light Client
            • Rust for Substrate
            • Introduction to Library
            • Architecture and Rust Libraries
            • File Architecture
            • Accounts, Addresses, and Keys
            • Transaction Format
            • Blockchain Randomness
          • FRAME
            • FRAME Pallets
            • FRAME Macros
            • Custom Pallets
            • Pallet Coupling
            • Origin
            • Events and Erros
            • Runtime Storage
            • State Transitions and Storage
            • SCALE Encoding
            • Weight and Fee
            • Runtime API
            • Runtime Development
          • Account
          • Address Format
          • Glossary
          • CLI
            • Archive
            • Memory Profiler
            • Node Template
            • sidecar
            • srtool
            • Subkey
            • subxt
            • try-runtime
            • tx-wrapper
          • Runtime Development
            • Basics
              • Configure Genesis State
              • Configure Runtime Constants
              • Customize a Chain Spec
              • Import a Pallet
              • Use Helper Function
            • Consensus Model
              • PoW
              • Create a Hybrid Node
            • Offchain Worker
              • Request Offchain HTTP
              • Offchain Indexing
              • Offchain Local Storage
            • Pallet Design
              • Create a Storage Structure
              • Implement Lockable Currency
              • Incorporate Randomness
              • Loose Coupling
              • Tight Coupling
            • Parachain Development
              • Add HRMP Channel
              • Add Paranodes
              • Connect to a Local Relay Chain
              • Convert a Solo Chain
              • Prepare to Launch
              • Select Collator
              • Upgrade a Parachain
            • Storage Migration
              • Basics
              • Trigger Migration
            • Test
              • Basics
              • Test a Transfer Transaction
            • Tools
              • Create a TxWrapper
              • Use Sidecar
              • try-runtime
              • Verify WASM
            • Weigths
              • Benchmark
              • Calculate Fees
              • Use Conditional Weights
              • Use Custom Weights
        • Build
          • Decide What to Build
          • Build Process
          • Determinisitc Runtime
          • Chain Spec
          • Genesis Configuration
          • Application Development
          • RPC
          • Troubleshoot Your Code
        • Tutorials
          • Install
            • Developer Tools
            • Linux
            • macOS
            • Rust Toolchain
            • Issues
            • Windows
          • Quick Start
            • Explore the Code
            • Modify Runtime
            • Start a Node
            • Substrate Basics
          • Build a Blockchain
            • Add Trusted Nodes
            • Authorize Specific Nodes
            • Build a Local Blockchain
            • Simulate Network
            • Upgrade a Running Network
          • Build Application Logic
            • Add a Pallet
            • Add Offchasin Workers
            • Publish Custom Pallets
            • Specify Origin for a Call
            • Use Macros in a Custom Pallet
          • Integrate with Tools
            • Access EVM Accounts
            • EVM Integration
            • Explore Sidecar Endpoints
            • Integrate a Light Client Node
          • Smart Contracts
            • Strategy
            • Build a Token Contract
            • Develop a Smart Contract
            • Prepare Your First Contract
            • Troubleshoot Smart Contracts
            • Use Maps for Storing Values
      • XCM
        • XCM
        • XCM Format
    • Service Chains
      • InfraDID
      • InfraEVM
      • URAuth(Universal Resource Auth)
    • DevOps
      • Build
      • Deploy
      • Monitoring
      • Runtime Upgrade
    • Tutorials
      • Basic
        • How to Interact with System Token
        • How To Pay Transaction Fee
        • How To Vote with TaaV
        • Hot to Get Validator Reward
      • Build
        • Build InfraRelayChain
        • Build Parachain
        • Open Message Passing Channels
        • Transfer Assets with XCM
      • Test
        • Benchmark
        • Check Runtime
        • Debug
        • Simulate Parachains
        • Unit Testing
      • Service Chains
        • Play with InfraDID
          • Build
          • Add Keys
          • Add Service Endpoint
          • Create InfraDID
        • Play with InfraEVM
          • Build
          • Deposit and Withdraw Token
          • Deploy ERC20 Contract
          • Deploy ERC721 Contract
          • Deploy ERC1155 Contract
  • Newnal Data Market
Powered by GitBook
On this page
  • Declaring an event
  • Exposing events to your runtime
  • Depositing an event
  • Supported types
  • Listening to events
  • Errors
  • Where to go next
  1. InfraBlockchain
  2. Learn
  3. Substrate
  4. Learn
  5. FRAME

Events and Erros

Explains how to emit events and errors from the runtime.

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

In custom pallets, you can define:

  • what type of events you want to be emitted

  • what information is contained within those events

  • when those events are emitted

Declaring an event

Events are created using the #[pallet::event] macro. For example:

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
	/// Set a value.
	ValueSet { value: u32, who: T::AccountId },
}

Then, the RuntimeEvent type is needed to aggregate them for the runtime.

#[pallet::config]
	pub trait Config: frame_system::Config {
		/// The overarching event type.
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
	}

Exposing events to your runtime

Any events you define in your pallet must be exposed to the runtime in the /runtime/src/lib.rsfile.

To expose events to the runtime:

  1. Open the /runtime/src/lib.rsfile in a text editor.

  2. Implement the RuntimeEvent type in the configuration trait for your pallet:

    impl template::Config for Runtime {
    	 type RuntimeEvent = RuntimeEvent;
    }
  3. Add the RuntimeEvent type to the construct_runtime! macro:

    construct_runtime!(
    	 pub enum Runtime where
     	 Block = Block,
    	   NodeBlock = opaque::Block,
    	   UncheckedExtrinsic = UncheckedExtrinsic
    	 {
        // --snip--
    	   TemplateModule: template::{Pallet, Call, Storage, Event<T>},
    	   //--add-this------------------------------------->
    		 }
    );

    In this example, the event is a generic type and requires the <T> parameter. The <T> parameter isn't needed if your events don't use generic types.

Depositing an event

Substrate provides a default implementation of how to deposit an event using macros. Depositing an event has the following structure:

// 1. Use the `generate_deposit` attribute when declaring the Events enum.
#[pallet::event]
	#[pallet::generate_deposit(pub(super) fn deposit_event)] // <------ here ----
	#[pallet::metadata(...)]
	pub enum Event<T: Config> {
		// --snip--
	}

// 2. Use `deposit_event` inside the dispatchable function
#[pallet::call]
	impl<T: Config> Pallet<T> {
		#[pallet::weight(1_000)]
		pub(super) fn set_value(
			origin: OriginFor<T>,
			value: u64,
		) -> DispatchResultWithPostInfo {
			let sender = ensure_signed(origin)?;
			// --snip--
			Self::deposit_event(RawEvent::ValueSet(value, sender));
		}
	}

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

Supported types

Listening to events

Errors

Each FRAME pallet can define a custom DispatchError by using the #[pallet::error] macro. For example:

#[pallet::error]
pub enum Error<T> {
		/// Error names should be descriptive.
		InvalidParameter,
		/// Errors should have helpful documentation associated with them.
		OutOfSpace,
	}
frame_support::ensure!(param < T::MaxVal::get(), Error::<T>::InvalidParameter);

Where to go next

PreviousOriginNextRuntime Storage

Last updated 1 year ago

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

Events deposited using the default implementation are directly supported by downstream libraries like the . However, you can implement your own deposit_event function if you want to handle events differently.

Events can emit any type which supports type encoding using .

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

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 pallet. Otherwise, the supports a WebSocket subscription on runtime events.

Runtime code should explicitly and gracefully handle all error cases. Functions in the runtime code must be non-throwing functions that never cause the compiler to . A common idiom for writing non-throwing Rust code is to write functions that return . The Result enum type possesses an Err variant that allows a function to indicate that it failed to execute successfully without needing to panic. Function calls that can be dispatched to the runtime in the FRAME development evironment must return a that could be a if the function encountered an error.

The FRAME Support module also includes a helpful that can be used to check pre-conditions and emit an error if they are not met.

.

deposit_event
Polkadot-JS API
SCALE codec
where clause
Polkadot-JS API
panic
Result types
DispatchResult type
DispatchError variant
ensure! macro
Frame macros
Polkadot-JS API
construct_runtime! macro
#[frame_support::pallet] macro
[pallet::error] macro