Payroll
Every payslip is a letter.
Pay the whole team in one run. Each line is a confidential transfer, and each person gets a letter that opens their own line to them and to nobody else. The chain keeps one row per person and no figure: not the salaries, not the total, not the ratio between any two of them. The owner can still answer an auditor, line by line, with a receipt for each answer.
- One run, up to 50 lines, one transfer each at 150k gas
- The payslip is the letter: verifiable by the payee offline, no key needed
- Nothing of it on a server; through bankhaus-mcp the keys stay on your machine
from house.bankhaus
to cy.bankhaus
memo October salary + on-call
amount 4,100.00 USDG opened to cy alone
randomness 0x9d41…c07a
check Enc(4,100.00, r, pk_cy) == Δr on chain ✓
the chain 5 rows this run · amount column: none
Try one
Run a payroll on paper.
Five people, one run. Each line becomes a confidential transfer from your paper account and a letter addressed to that person: their payslip. Edit the lines, add a few, then run it and look at what the chain would hold.
- One transfer per line, built in your browser with your key
- One letter per payee: the figure and the randomness, for them alone
- The chain holds the rows, never the figures, never the total
Run the payroll and the ledger rows appear here: from, to, two curve points each. No amount column. Or stream it: one sealed stream per person, by the hour.
What a payroll leaves behind
On chain
N confidential transfers from the house to N handles. Who was paid is public; what each was paid is two curve points.
With each person
Their letter: the figure, the randomness, the reference. They can verify it against the chain without any key, and show it to a bank or a landlord.
With the house
The list, the total, and one receipt per letter in DisclosureLog, reader and payload hashed. Enough to answer any question that is actually asked.
Through an agent
A payroll agent runs this once a month through bankhaus-mcp. The owner key signs the transfers on the owner's machine; the agent only prepares the list.
payroll({ lines: [
{ recipient: "ada", amount: "3200.00", memo: "October salary" },
{ recipient: "bo", amount: "2875.50", memo: "October salary" },
…
]})
→ paid 5 · total 14,755.75 USDG · one letter per lineWhy not a batch contract
A multisend would put one call with N amounts on chain. Here there is nothing to batch: each line is already its own sealed transfer, and the verifier checks each on its own. The run reference lives in the payslips, not on chain, so nobody can count how many people were paid together.