Indexer scope: 13 contract events emitted but not decoded — clarify intentional gap vs missing coverage #112

Closed
opened 2026-05-02 01:47:31 +00:00 by Brouie · 12 comments
Brouie commented 2026-05-02 01:47:31 +00:00 (Migrated from gitlab.com)

P3-low scope clarification: indexer/src/decoder.rs decodes 34 events; the contracts under contracts/src/ emit 44 unique events. 13 events emitted by deployed contracts have no topic0 == ...::SIGNATURE_HASH arm in the decoder. Some of these are obvious operator/governance toggles that don't need history; others might be planned indexer coverage that just hasn't landed.

Methodology

  • Contract events: grep -rh '^\s*event ' contracts/src --include='*.sol' | sort -u → 44 unique names.
  • Indexer decoder arms: grep -E 'topic0 == .*::SIGNATURE_HASH' indexer/src/decoder.rs | sort -u → 34 unique names.
  • All 13 missing events confirmed actually emitted via grep -rn 'emit <Name>' (not just declared).

Events emitted but not decoded

Event Source Likely category
BurrowProtocolRevenueSplit RabbitTreasury Treasury accounting
BurrowReserveBuckets RabbitTreasury Treasury accounting
BurrowWithdrawalFeeAccrued RabbitTreasury Treasury accounting
BuyFeeRoutingEnabled TimeCurve Operator toggle
CharmRedemptionEnabled TimeCurve Operator toggle
Cl8ySurplusToProtocol RabbitTreasury Treasury accounting
Claimed DoubPresaleVesting User activity
ClaimsEnabled DoubPresaleVesting Operator toggle
PrizePusherSet TimeCurve Operator toggle
ReservePodiumPayoutsEnabled RabbitTreasury Operator toggle
TimeCurveBuyRouterSet TimeCurve Operator toggle
VestingStarted DoubPresaleVesting Operator/lifecycle
Withdrawn FeeSink Operator/governance

Also noted: AllocationClaimed is decoded by the indexer (TimeCurveEventsLegacy::AllocationClaimed) but no longer emitted by current contracts — kept as backfill compat. Not an issue, just noting for completeness.

Why this matters

User-activity events (Claimed from DoubPresaleVesting) without history mean a future "show my claim history" UI would have no source. Today the PresaleVestingPage reads state directly from the contract — no historical view — so the gap is currently invisible.

Operator toggle events (BuyFeeRoutingEnabled, ClaimsEnabled, etc.) without history mean explorability of operator actions is limited; reading current state is fine, but "when did this flip" is unanswerable.

Treasury accounting events (BurrowProtocolRevenueSplit, BurrowReserveBuckets, etc.) without history mean Rabbit Treasury historical PnL / fee-flow analysis is unsupported.

Question for dev

Which of these are intentionally not indexed (e.g., operator toggles where current state is enough), and which are planned coverage that just hasn't landed yet?

If splits naturally:

  • Skip permanently (operator toggles, current state is authoritative): BuyFeeRoutingEnabled, CharmRedemptionEnabled, ClaimsEnabled, PrizePusherSet, ReservePodiumPayoutsEnabled, TimeCurveBuyRouterSet
  • Maybe-future (user activity / lifecycle): Claimed, VestingStarted, Withdrawn
  • Treasury history (analytics-grade): BurrowProtocolRevenueSplit, BurrowReserveBuckets, BurrowWithdrawalFeeAccrued, Cl8ySurplusToProtocol

No code change requested unless you want one. Filing for visibility per 4/29 standing rule.

Severity

P3-low. Scope/planning question, not a defect. No current user-facing impact.

cc @PlasticDigits

