Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Architect a System for Private Yet Compliant Dividends

A technical guide for developers on building a dividend distribution system that protects shareholder privacy using zero-knowledge proofs and Merkle trees, while maintaining regulatory compliance.
Chainscore © 2026
introduction
TUTORIAL

How to Architect a System for Private Yet Compliant Dividends

This guide explains the technical architecture for building a private dividend distribution system on blockchain, balancing confidentiality with regulatory requirements.

A private dividend system must reconcile two opposing goals: maintaining shareholder confidentiality and ensuring regulatory compliance. Traditional public blockchains like Ethereum expose all transaction details, which is unsuitable for sensitive corporate payouts. The core challenge is to architect a system where dividend amounts and recipient identities are kept private from the public and other shareholders, while providing verifiable proof of compliance to authorized entities like auditors or regulators. This requires a combination of zero-knowledge proofs (ZKPs), selective disclosure mechanisms, and a carefully designed smart contract architecture.

The foundational component is a commitment scheme. Instead of storing shareholder addresses and balances in plain text, the system stores cryptographic commitments (e.g., Pedersen commitments) on-chain. A commitment is a hash-like value that binds to a specific amount and address without revealing them. When dividends are declared, the smart contract logic operates on these commitments. For example, it can verify that a shareholder's committed balance is sufficient for a dividend entitlement using a zero-knowledge proof, without learning the actual balance. This keeps individual financial data private on the public ledger.

Compliance is enabled through selective disclosure. Shareholders generate zero-knowledge proofs, such as zk-SNARKs or zk-STARKs, that attest to specific statements: "My committed balance is greater than X," or "I am a verified accredited investor." These proofs are submitted to the dividend contract. Furthermore, the system can integrate a view key mechanism. Regulators or auditors are issued a key that allows them to decrypt the private transaction details associated with the commitments, providing an audit trail without exposing data to the general public. This architecture is exemplified by privacy-focused L2s like Aztec Network or application-specific zk-rollups.

A basic smart contract structure involves two main states: a shielded pool of commitments and a compliance verifier. The dividend distribution function would require a ZKP that validates: 1) the prover owns a valid commitment, 2) the committed balance meets the dividend threshold, and 3) the prover satisfies any KYC/AML flags (proven without revealing identity). The contract mints a new private commitment for the dividend amount to the shareholder. Off-chain, shareholders use wallets like zk.money or SDKs from ZK-proof libraries (e.g., circom, halo2) to generate the necessary proofs for interaction.

Key considerations for deployment include choosing the right base layer. While a generic privacy chain offers tools, a custom zk-rollup provides greater control over compliance logic and scalability. You must also design the data availability layer: will the private data be available off-chain to a committee (a "data availability committee" or DAC) or posted in encrypted form on-chain? Finally, integrate with identity providers like Circle's Verite or Ontology's DID to issue verifiable credentials that can be used in ZKPs for KYC, creating a system that is both private by default and compliant by design.

prerequisites
FOUNDATION

Prerequisites and Tech Stack

Building a system for private, compliant dividends requires a specific technical foundation. This section outlines the essential tools, protocols, and knowledge needed before you begin implementation.

To architect a private dividend system, you need a strong grasp of core blockchain concepts. You must understand zero-knowledge proofs (ZKPs), particularly zk-SNARKs or zk-STARKs, which enable transaction privacy by proving a statement is true without revealing the underlying data. Familiarity with smart contract development on EVM-compatible chains like Ethereum, Polygon, or Arbitrum is essential, as this is where your dividend logic will reside. You should also be comfortable with cryptographic primitives such as public-key encryption and Merkle trees for managing shareholder registries.

Your tech stack will involve several key components. For the smart contract layer, use a framework like Hardhat or Foundry for development, testing, and deployment. You'll need a library for ZKP operations; consider Circom for circuit design and snarkjs for proof generation, or a more integrated SDK like Aztec's Noir. For off-chain computation and proof generation, a Node.js or Python backend is typical. Finally, you'll require a tool for compliance, such as integrating with a Travel Rule protocol like TRISA or using an oracle to verify regulatory status.

A critical prerequisite is designing a compliant shareholder registry. This is often an off-chain, permissioned database (e.g., PostgreSQL) managed by the issuer, which holds verified investor identities (KYC/AML data). The on-chain system only interacts with cryptographic commitments (hashes) of this registry. You must architect a secure method for this off-chain entity to authorize dividend claims on-chain, typically via signed messages or by managing a Merkle root of eligible addresses, without leaking private shareholder information to the public blockchain.

