Skip to main content

Intent

Allow institutions to select public or private execution mode on a per-transaction or per-counterparty basis, optimizing for cost, latency, and confidentiality requirements. This enables hybrid workflows where some legs execute transparently on public infrastructure while others use privacy-preserving mechanisms.
Best for: Different legs of a trade have different privacy requirements (e.g., private cash, public asset), or counterparties have heterogeneous compliance regimes requiring flexible disclosure.
Avoid when: Uniform privacy is mandatory across all transactions (use a fully private L2 instead), or complexity overhead outweighs benefits for simple single-mode use cases.

Ingredients

Standards

  • ERC-7573: Atomic DvP settlement across execution modes
  • ERC-3643: Compliant token transfers with transfer rules
  • ERC-5564 (optional): Stealth addresses for private mode recipients

Infrastructure

Public Execution

  • Ethereum L1 or transparent L2 (Arbitrum, Optimism, Base)
  • Standard ERC-20/ERC-3643 token contracts
  • Public block explorers and indexing

Private Execution

  • Privacy L2 (Aztec, Miden) or shielded pool (Railgun)
  • ZK proof generation infrastructure
  • Encrypted state management

Mode-Routing Layer

  • Smart contract or middleware directing transactions based on policy
  • Cross-mode settlement coordinator

Off-chain Components

  • Policy engine: Rules defining when to use public vs. private mode per counterparty, asset class, or threshold
  • View key infrastructure: For selective disclosure from private legs to auditors
  • Coordination service: Manages cross-mode settlement timing

Protocol

1

Configure Policy Rules

Institution defines mode-selection criteria:
mode_policy:
  # Route by counterparty
  counterparties:
    - address: 0x1234...
      name: "Bank A"
      default_mode: private
      
  # Route by asset class
  assets:
    - token: BOND_XYZ
      mode: public  # Already public asset
    - token: EURC
      mode: private  # Confidential cash
      
  # Route by amount threshold
  thresholds:
    - amount_gte: 10000000  # €10M+
      mode: private
    - amount_lt: 10000000
      mode: public
      
  # Route by jurisdiction
  jurisdiction:
    - country: US
      mode: public  # US regulator preference
    - country: DE
      mode: private  # German privacy preference
2

Evaluate Mode Per Transaction

When initiating a trade, the policy engine evaluates rules and assigns each leg to public or private execution:
function evaluateMode(trade: Trade): ExecutionMode {
  // Check counterparty rules
  if (policy.counterparties[trade.counterparty]?.default_mode) {
    return policy.counterparties[trade.counterparty].default_mode;
  }
  
  // Check amount thresholds
  if (trade.amount >= policy.thresholds.private_threshold) {
    return ExecutionMode.Private;
  }
  
  // Check asset rules
  if (policy.assets[trade.assetToken]?.mode) {
    return policy.assets[trade.assetToken].mode;
  }
  
  // Default to public
  return ExecutionMode.Public;
}
3

Prepare Assets in Appropriate Environment

Public leg: Assets remain on transparent chainPrivate leg: Assets are shielded
  • Deposit to private pool (e.g., Railgun)
  • Bridge to privacy L2 (e.g., Aztec)
  • Generate ZK proof of deposit
4

Execute Legs in Parallel or Sequence

Each leg executes in its assigned environment:Public execution:
// Standard ERC-3643 transfer
function executePublicLeg(
  address from,
  address to,
  uint256 amount
) external {
  require(identityRegistry.isVerified(to), "Not verified");
  token.transferFrom(from, to, amount);
  emit PublicTransfer(from, to, amount);
}
Private execution:
// ZK proof-verified shielded transfer
function executePrivateLeg(
  bytes32 nullifier,
  bytes32 commitment,
  bytes calldata proof
) external {
  require(verifyProof(proof, nullifier, commitment), "Invalid proof");
  require(!nullifiers[nullifier], "Double spend");
  
  nullifiers[nullifier] = true;
  commitments[commitment] = true;
  emit PrivateTransfer(commitment);  // No amounts or addresses
}
5

Coordinate Cross-Mode Settlement

