ShieldCard is a confidential corporate spend control app built for the Fhenix Buildathon. It demonstrates how a company can enforce spend-policy logic on-chain without exposing employee request amounts, encrypted per-employee limits, or private policy decisions in public state.
Live demo: https://shieldcard-fhenix.netlify.app
Contract: 0x536b31435bFAE994169181AcA9BAadC784555b4B on Arbitrum Sepolia
Explorer: https://sepolia.arbiscan.io/address/0x536b31435bFAE994169181AcA9BAadC784555b4B
Most on-chain treasury tools are transparent by default. That is useful for auditability, but it is a poor fit for routine corporate operations where payment amounts, department budgets, category policies, and approval thresholds should not be public.
ShieldCard keeps those inputs encrypted while still allowing the policy engine to evaluate:
- whether a request amount is within an employee's encrypted limit
- whether the request category matches the allowed policy category
- whether the final result should be approved or denied
- Admin registers employees on-chain
- Admin stores encrypted employee limits
- Employee encrypts amount and category locally before submission
- Contract evaluates policy privately with FHE operations
- Employee can privately reveal their own result with a permit
- Admin can publish the final plain-text outcome to the public audit trail
- Observer sees only public metadata, ciphertext handles, and published outcomes
flowchart LR
E[Employee Browser] -->|Encrypt amount + category| C[ShieldCard Frontend]
C -->|submitRequest| P[ShieldCardPolicy.sol]
A[Admin Browser] -->|Encrypt limit| C
C -->|setEmployeeLimit| P
P -->|FHE policy evaluation| F[Fhenix CoFHE / Threshold Network]
F -->|encrypted result handle| P
E -->|permit-based decrypt| F
A -->|decrypt for tx + publish| F
A -->|publishDecryptedResult| P
O[Observer] -->|public reads only| P
flowchart TD
Start[Employee opens app] --> Connect[Connect wallet]
Connect --> Encrypt[Encrypt amount and category locally]
Encrypt --> Submit[Submit encrypted request]
Submit --> Evaluate[Contract evaluates private policy]
Evaluate --> Result[Encrypted result stored on-chain]
Result --> Reveal[Employee reveals result privately]
Result --> Publish[Admin publishes final outcome]
Publish --> Audit[Observer sees public audit trail]
flowchart LR
Admin -->|register employee| Contract
Admin -->|set encrypted limit| Contract
Employee -->|submit encrypted request| Contract
Employee -->|private reveal via permit| Threshold[Threshold Network]
Admin -->|publish decrypted result| Contract
Observer -->|read public request metadata| Contract
sequenceDiagram
participant Admin
participant Employee
participant Frontend
participant Contract
participant TN as Threshold Network
Admin->>Frontend: Encrypt employee limit
Frontend->>Contract: setEmployeeLimit(encLimit)
Employee->>Frontend: Enter amount, category, memo
Frontend->>Frontend: Encrypt amount + category locally
Frontend->>Contract: submitRequest(encAmount, encCategory, memo)
Contract->>Contract: FHE policy evaluation
Contract-->>Employee: Encrypted status handle available
Employee->>TN: Reveal with permit
TN-->>Employee: Private approved / denied result
Admin->>TN: Decrypt for transaction
TN-->>Admin: Plain status + signature
Admin->>Contract: publishDecryptedResult(status, sig)
AdminRegisters employees, stores encrypted limits, and publishes final outcomes.EmployeeSubmits encrypted requests and privately reveals personal results.ObserverReads public metadata and published outcomes without access to confidential values.
contracts/ Solidity contract and interfaces
scripts/ Deploy, seed, verify, and publish scripts
test/ Hardhat + mock CoFHE contract tests
deployments/ Saved deployed addresses by network
frontend/ Next.js app for landing, admin, employee, and observer views
brand-assets/ Project logo and wordmark assets
context.md Local continuity and release log
- Solidity
0.8.28 - Hardhat
@fhenixprotocol/cofhe-contracts@cofhe/sdk- Next.js 14 App Router
- React 18
- wagmi + viem
- Netlify static deployment
- Arbitrum Sepolia
- Network: Arbitrum Sepolia
- Contract:
ShieldCardPolicy - Address:
0x536b31435bFAE994169181AcA9BAadC784555b4B - Current admin:
0x94c188F8280cA706949CC030F69e42B5544514ac - Current registered employees:
0x8df6Dd7B18BD693DD98228D03fEe85424C4293A40x1D7f7354eDA779D15Ebd258aE92F82D9E1b98028
- Policy model:
- amount must be less than or equal to the employee's encrypted limit
- category must equal the allowed category id
1
Publicly visible:
- employee address
- memo
- timestamp
- ciphertext handles
- published final outcome after admin publication
Kept confidential:
- request amount
- request category meaningfully interpreted in policy evaluation
- employee spend limit
- raw decision before reveal/publication
- policy comparison inputs
The frontend was hardened for demo usage with:
- explicit
Open MetaMask,submitted, andconfirmingtransaction states - query invalidation after every write
- lightweight polling for request views
- direct injected-wallet connection flow instead of a broader wallet modal stack
- switch-network recovery controls on admin and employee flows
pnpm install
cd frontend && pnpm installRoot .env:
cp .env.example .envFrontend .env.local:
cp frontend/.env.example frontend/.env.localRequired root env values:
PRIVATE_KEYEMPLOYEE_A_PRIVATE_KEYEMPLOYEE_B_PRIVATE_KEYARB_SEPOLIA_RPC_URLARBISCAN_API_KEY
Required frontend env values:
NEXT_PUBLIC_SHIELDCARD_ADDRESSNEXT_PUBLIC_ARB_SEPOLIA_RPC_URL
pnpm compile
pnpm testcd frontend
pnpm devRoot:
pnpm compilepnpm testpnpm arb-sepolia:deploypnpm arb-sepolia:seed-demopnpm arb-sepolia:publish-resultspnpm arb-sepolia:verify-seed
Frontend:
pnpm lintpnpm buildpnpm dev
Recommended recording path:
- Open the landing page and move into
/app - Connect the admin wallet on Arbitrum Sepolia
- Show employee registration and encrypted limit setup
- Switch to an employee wallet and submit a request
- Show the explicit wallet/confirmation states resolving
- Reveal the result privately as the employee
- Switch back to the admin wallet and publish the outcome
- End on
/observerto show the public audit trail without exposing the confidential inputs
- Single-company demo contract
- Fixed allowed category model in the current MVP
- No real payment rails or settlement integration
- No mobile-first WalletConnect path in the present demo configuration
- Threshold-network latency still exists for publish/reveal flows and must be communicated in UX
- richer encrypted category policy support
- multi-policy or multi-company configuration
- better result indexing and filtering for admin operations
- audit exports and compliance-oriented observer reporting
- stronger end-to-end browser automation around demo-safe wallet flows