Skip to main content
Version: 3.x

Events

An ink! smart contract may define events that it can emit during contract execution. Emitting events can be used by third party tools to query information about a contract's execution and state.

The following example ink! contract shows how an event Transferred is defined and emitted in the #[ink(constructor)].

use ink_lang as ink;

#[ink::contract]
mod erc20 {
/// Defines an event that is emitted
/// every time value is transferred.
#[ink(event)]
pub struct Transferred {
from: Option<AccountId>,
to: Option<AccountId>,
value: Balance,
}

#[ink(storage)]
pub struct Erc20 {
total_supply: Balance,
// more fields ...
}

impl Erc20 {
#[ink(constructor)]
pub fn new(initial_supply: Balance) -> Self {
let caller = Self::env().caller();
Self::env().emit_event(Transferred {
from: None,
to: Some(caller),
value: initial_supply,
});
Self { total_supply: initial_supply }
}

#[ink(message)]
pub fn total_supply(&self) -> Balance {
self.total_supply
}
}
}

See our ERC20 example contract for an elaborate example which uses events.

Event Definition

This is how an event definition looks:

#[ink(event)]
pub struct Transferred {
#[ink(topic)]
from: Option<AccountId>,

#[ink(topic)]
to: Option<AccountId>,

amount: Balance

}

Add the #[ink(topic)] attribute tag to each item in your event that you want to have indexed. A good rule of thumb is to ask yourself if somebody might want to search for this topic. For this reason the amount in the exemplary event above was not made indexable ‒ there will most probably be a lot of different events with differing amounts each.

The signature of the event is by default one of the topics of the event, except if you annotate the event with #[ink(anonymous)]. See here for details on this attribute.

Emitting Events in a Constructor

In a constructor events are emitted via Self::env().emit_event(). See this example:

#[ink(constructor)]
pub fn new(initial_value: Balance) -> Self {
let caller = Self::env().caller();
let mut balances = HashMap::new();
balances.insert(caller, initial_supply);

Self::env().emit_event(Transferred {
from: None,
to: Some(caller),
amount: initial_supply
});

Self { total_supply: initial_supply, balances }
}

Emitting Events from Messages

In a message events are emitted via self.env().emit_event():

#[ink(message)]
pub fn transfer(&mut self, to: AccountId, amount: Balance) -> Result {
let from = self.env().caller();
// implementation hidden
self.env().emit_event(Transferred {
from: Some(from),
to: Some(to),
amount
});
Ok(())
}