Skip to content

Fix hooks::trigger — 5 of 7 HookEvent Variants Never Fire and the Payload Is Always Empty #797

Description

@Samuel1505

Description

HookEvent (types.rs) declares seven variants — GrantCreated, MilestoneApproved, MilestonePaid, DisputeRaised, DisputeResolved, ContributorRegistered, BountyAwarded — and hooks::register_hook happily accepts a registration for any of them, charging the caller gas and storing the registration. But hooks::trigger is only ever invoked from two places in lib.rs: once for HookEvent::GrantCreated (around line 4235) and once for HookEvent::MilestoneApproved (around line 633). A contributor who registers an external contract hook for MilestonePaid, DisputeRaised, DisputeResolved, ContributorRegistered, or BountyAwarded will never receive a callback — the registration silently succeeds but is permanently inert.

On top of that, both real call sites pass an empty payload:

// lib.rs:634
hooks::trigger(&env, HookEvent::MilestoneApproved, Bytes::new(&env));
...
// lib.rs:4236
hooks::trigger(env, HookEvent::GrantCreated, Bytes::new(env));

cross_contract::call_hook_receiver forwards event_type and payload to the target contract's on_hook function, but since payload is always an empty Bytes, external hook receivers have no way to know which grant_id (or milestone_idx) the event pertains to — they only learn that some event of a given type fired somewhere in the contract, which makes the payload parameter of the whole hook interface effectively useless for any receiver that needs to react to a specific grant.

Technical Requirements

Files to update

  • contracts/contracts/stellar-grants/src/lib.rs — add hooks::trigger call sites for MilestonePaid, DisputeRaised, DisputeResolved, ContributorRegistered, and BountyAwarded at their respective real state-transition points, and encode the relevant grant_id/milestone_idx into the payload Bytes at all six call sites (existing two plus the new ones).
  • contracts/contracts/stellar-grants/src/hooks.rs (trigger, lines 98-134 — no change needed, just needs real payload data from callers)

What to verify first

Confirm the current call sites via:

// lib.rs:633-634
if hooks::has_hooks(&env, HookEvent::MilestoneApproved) {
    hooks::trigger(&env, HookEvent::MilestoneApproved, Bytes::new(&env));
}
// lib.rs:4235-4236
if hooks::has_hooks(env, HookEvent::GrantCreated) {
    hooks::trigger(env, HookEvent::GrantCreated, Bytes::new(env));
}

These are the only two hooks::trigger call sites in the entire crate.

Acceptance Criteria

  • hooks::trigger is called at the correct real state-transition points for MilestonePaid, DisputeRaised, DisputeResolved, ContributorRegistered, and BountyAwarded (or the unreachable variants are removed from HookEvent if the maintainer decides some don't have a corresponding real entrypoint — confirm with a maintainer comment before removing).
  • All hooks::trigger call sites pass a non-empty payload encoding at minimum the relevant grant_id (and milestone_idx where applicable) instead of Bytes::new(&env).
  • A test registers a hook for a previously-unreachable event (e.g. DisputeRaised), performs the real action that should trigger it, and asserts HookTriggered was published / the mock receiver was called with a non-empty payload.
  • cargo test passes.

Estimated Effort

Beginner: 6 hours
Intermediate: 3 hours
Expert: 1.5 hours

How to work this issue

  1. Read contracts/ContributionGuide.md for the contribution workflow.
  2. Comment on the issue to claim it before starting.
  3. Branch: fix/issue-114-hooks-missing-triggers-empty-payload.
  4. Run cargo fmt, cargo clippy -- -D warnings, cargo test before opening your PR.
  5. Use a Conventional Commit message, e.g. fix: wire up remaining HookEvent triggers and populate hook payloads.

Before you start

If you find this project interesting, please consider starring the repository on GitHub. It helps the project gain visibility and supports the Drips Wave program that rewards contributors for merged fixes like this one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions