privacy protocol logo
Skip to Content

Deployment

Your DAO is deploy-your-own — you inherit PrivateDaoAdapter and deploy your contract. The membership verifier is shared, reusable infrastructure: point your DAO at the pre-deployed one instead of redeploying a multi-million-gas contract.

Reusable deployments

The verifier matching the bundled circuit is live on Sepolia (deployments.json in the package lists these):

ContractSepolia address
HonkVerifier (membership verifier)0x6554ebdBc25e9023BC80006775958be57f8d8ea1
ZKTranscriptLib (linked library)0xa567D41325Cfc5670827eCfDc980f7e381791d27
import deployments from "@privacy-protocol/cipher-contracts/deployments.json"; const { HonkVerifier } = deployments["ethereum-sepolia"];

Deploy your DAO

Bring your own confidential votes token and (optionally) a membership root.

// scripts/deploy.ts import { ethers } from "hardhat"; const VERIFIER = "0x6554ebdBc25e9023BC80006775958be57f8d8ea1"; // reuse the shared verifier const TOKEN = process.env.VOTES_TOKEN!; // your ERC-7984 votes token const MEMBERSHIP_ROOT = process.env.MEMBERSHIP_ROOT!; // Poseidon2 root of your members async function main() { const MyDao = await ethers.getContractFactory("MyDao"); const dao = await MyDao.deploy(TOKEN, VERIFIER, MEMBERSHIP_ROOT); await dao.waitForDeployment(); console.log("MyDao:", await dao.getAddress()); } main().catch((e) => { console.error(e); process.exitCode = 1; });
npx hardhat run scripts/deploy.ts --network sepolia

Start confidential-only (no ZK)

Deploy with a zero verifier and zero root, then turn the gate on later with setZkMembership:

const dao = await MyDao.deploy(TOKEN, ethers.ZeroAddress, ethers.ZeroHash);

Deploy your own verifier (custom circuit only)

You only need this if you author your own Noir membership circuit. Cipher ships the verifier, not the circuit — regenerate the verifier from your circuit (it’s the standard Noir → Solidity HonkVerifier output), then deploy it. The HonkVerifier links the ZKTranscriptLib library:

// scripts/deployVerifier.ts import { ethers } from "hardhat"; async function main() { const lib = await (await ethers.getContractFactory("ZKTranscriptLib")).deploy(); await lib.waitForDeployment(); const HonkVerifier = await ethers.getContractFactory("HonkVerifier", { libraries: { ZKTranscriptLib: await lib.getAddress() }, }); const verifier = await HonkVerifier.deploy(); await verifier.waitForDeployment(); console.log("ZKTranscriptLib:", await lib.getAddress()); console.log("HonkVerifier:", await verifier.getAddress()); } main().catch((e) => { console.error(e); process.exitCode = 1; });

Then pass that verifier address to your DAO constructor (or setZkMembership).

Reusing the shared verifier only works if you use the bundled circuit. A custom circuit produces a different verification key, so it needs its own verifier.

Environment

# .env SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_KEY PRIVATE_KEY=your_deployer_private_key VOTES_TOKEN=0xYourConfidentialVotesToken MEMBERSHIP_ROOT=0xYourPoseidon2Root

Network support

NetworkStatus
SepoliaAvailable — reusable verifier deployed
Ethereum mainnetComing soon
L2 networksPlanned

Next steps

Last updated on