A privacy-focused encrypted ERC token protocol built on zero-knowledge proofs. This frontend application provides a user interface for registering with the protocol, depositing tokens, and performing private transfers using cryptographic proofs.
- Zero-Knowledge Registration: Register your identity without revealing private information
- Encrypted Balances: All token balances are encrypted using ElGamal encryption
- Private Transfers: Transfer tokens without revealing amounts or recipient details
- Auditable Privacy: Supports auditor functionality for compliance while maintaining user privacy
- Multi-Token Support: Handle multiple ERC20 tokens within the encrypted system
The system uses Groth16 zero-knowledge proofs with the following circuits:
- RegistrationCircuit: Proves identity ownership without revealing private keys
- TransferCircuit: Proves valid transfers while keeping amounts and balances private
- MintCircuit: Handles encrypted deposits into the system
- WithdrawCircuit: Handles encrypted withdrawals from the system
- BurnCircuit: Handles token burning operations
- Node.js 18+ and npm/yarn/pnpm
- MetaMask or compatible Web3 wallet
- Access to Avalanche Fuji testnet
- Clone and install dependencies:
git clone <repository-url>
cd eerc-frontend
npm install- Ensure circuit files are in place:
# Circuit files should be located at:
public/circuits/RegistrationCircuit.wasm
public/circuits/RegistrationCircuit.groth16.zkey
public/circuits/TransferCircuit.wasm
public/circuits/TransferCircuit.groth16.zkey- Start the development server:
npm run dev- Open http://localhost:3000 in your browser
Contract addresses are defined in constants.json. To update them:
{
"EncryptedERC": {
"contractName": "EncryptedERC",
"address": "0x295257d84Ef96A3208703c550B83EE501F137b54",
"abi": [...]
},
"Registrar": {
"contractName": "Registrar",
"address": "0x98F23388B93D5FBB374331AAE493277db94E6177",
"abi": [...]
}
}To replace addresses:
- Update the
addressfields inconstants.json - Ensure the ABIs match your deployed contracts
- The addresses are automatically imported into
app/lib/contracts.ts
RPC endpoints are configured in app/lib/wagmi-config.ts:
export const config = createConfig({
chains: [mainnet, sepolia, avalancheFuji],
connectors: [injected()],
transports: {
[mainnet.id]: http(), // Uses default RPC
[sepolia.id]: http(), // Uses default RPC
[avalancheFuji.id]: http(), // Uses default RPC
},
})To replace RPC endpoints:
- Import custom RPC URLs:
transports: {
[avalancheFuji.id]: http('https://api.avax-test.network/ext/bc/C/rpc'),
// Add custom RPCs for other chains
}- Add new chains by importing from
wagmi/chainsor defining custom chain configs
The zero-knowledge proof system requires specific circuit files:
Required files in public/circuits/:
RegistrationCircuit.wasm- Compiled registration circuitRegistrationCircuit.groth16.zkey- Proving key for registrationTransferCircuit.wasm- Compiled transfer circuitTransferCircuit.groth16.zkey- Proving key for transfers
To update circuit files:
- Generate new circuits using your preferred zk-SNARK toolkit
- Place the
.wasmand.zkeyfiles inpublic/circuits/ - Update the file paths in the proof generation code if needed
- Message Signing: User signs a deterministic message with their wallet
- Private Key Derivation: A BabyJubJub private key is derived from the signature
- Public Key Generation: The corresponding public key is computed
- Proof Generation: A zero-knowledge proof is created that proves:
- Knowledge of the private key
- The public key corresponds to the private key
- The user controls the Ethereum address
- On-Chain Registration: The proof is submitted to the Registrar contract
Registration Circuit Inputs:
{
SenderPrivateKey: bigint, // BabyJubJub private key
SenderPublicKey: [bigint, bigint], // BabyJubJub public key
SenderAddress: bigint, // Ethereum address
ChainID: bigint, // Blockchain chain ID
RegistrationHash: bigint // Poseidon hash of above values
}- Balance Decryption: Sender decrypts their current encrypted balance
- Recipient Key Lookup: Fetches recipient's public key from Registrar
- New Balance Encryption: Encrypts new balances for sender and recipient
- Proof Generation: Creates a zero-knowledge proof that proves:
- Sender owns the current balance
- Transfer amount is valid (not exceeding balance)
- New encrypted balances are correctly computed
- No tokens are created or destroyed
- On-Chain Transfer: The proof is submitted to the EncryptedERC contract
Transfer Circuit Public Signals:
- Nullifier (prevents double-spending)
- New encrypted balance for sender
- New encrypted balance for recipient
- Transfer amount commitment
- Auditor's encrypted view of the transaction
- Click "Connect Wallet" and select your Web3 wallet
- Ensure you're connected to Avalanche Fuji testnet
- Click "Sign & Generate Proof" to start registration
- Sign the deterministic message in your wallet
- Wait for zero-knowledge proof generation (~30-60 seconds)
- Click "Register" to submit the proof on-chain
- Use the "Mint Test Tokens" section to get testnet tokens
- These will be used for deposits into the encrypted system
- Approve the EncryptedERC contract to spend your tokens
- Enter deposit amount and click "Deposit"
- Your tokens will be encrypted and added to your private balance
- Enter recipient address and transfer amount
- The system will automatically:
- Verify the recipient is registered
- Generate a zero-knowledge proof
- Submit the encrypted transfer on-chain
- Both sender and recipient balances remain private
eerc-frontend/
βββ app/
β βββ components/ # React components
β βββ hooks/ # Custom React hooks
β βββ lib/ # Utility libraries
β β βββ balances/ # Balance encryption/decryption
β β βββ contracts.ts # Contract ABIs and addresses
β β βββ wagmi-config.ts # Wallet and RPC configuration
β β βββ crypto-utils.ts # Cryptographic utilities
β βββ page.tsx # Main application page
βββ public/circuits/ # Zero-knowledge circuit files
βββ constants.json # Contract addresses and ABIs
- Next.js: React framework
- wagmi: Ethereum React hooks
- snarkjs: Zero-knowledge proof generation
- @zk-kit/baby-jubjub: Elliptic curve cryptography
- poseidon-lite: Poseidon hash function
- maci-crypto: Additional cryptographic utilities
"Circuit files not found" error:
- Ensure
.wasmand.zkeyfiles are inpublic/circuits/ - Check file names match exactly:
RegistrationCircuit.wasm, etc.
"Wrong network" error:
- Switch to Avalanche Fuji testnet in your wallet
- Check that contract addresses match the target network
Proof generation taking too long:
- Circuit files may be large - ensure good internet connection
- Consider hosting circuit files on a CDN for production
Transaction fails:
- Ensure you're registered before attempting transfers
- Check that recipient is registered
- Verify you have sufficient encrypted balance
- Use browser developer console to see detailed proof generation logs
- All cryptographic operations are logged with π emojis for easy filtering
- Circuit inputs and outputs are logged during proof generation
- Enable verbose logging by setting
console.login crypto utility files
npm run build
npm run start- Ensure circuit files are properly served in production
- Consider using a CDN for large
.zkeyfiles - Set up proper RPC endpoints for your target networks
- Update contract addresses to mainnet versions
This project is part of the eERC protocol ecosystem. Please refer to the main protocol documentation for licensing information.