For the dividend distribution mechanism, you need to decide on a privacy model. A common pattern uses a commit-reveal scheme or a shielded pool. In a commit-reveal scheme, shareholders commit to a secret, claim dividends to a stealth address, and later reveal the link between their public identity and the stealth address to the issuer for compliance. Alternatively, a shielded pool (inspired by Tornado Cash or Aztec) allows users to deposit funds privately and later withdraw them, but requires a robust anonymity set and careful design to avoid regulatory pitfalls.

Before writing code, ensure you have a clear legal and operational framework. Define the compliance requirements: which jurisdictions' regulations apply, what data must be reported, and to whom. Your architecture must include selective disclosure mechanisms, allowing you to cryptographically prove specific compliance facts (e.g., "this address passed KYC") to authorized regulators using ZKPs, without exposing the entire shareholder list. This balance between on-chain privacy and off-chain auditability is the core challenge of the system.

system-architecture
PRIVATE DIVIDEND DISTRIBUTION

System Architecture Overview

Designing a blockchain-based system that distributes dividends privately while maintaining compliance requires a layered architecture. This guide outlines the core components and data flows.

A private yet compliant dividend system is built on three foundational layers: the on-chain settlement layer, the privacy layer, and the compliance oracle layer. The on-chain layer, typically a smart contract on a network like Ethereum or Polygon, handles the final, immutable record of token ownership and dividend claims. It interacts with a zero-knowledge proof (ZKP) system—the privacy layer—which validates claims without revealing sensitive shareholder data. A separate, permissioned compliance service acts as an oracle, attesting to a user's eligibility based on off-chain KYC/AML checks before the privacy proof is generated.

The core privacy mechanism uses zk-SNARKs or zk-STARKs. When dividends are issued, the system generates a cryptographic commitment (a hash) representing the list of eligible shareholders and their entitlements. To claim, a user submits a zk-proof to the smart contract. This proof cryptographically verifies that: 1) the user's identity is in the committed list, 2) they are claiming the correct amount, and 3) they have not claimed before. The contract verifies the proof against the public commitment, disbursing funds without ever revealing which specific identity in the list made the claim.

Compliance is enforced through a gatekeeper oracle. Before a user can generate a claim proof, they must privately submit their credentials to this off-chain service. The service performs checks (e.g., against sanctions lists, jurisdiction rules) and, if approved, issues a signed attestation. This attestation becomes a private input to the zk-proof, proving eligibility to the circuit. This decouples sensitive KYC data from the public blockchain, keeping it off-ledger while enabling on-chain verification of compliance status.

Key architectural considerations include gas optimization for proof verification, key management for the compliance oracle's signing authority, and data availability for the eligibility commitment. Using a rollup like zkSync or a validium can batch proofs and reduce costs. The commitment data must be stored in a way that is accessible for proof generation but does not leak information; using a decentralized storage solution like IPFS with access controls is a common pattern.

In practice, you would use libraries like circom or snarkjs to design the zk-circuit. The smart contract, written in Solidity or Vyper, would integrate a verifier contract, such as the one generated by snarkjs. An off-chain prover service, potentially using Node.js or Python, would fetch the user's attestation and eligibility data to generate the proof client-side before submitting the transaction. This architecture ensures dividends are distributed automatically, privately, and in a regulatorily-sound manner.

key-concepts
PRIVATE & COMPLIANT FINANCE

Core Technical Concepts

Architecting a system for private dividends requires balancing cryptographic privacy with regulatory requirements. These concepts form the technical foundation.

step1-merkle-tree
ARCHITECTURE

Step 1: Building the Eligibility Merkle Tree

The foundation of a private dividend system is a Merkle tree that cryptographically proves eligibility without revealing the full shareholder list.

A Merkle tree is a cryptographic data structure that efficiently verifies membership. For dividend distribution, each leaf node is a hash of a shareholder's address and their entitled dividend amount (e.g., keccak256(abi.encodePacked(address, uint256 amount))). The Merkle root—the final hash at the top of the tree—becomes a public, on-chain commitment to the entire list of eligible recipients and their exact allocations. This root is the single piece of data stored in the smart contract, ensuring the full list of shareholders remains private off-chain.

