Trust and security
A robot running robopay holds real money. This page explains what protects it, and where the current limits are.
The guiding rule is secure by default, convenient by choice: the safe setting is what you get without configuration, and anything more convenient is an explicit opt-in.
What protects the funds
Keys never cross ROS. Private keys stay inside payment_node. Services
and topics carry addresses and signatures only. A node on the ROS graph can
ask the payment node to pay, but can never read the key.
Encrypted at rest. Wallet files are encrypted with a key derived from your passphrase (scrypt), and written with owner-only permissions.
Spending caps at the signing point. Per-transaction and rolling-window limits are enforced just before signing, on by default. Every path that spends goes through them, including escrow deposits.
No double payments. Idempotency keys, a write-ahead record of every payment, and chain reconciliation after restarts mean a dropped connection or crash cannot cause a payment to be sent twice.
Invoices never pay. Receiving a payment request moves no money. Your code decides.
Two-of-two escrow. Escrowed funds release only with signatures from both payer and payee over the exact escrow contents, and return to the payer after the deadline.
Passphrase handling
The node looks for the passphrase in this order:
ROBOPAY_PASSPHRASE_FILE, a file readable only by its owner (mode0600). Recommended for robots that start unattended.ROBOPAY_PASSPHRASE, an environment variable. Convenient in development. Environment variables can leak into logs and child processes.A hidden terminal prompt.
The passphrase is never a ROS parameter.
Operating checklist
Never commit
.envfiles, wallet files, or passphrase files.Use a separate wallet for mainnet.
Keep only working funds on the robot and top up as needed.
Set spending caps to the robot’s real needs.
Back up each wallet file together with its passphrase, stored separately.
Known limitations
This is alpha software. Things to know before relying on it:
The unlocked key lives in the node’s memory. Anyone with root on the robot while the node runs can in principle extract it. Scoped session keys, which limit what a stolen key can do, are planned.
One node per wallet. Nonces are managed inside a single process. Running two nodes with the same wallet at the same time can cause failed transactions (not double payments).
Payer can let an escrow expire. A payer who never signs gets a refund at the deadline, even if the payee did the work. Escrow protects the money, not the outcome. Keep deadlines short and amounts proportionate while trust is being built.
The escrow contract has not had an external audit. It is small, uses OpenZeppelin building blocks, and is covered by tests, but no third party has reviewed it yet.
The contract admin role is permanent and can change the token allowlist. It cannot touch escrowed funds. See Escrow contract.
Reporting a vulnerability
Please do not open a public issue for security problems. Report them privately through GitHub’s security advisory feature on the robopay repository.