Skip to content

feat(scanner): 3-bucket DashMap health-factor scanner#34

Merged
obchain merged 3 commits intomainfrom
feat/09-health-scanner
Apr 24, 2026
Merged

feat(scanner): 3-bucket DashMap health-factor scanner#34
obchain merged 3 commits intomainfrom
feat/09-health-scanner

Conversation

@obchain
Copy link
Copy Markdown
Owner

@obchain obchain commented Apr 21, 2026

Closes #10

Classifies Position records into healthy / near-liquidation / liquidatable buckets based on health_factor, backed by a lock-free DashMap keyed by borrower. Unblocks the profit calculator and flash-loan router with a proper "what's currently liquidatable" query.

  • HealthScanner::new(liquidatable, near_liq) — validates and scales float thresholds once to 1e18-fixed U256; per-tick comparisons stay in integer arithmetic
  • upsert, classify, bucket_counts, liquidatable, near_liquidation — surface consumed by downstream stages
  • New liquidatable_threshold / near_liq_threshold on BotConfig with sane defaults (1.0 / 1.05) via serde default
  • dashmap 6 added as workspace dep
  • CLI listen pipes Venus scans through the scanner and emits per-block bucket counts alongside existing fields

Five unit tests cover boundary classification, bucket transitions, threshold validation (NaN / inverted).

Depends on #9 (feat/08-venus-adapter).

Classifies `Position` records into healthy / near-liquidation /
liquidatable buckets based on `health_factor`, backed by a lock-free
DashMap keyed by borrower address. Unblocks the profit calculator and
flash-loan router (Day 3 work) with a proper "what's currently
liquidatable" query.

- `HealthScanner::new(liquidatable, near_liq)` validates and scales
  float thresholds once to 1e18-fixed U256; per-tick comparisons stay
  in integer arithmetic
- `upsert`, `classify`, `bucket_counts`, `liquidatable`,
  `near_liquidation` — the surface downstream stages consume
- New `liquidatable_threshold` / `near_liq_threshold` fields on
  `BotConfig` with sane defaults (1.0 / 1.05) via serde `default`, so
  the existing config keeps loading cleanly
- `dashmap 6` added as a workspace dep
- CLI `listen` now pipes Venus scans through the scanner and emits
  per-block bucket counts alongside the existing fields
- Five unit tests cover boundary classification, bucket transitions on
  upsert, and threshold validation (NaN / inverted)
…metrics

- BotConfig drops the f64 liquidatable_threshold / near_liq_threshold in
  favour of integer basis-point fields (10_000 = 1.0e18). bps_to_1e18()
  uses integer arithmetic only; 10_500 bps -> exactly 1.05e18 rather
  than the ULP-short 1_049_999_999_999_999_872 the old f64_to_1e18()
  produced.
- Add hot_scan_blocks / warm_scan_blocks / cold_scan_blocks to BotConfig
  (defaults 1 / 10 / 100). ScanScheduler in charon-scanner consumes them
  and answers should_scan(bucket, block) so COLD positions stop burning
  RPC every block. main.rs now scans only the union of buckets whose
  cadence fires on the current block.
- HealthScanner tracks per-borrower bucket transitions inside upsert()
  and emits charon_scanner_transitions_total{from,to}. bucket_counts()
  feeds gauge charon_scanner_borrowers_in_bucket{bucket}. The CLI's
  scan loop records charon_scanner_scan_duration_seconds histogram per
  block. Grafana dashboards now have signals instead of log scraping.
- HealthScanner::remove(addr) and HealthScanner::prune(current) so
  borrowers that fully repay stop lingering as stale Liquidatable
  entries after adapter.fetch_positions stops returning them. prune() is
  invoked by main.rs every block after upsert.
- warn_if_binary_sentinel() emits a loud warning if every observed HF
  is 0 or 2e18, making the (ties to #98) binary-HF dependency visible
  at runtime instead of silently dead-coding the NearLiquidation bucket.
- HealthScanner::borrowers_in_bucket(b) exposed so the scheduler knows
  which addresses to refetch for each cadence.

Closes #103 #104 #105 #106 #107
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	crates/charon-cli/Cargo.toml
#	crates/charon-cli/src/main.rs
#	crates/charon-scanner/Cargo.toml
#	crates/charon-scanner/src/lib.rs
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.

[scanner] Health-factor scanner: 3-bucket DashMap classification (healthy / near-liq / liquidatable)

1 participant