BlackBase is a privacy-first document collaboration dApp built on Zama FHEVM. It keeps document bodies encrypted off-chain, stores only ciphertext on-chain, and uses Fully Homomorphic Encryption to protect the access key while still enabling shared editing and permissioned access.
BlackBase lets a user generate a random EVM address as a secret key, encrypt that key with Zama FHE, and store the encrypted key plus an empty document body on-chain. Authorized users can later decrypt the key locally and use it to encrypt or decrypt the document body. The chain never sees the plaintext key or body.
- On-chain documents are public by default. BlackBase provides a privacy-preserving workflow where only ciphertext is stored.
- Key sharing is hard in decentralized apps. BlackBase enables access control that does not reveal the key on-chain.
- Collaboration usually requires a centralized backend. This app stores the encrypted body on-chain while keeping decryption local.
- Traditional encryption flows leak metadata or require a trusted key server. Here, the key is protected by FHE and shared by permissions.
- End-to-end privacy for document bodies using client-side AES-GCM encryption.
- FHE-protected access key stored on-chain; the key is never revealed on-chain in plaintext.
- On-chain access control with explicit grants to collaborators.
- Works with standard wallets and Sepolia without a custom backend.
- Clear separation of read (viem) and write (ethers) responsibilities in the frontend.
-
Create a document
- The client generates a random EVM address A locally (used as the document key).
- A is encrypted using Zama FHE into an encrypted eaddress handle.
- The contract stores: document name, encrypted key, empty body, owner, and timestamp.
-
Open and decrypt
- An authorized user fetches the encrypted key and encrypted body from the contract.
- The user requests a Zama FHE user decrypt flow to decrypt the encrypted key locally.
- The decrypted key A never leaves the client.
-
Edit and update
- The document body is encrypted locally using AES-GCM derived from the key A.
- The encrypted body is sent on-chain via updateDocument.
-
Share access
- The owner grants access to another address.
- The contract adds permission and allows that address to decrypt the encrypted key via FHE.
On-chain:
- EncryptedDocuments contract stores metadata and ciphertext.
- Access control is enforced on-chain.
- Zama FHE allows encrypted key sharing without exposing the plaintext key.
Off-chain:
- The client encrypts/decrypts the document body locally.
- Zama FHE user decrypt is handled in the browser.
- No centralized server or storage is required.
Contract location: contracts/EncryptedDocuments.sol
Document fields stored on-chain:
- name: string (public)
- encryptedBody: string (ciphertext payload)
- encryptedKey: eaddress (FHE encrypted key)
- owner: address
- updatedAt: uint256 (timestamp)
- exists: bool
Main functions:
- createDocument(name, encryptedKey, inputProof) -> docId
- updateDocument(docId, encryptedBody)
- grantAccess(docId, grantee)
- getDocumentInfo(docId) -> (name, owner, updatedAt)
- getDocumentCiphertext(docId, viewer) -> (encryptedBody, encryptedKey)
- hasAccess(docId, viewer) -> bool
- getDocumentsByOwner(owner) -> uint256[]
Events:
- DocumentCreated(docId, owner, name)
- DocumentUpdated(docId, editor)
- AccessGranted(docId, owner, grantee)
Access model:
- Owner is recorded at creation.
- Only authorized addresses can update a document.
- Owner grants access for decryption and editing.
Location: src/
Key behaviors:
- Writes use ethers (signer, transactions).
- Reads use viem (public client).
- Document body encryption uses AES-GCM in the browser.
- Zama FHE SDK handles encrypted key creation and decryption.
- Network configuration is Sepolia-only.
Important frontend configs:
src/src/config/contracts.tsholds CONTRACT_ADDRESS and CONTRACT_ABI.src/src/config/wagmi.tsholds the WalletConnect projectId.
Encrypted key:
- The key is an EVM address A generated locally.
- It is encrypted using Zama FHE as an eaddress handle.
- FHE permissions allow authorized users to decrypt the key.
Encrypted body:
- The body is encrypted in the browser using AES-GCM.
- The key is derived from A by SHA-256 and used as an AES key.
- The payload is stored as "ivHex:cipherHex".
- Solidity 0.8.27
- Hardhat + hardhat-deploy
- Zama FHEVM Solidity + JS SDK
- React + Vite + TypeScript
- wagmi + RainbowKit
- viem (reads) + ethers v6 (writes)
contracts/ Smart contracts
deploy/ Deployment scripts
tasks/ Hardhat tasks
test/ Contract tests
docs/ Zama references
src/ Frontend (React + Vite)
Prerequisites:
- Node.js 20+
- npm
- A Sepolia wallet + test ETH
- Infura API key
- WalletConnect project ID
- Install root dependencies
npm install- Configure environment for Hardhat
Create a .env file in the repo root:
INFURA_API_KEY=YOUR_INFURA_KEY
PRIVATE_KEY=YOUR_PRIVATE_KEY
ETHERSCAN_API_KEY=OPTIONAL
Notes:
- Use PRIVATE_KEY only (no mnemonic).
- PRIVATE_KEY can include or omit the 0x prefix.
- Compile and test
npm run compile
npm run test- Deploy locally (Hardhat) if needed
npx hardhat deploy- Deploy to Sepolia
npx hardhat deploy --network sepolia- Sync contract address and ABI to the frontend
- Copy the deployed address into
src/src/config/contracts.tsas CONTRACT_ADDRESS. - Copy the ABI array from
deployments/sepolia/EncryptedDocuments.jsoninto CONTRACT_ABI.
- Configure WalletConnect
- Edit
src/src/config/wagmi.tsand set projectId.
- Install and run the frontend
cd src
npm install
npm run devCreate a document:
- Connect a wallet.
- Enter a name and click Create Document.
- Save the generated key and document id.
Open and edit a document:
- Enter the document id.
- Decrypt the key (requires access).
- Decrypt the body, edit, and save.
Share access:
- Enter the document id and recipient address.
- Grant access so the recipient can decrypt and edit.
Examples:
npx hardhat task:doc-address
npx hardhat task:doc-create --name "Research Draft"
npx hardhat task:doc-info --docid 1
npx hardhat task:doc-decrypt-key --docid 1
npx hardhat task:doc-grant --docid 1 --grantee 0xYourAddress
npx hardhat task:doc-update --docid 1 --body "ciphertext"- The FHEVM test suite runs against the mocked FHEVM in Hardhat.
- Sepolia tests are not supported by the FHEVM mock.
- Document names, owners, and timestamps are public on-chain.
- Document bodies are encrypted off-chain; only ciphertext is stored on-chain.
- The encryption key is never stored in plaintext and is protected by FHE.
- Access control is enforced on-chain; unauthorized writes revert.
- Losing the decrypted key A means you cannot decrypt existing ciphertext.
- Document version history and diff view.
- Stronger metadata privacy (name encryption).
- Multi-recipient key sharing with revocation policies.
- Large content support via encrypted off-chain storage and on-chain hash pointers.
- Activity feed and audit logs for team workflows.
- Mobile-friendly signer flow and batch updates.
BSD-3-Clause-Clear. See LICENSE.