[#138] Finding 1: Indexer — decode PodiumResidualRecipientSet, EthRescued, Erc20Rescued + persist/reorg #139
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#139
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?
Parent: Split from #138 — Pre-deploy review pass 2 (Finding 1).
Severity: Medium
Problem
Three audit-batch contract events are emitted onchain but never decoded by the indexer. They fall through to
DecodedEvent::Unknownand are not persisted, so there is no Postgres audit trail for ops/compliance dashboards.TimeCurve.PodiumResidualRecipientSet(address indexed recipient)—contracts/src/TimeCurve.sol(event near M-01 residual routing).TimeCurveBuyRouter.EthRescued(address indexed to, uint256 amount)—contracts/src/TimeCurveBuyRouter.sol.TimeCurveBuyRouter.Erc20Rescued(address indexed token, address indexed to, uint256 amount)— same file. Note: casing isErc20Rescued(lowercasec20); this is a different topic0 fromFeeRouter.ERC20Rescued— only the FeeRouter variant may already decode.Without rows,
reorg.rsrollback_aftercannot purge these (no tables), and owner changes to the residual sink mid-sale or post-end are invisible offchain.References
contracts/src/TimeCurve.sol(PodiumResidualRecipientSet)contracts/src/TimeCurveBuyRouter.sol(EthRescued,Erc20Rescued)indexer/src/decoder.rsindexer/src/persist.rsindexer/src/reorg.rsdocs/indexer/design.mddocs/testing/invariants-and-business-logic.md§ INV-INDEXER-112 / GitLab #112 — emitted events must decode +idx_*+ rollback.cursor/skills/yieldomega-guardrails/SKILL.md(indexer is derived read-model; event coverage for ops)Recommended fix
sol!event definitions for all three (verify exact ABI names/topics vs Solidity).decode_rpc_logwith matching arms.idx_*tables withblock_number,tx_hash,log_index, indexed fields (recipient,to,amount,tokenas appropriate).persist_decoded_logwith INSERT branches.rollback_afterdeletion set inreorg.rs.postgres_stage2_persist_all_events_and_rollback_afterincludes these variants (see existing pattern inindexer/tests/integration_stage2.rs— adjust path if repo differs).Acceptance criteria
reorg.rs).INV-INDEXER-112matrix in docs updated if there is an explicit checklist row for new events.rollback_afterfor the new variants.Verification checklist
cargo testinindexer/including integration tests withYIELDOMEGA_PG_TEST_URLif applicable.setPodiumResidualRecipient/ routerrescueETH/rescueERC20and confirm API or raw SQL shows rows.topic0hex in decoder matchescast sig-event "..."output for each event.rollback_afterfor new table names.ERC20Rescued— distinct variants.mentioned in issue #145
mentioned in issue #138
mentioned in commit
1c92aae5f1mentioned in commit
15fc07617bShip summary (merged to
main)Indexer support for GitLab #139 is on
main(fast-forward includes merge838a2c1and implementation1c92aae).What landed
TimeCurve.PodiumResidualRecipientSetTimeCurveBuyRouter.EthRescued/Erc20Rescuedindexer/migrations/20260504211000_gl139_residual_router_rescue_events.{up,down}.sql— dedicatedidx_*tables + indexes.decoder.rs,persist.rs,reorg.rs; Postgres integration extended inindexer/tests/integration_stage2.rs.INV-INDEXER-139indocs/testing/invariants-and-business-logic.md,docs/indexer/design.md, contributor cross-links inskills/README.mdand guardrails where applicable.How to verify (evaluation criteria)
decoder.rs—roundtrip_podium_residual_recipient_set,roundtrip_buy_router_eth_rescued,roundtrip_buy_router_erc20_rescued,roundtrip_gl139_audit_events_topic0_matches_cast; ensure topic0 matchescast sig/ deployed ABI (not confused with FeeRouterERC20Rescued).INV-INDEXER-146);reorg.rsclears GL139 tables on configured rollback depth.YIELDOMEGA_PG_TEST_URL,cargo test -p yieldomega_indexerrunsintegration_stage2— GL139 events covered alongside existing stage2 matrix and #146 all-or-nothing block test.If anything fails, capture failing test name + migration version + sample
tx_hash/ log index for repro.@PlasticDigits — verification PASS on
838a2c1/1c92aae. walked your checklist:20260504211000_gl139_residual_router_rescue_events.{up,down}.sql— three tables (idx_timecurve_podium_residual_recipient_set,idx_timecurve_buy_router_eth_rescued,idx_timecurve_buy_router_erc20_rescued) with block_number/tx_hash/log_index plus indexed fields per design doc.cargo test roundtripgreen, 18/18 PASS. #139 tests specifically:roundtrip_podium_residual_recipient_set✓roundtrip_buy_router_eth_rescued✓roundtrip_buy_router_erc20_rescued_distinct_from_fee_router✓ (the casing-collision concern explicitly tested — distinct topic0 from FeeRouterERC20Rescued)roundtrip_gl139_audit_events_topic0_matches_cast✓PodiumResidualRecipientSetonTimeCurveEvents, L156-161EthRescued/Erc20RescuedonTimeCurveBuyRouterEvents(3-arg vs FeeRouter's 4-arg, distinct signatures). decode dispatch at L946-988, variants at L349-358 + L458-461. persist handlers at persist.rs L1083-1148 withON CONFLICT (tx_hash, log_index) DO NOTHING. reorg.rs L151/153/161 includes all three tables in rollback list — atomic with rest of indexer per #140.integration_stage2.rsL707-719 + L922-937 covers persistence + rollback alongside the rest of the stage2 matrix.INV-INDEXER-139row ininvariants-and-business-logic.md,docs/indexer/design.mddesign doc reads cleanly. cross-links inskills/README.md+ guardrails.prod check item skipped — no live tx range yet on a deployed chain. logic verified end-to-end via roundtrip + integration tests.
ready for close on your side.
mentioned in issue #149