Documentation

Docs.

For anyone who wants to check the plumbing: how consent is recorded, what the bridge emits, what the vault contract exposes, and how to read a payout on the chain.

Architecture

Four components. Three are off-chain services we run. One is a contract on Robinhood Chain that anyone can read.

ComponentRuns whereHolds
Consent serviceOur serversSigned consent records, relative preferences, wallet mapping
Call bridgeTelephony provider plus our media layerPer-second connection and live-audio flags for the duration of a call, then discarded
VerifierOur serversCall summaries (start, end, connected time, audio ratio, confirmation) and device integrity results
Vault contractRobinhood ChainStock tokens, per-stock fragment sizes, earmarks, nullifiers, payout events

Created when a relative taps yes. Stored off-chain, hashed on-chain alongside their wallet so a payout can prove consent existed without revealing the phone number.

{ // stored off-chain relative_phone_hash: "sha256(+1555...)", grandchild_ids: ["g_19a2"], stock: "KO", wallet: "0x91C4...e0a7", consented_at: "2026-09-07T20:14:03Z", withdrawn_at: null, signature: "0x..." // signed by relative's new wallet key }

Withdrawal: replying STOP or tapping withdraw sets withdrawn_at. Future calls do not pay. Existing fragments are untouched.

Call bridge

The bridge places two outbound legs and joins them. It emits a per-second event stream to the verifier for the duration of the call. Events are not persisted beyond the running window needed to compute the summary.

// per-second bridge event { call_id, t, leg: "relative" | "grandchild", connected: true, voice: 0.0..1.0 } // voice is an energy ratio from a VAD model on the media server. // audio is never written to disk and never leaves the media server.

Verifier

Turns the event stream into a pass or fail. The rules are fixed and public.

qualified = both_connected_continuous >= 20 * 60 && voice_ratio(relative) >= 0.70 && voice_ratio(grandchild) >= 0.70 && confirmed_by_both == true && device_integrity(grandchild) == "pass" && daily_count(relative, grandchild) < 1

On pass, the verifier signs a payout authorization and submits it to the vault contract. The authorization carries the call ID, both wallet addresses, the stock, and the verifier's signature. The contract checks the signature against the current verifier key, checks the nullifier is unused, checks the balance, and pays.

Vault contract

// interface, Robinhood Chain interface IGrandmaVault { function fragmentSize(bytes32 stock) external view returns (uint256); function balance(bytes32 stock) external view returns (uint256); function earmark(bytes32 stock, address relative) external view returns (uint256); function payout( bytes32 callId, bytes32 stock, address grandchild, address relative, bytes calldata verifierSig ) external; function topUp(bytes32 stock, address relative, uint256 amount) external; function sponsor(bytes32 stock, uint256 amount) external; }

payout reverts if the call ID has been used, the verifier signature is invalid, or the balance (general plus earmark for that relative) cannot cover two fragments. Earmarked balance is spent first.

Events

event Paid(bytes32 callId, bytes32 stock, address grandchild, address relative, uint256 fragment); event Queued(bytes32 callId, bytes32 stock, address relative); // qualified, vault short event TopUp(bytes32 stock, address relative, address from, uint256 amount); event Sponsored(bytes32 stock, address from, uint256 amount); event FragmentSizeChanged(bytes32 stock, uint256 oldSize, uint256 newSize);

Top up a relative

Anyone can add stock to the vault earmarked for a specific relative's wallet. Earmarked stock only pays out on calls with that relative. This is how a family funds its own calls.

// approve the vault, then vault.topUp(keccak256("KO"), 0x91C4...e0a7, 0.5e18); // Nana's calls now draw from your 0.5 KO before the general pool.

A company or fan can add to the general pool for a specific stock. Sponsored balance pays any relative who chose that stock. Sponsors get a public event and nothing else. No data, no targeting, no message in the call.

Read payouts

Every payout is a Paid event. Filter by relative wallet to see a family's history, or by stock to see how much of a company has gone out to grandmothers. The Vault page does this for you.

What is not on the chain

Phone numbers, names, call times, or anything about the conversation. The chain sees two wallets, a stock, a fragment, and an opaque call ID.