Skip to content

feat: smart contract event monitoring system#576

Open
zp6 wants to merge 3 commits into
Spectral-Finance:mainfrom
zp6:feature/event-monitoring-75
Open

feat: smart contract event monitoring system#576
zp6 wants to merge 3 commits into
Spectral-Finance:mainfrom
zp6:feature/event-monitoring-75

Conversation

@zp6
Copy link
Copy Markdown

@zp6 zp6 commented May 14, 2026

Closes #75

Smart Contract Event Monitoring System

Modules

  • EventMonitor - Main supervisor, multi-chain support (Ethereum, Polygon, BSC, Arbitrum)
  • Subscriber - Contract event subscriptions with filtering, resume from block number
  • Decoder - ABI-based log decoding, auto-detects ERC-20/721/1155 standard events
  • Storage - Persistent event storage with query interface (ETS/Postgres)
  • Alerts - Rule-based event alerting (Discord, Telegram, webhooks)

Stats

  • 7 files, 2,507 lines
  • 16K+ test suite
  • Follows existing Lux conventions (moduledoc, @SPEC, {:ok, result} | {:error, reason})
  • Uses existing deps (Req, Jason) - no new dependencies

GitHub: @zp6

zp6 added 2 commits May 14, 2026 12:54
Implements comprehensive gas optimization toolkit for EVM chains:

- GasOptimizer: Real-time gas price monitoring (EIP-1559 + legacy)
  with multi-chain support (Ethereum, Polygon, BSC, Arbitrum)
- Estimator: Gas limit estimation with historical tracking,
  safety margins, and anomaly detection
- Batcher: Transaction batching for ERC-20 transfers with
  gas savings estimation (up to 60% for 10+ transfers)
- Predictor: Gas price prediction using linear regression,
  trend analysis, and low-traffic period detection

Includes unit tests and documentation guide.

Refs Spectral-Finance#76
- EventMonitor: real-time event tracking for EVM chains
- Subscriber: contract event subscriptions with filtering and resume
- Decoder: ABI-based log decoding with ERC-20/721/1155 auto-detection
- Storage: persistent event storage with query interface
- Alerts: rule-based event alerting (Discord, Telegram, webhooks)
- Multi-chain support: Ethereum, Polygon, BSC, Arbitrum
- 16K+ test suite covering all modules
@MyTH-zyxeon
Copy link
Copy Markdown

