CipherWrap
Developer Kit

Build with the official Zama registry

Every snippet on this page uses real, verified Sepolia addresses from src/config/zamaSepolia.ts — the single source of truth in CipherWrap. Addresses interpolated at build time; they can't go stale.

Why use the official registry?

The Zama Wrappers Registry is the canonical on-chain index of all production-grade ERC-7984 confidential wrappers for Sepolia. Integrating it — rather than deploying your own throwaway wrapper — gives you:

  • Shared liquidity. Your users share depth with every other app that wraps the same underlying token.
  • Revocation visibility. The isValid flag lets you disable wrap/unwrap instantly if a wrapper is deprecated — no redeployment needed.
  • One place to check for new pairs. When Zama deploys new wrappers, your app discovers them automatically at runtime.

1. Read all pairs from the registry

One call returns every pair, including revoked ones. Filter by isValid before enabling actions.

TypeScript · wagmi
import { useReadContract } from 'wagmi'

// Always read pairs live — never substitute a static list.
const { data: pairs } = useReadContract({
  address: '0x2f0750Bbb0A246059d80e94c454586a7F27a128e', // official Zama Wrappers Registry (Sepolia)
  abi: registryAbi,       // from src/abis/registry.ts in CipherWrap
  functionName: 'getTokenConfidentialTokenPairs',
})
// pairs: Array<{ confidentialTokenAddress, tokenAddress, isValid }>

// Always check isValid. Revoked pairs are still returned.
const valid = pairs?.filter((p) => p.isValid) ?? []

2. Token-specific snippets

Select any known wrapper — all snippets update to show that pair's real addresses.

Token:

a. Config object

TypeScript · cUSDCMock
// Drop this into your project — all values from the official Zama registry.
const TOKEN = {
  symbol:            'cUSDCMock',
  name:              'Confidential USDC (Mock)',
  wrapperAddress:    '0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639',
  underlyingAddress: '0x9b5Cd13b8eFbB58Dc25A05CF411D8056058aDFfF',
  registry:          '0x2f0750Bbb0A246059d80e94c454586a7F27a128e',  // official Zama Wrappers Registry
  chainId:           11155111,                  // Sepolia
  decimals:          6,
} as const

b. Approve + Wrap (shield)

TypeScript · @zama-fhe/react-sdk · cUSDCMock
import { parseUnits } from 'viem'
import { useApproveUnderlying, useShield } from '@zama-fhe/react-sdk'

// Step 1 — approve the cUSDCMock wrapper to pull USDCMock
const { mutate: approve } = useApproveUnderlying(
  '0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639',
)
approve({ amount: parseUnits('100', 6) })

// Step 2 — FHE-encrypt locally, then deposit (shield)
const { mutate: shield } = useShield({
  address: '0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639',
})
shield({
  amount: parseUnits('100', 6),
  approvalStrategy: 'skip',                     // pre-approved in step 1
  onShieldSubmitted: (txHash) => console.log('wrap tx:', txHash),
})
// On-chain your USDCMock balance becomes an FHE ciphertext handle.
// No observer — including the contract owner — can read your balance.

c. Decrypt confidential balance

TypeScript · @zama-fhe/react-sdk · cUSDCMock
import { formatUnits } from 'viem'
import {
  useHasPermit,
  useGrantPermit,
  useConfidentialBalance,
} from '@zama-fhe/react-sdk'

const WRAPPER = '0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639' // cUSDCMock

// Step 1 — grant a user-specific permit (off-chain EIP-712 — zero gas)
const { data: hasPermit } = useHasPermit({ contractAddresses: [WRAPPER] })
const { mutate: grantPermit } = useGrantPermit()
// call once: grantPermit([WRAPPER])

// Step 2 — read and auto-decrypt the confidential balance
const { data: balance } = useConfidentialBalance(
  { address: WRAPPER, account: userAddress },
  { enabled: hasPermit === true },
)
// balance is a bigint — decrypted only for the permit holder.
// Nobody else can produce this value.
// formatUnits(balance, 6) → e.g. "100.0"

d. Unwrap (two-phase unshield)

TypeScript · @zama-fhe/react-sdk · cUSDCMock
import { parseUnits } from 'viem'
import { useUnshield } from '@zama-fhe/react-sdk'

// Two on-chain phases — the SDK manages both automatically.
// Phase 1: FHE-encrypt the amount → submit unwrap() on-chain
// Phase 2: await Zama FHE network proof → submit finalizeUnwrap()

const { mutate: unshield } = useUnshield(
  '0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639', // cUSDCMock
)

unshield({
  amount: parseUnits('100', 6),
  onUnwrapSubmitted:   (txHash) => console.log('Phase 1 tx:', txHash),
  onFinalizing:        ()       => console.log('Waiting for FHE proof…'),
  onFinalizeSubmitted: (txHash) => console.log('Phase 2 tx:', txHash),
})
// When onFinalizeSubmitted fires, your USDCMock is back
// in your ERC-20 balance at 0x9b5Cd13b8eFbB58Dc25A05CF411D8056058aDFfF

If finalization is interrupted, use useResumeUnshield(wrapperAddress) with the original phase-1 tx hash to continue from phase 2.

3. Verified Sepolia contract addresses

All addresses verified against the official Zama protocol-apps repository. Do not use unverified addresses.

Wrappers Registry0x2f0750Bbb0A246059d80e94c454586a7F27a128e

Known wrapper pairs · Sepolia (chainId 11155111)

cUSDCMockConfidential USDC (Mock)Public faucet
Wrapper0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639
Underlying0x9b5Cd13b8eFbB58Dc25A05CF411D8056058aDFfF
Decimals6
cUSDTMockConfidential USDT (Mock)Public faucet
Wrapper0x4E7B06D78965594eB5EF5414c357ca21E1554491
Underlying0xa7dA08FafDC9097Cc0E7D4f113A61e31d7e8e9b0
Decimals6
cWETHMockConfidential WETH (Mock)Public faucet
Wrapper0x46208622DA27d91db4f0393733C8BA082ed83158
Underlying0xff54739b16576FA5402F211D0b938469Ab9A5f3F
Decimals6
cBRONMockConfidential BRON (Mock)Public faucet
Wrapper0xaa5612FA27c927a0c7961f5AEFEE5ba3A0F9C891
Underlying0xFf021fB13cA64e5354c62c954b949a88cfDEb25E
Decimals6
cZAMAMockConfidential ZAMA (Mock)Public faucet
Wrapper0xf2D628d2598aF4eAF94CB76a437Ff86CA78FfbFB
Underlying0x75355a85c6FB9df5f0C80FF54e8747EEe9a0BF57
Decimals6

Underlying is a TEST token, not the real Sepolia ZAMA token.

ctGBPMockConfidential tGBP (Mock)Public faucet
Wrapper0xfCE5c7069c5525eF6c8C2b2E35A745bA20a2F7CC
Underlying0x93c931278A2aad1916783F952f94276eA5111442
Decimals6

Mock tGBP for developer testing. Distinct from the non-mock ctGBP.

cXAUtMockConfidential XAUt (Mock)Public faucet
Wrapper0xe4FcF848739845BC81Dee1d5352cf3844F0a60C7
Underlying0x24377AE4AA0C45ecEe71225007f17c5D423dd940
Decimals6
ctGBPConfidential tGBPRestricted
Wrapper0x167DC962808B32CFFFc7e14B5018c0bE06A3A208
Underlying0xf6Ef9ADB61A48E29E36bc873070A46A3D2667ff3
Decimals6

Restricted mint — wraps the real testnet tGBP. No public faucet.

4. Resources

Official Zama documentation and standards.