Skip to content

chore(metrics): drop_reason::LIQUIDATOR_NOT_DEPLOYED + Grafana panel (closes #402)#408

Merged
obchain merged 1 commit intomainfrom
chore/402-drop-reason-liquidator-not-deployed
May 2, 2026
Merged

chore(metrics): drop_reason::LIQUIDATOR_NOT_DEPLOYED + Grafana panel (closes #402)#408
obchain merged 1 commit intomainfrom
chore/402-drop-reason-liquidator-not-deployed

Conversation

@obchain
Copy link
Copy Markdown
Owner

@obchain obchain commented May 2, 2026

Summary

  • Constant drop_reason::LIQUIDATOR_NOT_DEPLOYED = "liquidator_not_deployed" plus stable-name pin + typed-helper round trip.
  • process_opportunity probes eth_getCode at the liquidator address before the simulation gate. Empty bytecode → drop with the new reason and return early; non-empty → fall through to encode_and_simulate (Err arm now genuinely means logic-revert).
  • Why upstream: geth/anvil reply to eth_call against no-code with Ok(0x), so a missing contract would otherwise pass the gate, queue, and only surface as submit_failed at broadcast — generic and indistinguishable from a real revert.
  • New Grafana panel "Executor — drops by reason" using charon_opportunities_dropped_total{reason} (distinct metric name from the stage-labelled charon_executor_opportunities_dropped_total).

Test plan

  • cargo test -p charon-metrics --lib — 5/5 pass (extended opportunities_drop_reason_names_are_stable + typed_helpers_are_panic_free).
  • cargo build -p charon-cli clean.

Closes

#402

Follow-up

File a separate issue for broadcast_opportunity to re-probe eth_getCode on submit_failed and relabel as liquidator_not_deployed when the address has gone empty between gate and broadcast (covers the narrow window where a self-destruct lands between the upstream probe and broadcast).

@obchain obchain force-pushed the chore/402-drop-reason-liquidator-not-deployed branch from 86fe0f4 to e1d4da3 Compare May 2, 2026 20:29
…loses #402)

A misconfigured fork or a runtime self-destruct on the deployed
CharonLiquidator surfaced as a generic submit_failed (broadcast-stage
estimateGas revert), leaving operators unable to distinguish "the
liquidation logic reverted" from "no code at the configured address".

Mechanism:
- New constant drop_reason::LIQUIDATOR_NOT_DEPLOYED. Stable-name pin
  + typed-helper round-trip extended.
- process_opportunity probes eth_getCode at the liquidator address
  upstream of encode_and_simulate. If empty, label drop
  liquidator_not_deployed and return early. Why upstream: geth/anvil
  reply to eth_call against a no-code address with Ok(0x), so a
  missing contract would otherwise pass the gate and queue. Reviewer
  caught the unreachable-branch regression in v1.
- Cost: one eth_getCode per actionable opportunity (subset of
  liquidatable bucket). ~10/min on busy mainnet, well within budget.
- New Grafana panel "Executor — drops by reason" using the reason
  metric (charon_opportunities_dropped_total, distinct from the
  stage-labelled charon_executor_opportunities_dropped_total).
@obchain obchain force-pushed the chore/402-drop-reason-liquidator-not-deployed branch from e1d4da3 to d99d275 Compare May 2, 2026 20:33
@obchain obchain merged commit 1218847 into main May 2, 2026
6 checks passed
@obchain obchain deleted the chore/402-drop-reason-liquidator-not-deployed branch May 2, 2026 20:39
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.

1 participant