Skip to main content

Intent

Run transactions on a low-cost Layer 2, putting only commitments and hashes on-chain while storing full transaction details in an append-only encrypted log off-chain. This pattern anchors data integrity on-chain while providing auditor access via scoped keys and atomic DvP via ERC-7573.
Best for: Hidden amounts and positions with minimal on-chain footprint. Ideal when you prefer cheap daily settlement over full on-chain private compute.
Avoid when: Regulators demand full on-chain plaintext or off-chain infrastructure is not feasible.

Ingredients

Standards

  • ERC-7573: Atomic DvP settlement
  • ERC-3643: Compliant security tokens
  • EAS (Ethereum Attestation Service): Access logging and disclosure audit trail
  • EIP-4844: Blob transactions for data availability

Infrastructure

  • L2 contracts: Simple AuditCommit(bytes32) function for recording commitments
  • Merkle tree anchor: Hourly or daily root anchoring to L1 or L2
  • Encrypted storage: Off-chain database with append-only guarantees

Off-chain Components

  • Encrypted audit log: Per-trade symmetric keys wrapped to threshold authorities
  • Threshold KMS: Multi-party key management for scoped disclosure
  • RFQ/matching engine: Optionally encrypted order routing
  • Disclosure service: Issues time-limited viewing keys to authorized parties

Protocol

1

Off-chain Trade Matching

RFQ (request-for-quote) or order matching occurs off-chain. Optionally use encrypted communication channels to hide pre-trade information.
  • Buyer and seller agree on price, amount, settlement time
  • Trade parameters encrypted with symmetric key K
  • Key K wrapped to threshold authorities for future disclosure
2

Record Commitment On-chain

Compute commitment hash of the encrypted trade record and emit on L2:
function auditCommit(bytes32 commitment) external {
  require(msg.sender == authorizedTrader, "Unauthorized");
  commits[commitIndex++] = commitment;
  emit AuditCommit(msg.sender, commitment, block.timestamp);
}
Public observers see only the commitment hash, trader identity, and timestamp. No amounts or asset details are revealed.
3

Anchor Merkle Root Periodically

Every hour (or custom interval), compute Merkle root of all commitments and anchor to L1 or L2 mainnet:
function anchorRoot(bytes32 merkleRoot, uint256 fromIndex, uint256 toIndex) external {
  require(msg.sender == operator, "Unauthorized");
  roots[rootIndex++] = Root({
    root: merkleRoot,
    fromCommit: fromIndex,
    toCommit: toIndex,
    timestamp: block.timestamp
  });
  emit RootAnchored(merkleRoot, fromIndex, toIndex);
}
This provides tamper-evident proof that commitments existed at a specific time.
4

Atomic DvP Settlement

Escrow both legs (asset and cash) and finalize atomically using ERC-7573:
function settleDvP(
  bytes32 tradeCommitment,
  bytes32 assetOutcomeKey,
  bytes32 cashOutcomeKey
) external {
  require(commits[tradeIndex] == tradeCommitment, "Invalid commitment");
  
  // Execute both legs atomically
  assetContract.settleConditional(assetOutcomeKey);
  cashContract.settleConditional(cashOutcomeKey);
  
  emit DvPSettled(tradeCommitment);
}
5

Regulatory Disclosure

When a regulator requests access:
  1. Policy engine verifies the regulator’s mandate and scope (e.g., ISIN, date range)
  2. Threshold KMS generates a time-limited viewing key for the specific encrypted records
  3. Disclosure event logged via EAS attestation:
struct DisclosureAttestation {
  bytes32 tradeCommitment;
  address regulator;
  uint256 expiryTimestamp;
  bytes32 scopeHash; // Hash of scope criteria
}
  1. Regulator decrypts the specific trade records using the viewing key
  2. Key automatically revokes after expiry period (e.g., 24 hours)

Guarantees

Public observers see:
  • Trader identities (required for compliance)
  • Commitment hashes
  • Settlement events
They cannot see:
  • Transaction amounts
  • Asset ISINs or types
  • Prices or valuations
  • Full counterparty graph
Anchored Merkle roots provide cryptographic proof that:
  • Commitments existed at a specific time
  • Records have not been modified after anchoring
  • Audit log is append-only
