Skip to content

feat(governance): emit events for signer and admin changes#718

Merged
Jagadeeshftw merged 2 commits into
Fluxora-Org:mainfrom
shaaibu7:governance-membership-events
Jun 25, 2026
Merged

feat(governance): emit events for signer and admin changes#718
Jagadeeshftw merged 2 commits into
Fluxora-Org:mainfrom
shaaibu7:governance-membership-events

Conversation

@shaaibu7

Copy link
Copy Markdown
Contributor

Closes #637

Summary

fluxora_governance emitted events for the proposal lifecycle but mutated critical membership/admin state silently. add_signer, remove_signer, and set_admin now emit structured events so indexers can reconstruct the signer set and admin history from chain events alone.

Changes

Contract (contracts/governance/src/lib.rs)

  • Added three #[contracttype] event structs (with /// docs):
    • SignerAdded { signer }
    • SignerRemoved { signer }
    • AdminChanged { old, new }
  • Published them with distinct, non-colliding symbol_short! topics:
    • add_signer("sgnr_add",)
    • remove_signer("sgnr_rm",)
    • set_admin("adm_chg",)
  • All events emitted after the state mutation is persisted (CEI). set_admin captures the old admin before overwriting so the event carries both old and new. remove_signer publishes only inside the matched-index branch, so removing an unregistered address stays a silent no-op.

Tests (contracts/stream/tests/governance_integration.rs)

  • Snapshot/assertion tests verifying topics and payloads for all three events.
  • Admin rotation chain test confirming old/new are correct across consecutive rotations.
  • Negative no-event coverage: removing a non-existent signer, a QuorumWouldBreak-rejected removal, and a DuplicateSigner-rejected add all emit no event.

Docs (docs/governance.md)

Incidental fixes

The governance_integration.rs test target did not compile on main, so its tests had never run. Two pre-existing issues were fixed to enable the suite:

  1. test_init_duplicate_signers_errors called try_init with 2 args (missing threshold).
  2. test_execute_at_expiry_boundary_succeeds asserted TimelockNotElapsed despite its name — at created_at + MAX_AGE the 48h timelock has long elapsed, so it succeeds. Aligned with its lib.rs twin.

Acceptance criteria

  • Each membership/admin mutation emits a structured event
  • Topics are unique and documented
  • remove_signer of a missing address emits no spurious event
  • Snapshot/assertion tests cover topics and payloads

Test output

  • cargo test -p fluxora_governance --lib50 passed
  • cargo test -p fluxora_stream --test governance_integration49 passed

Security notes

  • Events follow CEI: state is persisted before emission.
  • An emitted event faithfully implies a real state change — no-op and rejected mutations emit nothing.
  • AdminChanged carries both old and new, making the full admin rotation chain reconstructable from events without reading historical state.

Add SignerAdded { signer }, SignerRemoved { signer }, and
AdminChanged { old, new } event structs and publish them from
add_signer, remove_signer, and set_admin respectively.

- Topics use distinct single-element symbols (sgnr_add, sgnr_rm,
  adm_chg) that do not collide with proposal topics.
- Events are emitted after state is persisted (CEI ordering).
- remove_signer of a non-registered address remains a no-op and
  emits no event; rejected add/remove mutations emit nothing.

Add snapshot/assertion tests covering topics and payloads, admin
rotation chains, and negative no-event cases. Also fix two stale
pre-existing tests in governance_integration.rs that prevented the
target from compiling and running (try_init arity, and an expiry
boundary assertion that contradicted its own name).

Document the new topics, CEI guarantees, and test coverage in
docs/governance.md.
@drips-wave

drips-wave Bot commented Jun 24, 2026

Copy link
Copy Markdown

@shaaibu7 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

# Conflicts:
#	contracts/governance/src/lib.rs
@Jagadeeshftw

Copy link
Copy Markdown
Contributor

emitting sgnr_add, sgnr_rm and adm_chg events gives indexers a clean audit trail for membership and admin changes, and i like that the publishes stay CEI-after-persist. this collided with the new map-backed membership index on main, so i rebased and combined the two: the add/remove paths keep the O(1) signer_index updates and also emit your events (the silent no-op on removing a non-member happens before any event, as intended). builds clean.

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.

Emit a structured SignerAdded/SignerRemoved/AdminChanged event set from fluxora_governance

3 participants