Skip to main content
Version: v3.0.0-nightly.20251231

Emitting Events

Events allow contracts to communicate with offchain applications. Private events are encrypted and delivered to specific recipients, while public events are visible to everyone.

Prerequisites

  • An Aztec contract project set up with aztec-nr dependency
  • Understanding of private vs public functions in Aztec

Define an event

Declare events using the #[event] attribute:

#[event]
struct Transfer {
from: AztecAddress,
to: AztecAddress,
amount: u128,
}

Emit private events

In private functions, emit events using self.emit() and deliver them to recipients:

use aztec::messages::message_delivery::MessageDelivery;

#[external("private")]
fn transfer(to: AztecAddress, amount: u128) {
let from = self.msg_sender().unwrap();

// ... transfer logic ...

self.emit(Transfer { from, to, amount }).deliver_to(
to,
MessageDelivery.UNCONSTRAINED_ONCHAIN,
);
}
warning

You must call deliver_to() on the returned EventMessage. If you don't, the event information is lost forever. The compiler will warn you about unused EventMessage values.

Deliver to multiple recipients

You can deliver the same event to multiple recipients with different delivery modes:

let message = self.emit(Transfer { from, to, amount });
message.deliver_to(from, MessageDelivery.UNCONSTRAINED_OFFCHAIN);
message.deliver_to(to, MessageDelivery.CONSTRAINED_ONCHAIN);

The MessageDelivery options are:

  • CONSTRAINED_ONCHAIN - Constrained encryption with onchain delivery. Slowest proving but provides cryptographic guarantees that recipients can decrypt messages.
  • UNCONSTRAINED_ONCHAIN - Unconstrained encryption with onchain delivery. Faster proving, but trusts the sender to encrypt correctly.
  • UNCONSTRAINED_OFFCHAIN - Unconstrained encryption with offchain delivery. Lowest cost, but requires custom infrastructure to deliver messages to recipients.
note

Emitting private events is optional. Onchain delivery publishes encrypted data to Ethereum blobs, inheriting Ethereum's data availability guarantees. You can choose to share information offchain instead.

Emit public events

In public functions, emit events using self.emit():

#[external("public")]
fn update_value(value: Field) {
// ... update logic ...

self.emit(ValueUpdated { value });
}

Public events are emitted as plaintext logs, similar to Solidity events.

Emit unstructured public logs

For unstructured data, use emit_public_log directly on the context:

self.context.emit_public_log("My message");
self.context.emit_public_log([1, 2, 3]);

Query public logs

Query public logs from offchain applications using the Aztec node:

const fromBlock = await node.getBlockNumber();
const logFilter = {
fromBlock,
toBlock: fromBlock + 1,
};
const publicLogs = (await node.getPublicLogs(logFilter)).logs;

Cost considerations

Event data published onchain is stored in Ethereum blobs, which incurs costs. Consider:

  • Use UNCONSTRAINED_OFFCHAIN delivery for lower costs when you have custom delivery infrastructure
  • Only emit events when necessary for your application's functionality

Next steps