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). These CLI helpers get those files onto disk and answer questions about them.

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=…); needs an ETHERSCAN_API_KEY env var. No key and no Sourcify 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.

Limits: fetch needs outbound network access, only verified contracts resolve, and Sourcify coverage varies by chain (hence the Etherscan fallback). For proxies the explorer returns the ABI of the address you give it, often the proxy's own; fetch the implementation address for 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. A Gelato task carrying a bare event topic hash is matched against ABI json files next to the export (and in an abis/ dir beside it); an ABI declaring that topic0 supplies the real event name + ABI. Every event it could not name gets a note with 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: load-time fetching 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. There is no fetch surface in rflow.schema.json.

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