Indexer: ingest Arena buy vault funding events (PodiumFunded, SeedFunded, AdminVaultFunded) #267
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#267
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Extend Arena v2 indexer coverage to persist per-buy DOUB prize routing events emitted from
PodiumVaultsandAdminSellVault— completing the guardrail in yieldomega-guardrails andarena-v2.mdthat 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,AdminVaultFundedfrom each qualifyingTimeArenabuy (and top-up vault notifications).Parent epic: #238.
Current codebase
Onchain (authoritative)
Each DOUB
buy(not CRED burn) calls_routeDoubPrizeSplitinTimeArena.sol:PodiumVaults.notifyPodiumFunded→PodiumFunded(podiumId, amount, pool)PodiumVaults.notifySeedFunded→SeedFunded(podiumId, amount, pool)AdminSellVaultAdminVaultFunded(amount)topUpPodiumPoolsroutes 100% to eight vaults and emitsPodiumPoolsToppedUponly — already indexed.Math:
ArenaBuyRouting.splitBuyAmount— tested inArenaPrizeRouting.t.sol.Indexer (partial)
PodiumVaultsandAdminSellVaultinindex_addresses()foreth_getLogsfiltering.decoder.rs) handlesTimeArenaevents +PodiumPoolsToppedUp; does not decodePodiumFunded,SeedFunded, orAdminVaultFunded.persist.rs) has no tables for buy-sourced vault funding rows.idx_arena_buy.doub_paid.Frontend
FeeTransparencyshows static 40/30/30 copy + vault addresses.Why this is needed
tx_hashshould equalBuy.doub_paid(CRED buys: zero funding events).TimeArenais in registry — currently gap vs implemented donate-pools path.Constraints and guardrails
ON CONFLICT (tx_hash, log_index) DO NOTHING.reorg.rsrollback list.TimeArena,PodiumVaults,AdminSellVaultin registry whenINDEXER_PRODUCTION+ ingestion (#156).PodiumPoolsToppedUptoward buy routing totals (separate table/API already exists).PodiumVaults/AdminSellVaultcontract addresses (events are emitted there, not onTimeArena).msg.sender == arenacan emit funding notifications onchain — still validatepodiumId < 4and amounts in tests.x-schema-version/ document inindexer/README.md.Relevant files
PodiumVaults.sol,AdminSellVault.sol,TimeArena.solindexer/migrations/*_arena_vault_funding_*.sql(new)decoder.rs,persist.rs,ingestion.rsapi_arena.rsor newapi_arena_funding.rsintegration_stage2.rsdocs/indexer/design.md,docs/testing/invariants-and-business-logic.md,docs/onchain/fee-routing-and-governance.md(Arena prize routing section)indexer/address-registry.megaeth-mainnet.jsonRecommended direction
1. Schema
Option A — single table
idx_arena_vault_fundingwithkindenum (podium_active,podium_seed,admin):block_number,block_timestamp,tx_hash,log_index,kind,podium_id(nullable),amount_doub_wad,pool_address(nullable),buyer(optional — join via sametx_hashtoidx_arena_buyin 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:Map contract address → decode variant (PodiumVaults vs AdminSellVault).
3. Persist + integration test
integration_stage2“all events” fixture.doub_paidfrom pairedBuyin same tx.4. HTTP API (minimum viable)
Proposed routes (names negotiable):
GET /v1/arena/vault-funding/recent?limit=&offset=GET /v1/arena/vault-funding/by-tx/{tx_hash}GET /v1/arena/vault-funding/totalskind(+ perpodium_idfor 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):idx_arena_buyrow withpaid_with_cred = false, sum funding rows in sametx_hash=doub_paid.6. Frontend (optional in this issue)
Acceptance criteria
PodiumFunded,SeedFunded,AdminVaultFundedfrom registry vault addresses.integration_stage2covers ingest + at least one HTTP route.GETtotals match manual sum of fixture rows.idx_arena_buyexists, funding sum = 0 for that tx.SCHEMA_VERSION/ README updated.idx_arena_podium_pool_top_up/GET /v1/arena/podium-pool-donations.Test plan — functional paths
Buyamountper txdoub_paidon buy rowtopUpPodiumPoolstxPodiumPoolsToppedUp)GET .../by-tx/{hash}GET .../totalsSUM(amount)grouped by kind[]Automated:
cd indexer && cargo test; optionalYIELDOMEGA_PG_TEST_URL=...integration.Test plan — attack / abuse vectors
Buy.doub_paidON CONFLICT DO NOTHINGpaid_with_cred=trueVerification criteria
cargo testgreen; integration_stage2 funding section passes on CI Postgres when enabled.GET /v1/arena/vault-funding/by-tx/...→ 40/30/30 visible.cast logson test tx matches DB row count and amounts.docs/indexer/design.mdwith anchor for manual QA.Out of scope
idx_arena_buy— buy row remains primary participant record.marked as related to #262
marked as related to #261
marked as related to #238
mentioned in commit
a187b9fe64mentioned in commit
02f557c540Implementation complete (merged to
main@02f557c)Indexer now ingests per-buy DOUB prize routing from registry
PodiumVaults/AdminSellVaultlogs:kindPodiumFundedpodium_activeSeedFundedpodium_seedAdminVaultFundedadminShipped
idx_arena_vault_funding(+ reorg rollback)ON CONFLICT (tx_hash, log_index) DO NOTHING)GET /v1/arena/vault-funding/recent,…/by-tx/{tx_hash},…/totalsintegration_stage2.rs(api_vault_funding_smoke)INV-INDEXER-267-VAULT-FUNDING+ cross-links in design.md, arena-v2.md, fee-routing doc, play skillVerification checklist
cd indexer && cargo clippy --all-targets -- -D warnings && cargo testgreenYIELDOMEGA_PG_TEST_URL=… cargo test --test integration_stage2— 9 funding rows per 1000 DOUB buy tx; CRED buy tx has 0 funding rowsGET /v1/arena/vault-funding/by-tx/0x…after Anvil DOUB buy shows 40/30/30 breakdown (9 lines)GET /v1/arena/vault-funding/totalssums match SQL onidx_arena_vault_fundingrollback_afterin integration test)GET /v1/arena/podium-pool-donationsunchanged (#262)bash scripts/check-doc-anchors.shpasses@brouie — please verify on dev/staging when convenient; leaving this issue open until sign-off.
/cc @brouie
mentioned in commit
a5c05615bamentioned in commit
c40afd047dQA verification complete (@
a5c0561onmain)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
cd indexer && cargo clippy --all-targets -- -D warnings && cargo testintegration_stage2(api_vault_funding_smoke, reorg rollback clearsidx_arena_vault_funding)PodiumFunded/SeedFunded/AdminVaultFundedGET /v1/arena/vault-funding/by-tx/{hash}doub_paidGET /v1/arena/vault-funding/totalsSUMby kindcast receiptlog count vs DBGET /v1/arena/podium-pool-donations(#262)bash scripts/check-doc-anchors.shbash 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 receiptreconciliationdocs/testing/manual-qa-checklists.mdindexer/README.md,docs/indexer/design.md, invariants table,skills/play-time-arena-doub/SKILL.mdChecklist for follow-up verification
bash scripts/verify-vault-funding-anvil.shon CI/dev Postgres hostGET /v1/arena/vault-funding/by-tx/0x…shows 40/30/30 breakdowntopUpPodiumPoolstxs appear only inpodium-pool-donations, not vault-fundingClosing — all acceptance criteria from the issue body and implementation comment checklist pass.
mentioned in issue #262
mentioned in issue #300