The shape#
DEPLOYED_ADDRESSES is a nested object indexed by product → contract → chainId. Sepolia (11155111) is the common chain across all products. Mainnet (1) has an entry only for fhe-disperse. The testnet faucet also supports local Anvil (31337), but canonical registry addresses exist only for Sepolia; local faucet clients pass an explicit CTTT address override and discover TTT through the wrapper. Other local chains get their addresses from .cache/local-deploys.json written by pnpm fhevm:up in the SDK monorepo.
import {
DEPLOYED_ADDRESSES,
getFheVestingFactoryAddress,
} from "@tokenops/sdk";
import { sepolia } from "viem/chains";
const addr = getFheVestingFactoryAddress(sepolia.id);
// → "0xA87701CE9A52D43681600583a99c85b50DbE3150"
// Or read the raw map:
const raw = DEPLOYED_ADDRESSES.fheVesting.confidentialVestingFactory[sepolia.id];The matrix#
fhe-vesting: Sepolia live, audited by OpenZeppelin. Mainnet pending deployment + Zama KMS readiness.
fhe-airdrop: Sepolia live, audited by OpenZeppelin. Mainnet pending deployment + Zama KMS readiness.
fhe-disperse: Sepolia and Ethereum mainnet both live.
testnet-faucet: Sepolia canonical TTT/CTTT live. Local Anvil (31337) is supported for fixtures and forks with an explicit CTTT address override; no mainnet deployment.
Always check Resources for the canonical list — it reads from this same export at build time, so the page is never out of date with the SDK.
Accessors vs raw map#
The typed accessors (getFheVestingFactoryAddress,getFheAirdropFactoryAddress,getFheDisperseSingletonAddress) collapse the "explicitly null" and "missing key" cases to undefined. Use them in product code; reach into the raw map only if you need to distinguish "known chain, not deployed yet" from "unknown chain."
Custom RPCs#
The SDK takes a viem PublicClient and WalletClient as input. You configure RPC at the viem layer; the SDK is RPC-agnostic. Public RPCs work; Alchemy / Infura / your own works the same.