To build the tree, the issuer first compiles the off-chain shareholder registry. Using a library like OpenZeppelin's MerkleProof, they generate the tree and compute the root. The critical security property is that it's computationally infeasible to derive the original list from the root or to find a valid proof for an address not in the original dataset. This allows any shareholder to independently verify their inclusion by checking a Merkle proof—a small set of sibling hashes—against the published root, without needing to trust the issuer's off-chain data.

The architecture must account for deterministic leaf encoding. The same hashing function (keccak256), encoding order (address then amount), and packing method must be used for both tree generation and on-chain verification. Inconsistencies here will cause valid proofs to fail. For example, a Solidity verifier would reconstruct the leaf as keccak256(abi.encodePacked(account, amount)) and use MerkleProof.verify(proof, root, leaf) to validate. This standardization is essential for interoperability between the off-chain generator and the on-chain contract.

This setup enables selective disclosure. A shareholder receives their specific amount and a unique proof from the issuer. They submit this proof in a transaction to claim their dividend. The contract verifies it against the stored root and transfers the specified amount. Crucially, this transaction does not reveal other shareholders' information on-chain; observers only see that a valid proof was submitted for some leaf in the tree, preserving privacy for all other participants.

For compliance, the issuer maintains the authoritative off-chain registry and Merkle tree. If regulatory scrutiny requires, they can provide the full tree to auditors, proving the total dividend pool matches the sum of all leaf amounts. This creates a system where privacy is the default for everyday operations, but provable accountability is available when legally mandated, satisfying both technological and regulatory requirements for private, compliant distributions.

step2-zk-circuit
ARCHITECTURE

Step 2: Designing the ZK Circuit

This step translates the dividend logic into a provable, private computation using a zero-knowledge circuit.

A ZK circuit is a programmatic representation of a computation, where the prover demonstrates they know a valid input that produces a specific output, without revealing the input itself. For private dividends, the circuit must prove that a user's token holdings at a specific past block met the eligibility threshold, without disclosing the exact amount or wallet address. We'll use the Circom language for this example, a popular domain-specific language for constructing arithmetic circuits compatible with the SnarkJS proving system.

The core logic of our circuit, DividendEligibility.circom, will have two primary private inputs: the user's balance and a cryptographic nullifier. The public inputs are the eligibilityThreshold and a public root representing the Merkle tree of eligible balances. The circuit must verify: 1) The provided balance is greater than or equal to the threshold. 2) The nullifier correctly hashes to a leaf within the published Merkle root. This nullifier prevents double-claiming, as its hash will be recorded on-chain after a successful claim.

Here is a simplified template for the circuit's main component:

circom
template DividendEligibility() {
    signal input balance;
    signal input nullifier;
    signal input threshold;
    signal input root;
    signal output verified;

    // 1. Prove balance >= threshold
    component gt = GreaterEqThan(252); // Assume 252-bit numbers
    gt.in[0] <== balance;
    gt.in[1] <== threshold;

    // 2. Verify nullifier is in the Merkle tree
    component leafHasher = Poseidon(1);
    leafHasher.in[0] <== nullifier;
    signal leaf <== leafHasher.out;

    component treeVerifier = MerkleTreeChecker(levels);
    treeVerifier.leaf <== leaf;
    treeVerifier.root <== root;
    // ... connect sibling signals

    // 3. Output verification
    verified <== gt.out * treeVerifier.out;
}

This circuit outputs verified = 1 only if both conditions are met.

For compliance, the system architect must decide what data is made available to a designated auditor. Using a viewing key mechanism, the auditor can be granted the ability to decrypt a user's claim transaction to verify their identity and eligibility against KYC records, without this link being public. The circuit itself remains unchanged; this is an application-layer design choice where the user encrypts a portion of their proof data with the auditor's public key.

After writing the circuit, you must compile it with circom to generate R1CS constraints and a WebAssembly calculator. Then, use SnarkJS to perform a trusted setup ceremony to generate the proving and verification keys. The final output is a verification_key.json that will be used by the smart contract to validate proofs, ensuring only users with valid, unspent eligibility can claim their dividends.

step3-smart-contract
IMPLEMENTING THE CORE LOGIC

Step 3: Deploying the Claim Smart Contract

This step involves writing and deploying the smart contract that will hold the dividend funds and manage the private claim process for verified users.

