Skip to content

Repository files navigation

Shade — Private Payments on Zama fhEVM

Shade is a confidential payments protocol built on Zama's fhEVM. Every balance and transaction amount is an encrypted euint64 ciphertext stored on-chain. Senders, receivers, timestamps, and finality remain public — only the numbers are hidden.

Trust model: FHE runs natively inside the EVM. There is no off-chain coprocessor in the trust model — the math is the trust.

Live on Sepolia · Launch App · Docs


Contracts

Five UUPS-upgradeable contracts, all deployed on Sepolia testnet.

Contract Address What it does
ConfidentialUSDC 0xc2A8ed637BCBFC01CF703CF5F5e7ECf74Fe52D06 Encrypted ERC-20 wrapping Circle's Sepolia USDC. Balances, allowances, and total supply are euint64 ciphertexts. Includes compliance controls (freeze/allowlist) and a two-step async unshield via KMS public decryption.
PayrollVault 0xdcba2eB04B8443fee9AD9E77cEcDb435fCDc0030 Employer creates reusable employee rosters (templates) and payroll runs with per-employee encrypted salaries. No employee can see another's salary.
PrivateEscrow 0x66bDF650d3E3F0F31Be202a379Aeb91ACD822320 Six-state escrow where the locked amount stays encrypted throughout its entire lifecycle — even the arbiter never sees the plaintext.
BalanceProver 0xB11e05B15F7f8249A31d87F623483e6d8Dd67eBA Publishes a verifiable on-chain boolean: "balance ≥ threshold" — without revealing the balance or the threshold. Powered by async KMS public decryption.
StealthSend 0x4a66204aDa1F5F7a25DaE0c17267EfeDB9572907 Recipient address is encrypted as eaddress. Only the intended recipient can claim. Senders can grant selective view access to auditors via grantViewAccess.

Underlying USDC (Sepolia): 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238

Test suite

npx hardhat test

  BalanceProver ......... 4 passing
  ConfidentialUSDC ...... 8 passing
  PayrollVault .......... 6 passing
  PrivateEscrow ......... 6 passing
  StealthSend ........... 4 passing
  28 passing

Architecture

How contracts compose

Feature contracts never hold cUSDC directly. They move it by passing internal euint64 handles into ConfidentialUSDC.transfer / transferFrom, first granting FHE.allowTransient(handle, address(cUSDC)). BalanceProver additionally calls cUSDC.authorizeBalanceRead(prover) so the prover contract has ACL access to compare a user's balance.

Two-step async operations

Two flows cannot complete in a single transaction because they require a plaintext value produced by the Zama KMS off-chain:

Unshield (ConfidentialUSDC)

  1. requestUnshield(handle, proof) — validates, burns the encrypted amount, marks it publicly decryptable
  2. finalizeUnshield(requestId, abiEncodedClearValues, decryptionProof) — anyone submits the KMS-signed plaintext; the contract verifies with FHE.checkSignatures and releases USDC

Balance proof (BalanceProver)

  1. proveAbove(handle, proof) — stores the comparison result as an encrypted handle
  2. Off-chain: publicDecrypt([handle]) via the fhEVM SDK → KMS returns abiEncodedClearValues + decryptionProof
  3. publishProof(user, abiEncodedClearValues, decryptionProof) — verifies and stores the boolean result on-chain

Compliance controls (ConfidentialUSDC)

ConfidentialUSDC includes a lightweight compliance layer without breaking the encryption model:

  • Freezefreeze(address) / unfreeze(address) block an account from sending or receiving. State is a plaintext mapping(address => bool) checked before any FHE operation.
  • AllowlistsetAllowlist(address, bool) and setAllowlistEnabled(bool) restrict transfers to a permitted set when active. Same plaintext-before-FHE guard pattern.
  • Role delegation — the contract owner can assign a complianceAdmin who can manage freeze and allowlist without holding contract ownership.

All guards run before any FHE computation, so no ciphertext is ever touched for a non-compliant account.

Selective disclosure (StealthSend)

function grantViewAccess(uint256 id, address viewer) external {
    require(msg.sender == _transfers[id].sender, "not sender");
    FHE.allow(_transfers[id].amount, viewer);
    FHE.allow(_transfers[id].recipient, viewer);
    emit ViewAccessGranted(id, viewer);
}

ACL grants are permanent in fhEVM v0.11. Once granted, a viewer can request decryption of the amount and recipient address via the Zama gateway. The UI surfaces this as a per-transfer "Grant View Access" flow with an explicit permanence warning.

UUPS + fhEVM initialisation

The coprocessor config lives in proxy storage (ERC-7201 namespaced slot), so FHE.setCoprocessor(ZamaConfig.getEthereumCoprocessorConfig()) is called inside initialize(), not in a constructor.

API version — fhEVM v0.11

Legacy API (spec snippets) This repo (v0.11)
TFHE.* FHE.*
einput externalEuint64 / externalEaddress
TFHE.asEuint64(einput, proof) FHE.fromExternal(ext, proof)
TFHE.allow(x, address(this)) FHE.allowThis(x)
TFHE.gte(...) FHE.ge(...)
GatewayContract + callback FHE.makePubliclyDecryptable → relayer → FHE.checkSignatures

Privacy model

Public on-chain Encrypted on-chain
Sender / receiver address (standard send) Transaction amount (euint64)
That a transfer occurred All balances and allowances
Timestamp, transaction hash Total supply
Gas paid Receiver address (stealth send only, eaddress)
Freeze / allowlist status

Rules enforced in code: no synchronous decryption in state-changing functions; insufficient balance handled via FHE.select (silent, no revert, no information leak); every ciphertext gets explicit ACL grants; events never carry amounts.


Quick start

Contracts

npm install
cp .env.example .env        # fill PRIVATE_KEY and SEPOLIA_RPC_URL
npx hardhat test            # run full suite against fhEVM mock
npx hardhat run scripts/deploy.ts --network sepolia

Deployment writes deployments/sepolia.json with all proxy addresses.

Frontend

See frontend/README.md for full setup instructions.


Repo structure

contracts/          Solidity source (5 contracts + MockUSDC)
test/               Hardhat tests (fhEVM mock)
scripts/            Deploy script
deployments/        JSON address files per network
frontend/           Next.js 14 app — see frontend/README.md

About

Confidential payments protocol on Zama's fhEVM

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages