Chainlink deviation alert
Template: chainlink-deviation-alert ยท category: monitoring ยท risk: monitor_only
Compares two Chainlink price feeds on a schedule and pages when they disagree by more than a basis-point threshold โ a primary oracle vs a fallback, or two oracles for the same asset. A disagreement is the signal a feed has frozen, been manipulated, or a fallback is drifting.
When to use it
- cross-check the oracle your protocol relies on against a second source
- catch a stuck/laggy feed before it prices a liquidation wrong
- watch a fallback oracle drift away from the primary
Generate it
rflow new --template chainlink-deviation-alert
# or add the workflow to an existing project
rflow add workflow chainlink-deviation-alertNon-interactive (CI/agents):
rflow new --template chainlink-deviation-alert --yes --output ./deviation \
--answer deviation_bps=50Inputs
| key | type | default |
|---|---|---|
project_name | string | chainlink-deviation-alert |
network / chain_id / rpc_env / rpc_url | network / chain_id / env_var / string | ethereum / 1 / ETH_RPC / a public RPC |
feed_a_name / feed_a_address | contract / address | FeedA / zero placeholder (replace!) |
feed_b_name / feed_b_address | contract / address | FeedB / zero placeholder (replace!) |
feed_decimals | int | 8 |
deviation_bps | int | 50 |
poll_cron | cron | */5 * * * * |
channel | string | ops |
Deviation is |a - b| * 10000 / min(a, b) basis points (100 bps = 1%),
computed with mul_div in full precision. Both feeds must be positive and
share the same decimals (true for same-asset USD feeds, which are 8).
Required env vars
DATABASE_URL, the RPC env var (default ETH_RPC), TG_BOT_TOKEN,
TG_CHAT_ID โ all listed in the generated .env.example.
Safety notes
Monitor-only: no signer: and no relayers:, so the relayer engine never
boots. The trigger is a cron, so a persistent gap re-alerts every tick โ
widen poll_cron or add a dedupe list if that is too chatty (a two-feed
comparison can't use the read trigger's edge-triggered mode). The workflow
ends in on_failure: dead_letter.
Run it locally
docker compose up -d # postgres on localhost:5448
# fill .env, set both feed addresses
rflow validate
rflow startCommon modifications
- tighten
deviation_bpsto page on smaller disagreements - compare a Chainlink feed against a DEX TWAP by swapping one contract
- widen
poll_cronto cut RPC load