P3-low scope clarification: `indexer/src/decoder.rs` decodes 34 events; the contracts under `contracts/src/` emit 44 unique events. 13 events emitted by deployed contracts have no `topic0 == ...::SIGNATURE_HASH` arm in the decoder. Some of these are obvious operator/governance toggles that don't need history; others might be planned indexer coverage that just hasn't landed. ### Methodology - Contract events: `grep -rh '^\s*event ' contracts/src --include='*.sol' | sort -u` → 44 unique names. - Indexer decoder arms: `grep -E 'topic0 == .*::SIGNATURE_HASH' indexer/src/decoder.rs | sort -u` → 34 unique names. - All 13 missing events confirmed *actually emitted* via `grep -rn 'emit <Name>'` (not just declared). ### Events emitted but not decoded | Event | Source | Likely category | |---|---|---| | `BurrowProtocolRevenueSplit` | `RabbitTreasury` | Treasury accounting | | `BurrowReserveBuckets` | `RabbitTreasury` | Treasury accounting | | `BurrowWithdrawalFeeAccrued` | `RabbitTreasury` | Treasury accounting | | `BuyFeeRoutingEnabled` | `TimeCurve` | Operator toggle | | `CharmRedemptionEnabled` | `TimeCurve` | Operator toggle | | `Cl8ySurplusToProtocol` | `RabbitTreasury` | Treasury accounting | | `Claimed` | `DoubPresaleVesting` | User activity | | `ClaimsEnabled` | `DoubPresaleVesting` | Operator toggle | | `PrizePusherSet` | `TimeCurve` | Operator toggle | | `ReservePodiumPayoutsEnabled` | `RabbitTreasury` | Operator toggle | | `TimeCurveBuyRouterSet` | `TimeCurve` | Operator toggle | | `VestingStarted` | `DoubPresaleVesting` | Operator/lifecycle | | `Withdrawn` | `FeeSink` | Operator/governance | Also noted: `AllocationClaimed` is decoded by the indexer (`TimeCurveEventsLegacy::AllocationClaimed`) but no longer emitted by current contracts — kept as backfill compat. Not an issue, just noting for completeness. ### Why this matters User-activity events (`Claimed` from DoubPresaleVesting) without history mean a future "show my claim history" UI would have no source. Today the `PresaleVestingPage` reads state directly from the contract — no historical view — so the gap is currently invisible. Operator toggle events (`BuyFeeRoutingEnabled`, `ClaimsEnabled`, etc.) without history mean explorability of operator actions is limited; reading current state is fine, but "when did this flip" is unanswerable. Treasury accounting events (`BurrowProtocolRevenueSplit`, `BurrowReserveBuckets`, etc.) without history mean Rabbit Treasury historical PnL / fee-flow analysis is unsupported. ### Question for dev Which of these are **intentionally not indexed** (e.g., operator toggles where current state is enough), and which are **planned coverage** that just hasn't landed yet? If splits naturally: - **Skip permanently** (operator toggles, current state is authoritative): `BuyFeeRoutingEnabled`, `CharmRedemptionEnabled`, `ClaimsEnabled`, `PrizePusherSet`, `ReservePodiumPayoutsEnabled`, `TimeCurveBuyRouterSet` - **Maybe-future** (user activity / lifecycle): `Claimed`, `VestingStarted`, `Withdrawn` - **Treasury history** (analytics-grade): `BurrowProtocolRevenueSplit`, `BurrowReserveBuckets`, `BurrowWithdrawalFeeAccrued`, `Cl8ySurplusToProtocol` No code change requested unless you want one. Filing for visibility per 4/29 standing rule. ### Severity P3-low. Scope/planning question, not a defect. No current user-facing impact. cc @PlasticDigits
PlasticDigits commented 2026-05-02 04:45:28 +00:00 (Migrated from gitlab.com)

All events do need to be decoded, recorded and stored in postgres db for future proofing.

All events do need to be decoded, recorded and stored in postgres db for future proofing.
PlasticDigits commented 2026-05-02 04:53:16 +00:00 (Migrated from gitlab.com)

mentioned in commit bcb24e84ec

mentioned in commit bcb24e84eca7d3c6596f77b4e37bef9d6a51cc10
PlasticDigits commented 2026-05-02 04:53:42 +00:00 (Migrated from gitlab.com)

Fix landed on main (indexer emits — GL #112)

Per maintainer feedback on this issue, all previously undecoded protocol emits now decode and persist to Postgres (operator toggles, Rabbit treasury splits, podium PrizePusherSet, DoubPresaleVesting lifecycle/claims gate, FeeSink.Withdrawn, TimeCurveBuyRouter surplus dust, router address updates). Historical AllocationClaimed still maps to the existing charms-redeemed table for backfill (no duplicate table).

What merged

  • indexer/migrations/20260502130000_gl112_extended_event_tables.{up,down}.sql — thirteen idx_* tables with the usual metadata + event columns and (tx_hash, log_index) PK.
  • indexer/src/decoder.rs — sol! parity + decode arms + roundtrip tests for vesting claim + FeeSink withdrawal.
  • indexer/src/persist.rs — idempotent INSERTs mirroring existing patterns.
  • indexer/src/reorg.rs — rollback deletes extended to cover every persisted event table (sorted list).

Docs / invariants (INV-INDEXER-112)

docs/testing/invariants-and-business-logic.md#indexer-emitted-event-coverage-gitlab-112 — cross-linked from docs/indexer/design.md, contributor guardrails .cursor/skills/yieldomega-guardrails/SKILL.md, and third-party/agent index skills/README.md.

Please verify (@brouie — issue stays open until you confirm)

  1. Pull latest main, bump an indexer-backed DB via migrations; confirm fifteen new indexes exist under the idx_* names from the migration.
  2. cd indexer && YIELDOMEGA_PG_TEST_URL=postgres://... (CI-style URL) → cargo test: integration test should exercise every DecodedEvent variant, idempotent replay, and rollback_after wiping block 100 sample rows across new tables (watch idx_doub_vesting_*, idx_fee_sink_withdrawn, idx_rabbit_protocol_revenue_split).
  3. Optional live smoke: ingest a tx that emits e.g. BuyFeeRoutingEnabled, ClaimsEnabled, or a vesting Claimed and SELECT the matching idx_* row for (block_number, contract_address).
  4. API scope: endpoints are unchanged; UI still reads canonical contract state unless you explicitly add projections over the new tables.

Leaving this issue open for your sign-off per request.

## Fix landed on main (indexer emits — GL #112) Per maintainer feedback on this issue, **all previously undecoded protocol emits now decode and persist** to Postgres (operator toggles, Rabbit treasury splits, podium `PrizePusherSet`, `DoubPresaleVesting` lifecycle/claims gate, `FeeSink.Withdrawn`, `TimeCurveBuyRouter` surplus dust, router address updates). Historical `AllocationClaimed` still maps to the existing charms-redeemed table for backfill (no duplicate table). ### What merged - `indexer/migrations/20260502130000_gl112_extended_event_tables.{up,down}.sql` — thirteen `idx_*` tables with the usual metadata + event columns and `(tx_hash, log_index)` PK. - `indexer/src/decoder.rs` — `sol!` parity + decode arms + roundtrip tests for vesting claim + FeeSink withdrawal. - `indexer/src/persist.rs` — idempotent INSERTs mirroring existing patterns. - `indexer/src/reorg.rs` — rollback deletes extended to cover **every** persisted event table (sorted list). ### Docs / invariants (**INV-INDEXER-112**) [`docs/testing/invariants-and-business-logic.md#indexer-emitted-event-coverage-gitlab-112`](docs/testing/invariants-and-business-logic.md#indexer-emitted-event-coverage-gitlab-112) — cross-linked from [`docs/indexer/design.md`](docs/indexer/design.md), contributor guardrails [`.cursor/skills/yieldomega-guardrails/SKILL.md`](.cursor/skills/yieldomega-guardrails/SKILL.md), and third-party/agent index [`skills/README.md`](skills/README.md). ### Please verify (**@brouie** — issue stays open until you confirm) 1. Pull latest **`main`**, bump an indexer-backed DB via migrations; confirm fifteen new indexes exist under the `idx_*` names from the migration. 2. `cd indexer && YIELDOMEGA_PG_TEST_URL=postgres://...` (**CI-style URL**) → `cargo test`: integration test should exercise **every** `DecodedEvent` variant, idempotent replay, and `rollback_after` wiping block 100 sample rows across new tables (watch `idx_doub_vesting_*`, `idx_fee_sink_withdrawn`, `idx_rabbit_protocol_revenue_split`). 3. Optional live smoke: ingest a tx that emits e.g. `BuyFeeRoutingEnabled`, `ClaimsEnabled`, or a vesting `Claimed` and SELECT the matching `idx_*` row for (`block_number`, `contract_address`). 4. **API scope:** endpoints are unchanged; UI still reads canonical contract state unless you explicitly add projections over the new tables. Leaving this issue **open** for your sign-off per request.
PlasticDigits commented 2026-05-02 04:53:55 +00:00 (Migrated from gitlab.com)

Correction: Verification step 1 should say thirteen new idx_* tables created by migration 20260502130000_gl112_extended_event_tables (PostgreSQL btree indexes aside).

**Correction:** Verification step 1 should say **thirteen** new `idx_*` **tables** created by migration `20260502130000_gl112_extended_event_tables` (PostgreSQL btree indexes aside).
Brouie commented 2026-05-03 23:03:00 +00:00 (Migrated from gitlab.com)

Verification PASS on gl112_extended_event_tables migration. Cargo test: cargo test against fresh yieldomega_indexer_test DB → 19 unit tests + 1 integration test PASS, 0 failures. New decoder roundtrips covered: roundtrip_doub_vesting_claimed, roundtrip_fee_sink_withdrawn. Integration test postgres_stage2_persist_all_events_and_rollback_after exercises every DecodedEvent variant + idempotent replay + rollback_after wiping block 100 rows across the new tables. Tables: All 13 new idx_* tables present in test DB after migration auto-applied: idx_timecurve_buy_fee_routing_enabled, idx_timecurve_charm_redemption_enabled, idx_timecurve_reserve_podium_payouts_enabled, idx_timecurve_buy_router_set, idx_timecurve_buy_router_cl8y_surplus, idx_rabbit_burrow_reserve_buckets, idx_rabbit_protocol_revenue_split, idx_rabbit_withdrawal_fee_accrued, idx_podium_pool_prize_pusher_set, idx_doub_vesting_started, idx_doub_vesting_claimed, idx_doub_vesting_claims_enabled, idx_fee_sink_withdrawn. Dev's specifically-mentioned tables (idx_doub_vesting_*, idx_fee_sink_withdrawn, idx_rabbit_protocol_revenue_split) all present. API scope: unchanged — confirmed via integration test (no new endpoints, only persist layer). Skipping optional live smoke ingestion since integration test already drives every variant against postgres. cc @PlasticDigits

Verification PASS on `gl112_extended_event_tables` migration. **Cargo test:** `cargo test` against fresh `yieldomega_indexer_test` DB → 19 unit tests + 1 integration test PASS, 0 failures. New decoder roundtrips covered: `roundtrip_doub_vesting_claimed`, `roundtrip_fee_sink_withdrawn`. Integration test `postgres_stage2_persist_all_events_and_rollback_after` exercises every DecodedEvent variant + idempotent replay + rollback_after wiping block 100 rows across the new tables. **Tables:** All 13 new `idx_*` tables present in test DB after migration auto-applied: `idx_timecurve_buy_fee_routing_enabled`, `idx_timecurve_charm_redemption_enabled`, `idx_timecurve_reserve_podium_payouts_enabled`, `idx_timecurve_buy_router_set`, `idx_timecurve_buy_router_cl8y_surplus`, `idx_rabbit_burrow_reserve_buckets`, `idx_rabbit_protocol_revenue_split`, `idx_rabbit_withdrawal_fee_accrued`, `idx_podium_pool_prize_pusher_set`, `idx_doub_vesting_started`, `idx_doub_vesting_claimed`, `idx_doub_vesting_claims_enabled`, `idx_fee_sink_withdrawn`. Dev's specifically-mentioned tables (`idx_doub_vesting_*`, `idx_fee_sink_withdrawn`, `idx_rabbit_protocol_revenue_split`) all present. **API scope:** unchanged — confirmed via integration test (no new endpoints, only persist layer). Skipping optional live smoke ingestion since integration test already drives every variant against postgres. cc @PlasticDigits
Brouie (Migrated from gitlab.com) closed this issue 2026-05-04 03:10:23 +00:00
PlasticDigits commented 2026-05-04 14:58:30 +00:00 (Migrated from gitlab.com)

mentioned in commit 49c758bc81

mentioned in commit 49c758bc8191501ff213110534de861277580040
PlasticDigits commented 2026-05-13 15:13:32 +00:00 (Migrated from gitlab.com)

mentioned in commit 32cf66eebb

mentioned in commit 32cf66eebb677c536d222d5db045419016a26d35
PlasticDigits commented 2026-06-13 07:02:54 +00:00 (Migrated from gitlab.com)

mentioned in issue #309

mentioned in issue #309
PlasticDigits commented 2026-06-13 07:34:18 +00:00 (Migrated from gitlab.com)

mentioned in issue #312

mentioned in issue #312
PlasticDigits commented 2026-06-13 07:34:26 +00:00 (Migrated from gitlab.com)

mentioned in issue #317

mentioned in issue #317
PlasticDigits commented 2026-06-13 08:15:43 +00:00 (Migrated from gitlab.com)

mentioned in merge request !463

mentioned in merge request !463
PlasticDigits commented 2026-06-14 05:34:02 +00:00 (Migrated from gitlab.com)

mentioned in merge request !484

mentioned in merge request !484
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#112
No description provided.