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 neededFetches 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:
- Sourcify first — keyless, no account needed.
- Etherscan v2 — the multichain API
(
https://api.etherscan.io/v2/api?chainid=…), which needs anETHERSCAN_API_KEYenv 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 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48Fetch + 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 | nonpayableEvery 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 youMaps 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.