Uniquity is a privacy-first platform that combines Sybil-resistant biometric verification with fully encrypted campaign submissions β all powered by Fully Homomorphic Encryption (FHE). Your biometric data never leaves your device unencrypted, and your submissions remain private until the campaign admin decrypts them.
Prove you're human. Submit privately. Stay anonymous.
π₯ Watch Demo Video Β· π Documentation Β· π Live Demo
Every existing identity system forces a terrible tradeoff:
| System | Privacy | Sybil-Resistant | Decentralized |
|---|---|---|---|
| KYC/ID Verification | β | β | β |
| Social Vouching | β | β | |
| Token Staking | β | β | |
| Captchas | β | β | β |
| Worldcoin (Iris Scan) | β | β |
The core issue: To prove you're unique, you typically must surrender your biometric data to a centralized party who can:
- Track you across platforms
- Sell your data
- Get hacked and leak your biometrics forever
When you submit to a hackathon, grant program, or survey:
- Your submission data is often visible to everyone
- Your identity can be linked to your submissions
- Sensitive information (contact details, project ideas) is exposed
Uniquity solves both problems using Fully Homomorphic Encryption (FHE):
- Facial embeddings are computed locally on your device
- Embeddings are FHE-encrypted before leaving your browser
- The smart contract stores encrypted embeddings without ever decrypting them
- v2 will compare encrypted embeddings to ensure one human = one account
- Submission data is AES-encrypted locally
- The AES key is FHE-encrypted on-chain
- Only campaign admins can decrypt submissions
- Even the blockchain can't see your data
Zero trust. Zero knowledge. Full privacy.
- β Client-side facial embedding extraction (face-api.js)
- β FHE-encrypted storage on-chain (Zama fhEVM)
- β No biometric data stored in plaintext
- β One-time verification, permanent credential
- π v2: Encrypted similarity comparison for uniqueness
- β Bucket-based organization for scalability
- β Configurable similarity threshold
- π v2: Cryptographic uniqueness guarantee
- π v2: Cannot create multiple accounts with same face
- β End-to-end encrypted submissions
- β Admin-only decryption with FHE permissions
- β Editable submissions with re-encryption
- β Batch decryption for efficiency
- β Create campaigns with custom fields
- β Set deadlines and submission limits
- β Extend deadlines, toggle settings
- β Export submissions as CSV
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER DEVICE β
β βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββββ β
β β Camera Feed βββββΆβ face-api.js βββββΆβ FHE Encryption β β
β β β β (Embedding) β β (Client-side) β β
β βββββββββββββββββββ ββββββββββββββββββββ βββββββββββ¬ββββββββββ β
β β β
β βββββββββββββββββββ ββββββββββββββββββββ β β
β β Submission βββββΆβ AES Encryption ββββββββββββββββ€ β
β β Form Data β β (Local) β β β
β βββββββββββββββββββ ββββββββββββββββββββ β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββ
β
βββββββββββββββββββββββββββββββββββΌββββββββββββββ
β BLOCKCHAIN (fhEVM) β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β UniquityCore Contract β β
β β β’ Instant human verification (v1) β β
β β β’ FHE-encrypted embedding storage β β
β β β’ Encrypted comparison (v2) β β
β β β’ Scalable off-chain comparison (v2) β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β UniquitySubmit Contract β β
β β β’ Campaign management β β
β β β’ Encrypted submission storage β β
β β β’ FHE key permissions β β
β β β’ Admin-only decryption access β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ
β IPFS / STORAGE β β SUBGRAPH / INDEXER β β ZAMA RELAYER + KMS β
β ββββββββββββββββββββββββββββββ β ββββββββββββββββββββββββββββββ β ββββββββββββββββββββββββββββββ
β β’ Encrypted submission data β β β’ Event indexing β β β’ Off-chain publicDecrypt β
β β’ Campaign metadata β β β’ GraphQL API β β β’ KMS signature generation β
β β’ Never stores plaintext β β β’ Fast queries for UI β β β’ Decryption proof creation β
β β β β’ User/Campaign analytics β β β
βββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ
Note: Current v1 verifies users instantly upon submission. The full comparison flow below will be enabled in v2 with scalable off-chain FHE computation.
%%{init: {'theme':'dark', 'themeVariables': {
'primaryColor':'#a855f7',
'primaryTextColor':'#fff',
'primaryBorderColor':'#9333ea',
'lineColor':'#a855f7',
'secondaryColor':'#3b82f6',
'tertiaryColor':'#10b981',
'background':'#111',
'mainBkg':'#1b1b1b',
'secondBkg':'#242424',
'actorBkg':'#2f2f2f',
'actorBorder':'#a855f7',
'actorTextColor':'#fff',
'signalColor':'#a855f7',
'signalTextColor':'#fff'
}}}%%
sequenceDiagram
participant User
participant Browser
participant fhEVM
participant ComparisonService as Comparison Service (v2)
participant RelayerSDK as Relayer SDK
participant KMS as Zama KMS
User->>Browser: Capture selfie
Browser->>Browser: Extract facial embedding (face-api.js)
Browser->>Browser: Quantize to 4 Γ uint64 chunks
Browser->>Browser: FHE-encrypt chunks
Browser->>fhEVM: proveHumanity(encrypted chunks)
alt v1: Instant Verification (Current)
fhEVM->>fhEVM: Store encrypted profile
fhEVM->>fhEVM: Mark user as verified
fhEVM-->>Browser: VerificationComplete(true)
else v2: With Uniqueness Check (Coming Soon)
fhEVM->>fhEVM: Store pending request, emit event
fhEVM-->>Browser: EmbeddingSubmitted event
Note over Browser,KMS: Off-Chain FHE Comparison (Scalable)
ComparisonService->>fhEVM: Fetch encrypted profiles
ComparisonService->>ComparisonService: Compute FHE distance (no gas limit!)
ComparisonService->>fhEVM: submitComparisonResult(minDistance)
fhEVM-->>Browser: ComparisonReady event
Note over Browser,KMS: Decryption Flow
Browser->>fhEVM: requestDecryption()
fhEVM->>fhEVM: FHE.makePubliclyDecryptable(minDistance)
Browser->>RelayerSDK: publicDecrypt([distanceHandle])
RelayerSDK->>KMS: Request decryption + proof
KMS-->>RelayerSDK: clearValue + decryptionProof
RelayerSDK-->>Browser: {clearValues, decryptionProof}
Browser->>fhEVM: finalizeVerification(clearDistance, proof)
fhEVM->>fhEVM: FHE.checkSignatures(handles, cleartext, proof)
alt Distance > Threshold (Unique)
fhEVM->>fhEVM: Register profile, mark verified
fhEVM-->>Browser: VerificationComplete(true)
else Distance β€ Threshold (Duplicate)
fhEVM-->>Browser: VerificationComplete(false)
end
end
%%{init: {'theme':'dark', 'themeVariables': {
'primaryColor':'#10b981',
'primaryTextColor':'#fff',
'primaryBorderColor':'#059669',
'lineColor':'#10b981',
'secondaryColor':'#3b82f6',
'tertiaryColor':'#a855f7',
'background':'#111',
'mainBkg':'#1b1b1b',
'secondBkg':'#242424',
'actorBkg':'#2f2f2f',
'actorBorder':'#10b981',
'actorTextColor':'#fff',
'signalColor':'#10b981',
'signalTextColor':'#fff'
}}}%%
sequenceDiagram
participant User
participant Browser
participant IPFS
participant fhEVM
participant Admin
User->>Browser: Fill submission form
Browser->>Browser: Generate AES-256 key
Browser->>Browser: AES-encrypt form data
Browser->>IPFS: Upload encrypted data
IPFS-->>Browser: CID (content identifier)
Browser->>Browser: FHE-encrypt AES key
Browser->>fhEVM: submit(campaignId, CID, encrypted key)
fhEVM->>fhEVM: Store submission, grant admin FHE access
fhEVM-->>Browser: SubmissionReceived event
Note over Admin,fhEVM: Admin Decryption (later)
Admin->>fhEVM: getSubmissionKeyHandle(campaignId, index)
fhEVM-->>Admin: Encrypted key handle
Admin->>Admin: userDecrypt(handle) β AES key
Admin->>IPFS: Download encrypted data
Admin->>Admin: AES-decrypt β plaintext submission
| Feature | Implementation |
|---|---|
| Embedding Size | 4 Γ euint64 (256-bit total) |
| Similarity Metric | Manhattan distance (L1) |
| Threshold | 400,000 (configurable) |
| Bucket Count | 8 (for scalable comparison) |
| Current Mode | Instant verification (v1 demo) |
| v2 Decryption | Public Decryption (makePubliclyDecryptable β publicDecrypt β checkSignatures) |
| Feature | Implementation |
|---|---|
| Encryption | AES-256-GCM (client) + FHE (on-chain) |
| Storage | IPFS (encrypted data) |
| Permissions | FHE.allow() for admin/submitter |
| Edit Support | Re-encryption with new AES key |
| Batch Decryption | Multi-handle retrieval via userDecrypt |
- Node.js v18+
- Git
- MetaMask or compatible wallet
# Clone the repository
git clone https://github.com/your-org/uniquity.git
cd uniquity
# Install dependencies
npm install
# Start local FHEVM node
npx hardhat node
# Deploy contracts
npx hardhat run scripts/deploy.ts --network localhost
# Start frontend
cd frontend
npm install
npm run dev# Frontend (.env.local)
NEXT_PUBLIC_UNIQUITY_CORE_ADDRESS=0x...
NEXT_PUBLIC_UNIQUITY_SUBMIT_ADDRESS=0x...
NEXT_PUBLIC_SUBGRAPH_URL=https://...
NEXT_PUBLIC_STORACHA_KEY=...
# Contracts (.env)
PRIVATE_KEY=...
SEPOLIA_RPC_URL=...uniquity/
βββ contracts/ # Smart contracts
β βββ UniquityCore.sol # Proof of humanity
β βββ UniquitySubmit.sol # Campaign submissions
βββ test/ # Contract tests
βββ frontend/ # Next.js application
β βββ src/
β β βββ app/ # Pages (App Router)
β β βββ components/ # React components
β β βββ hooks/ # Custom hooks
β β βββ lib/ # Utilities
β β βββ contexts/ # React contexts
βββ subgraph/ # The Graph indexer
β βββ schema.graphql # Data schema
β βββ subgraph.yaml # Manifest
β βββ src/ # Mappings
βββ docs/ # Documentation
| Contract Name | Address | Explorer Link |
|---|---|---|
| UniquityCore | 0x00E3a268Fe868D572a35A5d06dAA173B91F57F32 | View on Etherscan |
| UniquitySubmit | 0xF9ceba08282bA5015194bdbBb895cA4921391d23 | View on Etherscan |
// Prove humanity with encrypted biometrics (v1: instant, v2: with comparison)
function proveHumanity(
externalEuint64 chunk0,
externalEuint64 chunk1,
externalEuint64 chunk2,
externalEuint64 chunk3,
bytes calldata inputProof,
uint8 bucketId
) external;
// v2: Request decryption of similarity result
function requestDecryption() external;
// v2: Finalize with KMS proof
function finalizeVerification(
uint256 requestId,
uint64 clearDistance,
bytes calldata decryptionProof
) external;
// Check verification status
function isVerified(address user) external view returns (bool);// Create a campaign
function createCampaign(
bytes32 metadataCid,
string calldata metadataCidString,
uint256 deadline,
uint256 editDeadline,
bool requiresVerification,
bool allowEdits,
uint64 maxSubmissions
) external returns (uint256 campaignId);
// Submit to a campaign
function submit(
uint256 campaignId,
bytes32 ipfsCid,
string calldata ipfsCidString,
externalEuint256 inEncryptedAesKey,
bytes calldata inputProof
) external;
// Admin: Get decryption key handle
function getSubmissionKeyHandle(
uint256 campaignId,
uint256 submissionIndex
) external view returns (bytes32);# Run all tests
npx hardhat test
# Run specific test file
npx hardhat test test/UniquityCore.test.ts
npx hardhat test test/UniquitySubmit.test.ts
# With coverage
npx hardhat coverage| Category | Tests | Description |
|---|---|---|
| Deployment | 3 | Contract deployment, constants verification, initial state |
| proveHumanity | 5 | User verification, encrypted storage, bucket assignment |
| requestDecryption | 1 | Decryption request flow, error handling (v2) |
| cancelVerification | 1 | Cancel pending, retry after cancel, validation |
| View Functions | 5 | hasPendingVerification, getBucketSize, hasHumanCredential, isVerified |
| Bucket Distribution | 1 | All 8 buckets supported |
Key Test Cases:
- Users are verified immediately (v1 demo mode)
- Encrypted embeddings stored correctly
- Invalid bucket IDs rejected
- Already verified users cannot re-verify
- Pending requests can be cancelled and retried
| Category | Tests | Description |
|---|---|---|
| Deployment | 3 | Contract deployment, UniquityCore reference, initial state |
| createCampaign | 8 | Campaign creation, data storage, admin tracking, validation |
| submit | 10 | Submission flow, count tracking, user tracking, validation |
| editSubmission | 6 | Edit flow, edit count, CID updates, validation |
| Admin Management | 12 | updateMetadata, updateSettings, extendDeadline, close/reopen |
| Key Handle Functions | 6 | Admin key retrieval, user key retrieval, batch retrieval |
| View Functions | 8 | canSubmit, canEdit, getAllSubmissionCids, isAdmin |
| No Verification Campaign | 1 | Campaigns without verification requirement |
Key Test Cases:
- Campaign creation with IPFS metadata and custom settings
- Submission with FHE-encrypted AES keys
- Edit submission with new encrypted key and updated CID
- Admin-only functions properly gated
- Max submissions enforced
- Deadline and edit deadline validation
- Campaigns with/without verification requirement
- InputVerifier proof validation
- Encrypted handle storage and retrieval
- FHE.allow() permission grants
- Proper ciphertext handling across functions
| Contract | Statements | Branches | Functions | Lines |
|---|---|---|---|---|
| UniquityCore | ~95% | ~90% | 100% | ~95% |
| UniquitySubmit | ~95% | ~90% | 100% | ~95% |
- / - Landing page with project overview
- /verify - Biometric verification flow
- /campaigns - Browse all campaigns
- /campaigns/create - Create new campaign
- /campaigns/[id] - View & submit to campaign
- /campaigns/[id]/admin - Admin dashboard
- /dashboard - User's submissions & campaigns
- BiometricCapture - Webcam + face-api.js integration
- SubmissionForm - Dynamic form based on campaign config
- AdminDecryptionPanel - Batch decryption interface
- CampaignSettingsModal - Admin controls
- Documentation: ./docs/
- API Reference: ./docs/API.md
- Architecture Deep Dive: ./docs/ARCHITECTURE.md
- Security Model: ./docs/SECURITY.md
- Scalability Plan: ./docs/SCALABILITY.md
- Use Cases: ./docs/USE_CASES.md
| Aspect | Worldcoin | Uniquity |
|---|---|---|
| Biometric | Iris scan | Facial embedding |
| Hardware | Custom Orb required | Any webcam |
| Data Storage | Centralized | Never stored unencrypted |
| Privacy | Trust Worldcoin | Trustless (FHE) |
| Aspect | BrightID | Uniquity |
|---|---|---|
| Method | Social vouching | Biometric |
| Sybil-Resistant | Depends on social graph | Cryptographic guarantee |
| Privacy | Graph is public | Fully private |
| Aspect | KYC | Uniquity |
|---|---|---|
| Data Required | ID documents, selfie | Selfie only |
| Privacy | Company sees everything | No one sees data |
| Decentralized | No | Yes |
Uniquity enables a new class of applications where privacy and fairness coexist. Here are some key use cases:
- Problem: Competitors can see and copy ideas; same team submits multiple entries
- Solution: Encrypted submissions only visible to judges; one entry per verified human
- Benefit: Fair, private competition where ideas stay protected until judging
- Problem: Public applications expose strategy; known applicants get biased reviews
- Solution: Only grant committee can decrypt applications; unbiased review process
- Benefit: Applicants can share sensitive financials and strategies safely
- Problem: Sybil farmers create thousands of wallets; real users get outcompeted
- Solution: One claim per verified unique human; cryptographic guarantee
- Benefit: True 1:1 human-to-allocation ratio; community-first distribution
- Problem: Traditional surveys aren't truly anonymous; one person submits multiple responses
- Solution: True anonymity with one response per human; encrypted until analysis
- Benefit: Honest feedback without fear of identification
- Problem: Plutocracy (wealth = power); vote buying; public votes enable coercion
- Solution: One human, one vote; encrypted choices revealed after voting ends
- Benefit: Democratic governance resistant to manipulation
- Problem: Must reveal full identity for simple checks; credentials enable tracking
- Solution: Verify once, use everywhere; platforms only see "verified" status
- Benefit: Portable proof of humanity without identity exposure
π See USE_CASES.md for detailed examples with code samples
- FHE-encrypted biometric storage
- Instant human verification (demo mode)
- Encrypted campaign submissions
- Admin decryption interface
- Subgraph indexing
- Off-chain FHE comparison service
- Full uniqueness verification (1 human = 1 account)
- Public decryption flow (makePubliclyDecryptable β publicDecrypt β checkSignatures)
- Support for millions of profiles
- Multi-factor verification (face + voice)
- Encrypted search over submissions
- Group-based permissions
- Mobile app
- Cross-chain verification
- SDK for third-party integration
- Enterprise deployment
MIT License β see LICENSE file.