C0DL3 is a sovereign ZK privacy darkpool Layer-3 for the public zkSync ecosystem. Every account is an AA smart contract wallet allowing all balances to be private by default-- storing Pedersen commitments instead of plaintext values. A shielded pool provides full sender/recipient anonymity on demand. Fixed-denomination darkbridge pools (HEAT, ZK, C0LD, ETH) create anonymity sets at the privacy boundary. ZK validity proofs generated via SP1 (RISC-V zkVM).
User Wallet (SDK)
β UserOperation (commitments + proofs instead of public/plaintext amounts)
βΌ
Sequencer (C0DL3 node)
β Blind processing β sees only commitments
βΌ
SP1 Prover
β Groth16 proof of block validity
βΌ
zkSync Era L2 (settlement) β Ethereum (L1)
Privacy layers:
| Layer | What's hidden | Mechanism |
|---|---|---|
| AA wallet balances | Amount | Pedersen commitments |
| Transfers | Amount | Commitment arithmetic + conservation proof |
| Shielded pool transfers | Amount + sender + recipient | Nullifiers + Merkle proofs |
| Gas payment | Sender identity | Paymasters |
| Wallet creation | Recipient address | Stealth addresses (ECDH) |
| Balance discovery | Amount + blinding | ElGamal encrypted memos |
Every account is a PrivateWallet contract storing balanceCommitment β a Pedersen commitment C = amount*G + r*H. The sequencer never sees plaintext balances. Wallet auth uses Schnorr signatures (Ristretto255). Gas is paid by paymasters to break the sender-gas link.
For full anonymity (hidden sender + recipient + amount), the SDK auto-routes transfers through the shielded pool: shield β private transfer β delayed unshield. Commitments, nullifiers, Merkle membership proofs β nothing is revealed to the sequencer.
Transfers using Pedersen commitments are verified by the conservation check precompile: old_sender_commit - new_sender_commit == new_recipient_commit - old_recipient_commit. Bulletproofs ensure amounts stay in [0, 2^64).
C0DL3 ships both privacy-native and Ethereum-compatible precompiles, all SP1-accelerated:
Privacy primitives:
| Address | Precompile | Gas |
|---|---|---|
| 0x0100 | Ristretto255 scalar mul | 2,000 |
| 0x0101 | Pedersen Commit | 2,500 |
| 0x0102 | Bulletproofs Range Verify | 10,000 |
| 0x0103 | Poseidon Hash | 1,500 |
| 0x0104 | ElGamal Encrypt | 5,000 |
| 0x0106 | Schnorr Verify | 3,000 |
| 0x0107 | Conservation Check | 4,000 |
| 0x010A | Encrypted Memo Verify | 5,000 |
| 0x0110 | Shield | 15,000 |
| 0x0111 | Unshield | 15,000 |
| 0x0120 | Private Swap | 12,000 |
| 0x0121 | Threshold Proof | 8,000 |
| 0x0122 | Commitment Arithmetic | 3,000 |
| 0x0132 | Batch Schnorr Verify | 2,000/sig |
| 0x0140 | Ed25519 Verify | 3,000 |
Ethereum-compatible:
| Address | Precompile | Gas |
|---|---|---|
| 0x0001 | ecRecover (secp256k1) | 3,000 |
| 0x0002 | SHA-256 | 60 + 12/word |
| 0x0005 | ModExp | EIP-2565 |
| 0x0006 | BN254 ecAdd | 150 |
| 0x0007 | BN254 ecMul | 6,000 |
| 0x0008 | BN254 ecPairing | 45,000 + 34,000/pair |
| 0x0201 | P-256 Verify (WebAuthn) | 3,000 |
BN254 ecPairing (0x0008) enables on-chain Groth16 ZK proof verification in any Solidity contract. P-256 (0x0201) enables passkey-based wallet auth β Face ID, Touch ID, YubiKey, no seed phrases.
C0DL3 uses a sovereign prover model β anyone with a GPU can prove blocks and earn HEAT rewards.
Proof flow:
1. Block proposed (2s cadence) ββββββββββββ soft-confirmed
2. Prover polls /proof/pending, downloads block data + pre-state
3. SP1 guest executes block (revm + privacy validation) inside zkVM
4. Prover submits proof via /proof/submit
5. Sequencer verifies proof (SP1 SDK / Groth16 verifier)
6. Block hard-confirmed βββ proof batched for L2 settlement
Settlement path: L3 batch β Groth16/PLONK proof β COLDL3Settlement.sol on zkSync Era L2 β Ethereum L1
Proof modes:
| Mode | Speed | On-chain | Use case |
|---|---|---|---|
execute |
~1s | No | Test correctness |
compressed |
30-60s | No | Internal verification |
groth16 |
60-120s | Yes | Production settlement |
plonk |
60-120s | Yes | Alternative on-chain |
Two-mode verification: real-proofs feature off = mock/testnet (fast iteration), on = cryptographic SP1 Groth16 verification (mainnet).
BlockExecutionClaim public inputs β what the proof commits to:
| Field | Size | Description |
|---|---|---|
prev_state_root |
32B | State root before block |
new_state_root |
32B | State root after block |
tx_merkle_root |
32B | Merkle root of transaction hashes |
note_tree_root |
32B | Shielded pool note tree root |
nullifier_count |
4B | Nullifiers consumed |
total_gas_used |
8B | Gas consumed |
See prover/README.md for operator setup β how to run a prover node, export verification keys, and earn HEAT rewards.
Block proofs run on SP1 (RISC-V zkVM). The guest verifies all client-supplied proofs (Schnorr, Bulletproofs, Merkle membership) inside the ZK circuit β the sequencer's processing is early rejection only, trustless by design.
SP1 patches active: sha2, curve25519-dalek-ng (Ristretto255), k256 (secp256k1), p256 (P-256/WebAuthn), ed25519-consensus, BN254 native syscalls, revm (2β5x EVM speedup).
/
βββ src/ Host β sequencer node, RPC, block building
β βββ main.rs HTTP server, block loop, EVM execution
β βββ aa/ Account Abstraction β types, Schnorr, validation, factory, paymaster
β βββ privacy/ Shielded pool, commitment proofs, stealth addresses
β βββ genesis/ Chain identity, testnet bootstrap, initial allocations
β βββ proving/ SP1 proof verification (real-proofs feature gate)
β βββ bridge/ Canonical darkbridge (Era β C0DL3, withdrawal tree)
β βββ settlement/ L3βL2βL1 batch settlement pipeline
β βββ storage/ Persistent state (sled KV store)
βββ program/ SP1 guest β zkVM block proof circuit
β βββ src/main.rs Block verification phases (state, EVM, privacy, AA)
β βββ precompiles.rs All precompiles
β βββ privacy.rs ZK-side privacy verification
βββ contracts/ Reference Solidity contracts
β βββ PrivateWallet.sol AA wallet (Pedersen commitments)
β βββ Paymaster.sol Gas payment abstraction
β βββ COLDL3Settlement.sol L2 settlement (SP1 proof verification)
β βββ C0DL3Bridge.sol Canonical darkbridge (deposit pools, withdrawal proofs)
βββ sdk/ Wallet SDK β proof builders, auto-shield, stealth, memos
βββ prover/ Standalone SP1 prover node
βββ explorer/ Minimal block explorer UI (served at /explorer)
βββ docker/ Dockerfile + docker-compose
git clone https://github.com/ColinRitman/C0DL3.git
cd C0DL3
cargo build --release
# Run sequencer node
cargo run --release
# Run tests
cargo test --lib
# Open block explorer
open http://localhost:9944/explorerDependencies: Rust 1.75+
Docker:
# Build and run
docker build -t c0dl3-node -f docker/Dockerfile .
docker run -p 9944:9944 -p 30333:30333 -v c0dl3-data:/app/data c0dl3-node
# Or with docker-compose
cd docker && docker compose upC0DL3 settles to Ethereum via zkSync Era (L2). The settlement pipeline:
1. Prover generates SP1 Groth16 proof for L3 block
2. Sequencer verifies proof and records ProvenBlock
3. Settlement manager batches proven blocks (configurable batch_size)
4. Submits (publicValues, proofBytes) to COLDL3Settlement.sol on Era
5. Contract verifies proof via SP1VerifierGateway
6. State root committed on L2 β inherits Ethereum L1 finality
Contracts:
| Contract | Chain | Purpose |
|---|---|---|
COLDL3Settlement.sol |
zkSync Era (L2) | Verifies SP1 proofs, commits L3 state roots |
SP1VerifierGateway |
zkSync Era (L2) | Succinct's on-chain Groth16/PLONK verifier |
Modes:
| Mode | Trigger | Behavior |
|---|---|---|
| Mock | No --sequencer-key or --settlement-contract |
Synthetic tx hashes, auto-confirms (testnet dev) |
| Live | Both flags set | Signs real txs via ethers, polls Era for receipts |
# Mock mode (default β no Era deployment needed)
cargo run --release
# Live mode (requires deployed COLDL3Settlement.sol + funded sequencer)
cargo run --release -- \
--era-rpc-url https://sepolia.era.zksync.dev \
--settlement-contract 0xYOUR_CONTRACT \
--sequencer-key YOUR_PRIVATE_KEY_HEXRPC endpoints:
| Endpoint | Method | Description |
|---|---|---|
/settlement |
GET | Settlement pipeline status (mode, batch counts) |
/settlement/batches |
GET | List all settlement batches |
Chain ID: 0xC0D13 (789779)
Genesis accounts:
| Address | Balance | Role |
|---|---|---|
0xC0DL3_FAUCET_...01 |
1B HEAT | Testnet faucet |
0xC0DL3_SEQUENCER_...01 |
100M HEAT | Sequencer operator |
0xC0DL3_PAYMASTER_...01 |
50M HEAT | Default paymaster |
Testnet endpoints:
| Endpoint | Method | Description |
|---|---|---|
/rpc |
POST | Ethereum JSON-RPC (eth_chainId, eth_blockNumber, eth_getBalance, etc.) |
/faucet |
POST | Drip testnet HEAT ({"address": "0x...", "amount": 1000000000000}) |
/storage/status |
GET | Persistent state database info |
/aa/create_wallet |
POST | Create AA PrivateWallet |
/aa/send |
POST | Submit AA UserOperation |
/bridge/status |
GET | Bridge pipeline status (deposits, withdrawals, tree root) |
/bridge/pools |
GET | Darkpool anonymity set health per token/tier |
/bridge/withdraw |
POST | Request withdrawal from C0DL3 to Era |
/bridge/withdrawal_proof/{pos} |
GET | Merkle proof for claiming on Era |
/explorer |
GET | Block explorer UI |
Persistent state: The node stores all state to disk (sled). Survives restarts β resumes from last block height.
Privacy-preserving canon bridge β the privacy boundary between public DeFi and the C0DL3 darkpool. Fixed-denomination pools prevent amount-based correlation. Inside C0DL3, amounts are arbitrary (Pedersen commitments). No multisig, no oracle β security = SP1 proofs.
Deposit (Era β C0DL3):
1. User deposits token into a fixed-denomination pool on C0DL3Bridge.sol (Era)
2. Sequencer observes Deposit event on Era
3. L3 mints shielded Pedersen commitment to user's stealth address
4. Privacy begins β all activity inside C0DL3 is hidden
Withdrawal (C0DL3 β Era):
1. User proves ownership of commitment on L3 (spends nullifier)
2. L3 adds withdrawal leaf to withdrawal Merkle tree
3. Withdrawal tree root committed in SP1 proof (BlockExecutionClaim)
4. After settlement + delay (1-4h), user claims on Era with Merkle proof
Launch tokens (4 tokens Γ 3 denominations = 12 pools):
| Token | Small | Medium | Large | Role |
|---|---|---|---|---|
| HEAT | 100,000 | 10 Million | 1 Billion | Native gas token |
| ZK | 1000 | 10,000 | 100,000 | Era native β privacy for ZK holders |
| C0LD | 0.0001 | 0.001 | 0.1 | COLDAO governance |
| ETH | 0.1 | 1 | 10 | Based asset |
Why 3 denominations per token:
- Expected anonymity = N/K (N=total deposits, K=tiers) β 3 tiers leak only 1.58 bits about amount
- Exponential spacing covers 3 orders of magnitude (retail through whale)
- Each additional tier dilutes anonymity by 1/(K+1) β 4th tier costs 25% for only marginal efficiency gain
- Minimum anonymity set threshold: 50 deposits per pool before meaningful privacy begins
Per-token denomination registry:
- Configurable via governance (sequencer can
addToken()/addDenomination()) - Maximum 3 tiers per token (prevents over-fragmentation)
- On-chain anonymity set counters via
getPoolHealth()lets users verify pool safety before depositing - New tokens added by C0LDAO approval, only when existing pools have healthy anonymity sets
Privacy features:
- Fixed denomination pools prevent amount-based deposit/withdrawal correlation
- Withdrawal amounts need not match deposit amounts
- No on-chain link between deposit address and withdrawal address
- Time-delayed withdrawals (1-4 hour window for timing decorrelation)
- State root history β supports withdrawal proofs against historical settled roots
- SDK auto-splits deposits (e.g., 7 ETH β 7Γ1 ETH)
Bridge endpoints:
| Endpoint | Method | Description |
|---|---|---|
/bridge/status |
GET | Bridge pipeline status (deposits, withdrawals, tree root) |
/bridge/pools |
GET | Darkpool anonymity sets for all tokens and tiers |
/bridge/withdraw |
POST | Request withdrawal from C0DL3 to Era |
/bridge/withdrawal_proof/{pos} |
GET | Merkle proof for claiming on Era |
| Contract | Chain | Purpose |
|---|---|---|
C0DL3Bridge.sol |
zkSync Era | Per-token denomination pools, withdrawal Merkle verification |
COLDL3Settlement.sol |
zkSync Era | Commits L3 state roots (bridge verifies against these) |
C0DL3 maintains a bidirectional bridge to Fuego L1 for banking commitments. Bridge operations are privacy-preserving β amounts are shielded during cross-chain transit.
- Confidential transactions (Bulletproofs)
- Shielded pool (nullifiers + Merkle proofs)
- Client-side partial proving (commitment knowledge proofs)
- Privacy precompile suite (Schnorr, conservation, ElGamal, Ed25519)
- Ethereum-compatible precompiles (ecRecover, SHA-256, BN254, ModExp)
- Native AA wallets (private-by-default balances)
- Paymaster gas abstraction
- SDK auto-shield flow
- Guest-side AA verification (SP1 Phase 7)
- Reference Solidity contracts (PrivateWallet.sol, Paymaster.sol)
- WebAuthn wallet auth (P-256 passkeys precompile)
- SP1 proving pipeline
- Settlement contracts on zkSync Era
- Data availability (via zkSync Era L2 β Ethereum L1)
- Persistent state storage (sled)
- Genesis config + chain ID (0xC0D13)
- Testnet faucet
- Ethereum JSON-RPC compatibility
- Block explorer UI
- Docker image + docker-compose
- Live Era Sepolia settlement (ethers, dual-mode)
- Darkpool bridge β per-token denominations, anonymity set tracking (HEAT, ZK, C0LD, ETH)
- Withdrawal tree root committed in SP1 proofs (BlockExecutionClaim)
- Bridge deposit β shielded pool (auto-mint on block production)
MIT β see LICENSE