read
eth_call a view function. With assert: it becomes a hard gate; without, it's
enrichment for later steps.
rflow_version: 1
name: usdc-deposit-relay
config:
port: 3940
db_connection: ${DATABASE_URL}
networks:
- name: base
chain_id: 8453
rpc: ${BASE_RPC}
signer:
raw:
mnemonic: ${RAW_DANGEROUS_MNEMONIC}
relayers:
payout:
networks: [base]
contracts:
USDC:
abi: ./abis/erc20.json
addresses:
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
workflows:
usdc-deposit-relay:
trigger:
event:
contract: USDC
name: Transfer
network: base
confirmations: 12
steps:
# the payout wallet must hold enough to echo the deposit
- id: gate
read:
contract: USDC
network: base
function: "balanceOf(address)"
args: ["${{ relayers.payout.address }}"]
assert: "${{ output >= trigger.args.value }}"
- id: payout
send_transaction:
network: base
relayer: payout
contract: USDC
function: "transfer(address,uint256)"
args: ["${{ trigger.args.from }}", "${{ trigger.args.value }}"]Fields
| Field | Required | Description |
|---|---|---|
contract | ✅ | A contract registry name |
network | ✅ | A declared network |
function | ✅ | Solidity signature, e.g. balanceOf(address) |
args | Arguments; each may be an expression | |
assert | Expression over the decoded output; false fails the step with kind assert_failed | |
on_error | fail | fail | continue — see below |
Output
The decoded return values become steps.<id>.output:
- a single return value is unwrapped:
balanceOf→steps.gate.outputis the balance itself - multiple return values become a map keyed by ABI output names (positional when unnamed)
uint256 outputs stay exact. Compare and do math on them directly; see
U256 semantics.
assert — the gate
The assert: expression sees output alongside the full run context:
assert: "${{ output >= trigger.args.value and output > wei('1', 6) }}"A false assert fails the step with kind assert_failed: a deliberate stop, never
retried. The run then follows on_failure.
on_error: continue — soft enrichment
By default a failed read (RPC error, revert, false assert) fails the step. Set
on_error: continue to turn it into soft enrichment instead: the step succeeds with
output: null and the run continues.
rflow_version: 1
name: hourly-price-report
config:
port: 3940
db_connection: ${DATABASE_URL}
networks:
- name: ethereum
chain_id: 1
rpc: ${ETH_RPC}
contracts:
Oracle:
abi: ./abis/oracle.json
addresses:
ethereum: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"
workflows:
hourly-price-report:
trigger:
cron:
expression: "0 * * * *"
steps:
- id: price
read:
contract: Oracle
network: ethereum
function: "latestAnswer()"
on_error: continue # nice-to-have, not load-bearing
- id: report
http_call:
url: https://ops.example.com/price-report
body:
price: "${{ steps.price.output }}"