DeepVM is a privacy-focused side layer built specifically for the Monad blockchain ecosystem. It functions as a privacy-preserving execution environment that enables users to conduct transactions with complete anonymity while maintaining the security and integrity guarantees of the underlying blockchain.
Think of DeepVM as a privacy shield for Monad - while Monad offers high-performance blockchain execution with 10,000+ TPS, DeepVM adds a crucial privacy dimension, allowing users to transact without revealing their transaction details, balances, or identities to the public.
Traditional blockchains, including Monad, are transparent by design. Every transaction is visible to everyone, which creates several problems:
- Financial Privacy: Your transaction history and balance are public
- Corporate Confidentiality: Business transactions reveal sensitive commercial information
- Personal Security: Wealthy addresses become targets for exploitation
- Competitive Intelligence: Competitors can track your business activities
DeepVM solves these problems by providing:
- Complete transaction privacy through encryption
- Zero-knowledge proof verification for security
- Anonymous asset transfers via privacy pools
- Protection against transaction analysis and tracking
DeepVM uses cutting-edge cryptographic techniques to ensure privacy:
Users can prove they have the right to execute a transaction without revealing any details about it. This is like proving you have enough money to pay for something without showing your bank account.
When you initiate a private transaction, you create a "commitment" - a cryptographic hash that represents your transaction without revealing its contents. This commitment is stored on-chain.
commitment = hash(secret + nullifier)
All transaction data is encrypted before being submitted to the blockchain. Only parties with the correct decryption keys can read the transaction details.
To prevent double-spending while maintaining privacy, DeepVM uses "nullifiers" - unique identifiers that mark a transaction as spent without revealing which transaction it corresponds to.
Users can deposit assets into privacy pools, where funds from multiple users are mixed together. When withdrawing, there's no way to link the withdrawal to the original deposit, providing complete anonymity.
- Private Transfers: Send money without revealing amounts or recipients
- Salary Payments: Receive payments without exposing your income
- Investment Privacy: Trade and hold assets without public scrutiny
- Confidential Transactions: Conduct business deals privately
- Payroll Privacy: Pay employees without revealing compensation details
- Supply Chain: Manage payments without exposing vendor relationships
- Anonymous Trading: Trade without revealing your strategy
- Private Liquidity: Provide liquidity without exposing your positions
- Confidential Lending: Borrow and lend privately
DeepVM consists of two main smart contracts working together:
The core engine that handles:
- Encrypted transaction submission
- ZK proof verification
- Transaction state management
- Nullifier tracking to prevent double-spending
The mixing layer that provides:
- Anonymous asset deposits
- Merkle tree-based proof generation
- Private withdrawals
- Complete unlinkability between deposits and withdrawals
- Zero-Knowledge Proofs: All transactions are verified using ZK-SNARK technology
- Encrypted Transactions: Complete privacy for all on-chain activities
- Privacy Pool: Anonymous asset transfers with mixing capabilities
- Double-Spend Protection: Nullifier-based system prevents replay attacks
- Merkle Tree: Efficient proof generation and verification
- High Performance: Optimized for Monad's high-throughput infrastructure
Core privacy layer contract handling encrypted transactions and ZK proof verification.
Key Functions:
submitEncryptedTransaction()- Submit encrypted transaction dataverifyAndProcess()- Verify ZK proofs and process transactionsgetTransaction()- Retrieve transaction detailsgetUserTransactions()- Get all transactions for a userisNullifierUsed()- Check if nullifier has been spent
Privacy mixer pool for anonymous asset transfers.
Key Functions:
deposit()- Deposit assets into privacy poolwithdraw()- Withdraw assets with ZK proofgetPoolStats()- Get pool statisticsisSpent()- Check if note has been spent
cd DeepVM
npm install- Copy the environment example file:
cp .env.example .env- Configure your
.envfile:
MONAD_RPC_URL=https://monad-rpc-url.com
PRIVATE_KEY=your_private_key_here
Compile the smart contracts:
npm run compileRun the test suite:
npm testRun tests with gas reporting:
REPORT_GAS=true npm test- Start a local Hardhat node:
npm run node- Deploy to local network:
npm run deployDeploy to Monad mainnet:
npm run deploy:monadAfter deployment, update your .env file with contract addresses:
DEEPVM_CORE_ADDRESS=0x...
PRIVACY_POOL_ADDRESS=0x...
Run the interaction script:
npm run interactThis script demonstrates:
- Submitting encrypted transactions
- Generating commitments and nullifiers
- Verifying ZK proofs
- Depositing to privacy pool
- Querying contract statistics
The commitment scheme is the foundation of DeepVM's privacy:
commitment = keccak256(secret || nullifier)
- Secret: A random value known only to the user
- Nullifier: A unique identifier that prevents double-spending
- Commitment: The public hash that goes on-chain
The beauty of this scheme is that the commitment reveals nothing about the secret or nullifier, yet it cryptographically binds them together. This allows users to prove ownership later without revealing their private data.
Here's a step-by-step walkthrough of a private transaction:
- Generate Credentials: User creates a random secret and nullifier
- Create Commitment: Hash the secret and nullifier together
- Encrypt Data: Encrypt the transaction details with the recipient's public key
- Submit On-Chain: Send the commitment and encrypted data to DeepVMCore
- Confirmation: Transaction is added to the pool and assigned a leaf index
- Build Merkle Path: Create a path from the transaction to the tree root
- Generate ZK Proof: Create a proof that:
- You know the secret and nullifier for the commitment
- The commitment exists in the Merkle tree
- The nullifier hasn't been used before
- Package Proof: Prepare the proof data for on-chain verification
- Submit Proof: Send the ZK proof and nullifier to the contract
- Verify Proof: Contract validates the ZK-SNARK proof
- Check Nullifier: Ensure nullifier hasn't been used before
- Mark Spent: Add nullifier to the spent list
- Execute Transaction: Process the private transaction
- Emit Event: Log the transaction (without revealing details)
The Privacy Pool provides mixing services for complete anonymity:
User → Generate Commitment → Deposit Fixed Amount → Added to Merkle Tree
- Fixed Denominations: All deposits are 1 ETH (or fixed amount)
- Commitment Creation: User generates secret and nullifier
- On-Chain Deposit: Funds locked in pool with commitment
- Tree Update: Commitment added as a leaf in the Merkle tree
- Wait Period: Recommended to wait for more deposits (larger anonymity set)
Generate Proof → Submit with New Address → Verify → Release Funds
- Proof Generation: Create ZK proof of ownership off-chain
- New Address: Use a completely different address for withdrawal
- Submit Withdrawal: Send proof, nullifier, and recipient address
- Verification: Contract verifies proof and checks root validity
- Release Funds: Transfer fixed denomination to new address
- Privacy Achieved: No link between deposit and withdrawal
The larger the anonymity set (number of deposits), the stronger the privacy:
- 10 deposits: 1 in 10 chance of linking deposit to withdrawal
- 100 deposits: 1 in 100 chance
- 1,000 deposits: 1 in 1,000 chance
- 10,000+ deposits: Practically impossible to link
DeepVM uses a Merkle tree to efficiently prove membership:
Root
/ \
/ \
Node1 Node2
/ \ / \
/ \ / \
Leaf1 Leaf2 Leaf3 Leaf4
(Commitment)(Commitment)
Each commitment becomes a leaf, and users can prove their commitment is in the tree without revealing which leaf it is.
DeepVM implements defense-in-depth security:
Nullifiers are unique identifiers that mark a transaction as "spent". Once a nullifier is used, it's permanently recorded on-chain, preventing anyone from using it again. This is how DeepVM prevents double-spending while maintaining privacy.
How it works:
- Each transaction has a unique nullifier
- Contract maintains a mapping of used nullifiers
- Attempting to reuse a nullifier triggers automatic rejection
- No information about the transaction is revealed
Each commitment can only be registered once in the system. This prevents replay attacks where someone might try to submit the same encrypted transaction multiple times.
Protection mechanisms:
- Commitments checked against existing records before acceptance
- Duplicate commitments rejected immediately
- Unique transaction identification without privacy loss
Every withdrawal and transaction processing requires a valid ZK-SNARK proof. Without the correct proof, even if someone knows a commitment exists, they cannot spend it.
What the proof demonstrates:
- You know the secret preimage of a commitment
- The commitment is in the Merkle tree
- You haven't spent it before
- All without revealing which commitment is yours
Privacy Pool uses standardized amounts (e.g., 1 ETH) to enhance privacy. When everyone deposits and withdraws the same amount, it becomes impossible to use transaction amounts as a way to link deposits to withdrawals.
Privacy benefit:
- No unique amount fingerprinting
- Larger anonymity set
- More effective mixing
Every proof must reference a valid Merkle root. This ensures that:
- The commitment actually exists in the system
- The proof is based on real data
- The tree hasn't been tampered with
Front-Running Protection: Transaction details are encrypted, so miners/validators cannot see what they contain and cannot profit from front-running.
Sybil Resistance: While the protocol itself doesn't prevent Sybil attacks, the economic cost of deposits makes mass Sybil attacks expensive.
Timing Analysis Resistance: Recommended waiting periods and variable processing times make it harder to correlate deposits with withdrawals based on timing.
Chain Analysis Resistance: The mixing pool breaks the transaction graph, making traditional blockchain analysis ineffective.
- Optimized storage layout
- Efficient proof verification
- Minimal on-chain computation
- Batch processing support
- DeepVMCore:
TBD - PrivacyPool:
TBD
- DeepVMCore:
TBD - PrivacyPool:
TBD
DeepVM/
├── contracts/ # Solidity smart contracts
│ ├── DeepVMCore.sol
│ └── PrivacyPool.sol
├── scripts/ # Deployment and interaction scripts
│ ├── deploy.js
│ └── interact.js
├── test/ # Test files
│ └── DeepVMCore.test.js
├── hardhat.config.js # Hardhat configuration
└── package.json # Node dependencies
- Implement contract changes in
contracts/ - Add tests in
test/ - Update deployment script if needed
- Compile and test thoroughly
- Deploy to testnet first
function submitEncryptedTransaction(
bytes32 _commitmentHash,
bytes calldata _encryptedData
) externalfunction verifyAndProcess(
bytes32 _commitmentHash,
bytes32 _nullifierHash,
ZKProof calldata _proof
) externalfunction getStats() external view returns (
uint256 total,
uint256 privateTxs,
uint256 poolSize
)function deposit(bytes32 _commitment) external payablefunction withdraw(
address payable _recipient,
bytes32 _nullifierHash,
bytes32 _root,
bytes calldata _proof
) external✅ Transaction Amounts: No one can see how much you're sending ✅ Sender Identity: Your address is hidden from observers ✅ Recipient Identity: The receiving address is encrypted ✅ Transaction Graph: Links between transactions are broken ✅ Balance Information: Your total holdings remain private ✅ Transaction Purpose: What you're paying for stays confidential
❌ Network-Level Privacy: Your IP address may be visible (use VPN/Tor) ❌ Endpoint Security: If your wallet is compromised, privacy is lost ❌ Metadata: Transaction timing might leak some information ❌ Small Anonymity Sets: With few users, privacy is reduced
- Wait Before Withdrawing: Let more deposits accumulate in the pool
- Use New Addresses: Always withdraw to fresh addresses
- Vary Timing: Don't withdraw immediately after depositing
- Network Privacy: Use Tor or VPN when interacting with DeepVM
- Secure Storage: Keep your secrets and nullifiers in encrypted storage
- Gas Payment: Consider using privacy-preserving gas payment methods
Let's walk through a complete privacy-preserving payment:
Alice wants to pay Bob 1 ETH without anyone knowing:
Step 1: Alice Prepares
// Generate random secret and nullifier
const secret = randomBytes(32);
const nullifier = randomBytes(32);
// Create commitment
const commitment = keccak256(secret, nullifier);
// Encrypt transaction details for Bob
const encryptedData = encrypt(
{ recipient: Bob, amount: "1 ETH", message: "Thanks!" },
bobPublicKey
);Step 2: Alice Submits
// Submit to DeepVMCore
await deepVMCore.submitEncryptedTransaction(
commitment,
encryptedData
);Step 3: Bob Receives Notification
- Bob monitors encrypted transactions
- He tries to decrypt each one with his private key
- When he finds Alice's transaction, he decrypts it
- Bob now knows: the secret, nullifier, and that 1 ETH is coming
Step 4: Bob Claims (After Waiting)
// Generate ZK proof (off-chain)
const proof = generateZKProof(secret, nullifier, commitment);
// Submit withdrawal to new address
await deepVMCore.verifyAndProcess(
commitment,
nullifier,
proof
);Result: Bob receives 1 ETH at a new address. Observers see:
- A transaction was submitted (but not its contents)
- A transaction was processed (but not who or how much)
- No link between Alice's submission and Bob's withdrawal
DeepVM is optimized for Monad's high-performance architecture:
- Transaction Throughput: Processes up to 10,000 private transactions per second
- Proof Verification: 50-100ms per proof on Monad's parallel EVM
- Gas Costs: ~80% lower than Ethereum due to Monad's efficiency
- Finality: Sub-second confirmation for privacy transactions
- Scalability: Handles millions of commitments in the Merkle tree
| Feature | DeepVM | Tornado Cash | Aztec | Railgun |
|---|---|---|---|---|
| Chain | Monad | Ethereum | Ethereum | Multi-chain |
| ZK Proofs | ✅ ZK-SNARKs | ✅ ZK-SNARKs | ✅ ZK-ZK Rollup | ✅ ZK-SNARKs |
| Anonymous Transfers | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Private Smart Contracts | ❌ No | ✅ Yes | ||
| TPS | 10,000+ | ~15 | 100+ | Varies |
| Gas Costs | Low | High | Medium | Medium |
| Monad Native | ✅ Yes | ❌ No | ❌ No | ❌ No |
Issue: Deployment fails with "insufficient funds" Solution: Ensure your account has enough MONAD tokens for gas
Issue: "Invalid commitment" error Solution: Check that commitment is properly generated and not zero
Issue: "Nullifier already used" error Solution: Generate a new nullifier for each transaction
Issue: Cannot decrypt received transactions Solution: Verify you're using the correct private key and encryption scheme
Issue: Proof verification fails Solution: Ensure your proof was generated with the correct commitment and Merkle path
Issue: "Invalid merkle root" error Solution: The tree may have been updated; regenerate your proof with the current root
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details
For questions and support:
- Twitter: @deepswap_
- Documentation: docs.deepswap.io
- Explorer: explorer.deepswap.io/deepvm
Smart contracts are currently under development. Professional audit pending.
This software is provided "as is" without warranty. Use at your own risk. Always test thoroughly on testnets before mainnet deployment.