Skip to main content

Confidential Token Deploy (fhEVM)

Deploy fully homomorphic encryption (FHE) tokens on fhEVM-compatible networks. Balances and transfers are encrypted on-chain — only authorized parties can decrypt them.

Supported Standards

StandardDescription
CONFIDENTIAL_ERC20Encrypted ERC-20 with private balances and transfers
CONFIDENTIAL_ERC20_VOTESEncrypted ERC-20 with private voting delegation
CONFIDENTIAL_ERC721Encrypted metadata ERC-721

Prerequisites

  1. fhEVM-enabled network — deploy to a network where is_fhevm = true (e.g., Zama devnet, Inco Rivest)
  2. Network configuration — the target network must have all fhEVM fields populated:
    • confidential_factory_address
    • acl_address
    • coprocessor_address
    • kms_verifier_address
    • gateway_url
  3. API key — secret key (sk_...)
tip

Use GET /v1/networks and filter by is_fhevm: true to discover available fhEVM networks.

1. Check Network Support

import Urblock from "@urblock/sdk";

const client = new Urblock({ apiKey: "sk_test_..." });

const networks = await client.networks.list();
const fhevmNetworks = networks.data.filter((n) => n.is_fhevm);
console.log("fhEVM networks:", fhevmNetworks.map((n) => n.name));

Or with curl:

curl https://api.urblock.io/v1/networks \
-H "Authorization: Bearer sk_test_..." | jq '.data[] | select(.is_fhevm == true) | .name'

2. Deploy a Confidential ERC-20

const token = await client.tokens.create({
name: "Private Stablecoin",
symbol: "pUSD",
standard: "ERC20",
network_id: "net_zama_devnet", // or chain_id
initial_supply: "1000000000000000000000000",
confidential: true, // ← enables fhEVM encryption
features: {
mintable: true,
burnable: true,
pausable: true,
},
idempotency_key: "deploy-pusd-001",
});

console.log("Token deployed:", token.id);
console.log("Contract:", token.contract_address);
console.log("Tx hash:", token.deploy_tx);
curl -X POST https://api.urblock.io/v1/tokens \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Private Stablecoin",
"symbol": "pUSD",
"standard": "ERC20",
"network_id": "net_zama_devnet",
"initial_supply": "1000000000000000000000000",
"confidential": true,
"features": { "mintable": true, "burnable": true },
"idempotency_key": "deploy-pusd-001"
}'

3. Deploy Confidential ERC-20 with Votes

caution

CONFIDENTIAL_ERC20_VOTES requires networks with full coprocessor support. Some fhEVM testnets may not yet support encrypted delegate/vote flows.

const govToken = await client.tokens.create({
name: "Private Governance",
symbol: "pGOV",
standard: "ERC20_VOTES",
network_id: "net_zama_devnet",
initial_supply: "10000000000000000000000000",
confidential: true,
features: { mintable: true, burnable: true },
idempotency_key: "deploy-pgov-001",
});

4. Deploy Confidential ERC-721

const nft = await client.tokens.create({
name: "Private Art",
symbol: "pART",
standard: "ERC721",
network_id: "net_zama_devnet",
confidential: true,
features: { mintable: true, burnable: true },
idempotency_key: "deploy-part-001",
});

How It Works

  1. The API detects confidential: true and validates the target network is fhEVM-enabled
  2. The token is deployed via UrblockConfidentialFactory instead of the standard factory
  3. Constructor args include the network's acl_address, coprocessor_address, and kms_verifier_address
  4. All balance and allowance state is stored as FHE ciphertexts on-chain
  5. Only the token owner and approved addresses can decrypt balances via the fhEVM gateway

Contract ABIs

Get the full ABIs for integration:

const abi = await client.contracts.getAbi("confidential_erc20");
// Also available: confidential_erc20_votes, confidential_erc721, confidential_factory

See the Contracts & ABIs reference for the full list.

Error Handling

Error CodeWhen
network_not_fhevmTarget network does not support fhEVM
incomplete_fhevm_configNetwork is fhEVM but missing required addresses (acl, coprocessor, kms_verifier)
confidential_votes_unsupportedERC20_VOTES with confidential: true not supported on this network