UNSHOR Open vault

How Unshor works

Unshor is one contract on Robinhood Chain. It holds ETH, USDG, WETH and the 27 listed Stock Tokens in vaults that only a Winternitz one-time signature can open. It has no owner, no admin, no fee, no pause and no proxy.

Why your wallet is exposed

A Robinhood Chain address is the last 20 bytes of the hash of its secp256k1 public key, so a fresh address hides the key. The first transaction it sends carries a signature from which anyone can recover the public key, and from then on it is public for good. Shor's algorithm, on a large enough quantum computer, turns a public key into its private key. No such computer exists today, and estimates of when one could run vary from years to decades.

The signature

Winternitz signatures use only a hash function, here Keccak-256 truncated to 24 bytes. Shor's algorithm does not apply to hashes; the best known quantum attack, Grover's search, halves the security bits, leaving 96-bit preimage resistance per chain value.

  • 34 chains: 32 for the bytes of keccak256(message) and 2 for a checksum of sum(255 - byte). The checksum is what stops anyone from turning one signature into a signature for a different message.
  • Each chain is 255 steps of H(i, j, x) = keccak256(uint8 i || uint8 j || x)[0:24]. A vault is named by its root: keccak256 of the 34 chain ends.
  • A signature reveals part of each chain, so a key signs exactly once. The contract enforces it: a root that has signed is marked spent and never takes deposits again.

The phrase

The app makes a standard 24-word phrase (256 bits of entropy) in your browser. The secret of vault k, chain i is keccak256("unshor-v1" || entropy || k || i)[0:24]. One phrase holds a whole line of vaults, #0, #1, #2 and so on. The phrase is never sent anywhere and never derived from your wallet: a key that comes from an ECDSA signature would fall with it.

The contract

deposit(root)                         ETH into a vault
depositToken(root, token, amount)     USDG, WETH or a Stock Token
withdraw(root, to, next, amounts, sig)
  signed message: abi.encode("UNSHOR-RH1", chainId, contract, root, to, next, amounts)
  • Deposits work for anyone into any root that is not spent. A vault exists from its first deposit.
  • Withdraw checks the signature against the root, sends amounts (one per asset, in the contract's order: ETH, USDG, WETH, then the 27 Stock Tokens) to to, and moves everything else to next, which must not be spent. The root is then spent.
  • Changing the amounts, the destination or the next vault breaks the signature, so a signature seen in flight is useless to anyone else.
  • Before your phrase signs, the app asks the contract for the exact message and compares it with its own.

Your wallet's role

Your usual wallet pays gas and makes deposits. It cannot move anything out of a vault: only the phrase can. While assets sit in your wallet they are exposed like any other balance on the chain.

Costs

  • Deposits: an ordinary transfer, plus a one-time approval per token.
  • A withdrawal walks about 4,400 hashes and moves each asset: roughly 0.9 to 3 million gas depending on how many assets the vault holds, a few cents of ETH at Robinhood Chain gas prices.
  • Unshor charges nothing.

Limits and risks

  • Only the listed assets: ETH, USDG, WETH and the 27 Stock Tokens. The list is fixed in the contract.
  • Lose the phrase and the vault cannot be opened by anyone.
  • The gas payer is still an ECDSA wallet. It can be broken, but it cannot redirect a withdrawal: the signed message fixes where everything goes.
  • Withdraw to an ordinary wallet address. A contract that refuses ETH would make the withdrawal fail, and the phrase would then have to sign again.
  • The contract is unaudited. It is tested in Foundry against an independent signer and against the app's own JavaScript signer, and on a fork of Robinhood Chain mainnet with all 27 Stock Tokens. The design follows Dean Little's Solana Winternitz Vault, with a checksum added.

Contract

Unshor vaultdeploys at launch
Ownernone