Decentralized private credit for SMEs using iExec Nox Confidential Computing and ERC-7984 Confidential Tokens on Arbitrum Sepolia.
- Project Overview
- Architecture
- Prerequisites
- Smart Contract Setup & Deployment
- Frontend Setup
- Testing the Flows
- Deployed Contract Addresses
- Project Structure
PrivCredit is a decentralized platform where:
- Originators tokenize private credit instruments (invoices, short-term SME loans) as PCT (PrivCreditToken) — an ERC-7984 Confidential Token.
- Lenders supply liquidity to credit pools privately. Their position sizes are never exposed on-chain.
- Auditors (the contract owner in this demo) can selectively decrypt balances for compliance — without exposing other participants.
Traditional DeFi lending exposes all position sizes publicly. For institutional private credit, this is unacceptable:
- Competitors can see your exposure
- Front-running is possible
- Regulatory selective disclosure is impossible
ERC-7984 + iExec Nox solves this by encrypting balances and transfer amounts inside a Trusted Execution Environment (TEE).
┌─────────────────────────────────────────────────────────┐
│ Arbitrum Sepolia │
│ │
│ ┌─────────────────────┐ ┌────────────────────────┐ │
│ │ PrivCreditToken │ │ PrivCreditPool │ │
│ │ (ERC-7984 / PCT) │───▶│ (Lending Pool) │ │
│ │ │ │ │ │
│ │ - encryptedBalance │ │ - deposit(encrypted) │ │
│ │ - confidentialXfer │ │ - Event: Deposited │ │
│ │ - auditBalance() │ │ (address only, NO │ │
│ └─────────────────────┘ │ amount emitted) │ │
│ └────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▲ ▲
│ │
┌────────┴──────────────────────────────┴────────┐
│ iExec Nox TEE Layer │
│ - FHE encryption of amounts before tx │
│ - Selective decryption for auditor only │
│ - No plaintext ever hits the chain │
└────────────────────────────────────────────────┘
▲
│
┌────────┴────────────────────────────────────────┐
│ Next.js Frontend (Wagmi + RainbowKit) │
│ - Connect wallet (Arbitrum Sepolia) │
│ - Mint PCT (originator flow) │
│ - Confidential transfer (hidden amount) │
│ - Deposit to pool (position stays private) │
└─────────────────────────────────────────────────┘
- Node.js >= 18
- npm >= 9
- A wallet with Arbitrum Sepolia ETH for gas
- An Arbiscan API key (optional, for contract verification): https://arbiscan.io/myapikey
- A WalletConnect Project ID (for the frontend): https://cloud.walletconnect.com
cd contracts
npm installcp .env.example .envEdit .env:
PRIVATE_KEY=your_deployer_wallet_private_key_here
ARBITRUM_SEPOLIA_RPC=https://sepolia-rollup.arbitrum.io/rpc
ARBISCAN_API_KEY=your_arbiscan_api_key_here # optionalnpm run compileExpected output:
Compiled 2 Solidity files successfully
npm run deploy:sepoliaExpected output:
🚀 Deploying PrivCredit contracts to arbitrumSepolia
──────────────────────────────────────────────────
📬 Deployer address: 0xYourAddress
📄 Deploying PrivCreditToken (PCT)...
✅ PrivCreditToken deployed at: 0xABC...
🏦 Deploying PrivCreditPool...
✅ PrivCreditPool deployed at: 0xDEF...
💰 Minting initial PCT to deployer (for demo)...
✅ Minted 10,000 PCT to 0xYourAddress
──────────────────────────────────────────────────
🎉 Deployment complete!
NEXT_PUBLIC_PCT_ADDRESS=0xABC...
NEXT_PUBLIC_POOL_ADDRESS=0xDEF...
Copy the two addresses — you will need them for the frontend.
Verification happens automatically during deploy if ARBISCAN_API_KEY is set.
Manual verification:
npx hardhat verify --network arbitrumSepolia 0xYourPCTAddress
npx hardhat verify --network arbitrumSepolia 0xYourPoolAddress "0xYourPCTAddress" "PrivCredit SME Invoice Pool" "Invoice Financing"cd frontend
npm installcp .env.local.example .env.localEdit .env.local:
NEXT_PUBLIC_PCT_ADDRESS=0xYourPrivCreditTokenAddress
NEXT_PUBLIC_POOL_ADDRESS=0xYourPrivCreditPoolAddress
NEXT_PUBLIC_CHAIN_ID=421614
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_idnpm run devnpm install -g vercel
vercel login
vercel --prodWhen prompted, add environment variables:
NEXT_PUBLIC_PCT_ADDRESSNEXT_PUBLIC_POOL_ADDRESSNEXT_PUBLIC_CHAIN_ID=421614NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID
- Push your
frontend/folder to a GitHub repo - Go to https://vercel.com/new
- Import the repository
- Set Root Directory to
frontend - Add environment variables in the Vercel dashboard
- Click Deploy
- Connect wallet to Arbitrum Sepolia
- Go to 01 / Mint tab
- Enter amount (e.g.
1000) - Click Mint PCT
- Approve transaction in wallet
- Check terminal log for confirmation
The deployer wallet is the contract owner. Only the owner can mint. If you want another wallet to mint, call
transferOwnership()on the PCT contract.
- Go to 02 / Transfer tab
- Enter a recipient address
- Enter amount (e.g.
100) - Click Send (Confidential)
- Approve transaction in wallet
What happens on-chain:
ConfidentialTransfer(from, to)event is emitted — NO amount- The Arbiscan explorer will show 0 value transfer
- The actual amount is ABI-encoded (simulating FHE encryption)
- First, mint some PCT to your wallet (Flow 1)
- Go to 03 / Deposit tab
- Enter deposit amount (e.g.
500) - Click Deposit (Private)
- Two transactions fire:
confidentialApprove— authorises pool to pull PCTconfidentialTransfer— sends PCT to pool
- Your position shows as "Active (amount hidden)"
- Pool lender count increments
Privacy check on Arbiscan:
- The
Depositedevent shows only your address - No amount is ever stored or emitted
Call auditBalance(address) directly on Arbiscan (connected as owner):
- Go to Arbiscan → contract → Write (as owner)
- Call
auditBalance(yourAddress)— returns plaintext balance - This demonstrates selective disclosure for compliance
Fill these in after deployment:
| Contract | Network | Address |
|---|---|---|
| PrivCreditToken (PCT) | Arbitrum Sepolia | 0x_FILL_AFTER_DEPLOY |
| PrivCreditPool | Arbitrum Sepolia | 0x_FILL_AFTER_DEPLOY |
Arbiscan: https://sepolia.arbiscan.io/address/0x_FILL_AFTER_DEPLOY
privcredit/
├── contracts/ # Hardhat project
│ ├── contracts/
│ │ ├── PrivCreditToken.sol # ERC-7984 Confidential Token
│ │ └── PrivCreditPool.sol # Private lending pool
│ ├── scripts/
│ │ └── deploy.ts # Deployment script
│ ├── hardhat.config.ts
│ ├── package.json
│ ├── tsconfig.json
│ └── .env.example
│
└── frontend/ # Next.js 15 app
├── app/
│ ├── page.tsx # Main interactive UI
│ ├── layout.tsx # Root layout
│ ├── providers.tsx # Wagmi + RainbowKit providers
│ ├── wagmi.ts # Chain config + contract ABIs
│ └── globals.css # Dark cipher aesthetic
├── next.config.js
├── tailwind.config.js
├── package.json
└── .env.local.example