fix(keeper): require USE_HELIUS_SENDER=true on mainnet - #364
Conversation
isMainnetSender() in keeper-send.ts is a literal `USE_HELIUS_SENDER === "true"` check with no NETWORK-based default. When unset or any non-"true" value, the keeper silently falls back to plain sendRawTransaction broadcast (skipPreflight, no Jito bundle) to public RPCs, exposing the liquidation target pubkey and close size to any RPC operator or mempool listener before confirmation -- enabling front-running/sandwiching or outright liquidation-sniping (a third party copying the observed instruction with their own fee payer). .env.example documents USE_HELIUS_SENDER=true as the mainnet default, but nothing enforced it -- a deployment built from a partial env degraded silently with zero boot-time signal, unlike every other mainnet-critical setting in env-guards.ts (DISCORD_ALERT_WEBHOOK, KEEPER_REDIS_URL, RPC URL scheme/host guards). This mirrors that existing fail-loud-on-mainnet pattern. BUG-101 from a clean-room Phase 4 audit pass.
|
Warning Review limit reached
More reviews will be available in 33 minutes and 32 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
isMainnetSender()insrc/lib/keeper-send.tsis a literalUSE_HELIUS_SENDER === "true"check with noNETWORK-based default:When
USE_HELIUS_SENDERis unset or any non-"true"value, the keeper silently falls back to plainsendRawTransactionbroadcast (skipPreflight: true, no Jito bundle) to public RPCs. This exposes the liquidation target pubkey and close size to any RPC operator or mempool listener before confirmation — enabling front-running/sandwiching, or outright liquidation-sniping (a third party copying the observed instruction with their own fee payer to capture the liquidation incentive)..env.exampledocumentsUSE_HELIUS_SENDER=trueas the recommended mainnet default, but nothing in code enforces it. A deployment built from a partial/incomplete env (not copying that line, or built directly from Railway env vars without referencing.env.example) degrades silently with zero boot-time signal — unlike every other mainnet-critical setting already guarded inenv-guards.ts(DISCORD_ALERT_WEBHOOK,KEEPER_REDIS_URL/KEEPER_REDIS_TOKEN, RPC URL scheme/host checks).Production Impact
On mainnet, with
USE_HELIUS_SENDERunset (a plausible operator mistake given it's optional in code), every liquidation and crank transaction broadcasts to public RPCs pre-confirmation with no MEV protection. A searcher watching the keeper's known fee-payer pubkey can observe a pending liquidation instruction and either sandwich it or race a copy of it with a higher fee, stealing the liquidation reward. This is a silent degradation — the keeper runs and appears healthy with no indication that it's operating without its intended MEV protection.Fix
Add a boot-time guard in
validateKeeperEnvGuards()requiringUSE_HELIUS_SENDER=truewhenNETWORK=mainnet, mirroring the existingDISCORD_ALERT_WEBHOOK(H-7) fail-loud pattern. Off mainnet (devnet/local dev), the setting remains optional as before.Proof of Fix
New tests in
tests/env-guards.test.ts(BUG-101: USE_HELIUS_SENDER required on mainnet):"false"on mainnet"true"string on mainnet"true"on mainnetExisting mainnet-accepting test fixtures elsewhere in the file were updated to include
USE_HELIUS_SENDER: "true"so they continue to exercise the happy path correctly.Test Output
The one failure (
tests/v17-risk-params.poc.test.ts) is pre-existing and unrelated to this change — a stale assertion left over from commit8ee810d(#345), which changed production code to acceptmaintenanceMarginBps==10000but didn't update that older PoC test. Confirmed unrelated by file scope (no overlap withenv-guards.ts/keeper-send.ts).pnpm build— clean, zero errors.