Robots don’t carry cash

Open-source ROS 2 tools for peer-to-peer
robot value exchange.

for ROS 2

Each robot gets its own wallet, behind ordinary ROS 2 services and actions.

Works from any ROS 2 client: rclpy, rclcpp, or the command line.

Every payment is written to disk before it is sent. A dropped connection never pays twice.

MIT-licensed. No accounts, no platform fees.

The toolkit

Everything a robot needs
to hold up its end of a deal.

01

Wallets and payments

Each robot holds its own keys, encrypted on disk. Send USDC with one service call. Payments survive dropped connections and restarts without paying twice.

ros2 run robopay_core robopay wallet create
02

Conditional payments

Pay when your code says the job is done: a topic fires, a sensor agrees. Built-in edge detection and rate limits stop a condition that stays true from paying twice.

if trigger.fired(msg.data): pay()
03

Escrow, built in

Lock funds before the work starts. They release when both robots sign off, and return to the payer automatically if the deadline passes.

escrow.open(payer=me, payee=them, amount="5.00")
04

Payment requests

Robots can invoice each other over a ROS topic. An invoice never moves money on its own: the payer’s code decides.

/payment_requests (PaymentRequest)

Settlement layer

Settled in USDC on Base

Machines need money they can actually hold: stable, digital, programmable. Every payment settles in USDC, a dollar stablecoin issued by Circle, on Base, a low-cost network. A drone leaving San Francisco can pay a charging pad in San Jose with no bank account in sight.

Each robot runs its own wallet. It holds a balance, pays, invoices and signs on its own, while you set the spending limits it cannot exceed.

  • Dollar-denominated
  • Settles in seconds
  • Sub-cent fees
  • Programmable

Peer-to-peer means
there is no middle.

A card payment passes through the payer’s bank, a processor, a scheme and the payee’s bank. Every hop needs an account, an approval and a business day. A stablecoin payment has none of that: the payer signs, the network settles, the payee holds the money. That is the part that lets a machine pay a machine.

  1. 01

    The robot owns its keys

    A wallet is a keypair, generated on the robot and stored encrypted on its disk. Nothing to open, nobody to ask for permission.

  2. 02

    Paying is signing

    To send value, the robot signs a transaction with its private key. That signature is the authorisation: it cannot be forged, and no intermediary has to approve it.

  3. 03

    The network settles

    The signed transaction goes to a public ledger. It confirms in seconds and the balance moves for good: no chargebacks, no month-end reconciliation.

  4. 04

    The unit holds still

    Everything settles in USDC, a dollar stablecoin, so a fleet’s balance does not drift while it works.

last_mile_courier.py
from rclpy.node import Node
from std_msgs.msg import Bool
from robopay_core.client import EscrowClient
 
HUB, COURIER = "0xHub...", "0xCourier..."
 
class Hub(Node):
    def __init__(self):
        super().__init__("hub")
        self.escrow = EscrowClient(self)
 
        # lock 5 USDC for the courier, refunded if not released in 30 min
        self.job = self.escrow.open(
            payer=HUB, payee=COURIER,
            amount="5.00", timeout_seconds=1800,
        )
        self.create_subscription(
            Bool, "/parcel/scanned", self.on_scan, 10)
 
    def on_scan(self, msg):
        if msg.data and self.job.escrow_id:   # parcel is physically here
            self.escrow.sign(self.job.escrow_id, role="payer")
            # funds release once the courier has signed too

Escrow

Money that waits for both sides

Lock the payment before the job starts. When both robots agree the work is done, they sign and the funds release. If the deadline passes first, the money goes back to the payer, automatically. What counts as done is up to your sensors.

  • Automatic refund after the deadline
  • Release needs both robots’ signatures
  • One shared, verified contract on Base

Safe by default

Built to hold real money

  • Keys never cross the ROS graph. Signing happens inside the payment node.
  • Spending caps on every payment, enforced before anything is signed.
  • No double payments. Every payment is recorded before it is sent and reconciled after a restart.

Early release. Tested end to end on mainnet with real funds, not yet production-ready.

Good to know

FAQs

Yes. robopay is MIT-licensed and runs on your own robots. There are no accounts and no platform fees. The only cost is the network fee on each payment, a fraction of a cent on Base, paid from a small amount of ETH in the robot’s wallet.

Anything running ROS 2. It is tested on Humble and Jazzy. Everything is exposed as standard ROS 2 services, actions and topics, so nodes written with rclpy or rclcpp, or the ros2 command line, can use it. The helper library is Python.

No. If you can write a ROS 2 node, you have what you need. robopay handles keys, fees, signing and confirmation. You can start on the free Base Sepolia testnet before using real money.

No. Each robot’s wallet holds USDC directly and can receive and send it without a bank or card processor. You fund the wallet and set the limits it works within.

Keys are generated on the robot and encrypted on disk with a passphrase. They never leave the payment node: other nodes only ever see addresses and signatures. While the node runs, the unlocked key is in its memory, so treat the robot like any machine holding money. Scoped session keys that limit what a key can do are on the roadmap.

Yes. Per-payment and per-time-window caps are on by default and enforced at the point of signing, so no other node can bypass them. Incoming invoices never pay on their own: your code decides.

Not yet. robopay is an early release. It has been tested end to end on Base mainnet with real funds, but its interfaces may still change and the escrow contract has not had an external audit. Start on testnet and keep amounts small.