Skip to content

feat(ingest): EVM deposit detection via ERC-20 Transfer logs - #235

Open
Malik6828 wants to merge 1 commit into
Octo-Protocol-org:mainfrom
Malik6828:feat/evm-ingest-worker
Open

feat(ingest): EVM deposit detection via ERC-20 Transfer logs#235
Malik6828 wants to merge 1 commit into
Octo-Protocol-org:mainfrom
Malik6828:feat/evm-ingest-worker

Conversation

@Malik6828

Copy link
Copy Markdown

Scans eth_getLogs for registered token contracts with a block-number cursor, advancing only after durable processing so a crash resumes exactly-once, the same guarantee the Horizon path gives.

Logs are matched on the emitting contract address, not topics alone: any contract can emit a Transfer event with arbitrary topics, so topic-only attribution would let an attacker mint balances for free. This is the primary security invariant in this module.

Deposits are recorded as 'unconfirmed'; crediting is gated on #222. Merging #221 before #222 cannot create spendable balances, enforced at the DB level, not by convention.

Changes:

  • crates/ingest/src/evm.rs: EvmIngestor (process_log, poll_once, run), EvmRpcClient (eth_blockNumber, eth_getLogs), EvmLog decoding, RegisteredToken registry, adaptive range bisection on RangeTooLarge.
  • crates/store/migrations/0021_evm_ingest.sql: chain_id + block_number on ingest_cursor; chain_id + evm_log_index on transactions; uq_tx_evm_onchain dedup index; 'unconfirmed' status value.
  • crates/store/src/lib.rs: get_evm_cursor, set_evm_cursor, mark_evm_polled, record_evm_deposit, evm_address_by_hex, NewEvmDeposit struct.
  • crates/ingest/tests/evm_ingest_tests.rs: 10 integration tests covering happy path, adversarial fake Transfer (critical security), idempotency/replay, crash-resume cursor, quarantine of unregistered tokens, range bisection, removed (reorged) logs, non-deposit address filtering, and unconfirmed-status invariant.
  • docs/ingest-integration.md: EVM section documenting native ETH scope decision, contract address verification, cursor contract, unconfirmed status, adaptive bisection, schema changes, and tests.

All 34 unit tests + 10 EVM integration tests pass; full workspace builds cleanly with no regressions.

Refs #221

Summary

Related step / issue

Checklist

  • cargo fmt --all -- --check passes
  • cargo clippy --workspace --all-targets -- -D warnings passes
  • cargo test --workspace passes
  • No secrets (seeds/keys) logged or persisted in plaintext
  • Added/updated tests (test vectors for crypto/derivation changes)
  • Updated docs / CHANGELOG if behavior changed

How to test

Closes

closes #221

Scans eth_getLogs for registered token contracts with a block-number
cursor, advancing only after durable processing so a crash resumes
exactly-once — the same guarantee the Horizon path gives.

Logs are matched on the emitting contract address, not topics alone:
any contract can emit a Transfer event with arbitrary topics, so
topic-only attribution would let an attacker mint balances for free.
This is the primary security invariant in this module.

Deposits are recorded as 'unconfirmed'; crediting is gated on Octo-Protocol-org#222.
Merging Octo-Protocol-org#221 before Octo-Protocol-org#222 cannot create spendable balances — enforced
at the DB level, not by convention.

Changes:
- crates/ingest/src/evm.rs: EvmIngestor (process_log, poll_once, run),
  EvmRpcClient (eth_blockNumber, eth_getLogs), EvmLog decoding,
  RegisteredToken registry, adaptive range bisection on RangeTooLarge.
- crates/store/migrations/0021_evm_ingest.sql: chain_id + block_number
  on ingest_cursor; chain_id + evm_log_index on transactions;
  uq_tx_evm_onchain dedup index; 'unconfirmed' status value.
- crates/store/src/lib.rs: get_evm_cursor, set_evm_cursor,
  mark_evm_polled, record_evm_deposit, evm_address_by_hex,
  NewEvmDeposit struct.
- crates/ingest/tests/evm_ingest_tests.rs: 10 integration tests
  covering happy path, adversarial fake Transfer (critical security),
  idempotency/replay, crash-resume cursor, quarantine of unregistered
  tokens, range bisection, removed (reorged) logs, non-deposit
  address filtering, and unconfirmed-status invariant.
- docs/ingest-integration.md: EVM section documenting native ETH
  scope decision, contract address verification, cursor contract,
  unconfirmed status, adaptive bisection, schema changes, and tests.

All 34 unit tests + 10 EVM integration tests pass; full workspace
builds cleanly with no regressions.

Refs Octo-Protocol-org#221
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ingest): EVM ingest worker — ERC-20 Transfer log scanning

1 participant