Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Large approval alert

Template: community/large-approval-alert ยท category: security ยท risk: monitor_only ยท community

Watches Approval events on an ERC20 token and notifies a telegram channel when an approval crosses a threshold. An outsized approval is the classic prelude to a drain. No signer, no relayer, no transactions.

This is the seed COMMUNITY template: it lives under templates/community/ in the rflow repo (not in the binary) and is fetched SHA-pinned and hash-verified at install time. The install prints a provenance banner (registry, commit, risk) and runs the full community gate before anything renders.

When to use it

  • watch a treasury or hot wallet for approvals it should never grant
  • catch a phishing-signed approve before the drain transaction lands
  • as a template for your own first community submission (see templates/community/SUBMITTING.md in the repo)

Generate it

# a full project (fetched from the registry, hash-verified, then gated)
rflow new --template community/large-approval-alert
 
# or add the workflow to an existing project
rflow add workflow community/large-approval-alert
 
# browse the community index first
rflow templates ls --community

Non-interactive (CI/agents):

rflow new --template community/large-approval-alert --yes --output ./approvals \
  --answer network=ethereum --answer min_amount=500000

Inputs

keytypedefault
project_namestringlarge-approval-alert
network / chain_id / rpc_env / rpc_urlnetwork / chain_id / env_var / stringethereum / 1 / ETH_RPC / a public RPC
token_name / token_address / token_decimalscontract / address / intUSDC mainnet
min_amounttoken_amount1000000
channelstringops
tg_bot_token_env / tg_chat_id_envenv_varTG_BOT_TOKEN / TG_CHAT_ID

The declared interface

The package ships NO ABI blob. Its manifest declares the surface it uses:

# recipe: partial
interfaces:
  token:
    abi:
      wellknown: erc20
    events:
      - "Approval(address,address,uint256)"

The install materializes abis/token.json from the curated builtin ERC20 standard and verifies the declared Approval topic0 against it.

The generated workflow

# recipe: partial
rflow_version: 1
name: large-approval-alert
 
config:
  port: 3940
  db_connection: ${DATABASE_URL}
 
networks:
  - name: ethereum
    chain_id: 1
    rpc: ${ETH_RPC}
 
contracts:
  # abis/token.json is materialized from the builtin ERC20 at install time
  USDC:
    abi: ./abis/token.json
    addresses:
      ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
 
notifications:
  channels:
    ops:
      telegram:
        bot_token: ${TG_BOT_TOKEN}
        chat_id: ${TG_CHAT_ID}
 
workflows: 
  large-approval-alert: 
    trigger: 
      event: 
        contract: USDC
        name: Approval
        network: ethereum
        where: "${{ trigger.args.value > wei('1000000', 6) }}"
        confirmations: 0
        start_block: latest
        end_block: live
    steps: 
      - id: alert
        notify: 
          channel: ops
          message: "large approval: ${{ trigger.args.owner }} approved ${{ format_units(trigger.args.value, 6) }} USDC to ${{ trigger.args.spender }} in ${{ trigger.tx_hash }}"
    on_failure: dead_letter

Required env vars

DATABASE_URL, the RPC env var (default ETH_RPC), and the telegram credentials (default TG_BOT_TOKEN / TG_CHAT_ID), all listed in the generated .env.example.

Safety notes

Monitor-only: the generated config declares no signer: and no relayers:, so the relayer engine never boots. The install records the registry, commit and per-file sha256s in .rflow/template-lock.yaml, and the workflow ends in on_failure: dead_letter so a failed notification is journaled, never lost.

Run it locally

docker compose up -d     # postgres on localhost:5448
# fill .env (RPC + telegram credentials)
rflow validate
rflow start

Common modifications

  • raise confirmations: on the trigger to trade latency for reorg safety
  • filter to approvals FROM your own wallets with a tighter where: clause
  • swap the channel for slack/discord/pagerduty: rflow add notification
  • pair it with the large transfer alert on the same token