Review-assist note for the $1,500 Smart Contract Event Monitoring System bounty (#75). This PR has a lot of useful structure, but a few acceptance criteria still look unproven from the diff:

  1. The subscriber poll path does not appear to call an RPC log source yet. poll_subscription/1 emits telemetry for a future eth_getLogs integration, so the PR may not yet satisfy real-time monitoring, historical sync from from_block, or actual event ingestion.

  2. The docs mention persistent storage, but Storage is still in-memory only. Either wire persistence_enabled / persistence_path into load/save behavior or narrow the docs until persistence and replay are implemented/tested.

  3. Alerts can call Discord/Telegram webhooks, but the tests only assert rule matching. A mocked Req.post / notifier adapter test would make the webhook acceptance criterion much easier for maintainers to verify without real credentials.

  4. The PR also adds a separate gas optimization subsystem. If that is meant for another bounty (Gas Optimization and Transaction Management $1,250 #76), it may be safer to split it out so Smart Contract Event Monitoring System $1,500 #75 can be reviewed against the event-monitoring criteria alone.

Suggested acceptance test slice: fake an RPC response with two logs across a block range, assert subscription polling decodes and stores both logs, advances last_block, rejects a duplicate log by {transaction_hash, log_index}, and triggers a mocked webhook alert for a matching rule.

@MyTH-zyxeon
Copy link
Copy Markdown

Follow-up review-assist pass for the $1,500 Smart Contract Event Monitoring System bounty (#75), focused on decoder/storage correctness after the earlier RPC/persistence/webhook/scope note.

The current shape still looks promising, but these details seem worth tightening before maintainers try to verify the acceptance criteria:

  1. The built-in ERC-20 Approval(address,address,uint256) topic appears incorrect in Decoder.@standard_events. The PR has:
    0x8c5be1e5ebec7d5fc14b5c74a56c5e62c6b4e4d1a5c7e5c5c5c5c5c5c5c5c5c
    but the canonical event topic is:
    0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
    As written, standard ERC-20 approvals may classify as unknown and skip the dedicated decoder path.

  2. The custom ABI path is effectively unreachable because compute_event_topic(_sig), do: nil, so find_custom_event/2 cannot match a real topic hash. Since the docs advertise custom ABI log decoding, this needs either a real Keccak event-topic implementation or narrower docs/tests.

  3. Generic ABI decoding calls String.to_atom(input["name"]) for externally supplied ABI field names. Contract ABIs are not a bounded atom source, so this can leak atoms over time. Returning string-keyed params, or using a fixed conversion boundary, would be safer.

  4. Storage.store_event/2 deduplicates only by {transaction_hash, log_index}. For a multi-chain monitor, the same tx hash/log index tuple can appear on different chains, so the dedupe key should include chain_id or chain to avoid dropping valid cross-chain events.

  5. from_block: "latest" currently resolves to 0. Once RPC polling is wired, that can turn a "latest" subscription into a full historical scan. It would be clearer to query the current chain head for "latest" or rename the behavior to an explicit genesis/default scan.

Suggested focused verification slice: add fixtures for canonical ERC-20 Approval, a custom ABI event with a computed topic, and two events with the same {transaction_hash, log_index} on different chain_ids. Those tests would make the decoder/storage acceptance story much easier to trust.

@MyTH-zyxeon
Copy link
Copy Markdown

Follow-up2 review assist for the $1,500 Smart Contract Event Monitoring System bounty (#75 / #576), after rechecking f5dc617b1f6e1770b603351539fa2e9605400e8c. I do not see a newer commit after the previous decoder/storage pass, so this is a separate acceptance-risk checklist:

  1. Alert conditions only match atom operators. create_rule/1 accepts both atom-keyed and string-keyed maps, but compare/3 only has clauses for :eq, :gt, :gte, etc. A rule coming from JSON/config/UI as %{"operator" => "gt"} will keep the string "gt" and never trigger. Normalizing operators on rule creation, or supporting string operators in compare/3, would make the public API safer.

  2. Subscriber event processing does not call the alert engine. process_event/2 stores the event, calls the optional callback, and emits telemetry, but it never invokes Lux.Web3.EventMonitor.Alerts.process_event/1. That means the advertised "event monitoring + configurable alerts" path still requires an external caller to glue storage and alerts together. A unit test where a matching rule fires from a subscriber-delivered event would cover the integration.

  3. The guide examples use Storage.query(contract: ..., event: ...), while Storage.query_events/2 only filters :contract_address and :event_name. Those examples will return unfiltered results, which is a subtle failure mode for anyone verifying the bounty from the docs. Either accept aliases or update the guide/tests to use the actual query keys.

  4. Subscriber.subscribe/1 can crash on missing or malformed contract_address. It validates the chain, but then calls normalize_address(contract_address) with no nil/type/address validation. A bad request should return {:error, :invalid_contract_address} rather than taking down the GenServer call path.

These are smaller than the RPC/persistence gaps already noted, but they are important for maintainer verification: alerts need to fire from subscribed events, and the documented public API should not silently no-op or crash on common input shapes.

…ectral-Finance#576)

Round 1 fixes:
- Subscriber: implement real eth_getLogs RPC polling instead of telemetry-only placeholder
- Storage: migrate from Agent to ETS-based persistent storage with disk persistence
- Webhook: new module with HTTP POST delivery, retry, signature, dead letter queue

Round 2 fixes:
- Decoder: correct ERC-20 Approval event topic hash to keccak256('Approval(address,address,uint256)')
- Storage: full ETS backend with persist/load, subscriber config storage for crash recovery
- Webhook: exponential backoff retry, HMAC-SHA256 signature headers, dead letter queue

Round 3 fixes:
- Alerts: handle string operator keys from JSON/config (normalize to atoms before matching)
- Event replay from block range via Subscriber.replay/2 with eth_getLogs
- Subscription crash recovery via persisted state (load on init, save on terminate)
@zp6 zp6 force-pushed the feature/event-monitoring-75 branch from 56df24c to 82e9157 Compare June 6, 2026 03:22
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.

Smart Contract Event Monitoring System $1,500

2 participants