How the vault works.
The details behind the vault, in order. Start with the overview, or jump to a chapter.
Overview
#01The vault is a Solana program plus this website. There is no backend: the site talks straight to a Solana RPC node, and everything about your vault lives on chain.
You deposit SOL from your normal wallet. To withdraw, your browser signs a message with a Winternitz one-time signature made from your vault phrase, and the program checks it. Your normal wallet signs the transaction and pays the fee, but it can't move vault funds on its own.
The vault phrase
#02When you create a vault the app makes a fresh 24-word phrase in your browser with its secure random number generator. You write it down and type three of its words back to prove the backup.
It is not a wallet phrase. It never makes a Solana wallet key; it only feeds the vault's one-time keys, through hash functions alone. The app never stores it, logs it or sends it over the network. Is the 24-word phrase quantum-safe?
One-time keys
#03Every vault uses one Winternitz key. Keys come from the phrase in order: key[i] = derive(phrase, i) for i = 0, 1, 2, and so on. One backup covers every future key.
A Winternitz key may sign only one message. Two different signatures from one key can leak enough to forge a third, so every withdrawal moves to the next key. Winternitz in plain words.
Vault addresses
#04A vault's address is a program-derived address from the seeds ["vault", pubkey_hash], where pubkey_hash is a hash of that vault's one-time public key. The chain only ever sees the hash; the key itself appears only when its single signature is used.
Deposits
#05Deposits go through the program's deposit instruction, from your normal wallet into the live vault. There is no limit on how much a vault holds.
SOL sent straight to a vault address also arrives, and can be withdrawn like any deposit. Every vault also holds a small rent deposit, which moves with each roll and comes back when you close it.
Withdrawals and the roll
#06A withdrawal from vault #n is one transaction that:
- carries one signed message: the program id, this vault's address, the amount, the recipient and the next vault's key hash;
- has the program check the signature against vault #n's key hash;
- sends the amount to the recipient;
- moves the rest into vault #n+1, opened with key #n+1;
- closes vault #n.
Change any part of the message and the signature fails, so the fee payer can't redirect funds. Closing a vault works the same way, but sends everything to you and opens no next vault.
If a withdrawal fails
#07The app retries with the exact same signed message (same amount, recipient and next hash), or moves on to the next key index. It never signs two different messages with one key.
Recovery
#08Enter the phrase on recover. The app derives key #0, #1, #2 and on, works out each vault address, and checks the chain until it finds the live vault. No server and no database: the chain is the source of truth.
Network and upgrades
#09The app runs on mainnet. On devnet the program can still be upgraded while it's being built. On mainnet its upgrade authority is revoked once the launch checks pass, so the program can never change: an ordinary upgrade key would be a quantum weak point for every vault.