Any attempt to modify historical records invalidates the Merkle proof.
ERC-7573 ensures both asset and cash legs settle atomically. If either leg fails:
  • Both legs revert
  • No partial settlement occurs
  • Escrowed assets return to original owners
Regulators receive:
  • Time-limited viewing keys (auto-expire)
  • Scoped access to specific trades only
  • Audit trail of all disclosure events via EAS
No blanket access to all transaction data.

Trade-offs

Trust in off-chain availability: The encrypted audit log must remain available for future disclosure. If the storage system fails or is compromised, historical audit capability is lost.
Mitigation strategies:
  • Replicate encrypted logs across multiple geographic regions
  • Use IPFS or Arweave for censorship-resistant storage
  • Regular anchor proofs demonstrate continued availability
  • Escrow encrypted backups with third-party custodians

Key Governance Overhead

  • Rotation: Keys must be rotated periodically; requires re-encrypting historical records
  • Authority changes: Adding/removing threshold authorities requires careful coordination
  • Revocation: Time-limited keys reduce but don’t eliminate revocation complexity

Cost Considerations

ItemCost per TradeMonthly (1000 trades)
L2 commitment~0.001 ETH1 ETH ($2,000)
Hourly anchor~0.01 ETH7.2 ETH ($14,400)
Off-chain storage~$0.01~$10
Total~$2.02~$16,410
Compare to L1 ZK commitment pool: ~2040pertrade,or20-40 per trade, or 20,000-40,000 monthly for 1000 trades. The L2 approach reduces costs by ~60-80%.

Example Workflow

Scenario: Private Bond-for-Cash Settlement

1

Pre-trade

  • Bank A offers €5M tokenized bond to Bank B
  • Bank B accepts; trade parameters encrypted with key K
  • Key K wrapped to threshold authorities (3-of-5 multisig)
2

On-chain Commitment

  • Commitment hash commit = H(encrypted_trade || salt) emitted on L2
  • Public sees: AuditCommit(BankA, 0x7f3a...)
  • No amount or ISIN visible
3

Hourly Anchor

  • System computes Merkle root of last hour’s commitments
  • Root 0x9c2e... anchored to L1: proves commitment existed at block height 18,456,789
4

Atomic Settlement

  • Bond contract: Bank A → Bank B transfer, conditional on cash outcome key
  • Cash contract (EURC ERC-7573): Bank B → Bank A transfer, conditional on bond outcome key
  • Both legs execute atomically on L2
5

Regulatory Disclosure (3 months later)

  • BaFin requests all trades involving ISIN XYZ in Q1 2026
  • Policy engine verifies mandate; generates 24-hour viewing key for matching records
  • EAS attestation logged: Disclosure(BaFin, 0x7f3a..., expiry: +24h)
  • BaFin decrypts: sees €5M bond trade, Bank A → Bank B, ISIN XYZ
  • Key auto-revokes after 24 hours

Implementation Considerations

Choosing a Data Availability Layer

Store commitments directly in L2 contract state. Simplest approach but limited by L2 storage costs.Pros: Low latency, integrated with settlement Cons: Higher cost, dependent on L2 availability

Threshold KMS Architecture

Security Considerations

Key custody is critical: Compromise of threshold authorities exposes all historical trade data.
  • Authority selection: Choose geographically and jurisdictionally diverse authorities
  • HSM protection: Store key shares in hardware security modules
  • Audit all disclosures: Every key generation event must be logged via EAS
  • Key rotation schedule: Rotate threshold keys quarterly; re-encrypt recent records

Disclosure Policy Example

allowed_requestors:
  - entity: BaFin
    jurisdiction: DE
    max_scope_days: 90
    max_key_lifetime_hours: 24
    
  - entity: SEC
    jurisdiction: US
    max_scope_days: 365
    max_key_lifetime_hours: 72
    
required_approvals: 2  # Number of internal approvers
min_threshold_signers: 3  # 3-of-5 for key reconstruction
autolog_attestation: true  # EAS logging mandatory

See Also

L1 ZK Commitment Pool

Higher-cost L1-native alternative with full ZK privacy

Regulatory Disclosure

Deep dive into selective disclosure mechanisms

Atomic DvP via ERC-7573

Settlement standard documentation

Modular Privacy Stack

How this pattern fits into a modular architecture

External References

Build docs developers (and LLMs) love