Events are a way to emit data from a contract. All events must be defined in the Event enum, which must be annotated with the #[event] attribute. An event is defined as struct that derives the #[starknet::Event] trait. The fields of that struct correspond to the data that will be emitted. An event can be indexed for easy and fast access when querying the data at a later time. Events data can be indexed by adding a #[key] attribute to a field member.

Here's a simple example of a contract using events that emit an event each time a counter is incremented by the "increment" function:

pub trait IEventCounter<TContractState> {
    fn increment(ref self: TContractState);

pub mod EventCounter {
    use starknet::{get_caller_address, ContractAddress};

    struct Storage {
        // Counter value
        counter: u128,

    #[derive(Drop, starknet::Event)]
    // The event enum must be annotated with the `#[event]` attribute.
    // It must also derive the `Drop` and `starknet::Event` traits.
    enum Event {
        CounterIncreased: CounterIncreased,
        UserIncreaseCounter: UserIncreaseCounter

    // By deriving the `starknet::Event` trait, we indicate to the compiler that
    // this struct will be used when emitting events.
    #[derive(Drop, starknet::Event)]
    struct CounterIncreased {
        amount: u128

    #[derive(Drop, starknet::Event)]
    struct UserIncreaseCounter {
        // The `#[key]` attribute indicates that this event will be indexed.
        user: ContractAddress,
        new_value: u128,

    impl EventCounter of super::IEventCounter<ContractState> {
        fn increment(ref self: ContractState) {
            let mut counter =;
            counter += 1;
            // Emit event
            self.emit(Event::CounterIncreased(CounterIncreased { amount: 1 }));
                        UserIncreaseCounter {
                            user: get_caller_address(), new_value:
Last change: 2024-02-15, commit: 89037ca