PR: #34 (feat/09-health-scanner)
File: crates/charon-scanner/src/scanner.rs — HealthScanner impl block
Problem: PRD review focus item 7 — borrowers that fully repay must be removed from all buckets; otherwise stale entries accumulate.
PR provides upsert(), bucket_counts(), liquidatable(), near_liquidation() but no remove() or prune(). Once borrower inserted, stays in DashMap for process lifetime regardless of repayment.
Two failure modes:
- Borrower repays debt. Position no longer returned by
get_positions(). Stale entry remains in DashMap as Liquidatable. Every call to liquidatable() returns that position. Flash-loan router attempts liquidation, on-chain call reverts (no debt to liquidate), gas wasted and profitable bundle reverted.
- On BSC mainnet with thousands of Venus borrowers over multi-day run, DashMap grows unbounded. Combined with sentinel HF issue,
liquidatable() Vec grows monotonically.
Fix: Add remove(address: Address) and prune(current_positions: &[Position]). prune() diffs current fetched set against DashMap keys, removes any address not present in latest snapshot. Call inside block loop before upsert().
PR: #34 (feat/09-health-scanner)
File: crates/charon-scanner/src/scanner.rs — HealthScanner impl block
Problem: PRD review focus item 7 — borrowers that fully repay must be removed from all buckets; otherwise stale entries accumulate.
PR provides
upsert(),bucket_counts(),liquidatable(),near_liquidation()but noremove()orprune(). Once borrower inserted, stays in DashMap for process lifetime regardless of repayment.Two failure modes:
get_positions(). Stale entry remains in DashMap as Liquidatable. Every call toliquidatable()returns that position. Flash-loan router attempts liquidation, on-chain call reverts (no debt to liquidate), gas wasted and profitable bundle reverted.liquidatable()Vec grows monotonically.Fix: Add
remove(address: Address)andprune(current_positions: &[Position]).prune()diffs current fetched set against DashMap keys, removes any address not present in latest snapshot. Call inside block loop beforeupsert().