ERC-7573 or commit-and-prove mechanism ensures atomicity across modes:
function settleHybridDvP(
  // Public leg parameters
  address publicFrom,
  address publicTo,
  uint256 publicAmount,
  
  // Private leg parameters
  bytes32 privateNullifier,
  bytes32 privateCommitment,
  bytes calldata privateProof,
  
  // Coordination
  bytes32 outcomeKey
) external {
  // Verify private leg proof
  require(verifyProof(privateProof, privateNullifier, privateCommitment));
  
  // Execute both legs atomically
  executePublicLeg(publicFrom, publicTo, publicAmount);
  executePrivateLeg(privateNullifier, privateCommitment, privateProof);
  
  // Signal completion via outcome key
  outcomeRegistry.setOutcome(outcomeKey, true);
  
  emit HybridDvPSettled(outcomeKey);
}
Outcome keys or shared commitments link the legs. Both settle or both revert.
6

Generate Disclosure Artifacts

Private legs produce view keys or ZK attestations for authorized parties:
  • Counterparty disclosure: View key for amount verification
  • Regulator disclosure: Scoped key for compliance checks
  • Auditor disclosure: Attestation of rule compliance without revealing amounts
7

Finalize and Reconcile

Both legs settle. Internal systems reconcile:
  • Public chain events (transaction hashes, block numbers)
  • Private proofs (commitments, nullifiers)
  • Audit trail linking both modes

Guarantees

Public mode:
  • Full transparency of amounts, counterparties, timing
  • Standard block explorer visibility
  • Low cost, high throughput
Private mode:
  • Amounts and/or counterparties hidden
  • Only commitments and nullifiers visible on-chain
  • Disclosed selectively via view keys
ERC-7573 outcome keys achieve conditional atomicity:
  • Both legs settle or both fail
  • No partial settlement possible
  • Timeout protection prevents indefinite escrow
Example:
// Public leg waits for private leg confirmation
require(outcomeRegistry.getOutcome(privateLegKey), "Private leg not settled");
// Now safe to finalize public leg
Regulators can verify private legs through selective disclosure:
  • View keys decrypt specific transactions
  • ZK proofs attest to rule compliance without revealing data
  • EAS logs all disclosure events
Public legs are always auditable via block explorers.
ERC-3643 transfer rules apply regardless of mode:
  • Identity verification checks before public transfers
  • Eligibility proofs required for private transfers
  • Jurisdictional restrictions enforced in both modes

Trade-offs

Metadata leakage: Mode selection itself reveals information. Choosing private mode signals sensitivity. Timing correlation between public and private legs may link transactions.

Operational Complexity

  • Dual infrastructure: Requires expertise in both transparent and privacy systems
  • Failure modes multiply: Public leg failure, private leg failure, or coordination failure
  • Key management: Different key types for different modes (private keys for public, proving keys for private)

Cost Asymmetry

ModeCost per TransactionLatencyPrivacy Level
Public~$0.50 (L2 gas)SecondsNone
Private~$5-20 (proof gen + verification)MinutesHigh
Hybrid$5.50-20.50MinutesMixed
Hybrid trades pay both public gas costs and private proof generation costs. The additional coordination overhead adds 10-20% to total costs.

Tooling Maturity

  • Cross-mode settlement is less battle-tested than single-environment flows
  • Limited production deployments exist (mostly PoC stage as of 2026)
  • SDK and developer tools are fragmented across privacy vendors

Policy Drift Risk

Rules must stay synchronized across systems. Misconfiguration can route sensitive transactions to public mode, exposing confidential data.
Mitigation:
  • Automated policy testing in staging environment
  • Dry-run mode evaluation before production execution
  • Alerting on mode selection anomalies
  • Regular policy audits by compliance team

Example Workflow

Scenario: Private Cash, Public Asset

1

Trade Setup

Bank A sells tokenized bond (public asset on L1) to Bank B for EURC (private cash on privacy L2).Policy evaluation:
  • Bond: Already public asset, no privacy benefit → Public mode
  • EURC: Amount confidentiality required → Private mode
2

Public Leg: Bond Transfer

Bank A locks bond in ERC-7573 contract on L1:
bondToken.approve(dvpContract, bondAmount);
dvpContract.escrowPublicAsset(bondAmount, tradeId);
Public observers see:
  • Bank A address
  • Bond token contract
  • Amount: 1000 bonds
  • Trade ID: 0xabc123...