The core of the system is the Claim Contract. This smart contract holds the dividend funds (e.g., USDC) and contains the logic for users to claim their share. Its primary functions are to: accept deposits from the issuer, verify a user's eligibility via a zero-knowledge proof, and transfer the correct dividend amount. The contract must be immutable and trustless once deployed, so rigorous testing on a testnet is essential before mainnet deployment. We'll use Solidity and the Foundry framework for development and testing.

The contract's critical state variables include the merkleRoot (representing the verified shareholder list), the token address (the ERC-20 dividend token), and the totalAllocation. A user's claim is authorized by submitting a Merkle proof generated off-chain by the backend. The contract function claim(uint256 amount, bytes32[] calldata merkleProof) will use MerkleProof.verify to confirm the caller's address and allocated amount are in the approved list before executing the transfer. This ensures only legitimate, verified shareholders can withdraw funds.

For enhanced security and gas efficiency, consider implementing a pull-over-push architecture. Instead of the contract automatically sending tokens (push), which can fail and lock funds, users initiate the claim (pull). Always include a claimPeriod with a start and end block number, and a function for the issuer to reclaimUnclaimedDividends after the period ends. This pattern, used by protocols like Uniswap for merkle drips, prevents loss and allows recovery of unclaimed assets. Test all edge cases, including duplicate claims and invalid proofs.

Deployment involves compiling the contract and verifying the source code on a block explorer like Etherscan. Use environment variables for private keys and RPC URLs. A sample Foundry deploy script would look like:

solidity
// Deploy script (Script.sol)
contract DeployClaim is Script {
    function run() external {
        vm.startBroadcast();
        ClaimContract claim = new ClaimContract(
            MERKLE_ROOT,
            TOKEN_ADDRESS,
            START_BLOCK,
            END_BLOCK
        );
        vm.stopBroadcast();
    }
}

Run with forge script script/Deploy.s.sol:DeployClaim --rpc-url $RPC_URL --broadcast --verify.

After deployment, the issuer must fund the contract with the total dividend amount by approving and transferring the ERC-20 tokens. The contract's address and ABI are then integrated with the backend API to generate the correct Merkle proofs for users. Monitor the contract's initial transactions and confirm the totalAllocation state matches the deposit. At this stage, the on-chain infrastructure is ready, and the system shifts to user interaction via the frontend application.

ARCHITECTURAL APPROACHES

Privacy vs. Compliance Trade-offs

A comparison of common system designs for distributing dividends, balancing user privacy with regulatory requirements.

Feature / MetricPrivacy-First (ZK Proofs)Compliance-First (On-Chain KYC)Hybrid (Off-Chain Attestation)

User Identity Exposure

None (pseudonymous)

Full (publicly linked)

Minimal (to issuer only)

Regulatory Audit Trail

On-Chain Gas Cost per User

$5-15

$2-5

$3-8

Sybil Attack Resistance

High via proof-of-personhood

High via verified identity

High via attestation checks

Dividend Claim Complexity

High (user generates proof)

Low (simple transfer)

Medium (signature verification)

Issuer Liability Risk

High

Low

Medium

Cross-Border Compliance

Conditional

Time to First Payout

24 hours

< 1 hour

2-6 hours

step4-client-integration
PRIVACY ENGINE

Step 4: Client-Side Proof Generation

This step details how the user's wallet generates a zero-knowledge proof to validate their dividend eligibility without revealing their identity or holdings.

The core privacy mechanism is executed client-side within the user's wallet. Using a zero-knowledge proof (ZKP) system like zk-SNARKs or zk-STARKs, the wallet generates a cryptographic proof. This proof cryptographically attests to a single, verifiable statement: "I hold a private key that controls a wallet address which is on the approved shareholder list, and I have not already claimed dividends for this distribution period." The actual address, token balance, or any other on-chain history remains hidden.

To construct this proof, the wallet needs access to two critical pieces of data. First, it requires the public parameters or proving key for the specific ZKP circuit, which are published by the dividend issuer. Second, it needs the private witness data, which includes the user's secret key and a Merkle proof. This Merkle proof demonstrates that a cryptographic commitment of the user's address is included in the off-chain Merkle tree root that represents the compliant shareholder list, without revealing which leaf it is.

