Skip to content

The new event-topic drift tests scan source text, so they assert literals rather than events #414

Description

@zachyo

Files: contracts/token/src/lib.rs lines 1227 to 1265; contracts/vesting/src/lib.rs lines 732 to 770

Issue: #340 asked for a test that stops docs/events.md, the contract and the indexer drifting apart, and the implementation is genuinely clever: scripts/generate_events_doc.py --check runs in CI, and each contract carries a test asserting its topic set. The test does it by reading its own source as a string:

const NEEDLE: &str = "symbol_short!(\"";
...
.split_once("#[cfg(test)]\nmod test {")

Three weaknesses follow, and the same logic is duplicated verbatim in both contracts.

It is brittle in the wrong direction. The split_once depends on the exact bytes #[cfg(test)]\nmod test {. Any reformatting of that line — a cargo fmt change, an added attribute, a doc comment between them — makes the split fail, and the failure mode is a confusing panic in an unrelated-looking test rather than a clear message.

It cannot see what it claims to check. It finds symbol_short! literals, so a topic built from a variable or a constant is invisible to it, and a publish call inside a branch that never executes still counts as an emitted event. It proves a string appears in the file, which is not the same as the contract emitting that topic.

It does not check payloads. #339's whole subject was that mint, clawback and approve had the wrong topic tuples and data. A literal scan cannot detect a regression there, so the test that exists to prevent event drift does not cover the axis on which event drift last happened.

Fix: Assert against the host instead of the source. Exercise each entry point in a test and read env.events().all(), comparing the full (topics, data) shape to a checked-in fixture — which also gives docs/events.json a real source of truth and lets generate_events_doc.py derive payload columns. Share the comparison helper between the two contracts via a small contracts/common test-support crate rather than copying it a third time when the factory contract in open issue #368 lands.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions