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

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

FieldRequiredDescription
contract✅A contract registry name
network✅A declared network
function✅Solidity signature, e.g. balanceOf(address)
argsArguments; each may be an expression
assertExpression over the decoded output; false fails the step with kind assert_failed
on_errorfailfail | continue — see below

Output

The decoded return values become steps.<id>.output:

  • a single return value is unwrapped: balanceOf → steps.gate.output is 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 }}"