🔐 以全同態加密 (FHE) 實現的隱私保護薪資支付系統
在傳統區塊鏈上,所有交易金額完全透明。這對薪資支付而言是個災難——任何人都能查看你的收入、比較同事薪水、甚至讓競爭對手分析公司支出結構。
PayWave 利用 Zama FHEVM 的全同態加密技術,打造一個**「公開存款、私密分發」**的薪資系統:
- 公司存入資金是可審計的公開交易
- 每位員工的薪資明細端到端加密
- 只有員工本人能解密並驗證自己的薪資
- 政府合規存取需要雙方批准 + 24 小時冷靜期
| 問題 | 傳統區塊鏈 | PayWave |
|---|---|---|
| 薪資金額 | ❌ 任何人可查 | ✅ 只有員工可見 |
| 同事比較 | ❌ 完全透明 | ✅ 無法互相比較 |
| 商業機密 | ❌ 競爭對手可分析支出 | ✅ 分配模式完全隱藏 |
| GDPR 合規 | ❌ 無法滿足最小化揭露 | ✅ 數據最小化原則 |
| 政府稽核 | ❌ 無控制機制 | ✅ 雙重批准 + 時間鎖 |
全同態加密 (Fully Homomorphic Encryption) 允許在密文上直接運算,無需解密:
加密(基本薪資) + 加密(獎金) - 加密(扣款) = 加密(淨薪資)
↓ ↓ ↓ ↓
密文A + 密文B - 密文C = 密文D
整個計算過程中,沒有任何人(包括區塊鏈驗證節點)能看到實際金額。
PayWave 系統架構
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 【公開層】 【機密層】 │
│ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ USDC │ ───deposit()───► │ cUSDC │ │
│ │ 公開代幣 │ │ 機密代幣 │ │
│ └──────────┘ ◄──withdraw()─── │ (加密餘額) │ │
│ │ └──────┬───────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ Wrapper │ │ Payroll │ │
│ │ 包裝合約 │ │ 薪資合約 │ │
│ └──────────┘ │ │ │
│ │ • 加密薪資單 │ │
│ ┌──────────┐ │ • FHE 計算 │ │
│ │ Treasury │ ◄────pay()──────── │ • ACL 權限 │ │
│ │ 國庫 │ └──────┬───────┘ │
│ │(公司資金) │ │ │
│ └──────────┘ │ grantGovAccess() │
│ ▼ │
│ ┌──────────────┐ │
│ │ Compliance │ │
│ │ Gate │ │
│ │ 合規閘道 │ │
│ │ │ │
│ │ • 雙重批准 │ │
│ │ • 24h 時間鎖 │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
| 合約 | 責任 | 資料可見性 |
|---|---|---|
| cUSDC | 機密代幣,餘額加密存儲 | 餘額:🔒 加密 |
| USDCWrapper | 公開 USDC ↔ 機密 cUSDC 轉換 | 存提金額:👁️ 公開 |
| PayrollTreasury | 持有公司 cUSDC 資金 | 總額:🔒 加密 |
| Payroll | 加密薪資單、FHE 計算、支付執行 | 薪資明細:🔒 加密 |
| ComplianceGate | Break-glass 機制狀態機 | 申請記錄:👁️ 公開 |
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 1️⃣ 存款 │
│ ───────────── │
│ HR 將 USDC 存入 Wrapper │
│ Wrapper 鑄造等額 cUSDC 到 Treasury │
│ │
│ 📊 可見性: 存款金額公開 (可審計) │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 2️⃣ 建立薪資單 │
│ ───────────── │
│ HR 在前端輸入薪資明細 │
│ 前端使用 FHEVM SDK 加密 → 產生 handles + ZK proof │
│ 送出 setPayslipInputs() 交易 │
│ │
│ 📊 可見性: 只有加密 handle,無人可見明細 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 3️⃣ 計算淨額 │
│ ───────────── │
│ HR 呼叫 computePayslip() │
│ 合約在密文上執行: net = max(base + bonus - penalty - leave, 0) │
│ 員工獲得解密權限 (ACL.allow) │
│ │
│ 📊 可見性: 計算在密文上進行,結果仍為密文 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 4️⃣ 執行支付 │
│ ───────────── │
│ HR 呼叫 pay() │
│ Payroll 授予 cUSDC 臨時權限 (allowTransient) │
│ cUSDC.transferEncryptedFrom(Treasury → Employee, 加密金額) │
│ │
│ 📊 可見性: 轉帳發生,但金額加密 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 5️⃣ 員工解密 │
│ ───────────── │
│ 員工使用錢包簽署 EIP-712 授權 │
│ Relayer 驗證簽名並返回解密後的明文 │
│ 前端本地驗算: base + bonus - penalty - leave = net ✓ │
│ │
│ 📊 可見性: 只有員工本人可見自己的薪資 │
│ │
└─────────────────────────────────────────────────────────────────┘
FHEVM 的 Access Control List (ACL) 決定誰能解密哪個密文:
薪資單建立時:
└─ FHE.allowThis(base/bonus/penalty/leave) → 合約可繼續使用
計算完成時:
└─ FHE.allow(所有欄位, employee) → 員工可解密
支付時:
└─ FHE.allowTransient(net, cUSDC) → cUSDC 在此交易中可使用
政府存取時:
└─ FHE.allow(所有欄位, govMultisig) → 政府可解密
當政府需要存取特定員工的薪資資料時,必須經過嚴格的控制流程:
┌─────────────────────────────────────────────────────────────────┐
│ Break-Glass 流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 🏛️ 政府提交申請 │
│ requestCase(employee, period, reasonHash, evidenceURI) │
│ ↓ │
│ 2. ✅ 公司批准 │
│ approveByIssuer(caseId) ← IssuerMultisig │
│ ↓ │
│ 3. ✅ 政府批准 │
│ approveByGov(caseId) ← GovMultisig │
│ ↓ │
│ 4. ⏳ 24 小時冷靜期 │
│ (員工有時間知悉並尋求法律建議) │
│ ↓ │
│ 5. 🔓 執行並授權 │
│ execute(caseId) │
│ → Payroll.grantGovAccess() │
│ → FHE.allow(欄位, govMultisig) │
│ ↓ │
│ 6. 👁️ 政府解密 │
│ 政府使用 userDecrypt 查看指定期間的薪資 │
│ │
└─────────────────────────────────────────────────────────────────┘
| 保護機制 | 說明 |
|---|---|
| 雙重批准 | 公司 + 政府都必須同意 |
| 24 小時時間鎖 | 給予員工反應時間 |
| 最小化存取 | 只授權特定員工特定期間 |
| 不公開解密 | 永遠不使用 makePubliclyDecryptable |
| 審計追蹤 | 所有存取請求和批准都記錄在鏈上 |
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ 👔 IssuerMultisig (公司 HR/財務) │
│ ├─ 存入 USDC 到 Treasury │
│ ├─ 建立和設定員工薪資單 │
│ ├─ 計算淨薪資 │
│ ├─ 執行支付 │
│ └─ 批准政府存取申請 │
│ │
│ 👤 Employee (員工) │
│ ├─ 解密自己的薪資單 │
│ ├─ 本地驗證計算正確性 │
│ └─ 查看自己的 cUSDC 餘額 │
│ │
│ 🏛️ GovMultisig (政府機關) │
│ ├─ 提交合規存取申請 │
│ ├─ 批准存取申請 │
│ └─ 執行後解密授權的薪資資料 │
│ │
└─────────────────────────────────────────────────────────────────────┘
| 資料 | 公眾 | 員工 | 公司 | 政府 (授權後) |
|---|---|---|---|---|
| 總存款金額 | ✅ | ✅ | ✅ | ✅ |
| 員工名單 | ✅ | ✅ | ✅ | ✅ |
| 薪資單狀態 | ✅ | ✅ | ✅ | ✅ |
| 個人薪資明細 | ❌ | ✅ (自己) | ❌ | ✅ (特定) |
| 支付金額 | ❌ | ✅ (自己) | ❌ | ✅ (特定) |
| cUSDC 餘額 | ❌ | ✅ (自己) | ❌ | ❌ |
- Solidity ^0.8.24
- Zama FHEVM SDK @fhevm/solidity v0.9.1
- 加密類型 encrypted-types v0.0.4
- 開發框架 Hardhat
- 框架 Next.js 14 (App Router)
- 樣式 Tailwind CSS + Vaporwave 設計系統
- Web3 wagmi + viem
- FHEVM 整合 Mock 模式 (SDK 正式發布後切換)
| 網路 | Chain ID | 用途 |
|---|---|---|
| Sepolia | 11155111 | 測試網部署 |
| Hardhat | 31337 | 本地開發 |
- 事件不洩漏金額 — 所有 emit 的事件只包含 ID 和狀態,不含金額
- 條件分支使用 FHE.select — 永遠不對
ebool使用if/else - 不使用公開解密 — 永遠不呼叫
makePubliclyDecryptable
- 角色閘控 — 所有敏感操作都有
onlyIssuer、onlyGate等修飾符 - ACL 驗證 — 使用
FHE.isSenderAllowed()驗證 caller 權限 - 最小權限原則 — 只授予完成操作所需的最小權限
- 不基於加密值的成功/失敗行為來推測資料
- 支付失敗不會透露是「餘額不足」還是其他原因
PayWave/
├── contracts/ # 智能合約
│ ├── src/
│ │ ├── cUSDC.sol # 機密 USDC 代幣
│ │ ├── Payroll.sol # 核心薪資合約
│ │ ├── PayrollTreasury.sol
│ │ ├── USDCWrapper.sol
│ │ ├── ComplianceGate.sol
│ │ └── lib/
│ │ └── Errors.sol
│ └── FHEVM_MIGRATION_NOTES.md
│
├── frontend/ # 前端應用
│ ├── src/
│ │ ├── app/
│ │ │ ├── issuer/ # HR 儀表板
│ │ │ ├── employee/ # 員工入口
│ │ │ └── government/ # 政府入口
│ │ ├── components/
│ │ └── lib/
│ │ ├── fhevm.ts # FHEVM SDK 整合
│ │ ├── contracts.ts # 合約 ABI
│ │ └── addresses.ts # 合約地址
│ └── package.json
│
└── PayWave_Work_Spec.md # 完整工作規格
MIT License
PayWave — 讓薪資回歸私密 🔐