The generation process involves running the ZKP circuit locally. The circuit takes the witness data as private inputs and the public Merkle root (published by the issuer) as a public input. It performs the verification steps—checking the Merkle proof validity and ensuring non-reuse—entirely within the constrained circuit logic. The output is a small, succinct proof (e.g., a few hundred bytes for a SNARK) that can be publicly verified by anyone with the corresponding verification key.

For developers, this is typically implemented using a library like SnarkJS (for Circom circuits) or Arkworks (for Rust). The code snippet below illustrates the high-level function call a wallet would make, assuming a pre-compiled circuit (circuit.wasm) and proving key (proving_key.zkey) are available:

javascript
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
  { privateKey: userSecret, merkleProof: proofData },
  "circuit.wasm",
  "proving_key.zkey"
);

The publicSignals usually contain just the public Merkle root, which is already known, keeping the proof data minimal.

This client-side proof generation is crucial for user sovereignty and scalability. The computationally intensive proving work is offloaded from the blockchain and distributed across users' devices. The resulting proof contains no personal data, transforming a sensitive claim of ownership into an anonymous, verifiable token of permission. This proof is the only item submitted to the blockchain in the next step.

PRIVATE DIVIDENDS

Frequently Asked Questions

Common technical questions about building systems for private, compliant dividend distributions on-chain.

The core challenge is reconciling two opposing requirements: transaction privacy and regulatory compliance. Public blockchains like Ethereum expose all transaction details, making dividend payments visible to anyone. This conflicts with corporate privacy and securities laws. A compliant system must:

  • Anonymize recipient addresses and payment amounts on-chain.
  • Securely prove to a designated verifier (e.g., an auditor) that payments were made correctly according to an off-chain shareholder list.
  • Maintain cryptographic integrity so the proof cannot be forged.

This is typically solved using zero-knowledge proofs (ZKPs). The system generates a ZKP that validates payments against a private Merkle tree of shareholders without revealing the tree's contents.

conclusion
ARCHITECTURE REVIEW

Conclusion and Next Steps

This guide has outlined the core components for building a system that distributes dividends with privacy and compliance. Here's a summary and a path forward.

Architecting a system for private yet compliant dividends requires balancing two opposing forces: user privacy and regulatory transparency. The solution lies in a multi-layered approach using zero-knowledge proofs (ZKPs) for privacy and trusted execution environments (TEEs) or secure multi-party computation (MPC) for compliance. The key is to separate the privacy layer (e.g., a ZK-rollup or shielded pool) from the compliance oracle, which can attest to legitimacy without exposing underlying data. This design ensures dividends are distributed confidentially while providing auditors or regulators with cryptographic proof of adherence to rules like sanctions lists or investor accreditation.

For implementation, start by defining the exact compliance requirements. Are you checking against the OFAC SDN list, enforcing KYC tiers, or verifying jurisdictional rules? This determines your oracle's logic. Next, select your privacy primitive. For high throughput, a ZK-rollup like those built with zkSNARKs (using Circom or Halo2) is efficient. For maximum privacy with complex state, a shielded pool protocol like Aztec or Zcash's circuit design may be suitable. The compliance attestation—a signed proof from a TEE (e.g., Intel SGX) or an MPC cluster—should be a required input to the private payment function, acting as a gatekeeper.

Your next steps should involve prototyping the core interaction. Use a testnet like Sepolia or a local Foundry / Hardhat setup. 1) Deploy a mock compliance verifier contract that accepts a signature from a predefined attestor. 2) Build or integrate a simple ZK circuit (e.g., with Circom and snarkjs) that proves a user's balance meets a dividend threshold without revealing it. 3) Create a main contract that requires both the ZK proof and the compliance attestation to mint a private dividend token or release funds. Tools like Semaphore for anonymous signaling or Tornado Cash Nova's architecture offer valuable reference code for privacy mechanics.

Finally, consider the operational and security model. Who controls the compliance oracle keys? A decentralized network of attested nodes is more robust than a single entity. How will users generate ZK proofs? You may need to provide a relayer service or a user-friendly SDK. Audit all components thoroughly, especially the ZK circuits and the TEE/MPC attestation code, as these are critical trust points. The field is evolving rapidly; follow developments in zkEVM rollups (Scroll, zkSync), TEE co-processors (EigenLayer, Oasis), and regulatory technology (RegTech) for compliant DeFi to continuously refine your architecture.