Skip to content

Instantly share code, notes, and snippets.

@mverzilli
Last active February 20, 2026 17:30
Show Gist options
  • Select an option

  • Save mverzilli/3f167e08cb15545d0ac4cf13f39b1a29 to your computer and use it in GitHub Desktop.

Select an option

Save mverzilli/3f167e08cb15545d0ac4cf13f39b1a29 to your computer and use it in GitHub Desktop.

API Impact Report: Custom Message Handlers

Audience: dapp developers, contract developers, wallet implementors


Breaking Changes

The one behavioral change is that unknown message types now panic instead of being silently ignored. Previously, a message with an unrecognized type ID would produce a debug log and be discarded. Now:

  • An unrecognized ID in the reserved range (< 2^16) panics with a link to /errors/2
  • An unrecognized custom ID (>= 2^16) with no handler configured panics with a link to /errors/1

This only affects contracts that were already receiving messages they couldn't process, so it surfaces latent bugs rather than breaking working flows.

Existing contracts that use #[aztec] with no arguments continue to work identically. The #[aztec] macro now accepts an optional AztecConfig argument via #[varargs], but the zero-argument form is unchanged.


New API Surface for Contract Developers

1. AztecConfig builder (aztec::macros::AztecConfig)

Configures the #[aztec] macro. Currently has one option:

#[aztec(AztecConfig::new().custom_message_handler(my_handler))]
contract MyContract { ... }

2. CustomMessageHandler type (aztec::messages::discovery::CustomMessageHandler)

The signature a custom handler must conform to:

pub type CustomMessageHandler<Env> = unconstrained fn[Env](
    AztecAddress,       // contract_address
    u64,                // msg_type_id
    u64,                // msg_metadata
    BoundedVec<Field, MAX_MESSAGE_CONTENT_LEN>,  // msg_content
    MessageContext,     // message_context (contains tx_hash, recipient, etc.)
);

The handler must be a #[contract_library_method].

3. custom_msg_type_id helper (aztec::messages::msg_type::custom_msg_type_id)

pub comptime fn custom_msg_type_id(local_id: u64) -> u64

Offsets a local index by MIN_CUSTOM_MSG_TYPE_ID (2^16). Custom messages must use IDs >= this threshold; IDs below it are reserved for aztec-nr built-in types.

4. enqueue_note_for_validation — visibility changed from pub(crate) to pub

Custom message handlers that reassemble notes can now call this to feed notes back to PXE. Previously internal-only.

5. enqueue_event_for_validation — visibility changed from pub(crate) to pub

Same as above but for events. This is the primary way custom handlers deliver reassembled events to PXE.

6. capsules module — visibility changed from mod to pub mod

aztec::capsules (wrapping store, load, delete oracles for per-contract non-volatile storage) is now publicly accessible. Custom handlers need this to accumulate state across multiple message parts (e.g. multi-log patterns).

7. MessageContext — already public, now re-exported from aztec::messages::processing

Contains tx_hash and recipient, passed to custom handlers so they can enqueue notes/events with proper provenance.


No Impact on Wallet Implementors / PXE / TS SDK

All custom message processing happens inside the contract's Noir code during sync_state. From PXE's perspective, the contract still calls the same enqueue_note_for_validation / enqueue_event_for_validation / validate_and_store_enqueued_notes_and_events pipeline. No new oracles, no TS API changes, no protocol-level changes.

Events reassembled by a custom handler are indistinguishable from standard events once enqueued — wallet.getPrivateEvents() works unchanged.


Summary Table

Change Who cares Breaking?
#[aztec] now accepts optional AztecConfig Contract devs (opt-in) No
AztecConfig::custom_message_handler() Contract devs writing custom handlers N/A (new)
custom_msg_type_id() helper Contract devs defining custom msg types N/A (new)
CustomMessageHandler type alias Contract devs N/A (new)
enqueue_note_for_validation now pub Contract devs in custom handlers No
enqueue_event_for_validation now pub Contract devs in custom handlers No
capsules module now pub Contract devs in custom handlers No
Unknown msg types now panic (not silently dropped) Contracts receiving unknown msgs Behavioral (bug-surfacing)
MIN_CUSTOM_MSG_TYPE_ID constant Contract devs N/A (new)
Error pages /errors/1, /errors/2 Devs debugging panics N/A (new)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment