Concepts
Confidentiality & FHEVM
How Obscura keeps amounts encrypted end to end using Zama's FHEVM, and exactly what is public versus private.
Encrypted end to end
Each allocation is encrypted to its recipient in the browser, as a 64-bit ciphertext, before anything is written onchain. Contracts store opaque handles rather than plaintext, and the homomorphic math runs off-chain on the Zama coprocessor. On a block explorer you see handles and addresses, never an amount.
Public vs private
| Public | Private |
|---|---|
| Recipient addresses | Allocation amounts |
| The ERC-7984 transfers | Pool sizes and subtotals |
| Contract, token, and admin addresses | Vested / claimed balances and totals |
Who can decrypt
Only the recipient can decrypt their own amount, and only the campaign owner can decrypt totals. Decryption is gated by an onchain ACL: the contract that stored a handle must have granted the wallet access, or the decrypt fails.
// First call for a contract asks for one signature, then it is silent.await sdk.allow([contractAddress]);const clear = await sdk.userDecrypt([{ handle, contractAddress }]);The first decrypt for a contract triggers one EIP-712 wallet signature. The session is cached in IndexedDB, so re-reading an already-allowed handle, like a held-token balance, is silent afterward. Revealing a vesting grant's vested, claimable, or settled amount is different: each one is computed onchain on the spot, so it submits its own transaction and costs a little gas every time, not only on the first decrypt.
Selective disclosure
Encrypted by default does not mean unauditable. When you need to prove an amount to a specific party, vesting grants support targeted disclosure: the recipient, or a distributor with the disclosure-admin role, grants one named address decrypt access to a single field of a grant, its total allocation, vested, claimable, or settled amount.
It is a persistent access grant to that address alone, not a public reveal. Obscura has no global make-it-public decryption. See Disclose on the vesting page for the recipient flow.
The stack
Obscura is built on:
- the Zama Protocol, FHEVM, and the Zama relayer,
- ERC-7984 with OpenZeppelin confidential contracts,
- the TokenOps SDK for the distribution contracts,
- a Next.js 15 and wagmi v2 frontend, live on Sepolia.
No wrap or unwrap
Obscura does not shield or unshield
Obscura does not wrap or unwrap ERC-20 tokens into confidential ones. It distributes tokens that are already confidential ERC-7984 (any confidential ERC-7984 token you import). Zama's onchain Wrappers Registry is only read, to list verified confidential tokens you can import.