Skip to content

Add event registration via emits attribute#18

Merged
moCello merged 9 commits intomainfrom
mocello/event-registration
Apr 15, 2026
Merged

Add event registration via emits attribute#18
moCello merged 9 commits intomainfrom
mocello/event-registration

Conversation

@moCello
Copy link
Copy Markdown
Member

@moCello moCello commented Apr 9, 2026

Summary

Add manual event registration for the #[contract] macro via three related features:

  • #[contract(emits = [...])] — method-level attribute that declares events emitted by trait default implementations (invisible to the macro's body scanner). Events listed in emits are included in the contract schema alongside those discovered from abi::emit() calls.
  • Compile error for silent mutations — public &mut self methods must now emit events or declare them via emits. Use #[contract(no_event)] to suppress the check for methods like init that intentionally skip emission.
  • Variable topic detection — detects lowercase single-segment identifiers used as abi::emit() topics (likely variables whose runtime value the macro can't capture). Warning is a no-op on stable Rust pending proc_macro_diagnostic stabilisation.

Stacks on #17.

@moCello moCello requested a review from HDauven April 9, 2026 14:22
moCello added 4 commits April 10, 2026 10:55
…tection

Add #[contract(emits = [...])] for manual event registration on trait
methods with default implementations. Add compile error for public
&mut self methods that emit no events, suppressible with
#[contract(no_event)]. Detect variable identifiers used as
abi::emit() topics (warning pending proc_macro_diagnostic stabilisation).
Add #[contract(emits = [...])] to Ownable trait methods and
#[contract(no_event)] to init. Add schema test verifying ownership
events appear via manual registration.
@moCello moCello force-pushed the mocello/event-registration branch from 22c2162 to dca0d73 Compare April 10, 2026 08:55
@moCello moCello force-pushed the mocello/ai-friendliness branch from a0e87ce to 736bcc8 Compare April 10, 2026 08:55
Base automatically changed from mocello/ai-friendliness to main April 10, 2026 11:34
Copy link
Copy Markdown
Member

@HDauven HDauven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

One follow-up we should still do is the helper/core delegation case. We already have that in DuskEVM dispute-game hubs: resolve() in
https://github.com/dusk-network/duskevm-contracts/blob/main/contracts/permissioned-dispute-game-hub/src/lib.rs#L780-L781
just delegates into core, while the actual abi::emit(...) calls happen in
https://github.com/dusk-network/duskevm-contracts/blob/main/core/src/dispute_game_hub/engine.rs#L478-L482
and
https://github.com/dusk-network/duskevm-contracts/blob/main/core/src/dispute_game_hub/engine.rs#L765-L769

Forge cannot infer/register helper events like this for the contract data-driver at this point.

moCello added 5 commits April 14, 2026 17:27
Previously `#[contract(emits = [...])]` was collected and validated
only on trait-impl methods; on inherent methods it was silently ignored
and the strict mutating-method check hardcoded `has_manual_events` to
false. This left no way to declare events for inherent methods that
delegate to a helper outside the impl block (the body scanner cannot
see the helper's `abi::emit` calls), so such methods broke the strict
check unless the author fell back to `no_event` — which drops the
events from the schema.

Treat `emits` as a property of "this method declares additional
events" regardless of where the method is defined. Both the trait and
inherent collection paths share an `impl_method_emits` helper that
differs only in the inclusion predicate.
Test scaffolding for the inherent-method `emits` path: a free function
that calls `abi::emit` from outside any contract impl block, exercising
the "emit invisible to the macro's body scanner" property.
Add `bump_tally`, an inherent `&mut self` method that delegates the
event emit to `helpers::emit_tally_bumped` and declares the event via
`#[contract(emits = [...])]`. Verify both the schema entry and the
runtime event emission.
`#[allow(dead_code)]` was masking two genuine issues in the shared
`test_session.rs` module:

- `assert_contract_panic` is unused in every test binary; remove it.
- `direct_call` and `feeder_call` are only used by the contract test
  binary, but were declared on the shared `TestSession` and warned in
  the schema binary. Move them into a binary-local impl block in
  contract.rs so each binary only sees what it actually exercises.
Copy link
Copy Markdown
Member

@HDauven HDauven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@moCello moCello merged commit ec367fb into main Apr 15, 2026
2 checks passed
@moCello moCello deleted the mocello/event-registration branch April 15, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants