Indexer: ingest Arena buy vault funding events (PodiumFunded, SeedFunded, AdminVaultFunded) #267

Closed
opened 2026-05-29 08:10:13 +00:00 by PlasticDigits · 11 comments
PlasticDigits commented 2026-05-29 08:10:13 +00:00 (Migrated from gitlab.com)

Summary

Extend Arena v2 indexer coverage to persist per-buy DOUB prize routing events emitted from PodiumVaults and AdminSellVault — completing the guardrail in yieldomega-guardrails and arena-v2.md that is not covered by the donate-pools slice of #262.

Already shipped (do not redo): #262 / #261 — PodiumPoolsToppedUp → idx_arena_podium_pool_top_up + GET /v1/arena/podium-pool-donations + protocol AUDIT card (TimeCurveProtocolDonatePoolsSection.tsx).

This issue: PodiumFunded, SeedFunded, AdminVaultFunded from each qualifying TimeArena buy (and top-up vault notifications).

Parent epic: #238.


Current codebase

Onchain (authoritative)

Each DOUB buy (not CRED burn) calls _routeDoubPrizeSplit in TimeArena.sol:

Share Bps (total) Notification
4× active podium pools 40% (10% each) PodiumVaults.notifyPodiumFunded → PodiumFunded(podiumId, amount, pool)
4× seed podium pools 30% (7.5% each) PodiumVaults.notifySeedFunded → SeedFunded(podiumId, amount, pool)
AdminSellVault 30% (+ wei dust) AdminVaultFunded(amount)

topUpPodiumPools routes 100% to eight vaults and emits PodiumPoolsToppedUp only — already indexed.

Math: ArenaBuyRouting.splitBuyAmount — tested in ArenaPrizeRouting.t.sol.

Indexer (partial)

  • Registry already includes PodiumVaults and AdminSellVault in index_addresses() for eth_getLogs filtering.
  • Decoder (decoder.rs) handles TimeArena events + PodiumPoolsToppedUp; does not decode PodiumFunded, SeedFunded, or AdminVaultFunded.
  • Persist (persist.rs) has no tables for buy-sourced vault funding rows.
  • HTTP: no public aggregate/route for “where did this buy’s DOUB go?” beyond inferring from idx_arena_buy.doub_paid.

Frontend

  • FeeTransparency shows static 40/30/30 copy + vault addresses.
  • No indexer-backed “funding breakdown per buy” or running totals per vault category.
  • Protocol AUDIT may later chart vault inflows — optional consumer of new API (can be follow-up).

Why this is needed

  1. Transparency / AUDIT: Operators and participants should verify onchain 40/30/30 routing without manual log scraping.
  2. Reconciliation: Sum of funding events for a tx_hash should equal Buy.doub_paid (CRED buys: zero funding events).
  3. Guardrails: Agent skill requires decoding these events when TimeArena is in registry — currently gap vs implemented donate-pools path.
  4. Analytics: Enables podium-pool balance history, admin vault inflow time series, and future wallet/profile views without re-indexing from scratch.

Constraints and guardrails

  • One SQL transaction per block (#140); idempotent inserts ON CONFLICT (tx_hash, log_index) DO NOTHING.
  • Reorg: register new tables in reorg.rs rollback list.
  • Production: non-zero TimeArena, PodiumVaults, AdminSellVault in registry when INDEXER_PRODUCTION + ingestion (#156).
  • Do not count PodiumPoolsToppedUp toward buy routing totals (separate table/API already exists).
  • Event source: decode logs from PodiumVaults / AdminSellVault contract addresses (events are emitted there, not on TimeArena).
  • Only msg.sender == arena can emit funding notifications onchain — still validate podiumId < 4 and amounts in tests.
  • HTTP 500 bodies redacted (#157).
  • Schema version: bump x-schema-version / document in indexer/README.md.

Relevant files

Area Files
Contracts (reference) PodiumVaults.sol, AdminSellVault.sol, TimeArena.sol
Migrations indexer/migrations/*_arena_vault_funding_*.sql (new)
Ingest decoder.rs, persist.rs, ingestion.rs
HTTP api_arena.rs or new api_arena_funding.rs
Tests integration_stage2.rs
Docs docs/indexer/design.md, docs/testing/invariants-and-business-logic.md, docs/onchain/fee-routing-and-governance.md (Arena prize routing section)
Registry indexer/address-registry.megaeth-mainnet.json

1. Schema

Option A — single table idx_arena_vault_funding with kind enum (podium_active, podium_seed, admin):

  • Columns: block_number, block_timestamp, tx_hash, log_index, kind, podium_id (nullable), amount_doub_wad, pool_address (nullable), buyer (optional — join via same tx_hash to idx_arena_buy in API layer).

Option B — three tables mirroring event names. Prefer Option A for simpler HTTP aggregates unless strong query isolation needed.

Indexes: (tx_hash), (block_number DESC), (kind, podium_id).

2. Decoder

Add sol! events matching onchain signatures:

event PodiumFunded(uint8 indexed podiumId, uint256 amount, address indexed pool);
event SeedFunded(uint8 indexed podiumId, uint256 amount, address indexed pool);
event AdminVaultFunded(uint256 amount);

Map contract address → decode variant (PodiumVaults vs AdminSellVault).

3. Persist + integration test

  • Insert on decode; include synthetic logs in integration_stage2 “all events” fixture.
  • Assert 9 rows per 1000 DOUB buy (4+4+1) for typical split, or sum equals doub_paid from paired Buy in same tx.

4. HTTP API (minimum viable)

Proposed routes (names negotiable):

Route Purpose
GET /v1/arena/vault-funding/recent?limit=&offset= Latest funding rows (all kinds)
GET /v1/arena/vault-funding/by-tx/{tx_hash} Breakdown for one buy tx
GET /v1/arena/vault-funding/totals Network sums by kind (+ per podium_id for podium kinds)

Empty DB → zeros / [] (not 404), consistent with #262 donate API.

5. Invariants

Add e.g. INV-INDEXER-262-VAULT-FUNDING (or new ID if #262 closed):

  • For each idx_arena_buy row with paid_with_cred = false, sum funding rows in same tx_hash = doub_paid.
  • CRED buys: no funding rows in same tx.

6. Frontend (optional in this issue)

  • If timeboxed: indexer-only + docs; frontend card in separate issue.
  • If included: small AUDIT table on protocol page — “Recent prize routing (from buys)”.

Acceptance criteria

  • Decoder persists PodiumFunded, SeedFunded, AdminVaultFunded from registry vault addresses.
  • Reorg rollback clears new table(s).
  • integration_stage2 covers ingest + at least one HTTP route.
  • GET totals match manual sum of fixture rows.
  • Per-tx breakdown API returns 9 lines (typical) for standard buy fixture tx.
  • CRED buy fixture: idx_arena_buy exists, funding sum = 0 for that tx.
  • SCHEMA_VERSION / README updated.
  • Invariant row + design.md section added.
  • No regression to idx_arena_podium_pool_top_up / GET /v1/arena/podium-pool-donations.

Test plan — functional paths

# Path Expected
1 Ingest block with one DOUB Buy 1 buy row + N funding rows (N≥9 before dust consolidation)
2 Sum funding amount per tx Equals doub_paid on buy row
3 topUpPodiumPools tx Donate row only; no funding rows or funding rows only if events also fire (document: top-up should not emit PodiumFunded — only PodiumPoolsToppedUp)
4 GET .../by-tx/{hash} JSON lists kinds, podium_id, amounts
5 GET .../totals Matches SQL SUM(amount) grouped by kind
6 Empty database Totals zero; recent []
7 Duplicate log replay Idempotent — row count unchanged
8 Reorg past block Funding rows for block removed with buy rows

Automated: cd indexer && cargo test; optional YIELDOMEGA_PG_TEST_URL=... integration.


Test plan — attack / abuse vectors

Vector Test Expected
Spoofed funding event Log from non-registry address Ignored (not in filter)
Fake PodiumVaults contract Wrong emitter in registry Production validation rejects misconfigured registry
Inflated amounts in logs Compare to Buy.doub_paid Invariant test fails CI if sum > buy (data quality alarm)
SQL injection via tx_hash param Fuzz HTTP path param Parameterized queries only
Log index collision Same tx_hash + log_index twice ON CONFLICT DO NOTHING
CRED buy confusion paid_with_cred=true No false funding attribution in API copy

Verification criteria

  • cargo test green; integration_stage2 funding section passes on CI Postgres when enabled.
  • Manual: run Anvil buy → query GET /v1/arena/vault-funding/by-tx/... → 40/30/30 visible.
  • cast logs on test tx matches DB row count and amounts.
  • Documented in docs/indexer/design.md with anchor for manual QA.
  • Close comment on #262 noting donate-pools complete; funding-events tracked here.

Out of scope

  • Onchain changes to event shapes.
  • Replacing idx_arena_buy — buy row remains primary participant record.
  • FeeRouter / TimeCurve CL8Y routing history.
  • Frontend prize charts (unless explicitly added with bandwidth).
## Summary Extend Arena v2 indexer coverage to persist **per-buy DOUB prize routing** events emitted from **`PodiumVaults`** and **`AdminSellVault`** — completing the guardrail in [yieldomega-guardrails](.cursor/skills/yieldomega-guardrails/SKILL.md) and [`arena-v2.md`](docs/product/arena-v2.md) that is **not** covered by the donate-pools slice of [#262](https://gitlab.com/PlasticDigits/yieldomega/-/issues/262). **Already shipped (do not redo):** [#262](https://gitlab.com/PlasticDigits/yieldomega/-/issues/262) / [#261](https://gitlab.com/PlasticDigits/yieldomega/-/issues/261) — `PodiumPoolsToppedUp` → `idx_arena_podium_pool_top_up` + `GET /v1/arena/podium-pool-donations` + protocol AUDIT card ([`TimeCurveProtocolDonatePoolsSection.tsx`](frontend/src/pages/timecurve/TimeCurveProtocolDonatePoolsSection.tsx)). **This issue:** **`PodiumFunded`**, **`SeedFunded`**, **`AdminVaultFunded`** from each qualifying **`TimeArena`** buy (and top-up vault notifications). Parent epic: [#238](https://gitlab.com/PlasticDigits/yieldomega/-/issues/238). --- ## Current codebase ### Onchain (authoritative) Each DOUB **`buy`** (not CRED burn) calls `_routeDoubPrizeSplit` in [`TimeArena.sol`](contracts/src/arena/TimeArena.sol): | Share | Bps (total) | Notification | |-------|-------------|----------------| | 4× active podium pools | 40% (10% each) | `PodiumVaults.notifyPodiumFunded` → **`PodiumFunded(podiumId, amount, pool)`** | | 4× seed podium pools | 30% (7.5% each) | `PodiumVaults.notifySeedFunded` → **`SeedFunded(podiumId, amount, pool)`** | | `AdminSellVault` | 30% (+ wei dust) | **`AdminVaultFunded(amount)`** | [`topUpPodiumPools`](contracts/src/arena/TimeArena.sol) routes 100% to eight vaults and emits **`PodiumPoolsToppedUp`** only — **already indexed**. Math: [`ArenaBuyRouting.splitBuyAmount`](contracts/src/arena/libraries/ArenaBuyRouting.sol) — tested in [`ArenaPrizeRouting.t.sol`](contracts/test/ArenaPrizeRouting.t.sol). ### Indexer (partial) - **Registry** already includes `PodiumVaults` and `AdminSellVault` in [`index_addresses()`](indexer/src/config.rs) for `eth_getLogs` filtering. - **Decoder** ([`decoder.rs`](indexer/src/decoder.rs)) handles `TimeArena` events + `PodiumPoolsToppedUp`; **does not** decode `PodiumFunded`, `SeedFunded`, or `AdminVaultFunded`. - **Persist** ([`persist.rs`](indexer/src/persist.rs)) has no tables for buy-sourced vault funding rows. - **HTTP:** no public aggregate/route for “where did this buy’s DOUB go?” beyond inferring from `idx_arena_buy.doub_paid`. ### Frontend - [`FeeTransparency`](frontend/src/components/FeeTransparency.tsx) shows static 40/30/30 copy + vault addresses. - No indexer-backed “funding breakdown per buy” or running totals per vault category. - Protocol AUDIT may later chart vault inflows — **optional** consumer of new API (can be follow-up). --- ## Why this is needed 1. **Transparency / AUDIT:** Operators and participants should verify onchain **40/30/30** routing without manual log scraping. 2. **Reconciliation:** Sum of funding events for a `tx_hash` should equal `Buy.doub_paid` (CRED buys: zero funding events). 3. **Guardrails:** Agent skill requires decoding these events when `TimeArena` is in registry — currently **gap** vs implemented donate-pools path. 4. **Analytics:** Enables podium-pool balance history, admin vault inflow time series, and future wallet/profile views without re-indexing from scratch. --- ## Constraints and guardrails - **One SQL transaction per block** ([#140](https://gitlab.com/PlasticDigits/yieldomega/-/issues/140)); idempotent inserts `ON CONFLICT (tx_hash, log_index) DO NOTHING`. - **Reorg:** register new tables in [`reorg.rs`](indexer/src/reorg.rs) rollback list. - **Production:** non-zero `TimeArena`, `PodiumVaults`, `AdminSellVault` in registry when `INDEXER_PRODUCTION` + ingestion ([#156](https://gitlab.com/PlasticDigits/yieldomega/-/issues/156)). - **Do not** count `PodiumPoolsToppedUp` toward buy routing totals (separate table/API already exists). - **Event source:** decode logs from **`PodiumVaults`** / **`AdminSellVault`** contract addresses (events are emitted there, not on `TimeArena`). - **Only `msg.sender == arena`** can emit funding notifications onchain — still validate `podiumId < 4` and amounts in tests. - **HTTP 500** bodies redacted ([#157](https://gitlab.com/PlasticDigits/yieldomega/-/issues/157)). - **Schema version:** bump `x-schema-version` / document in [`indexer/README.md`](indexer/README.md). --- ## Relevant files | Area | Files | |------|--------| | **Contracts (reference)** | [`PodiumVaults.sol`](contracts/src/arena/PodiumVaults.sol), [`AdminSellVault.sol`](contracts/src/arena/AdminSellVault.sol), [`TimeArena.sol`](contracts/src/arena/TimeArena.sol) | | **Migrations** | `indexer/migrations/*_arena_vault_funding_*.sql` (new) | | **Ingest** | [`decoder.rs`](indexer/src/decoder.rs), [`persist.rs`](indexer/src/persist.rs), [`ingestion.rs`](indexer/src/ingestion.rs) | | **HTTP** | [`api_arena.rs`](indexer/src/api_arena.rs) or new `api_arena_funding.rs` | | **Tests** | [`integration_stage2.rs`](indexer/tests/integration_stage2.rs) | | **Docs** | [`docs/indexer/design.md`](docs/indexer/design.md), [`docs/testing/invariants-and-business-logic.md`](docs/testing/invariants-and-business-logic.md), [`docs/onchain/fee-routing-and-governance.md`](docs/onchain/fee-routing-and-governance.md) (Arena prize routing section) | | **Registry** | [`indexer/address-registry.megaeth-mainnet.json`](indexer/address-registry.megaeth-mainnet.json) | --- ## Recommended direction ### 1. Schema Option A — **single table** `idx_arena_vault_funding` with `kind` enum (`podium_active`, `podium_seed`, `admin`): - Columns: `block_number`, `block_timestamp`, `tx_hash`, `log_index`, `kind`, `podium_id` (nullable), `amount_doub_wad`, `pool_address` (nullable), `buyer` (optional — join via same `tx_hash` to `idx_arena_buy` in API layer). Option B — **three tables** mirroring event names. Prefer **Option A** for simpler HTTP aggregates unless strong query isolation needed. Indexes: `(tx_hash)`, `(block_number DESC)`, `(kind, podium_id)`. ### 2. Decoder Add `sol!` events matching onchain signatures: ```solidity event PodiumFunded(uint8 indexed podiumId, uint256 amount, address indexed pool); event SeedFunded(uint8 indexed podiumId, uint256 amount, address indexed pool); event AdminVaultFunded(uint256 amount); ``` Map contract address → decode variant (PodiumVaults vs AdminSellVault). ### 3. Persist + integration test - Insert on decode; include synthetic logs in `integration_stage2` “all events” fixture. - Assert 9 rows per 1000 DOUB buy (4+4+1) for typical split, or sum equals `doub_paid` from paired `Buy` in same tx. ### 4. HTTP API (minimum viable) Proposed routes (names negotiable): | Route | Purpose | |-------|---------| | `GET /v1/arena/vault-funding/recent?limit=&offset=` | Latest funding rows (all kinds) | | `GET /v1/arena/vault-funding/by-tx/{tx_hash}` | Breakdown for one buy tx | | `GET /v1/arena/vault-funding/totals` | Network sums by `kind` (+ per `podium_id` for podium kinds) | Empty DB → zeros / `[]` (not 404), consistent with [#262](https://gitlab.com/PlasticDigits/yieldomega/-/issues/262) donate API. ### 5. Invariants Add e.g. **`INV-INDEXER-262-VAULT-FUNDING`** (or new ID if #262 closed): - For each `idx_arena_buy` row with `paid_with_cred = false`, sum funding rows in same `tx_hash` = `doub_paid`. - CRED buys: no funding rows in same tx. ### 6. Frontend (optional in this issue) - If timeboxed: **indexer-only** + docs; frontend card in separate issue. - If included: small AUDIT table on protocol page — “Recent prize routing (from buys)”. --- ## Acceptance criteria - [ ] Decoder persists `PodiumFunded`, `SeedFunded`, `AdminVaultFunded` from registry vault addresses. - [ ] Reorg rollback clears new table(s). - [ ] `integration_stage2` covers ingest + at least one HTTP route. - [ ] `GET` totals match manual sum of fixture rows. - [ ] Per-tx breakdown API returns 9 lines (typical) for standard buy fixture tx. - [ ] CRED buy fixture: `idx_arena_buy` exists, funding sum = 0 for that tx. - [ ] `SCHEMA_VERSION` / README updated. - [ ] Invariant row + design.md section added. - [ ] **No regression** to `idx_arena_podium_pool_top_up` / `GET /v1/arena/podium-pool-donations`. --- ## Test plan — functional paths | # | Path | Expected | |---|------|----------| | 1 | Ingest block with one DOUB `Buy` | 1 buy row + N funding rows (N≥9 before dust consolidation) | | 2 | Sum funding `amount` per tx | Equals `doub_paid` on buy row | | 3 | `topUpPodiumPools` tx | Donate row only; **no** funding rows **or** funding rows only if events also fire (document: top-up should **not** emit PodiumFunded — only `PodiumPoolsToppedUp`) | | 4 | `GET .../by-tx/{hash}` | JSON lists kinds, podium_id, amounts | | 5 | `GET .../totals` | Matches SQL `SUM(amount)` grouped by kind | | 6 | Empty database | Totals zero; recent `[]` | | 7 | Duplicate log replay | Idempotent — row count unchanged | | 8 | Reorg past block | Funding rows for block removed with buy rows | **Automated:** `cd indexer && cargo test`; optional `YIELDOMEGA_PG_TEST_URL=...` integration. --- ## Test plan — attack / abuse vectors | Vector | Test | Expected | |--------|------|----------| | **Spoofed funding event** | Log from non-registry address | Ignored (not in filter) | | **Fake PodiumVaults contract** | Wrong emitter in registry | Production validation rejects misconfigured registry | | **Inflated amounts in logs** | Compare to `Buy.doub_paid` | Invariant test fails CI if sum > buy (data quality alarm) | | **SQL injection via tx_hash param** | Fuzz HTTP path param | Parameterized queries only | | **Log index collision** | Same tx_hash + log_index twice | `ON CONFLICT DO NOTHING` | | **CRED buy confusion** | `paid_with_cred=true` | No false funding attribution in API copy | --- ## Verification criteria - [ ] `cargo test` green; integration_stage2 funding section passes on CI Postgres when enabled. - [ ] Manual: run Anvil buy → query `GET /v1/arena/vault-funding/by-tx/...` → 40/30/30 visible. - [ ] `cast logs` on test tx matches DB row count and amounts. - [ ] Documented in [`docs/indexer/design.md`](docs/indexer/design.md) with anchor for manual QA. - [ ] Close comment on [#262](https://gitlab.com/PlasticDigits/yieldomega/-/issues/262) noting donate-pools complete; funding-events tracked here. --- ## Out of scope - Onchain changes to event shapes. - Replacing `idx_arena_buy` — buy row remains primary participant record. - FeeRouter / TimeCurve CL8Y routing history. - Frontend prize charts (unless explicitly added with bandwidth).
PlasticDigits commented 2026-05-29 08:10:14 +00:00 (Migrated from gitlab.com)

marked as related to #262

marked as related to #262
PlasticDigits commented 2026-05-29 08:10:15 +00:00 (Migrated from gitlab.com)

marked as related to #261

marked as related to #261
PlasticDigits commented 2026-05-29 08:10:15 +00:00 (Migrated from gitlab.com)

marked as related to #238

marked as related to #238
PlasticDigits commented 2026-05-29 08:34:10 +00:00 (Migrated from gitlab.com)

mentioned in commit a187b9fe64

mentioned in commit a187b9fe64096b7ba19acc8859a1a65a7067c837
PlasticDigits commented 2026-05-29 08:34:10 +00:00 (Migrated from gitlab.com)

mentioned in commit 02f557c540

mentioned in commit 02f557c54026cc4098b22e3967e1ec466564a9cc
PlasticDigits commented 2026-05-29 08:35:17 +00:00 (Migrated from gitlab.com)

Implementation complete (merged to main @ 02f557c)

Indexer now ingests per-buy DOUB prize routing from registry PodiumVaults / AdminSellVault logs:

Event Table kind
PodiumFunded podium_active
SeedFunded podium_seed
AdminVaultFunded admin

Shipped

  • Migration idx_arena_vault_funding (+ reorg rollback)
  • Decoder + persist (idempotent ON CONFLICT (tx_hash, log_index) DO NOTHING)
  • HTTP (schema 2.2.0): GET /v1/arena/vault-funding/recent, …/by-tx/{tx_hash}, …/totals
  • Integration coverage in integration_stage2.rs (api_vault_funding_smoke)
  • Invariant INV-INDEXER-267-VAULT-FUNDING + cross-links in design.md, arena-v2.md, fee-routing doc, play skill

Verification checklist

  • cd indexer && cargo clippy --all-targets -- -D warnings && cargo test green
  • With Postgres: YIELDOMEGA_PG_TEST_URL=… cargo test --test integration_stage2 — 9 funding rows per 1000 DOUB buy tx; CRED buy tx has 0 funding rows
  • GET /v1/arena/vault-funding/by-tx/0x… after Anvil DOUB buy shows 40/30/30 breakdown (9 lines)
  • GET /v1/arena/vault-funding/totals sums match SQL on idx_arena_vault_funding
  • Reorg rollback removes funding rows with buy rows (rollback_after in integration test)
  • No regression: GET /v1/arena/podium-pool-donations unchanged (#262)
  • bash scripts/check-doc-anchors.sh passes

@brouie — please verify on dev/staging when convenient; leaving this issue open until sign-off.

/cc @brouie

## Implementation complete (merged to `main` @ 02f557c) Indexer now ingests **per-buy DOUB prize routing** from registry **`PodiumVaults`** / **`AdminSellVault`** logs: | Event | Table `kind` | |-------|----------------| | `PodiumFunded` | `podium_active` | | `SeedFunded` | `podium_seed` | | `AdminVaultFunded` | `admin` | ### Shipped - Migration `idx_arena_vault_funding` (+ reorg rollback) - Decoder + persist (idempotent `ON CONFLICT (tx_hash, log_index) DO NOTHING`) - HTTP (schema **2.2.0**): `GET /v1/arena/vault-funding/recent`, `…/by-tx/{tx_hash}`, `…/totals` - Integration coverage in `integration_stage2.rs` (`api_vault_funding_smoke`) - Invariant **`INV-INDEXER-267-VAULT-FUNDING`** + cross-links in design.md, arena-v2.md, fee-routing doc, play skill ### Verification checklist - [ ] `cd indexer && cargo clippy --all-targets -- -D warnings && cargo test` green - [ ] With Postgres: `YIELDOMEGA_PG_TEST_URL=… cargo test --test integration_stage2` — 9 funding rows per 1000 DOUB buy tx; CRED buy tx has 0 funding rows - [ ] `GET /v1/arena/vault-funding/by-tx/0x…` after Anvil DOUB buy shows 40/30/30 breakdown (9 lines) - [ ] `GET /v1/arena/vault-funding/totals` sums match SQL on `idx_arena_vault_funding` - [ ] Reorg rollback removes funding rows with buy rows (`rollback_after` in integration test) - [ ] No regression: `GET /v1/arena/podium-pool-donations` unchanged (#262) - [ ] `bash scripts/check-doc-anchors.sh` passes @brouie — please verify on dev/staging when convenient; leaving this issue **open** until sign-off. /cc @brouie
PlasticDigits commented 2026-06-01 13:13:00 +00:00 (Migrated from gitlab.com)

mentioned in commit a5c05615ba

mentioned in commit a5c05615baf9033e25431fce47c428194ff9139f
PlasticDigits commented 2026-06-01 13:13:00 +00:00 (Migrated from gitlab.com)

mentioned in commit c40afd047d

mentioned in commit c40afd047d15f28cf4015208907923c18815f2ae
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-01 13:13:08 +00:00
PlasticDigits commented 2026-06-01 13:13:17 +00:00 (Migrated from gitlab.com)

QA verification complete (@ a5c0561 on main)

Verified GitLab #267 end-to-end on a fresh Anvil + Postgres stack. Core indexer implementation (migration, decoder, persist, reorg rollback, HTTP routes) was already merged; this pass added the missing Anvil smoke script and manual QA / cross-link docs.

What was verified

Criterion Result
cd indexer && cargo clippy --all-targets -- -D warnings && cargo test ✅ green
integration_stage2 (api_vault_funding_smoke, reorg rollback clears idx_arena_vault_funding) ✅ green (Postgres via script)
Decoder persists PodiumFunded / SeedFunded / AdminVaultFunded ✅ 9 rows per 1000 DOUB buy
CRED buy: buy row exists, zero funding rows ✅
GET /v1/arena/vault-funding/by-tx/{hash} ✅ 9 lines, sum = doub_paid
GET /v1/arena/vault-funding/totals ✅ matches SQL SUM by kind
cast receipt log count vs DB ✅ 9 vault logs = 9 DB rows
No regression: GET /v1/arena/podium-pool-donations (#262) ✅
bash scripts/check-doc-anchors.sh ✅
bash scripts/verify-vault-funding-anvil.sh (new) ✅

Shipped in this QA pass

  • scripts/verify-vault-funding-anvil.sh — reset infra, DeployDev, indexer ingest, DOUB buy + CRED buy, HTTP + cast receipt reconciliation
  • Manual QA §267 in docs/testing/manual-qa-checklists.md
  • Cross-links: guardrails skill, indexer/README.md, docs/indexer/design.md, invariants table, skills/play-time-arena-doub/SKILL.md

Checklist for follow-up verification

  • Run bash scripts/verify-vault-funding-anvil.sh on CI/dev Postgres host
  • After a mainnet/staging DOUB buy, GET /v1/arena/vault-funding/by-tx/0x… shows 40/30/30 breakdown
  • Confirm topUpPodiumPools txs appear only in podium-pool-donations, not vault-funding

Closing — all acceptance criteria from the issue body and implementation comment checklist pass.

## QA verification complete (@ `a5c0561` on `main`) Verified GitLab #267 end-to-end on a fresh Anvil + Postgres stack. Core indexer implementation (migration, decoder, persist, reorg rollback, HTTP routes) was already merged; this pass added the missing **Anvil smoke script** and **manual QA / cross-link** docs. ### What was verified | Criterion | Result | |-----------|--------| | `cd indexer && cargo clippy --all-targets -- -D warnings && cargo test` | ✅ green | | `integration_stage2` (`api_vault_funding_smoke`, reorg rollback clears `idx_arena_vault_funding`) | ✅ green (Postgres via script) | | Decoder persists `PodiumFunded` / `SeedFunded` / `AdminVaultFunded` | ✅ 9 rows per 1000 DOUB buy | | CRED buy: buy row exists, zero funding rows | ✅ | | `GET /v1/arena/vault-funding/by-tx/{hash}` | ✅ 9 lines, sum = `doub_paid` | | `GET /v1/arena/vault-funding/totals` | ✅ matches SQL `SUM` by kind | | `cast receipt` log count vs DB | ✅ 9 vault logs = 9 DB rows | | No regression: `GET /v1/arena/podium-pool-donations` (#262) | ✅ | | `bash scripts/check-doc-anchors.sh` | ✅ | | **`bash scripts/verify-vault-funding-anvil.sh`** (new) | ✅ | ### Shipped in this QA pass - **`scripts/verify-vault-funding-anvil.sh`** — reset infra, DeployDev, indexer ingest, DOUB buy + CRED buy, HTTP + `cast receipt` reconciliation - **Manual QA §267** in `docs/testing/manual-qa-checklists.md` - Cross-links: guardrails skill, `indexer/README.md`, `docs/indexer/design.md`, invariants table, `skills/play-time-arena-doub/SKILL.md` ### Checklist for follow-up verification - [ ] Run `bash scripts/verify-vault-funding-anvil.sh` on CI/dev Postgres host - [ ] After a mainnet/staging DOUB buy, `GET /v1/arena/vault-funding/by-tx/0x…` shows 40/30/30 breakdown - [ ] Confirm `topUpPodiumPools` txs appear only in `podium-pool-donations`, not vault-funding Closing — all acceptance criteria from the issue body and implementation comment checklist pass.
PlasticDigits commented 2026-06-01 13:13:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #262

mentioned in issue #262
PlasticDigits commented 2026-06-07 07:50:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #300

mentioned in issue #300
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#267
No description provided.