3

Private Leg: Cash Payment

Bank B shields EURC on privacy L2 and executes private payment:
// Off-chain: generate ZK proof
const proof = await generatePaymentProof({
  amount: 5_000_000, // €5M, not revealed
  recipient: bankAShieldedAddress,
  tradeId: '0xabc123...'
});

// On-chain: submit proof
await privacyL2.executePrivatePayment(proof.nullifier, proof.commitment, proof.zkProof);
Public observers see:
  • Nullifier: 0x7f3a... (one-time identifier)
  • Commitment: 0x9c2e... (new note for Bank A)
  • No amount or recipient visible
4

Cross-Mode Coordination

Privacy L2 oracle confirms payment success to L1 outcome registry:
// Oracle submits ZK proof of payment to L1
outcomeRegistry.setOutcome(
  tradeId,
  true,
  zkProofOfPrivatePayment
);
5

Atomic Finalization

L1 DvP contract verifies outcome and releases bond:
function finalizeHybridDvP(bytes32 tradeId) external {
  require(outcomeRegistry.getOutcome(tradeId), "Private leg not confirmed");
  
  // Release bond to Bank B
  Trade memory trade = trades[tradeId];
  bondToken.transfer(trade.buyer, trade.bondAmount);
  
  emit HybridDvPComplete(tradeId);
}
Bond transfers to Bank B. Public sees bond transfer; private L2 holds encrypted cash payment record.
6

Regulatory Disclosure

Regulator requests Bank B’s payment details:
  • Bank B provides view key for the specific trade ID
  • Regulator decrypts: sees €5M payment, Bank B → Bank A
  • EAS logs disclosure event
  • Bond transfer already visible on public block explorer

Implementation Patterns

Pattern 1: Volition Architecture

Use a volition-style L2 with built-in public/private mode selection:
// StarkNet volition example
await account.execute({
  contractAddress: tokenAddress,
  entrypoint: 'transfer',
  calldata: [recipientAddress, amountLow, amountHigh],
  // Storage mode selection
  storageMode: 'VALIDIUM'  // Private (off-chain DA)
  // storageMode: 'ROLLUP'  // Public (on-chain DA)
});

Pattern 2: Dual-Chain Bridge

Maintain separate public and private chains with atomic bridge:
contract HybridBridge {
  // Public chain: lock asset
  function lockPublicAsset(uint256 amount, bytes32 tradeId) external {
    token.transferFrom(msg.sender, address(this), amount);
    emit AssetLocked(tradeId, amount);
  }
  
  // Wait for private chain confirmation
  function releaseOnPrivateConfirmation(
    bytes32 tradeId,
    bytes calldata privacyProof
  ) external {
    require(verifyPrivacyChainProof(privacyProof, tradeId));
    // Release to recipient
  }
}

Pattern 3: Policy-Driven Router

Centralized policy engine routes transactions:
class HybridRouter {
  async routeTransaction(trade: Trade): Promise<ExecutionPlan> {
    const policy = await this.policyEngine.evaluate(trade);
    
    return {
      assetLeg: {
        mode: policy.assetMode,
        executor: policy.assetMode === 'public' 
          ? this.publicExecutor 
          : this.privateExecutor,
        environment: policy.assetMode === 'public' 
          ? 'ethereum-l1' 
          : 'aztec-l2'
      },
      cashLeg: {
        mode: policy.cashMode,
        executor: policy.cashMode === 'public' 
          ? this.publicExecutor 
          : this.privateExecutor,
        environment: policy.cashMode === 'public' 
          ? 'ethereum-l1' 
          : 'railgun'
      },
      coordinator: this.crossModeCoordinator
    };
  }
}

See Also

Shielded ERC-20 Transfers

Private mode implementation details

Private L2s

Privacy-focused Layer 2 networks

Atomic DvP via ERC-7573

Cross-mode settlement standard

Commit-and-Prove Fallback

Alternative cross-environment coordination pattern

Regulatory Disclosure Keys

Selective disclosure for private legs

Modular Privacy Stack

Broader architectural framework

Build docs developers (and LLMs) love