Description
EVENT_SCHEMA.md is the canonical contract that indexers, frontends, and auditors build against — it pins exact topics and payload shapes for every event across all three crates. Today only a subset of events is asserted in tests (per SECURITY.md, deposit/deduct topics and the revenue-pool admin_changed event are pinned), and several documented events have no conformance test, so a payload-shape regression (like the kind that already documented stale string panics in docs/interfaces/vault.json) could ship undetected. This issue adds focused tests that read env.events().all() and assert the emitted topics/data byte-for-byte against the schema.
Requirements and context
Functional — events to pin (sampling across crates):
- Vault (
contracts/vault/src/lib.rs): init, deposit, deduct (3-topic form with the empty-Symbol sentinel for None, per the EVENT_SCHEMA.md request_id note), withdraw, withdraw_to, vault_paused / vault_unpaused, ownership_nominated / ownership_accepted, admin_nominated / admin_accepted, set_authorized_caller (old/new tuple), metadata_set / metadata_updated / metadata_removed.
- Settlement (
contracts/settlement/src/lib.rs): payment_received and balance_credited ordering and payload (to_pool=false always emits payment_received before balance_credited), plus developer_withdraw.
- Revenue pool (
contracts/revenue_pool/src/lib.rs): distribute, batch_distribute (one event per leg, in order), admin_changed + admin_transfer_started pairing.
Non-functional / repo conventions
- Use the
soroban_sdk test API (Env::events().all() returning Vec<(Address, Vec<Val>, Val)>) and assert both topic symbols and decoded data structs (e.g. PaymentReceivedEvent, BalanceCreditedEvent, WithdrawEventData).
- Each assertion must cite the
EVENT_SCHEMA.md section it enforces, so a schema change forces a test update (and vice-versa).
- Where the test reveals a mismatch between code and
EVENT_SCHEMA.md, fix the document (the code is the source of truth for emitted events) and note it in the PR.
- Tests must not drop coverage below 95%.
Acceptance criteria
Suggested execution
1. Fork the repo and create a branch
git checkout -b test/event-schema-conformance
2. Implement changes
- Add
#[cfg(test)] mod test_events; registrations in the three lib.rs files (or extend existing test*.rs modules).
3. Write/extend tests in contracts/vault/src/test_events.rs, contracts/settlement/src/test_events.rs, contracts/revenue_pool/src/test_events.rs:
- capture
env.events().all() after each operation and assert topic symbols + decoded data;
- assert event ordering for settlement and batch operations;
- assert no events on panic/error paths (e.g. deduct without settlement set).
4. Test and commit
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
./scripts/check-wasm-size.sh
./scripts/coverage.sh
Example commit message
test: assert emitted events conform to EVENT_SCHEMA.md across all crates
Guidelines
- Coverage must stay >= 95% (
scripts/coverage.sh), CI-enforced via .github/workflows/coverage.yml.
- Treat contract code as the source of truth for events; update
EVENT_SCHEMA.md to match and keep it authoritative.
- Timeframe: 96 hours.
Description
EVENT_SCHEMA.mdis the canonical contract that indexers, frontends, and auditors build against — it pins exact topics and payload shapes for every event across all three crates. Today only a subset of events is asserted in tests (perSECURITY.md,deposit/deducttopics and the revenue-pooladmin_changedevent are pinned), and several documented events have no conformance test, so a payload-shape regression (like the kind that already documented stale string panics indocs/interfaces/vault.json) could ship undetected. This issue adds focused tests that readenv.events().all()and assert the emitted topics/data byte-for-byte against the schema.Requirements and context
Functional — events to pin (sampling across crates):
contracts/vault/src/lib.rs):init,deposit,deduct(3-topic form with the empty-Symbolsentinel forNone, per theEVENT_SCHEMA.mdrequest_id note),withdraw,withdraw_to,vault_paused/vault_unpaused,ownership_nominated/ownership_accepted,admin_nominated/admin_accepted,set_authorized_caller(old/new tuple),metadata_set/metadata_updated/metadata_removed.contracts/settlement/src/lib.rs):payment_receivedandbalance_creditedordering and payload (to_pool=falsealways emitspayment_receivedbeforebalance_credited), plusdeveloper_withdraw.contracts/revenue_pool/src/lib.rs):distribute,batch_distribute(one event per leg, in order),admin_changed+admin_transfer_startedpairing.Non-functional / repo conventions
soroban_sdktest API (Env::events().all()returningVec<(Address, Vec<Val>, Val)>) and assert both topic symbols and decoded data structs (e.g.PaymentReceivedEvent,BalanceCreditedEvent,WithdrawEventData).EVENT_SCHEMA.mdsection it enforces, so a schema change forces a test update (and vice-versa).EVENT_SCHEMA.md, fix the document (the code is the source of truth for emitted events) and note it in the PR.Acceptance criteria
test_events.rsmodule per crate (or one consolidated module where practical), registered under#[cfg(test)].deductconformance test asserts exactly 3 topics and the empty-Symbolsentinel whenrequest_idisNone.payment_receivedprecedesbalance_creditedforto_pool=falseand that no events are emitted on the documented panic paths.batch_distributetest asserts one event per leg in submission order.EVENT_SCHEMA.mdand referenced in the PR description.cargo test --workspacepasses;./scripts/coverage.shstays >= 95%.Suggested execution
1. Fork the repo and create a branch
2. Implement changes
#[cfg(test)] mod test_events;registrations in the threelib.rsfiles (or extend existingtest*.rsmodules).3. Write/extend tests in
contracts/vault/src/test_events.rs,contracts/settlement/src/test_events.rs,contracts/revenue_pool/src/test_events.rs:env.events().all()after each operation and assert topic symbols + decoded data;4. Test and commit
cargo fmt --all -- --check cargo clippy --all-targets --all-features -- -D warnings cargo test --workspace ./scripts/check-wasm-size.sh ./scripts/coverage.shExample commit message
Guidelines
scripts/coverage.sh), CI-enforced via.github/workflows/coverage.yml.EVENT_SCHEMA.mdto match and keep it authoritative.