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

ABIs — fetch, inspect & discover

Every contract in rflow.yaml points at a committed ABI json file (abi: ./abis/usdc.json). This page covers the CLI helpers that get those files onto disk and answer questions about them — fetching the verified ABI for an address, adding a contract by address alone, inspecting events and selectors, and reverse-mapping topic hashes.

rflow abi fetch — the verified ABI, by address

rflow abi fetch --network ethereum --address 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --name usdc
rflow abi fetch --chain-id 8453 --address 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913   # no project needed

Fetches the verified ABI for an address and writes it pretty-printed under the project's abis/ dir (default abis/<--name>.json, or abis/<address>.json; --out overrides). Source order:

  1. Sourcify first — keyless, no account needed.
  2. Etherscan v2 — the multichain API (https://api.etherscan.io/v2/api?chainid=…), which needs an ETHERSCAN_API_KEY env var. When the key is absent and Sourcify had no match, the error says exactly that, per source.

--network reads the chain id from rflow.yaml; --chain-id works with no project at all. --source sourcify|etherscan pins one source. Re-fetching an identical file is a no-op, but a file with different content is never clobbered — delete it or pass --out.

Honest limits: fetch needs outbound network access, only verified contracts resolve, and Sourcify coverage varies by chain — Etherscan (with a key) is the fallback for exactly that reason. For proxies, the explorer returns the ABI of the address you give it (often the proxy's own ABI) — fetch the implementation address when you want the logic events.

rflow contract add — a contract by address alone

rflow contract add USDC --network ethereum --address 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48

Fetch + wire-up in one step: the verified ABI is fetched (Sourcify → Etherscan), written to abis/usdc.json, and the contract is appended to contracts: through the same comment-preserving, merge-validating code path as rflow add contract. The command prints what was fetched, the file written, and the validate result.

With --abi <path> no network is touched — it is exactly rflow add contract.

rflow abi inspect — events, topics, selectors

rflow abi inspect ./abis/usdc.json [--json]
Events in ./abis/usdc.json
 EVENT    | SIGNATURE                         | TOPIC0                | INDEXED
 Transfer | Transfer(address,address,uint256) | 0xddf252ad…523b3ef    | from: address, to: address
 
Functions in ./abis/usdc.json
 FUNCTION | SIGNATURE                 | SELECTOR   | MUTABILITY
 transfer | transfer(address,uint256) | 0xa9059cbb | nonpayable

Every event with its full signature, topic0 hash and indexed params; every function with its 4-byte selector and mutability. --json emits the same rows for tooling.

rflow abi find-event / find-function — reverse lookup

rflow abi find-event ./abis 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
rflow abi find-event --project 0xddf252ad…                     # every ABI rflow.yaml references
rflow abi find-function ./abis/erc20.json 0xa9059cbb
rflow abi find-function --project "transfer(address,uint256)"  # signatures are hashed for you

Maps a topic0 hash back to the event that emits it — against one ABI file, a directory of ABI json files, or (with --project) every ABI the project's rflow.yaml references. find-function is the same lookup for 4-byte selectors and also accepts a full signature. Unparseable json in a directory scan is skipped with a warning; no match exits 1 with an rflow abi fetch hint.

"did you mean?" — validation suggests the real name

rflow validate checks every event and function a workflow references against the contract's ABI. When a name doesn't exist but a close match does, the error says so:

- workflow 'large-transfer-alert' trigger: contract 'USDC' has no event 'Transferr' - did you mean 'Transfer'?

Case-insensitive exact matches win first, then a small edit-distance search (cap 2–3); a function signature with the wrong arity suggests the real signature.

Importers match topic hashes locally

The Defender and Gelato importers never touch the network — but when a Gelato task carries a bare event topic hash, the importer matches it against ABI json files next to the export (and in an abis/ dir beside it) and writes the real event name + ABI when one declares that topic0. Every note about an event it could not name carries the exact rflow abi find-event <file|dir> <topic0> and rflow abi fetch --network <net> --address <0x..> commands to finish the job.

Why there is no abi: { fetch: ... } in rflow.yaml

Deliberately omitted. A config that fetches ABIs at load time is not reproducible — a re-verification, an explorer outage, or a proxy upgrade would change what your money workflows decode. rflow.yaml only ever points at committed ABI files; the CLI fetches once and materialises the file, so git diff shows exactly what changed. No config surface changed (rflow.schema.json is untouched).

Full flag reference: rflow abi and rflow contract in the CLI docs.