Why I Built This
I love ENS, but I have a confession: I donât actually use the wallet linked to my primary .eth name for my daily transactions. Like many of you, I donât want every person I send 20 USDC to, or every observer on-chain, to know exactly how much I have in my main vault, where I spend my money, or what my total net worth is. Currently, ENS is the best identity system in Web3, but itâs also a massive âprivacy leakâ because it perfectly links a human-readable name to a transparent financial history.
I built Opaque because I wanted to stay within the ENS ecosystem while maintaining the basic right to financial privacy that we take for granted in the physical world.
What is Opaque?
Opaque is an open-source, non-custodial privacy layer built on EIP-5564 (Stealth Addresses). It allows users to receive ETH and ERC-20 tokens at unique, one-time âstealth addressesâ that are cryptographically derived from their ENS name or Meta-Address, but are unlinkable to it on-chain.
The protocol is not just a âconceptâ, it is fully built and functional on Sepolia right now.
- Live App: Opaque.cash
- Open Source: GitHub Repository (MIT/Apache 2.0)
Technical Architecture: How it Works
Opaque is a reference implementation of EIP-5564, designed to be a reusable infrastructure layer. It utilizes a Dual-Key Stealth Address Protocol (DKSAP) on the secp256k1 curve.
1. The Key Derivation Logic Instead of a single public key, a user registers a Stealth Meta-Address (M) consisting of two public keys: a spending public key (K) and a viewing public key (V):
M = (K, V)
To send funds, the sender generates an ephemeral private key (r) and its corresponding public key R = r * G. They then compute a shared secret (S) using the recipientâs viewing key:
S = r * V = v * R
The destination stealth address (P) is derived by âtweakingâ the spending key with the hash of this secret:
P_pub = K + hash(S) * G
The recipient, owning the private viewing key (v) and private spending key (k), derives the one-time private key (p) to control the funds:
p = k + hash(v * R)
High-Performance Scanning (Rust-WASM)
Since recipients must check every âAnnouncementâ on-chain, performance is the primary bottleneck. We implemented a Rust core compiled to WASM that uses View Tags (the first byte of the shared secret hash) to skip 99.6% of irrelevant transactions before performing expensive point addition. This ensures the protocol remains responsive on mobile devices.
Beyond the Standard: Reusable Infrastructure
I didnât build this to be a standalone app; I built it to be infrastructure that solves real-world UX hurdles:
- The âGas Tankâ Utility: The biggest privacy pitfall is funding gas. Users often de-anonymize stealth addresses by sending ETH from their main wallet to pay for a sweep. We implemented a Deterministic Gas Tank derived from the userâs keys. For tokens supporting EIP-2612 (Permit), the Gas Tank pays the fee while the stealth address remains unlinked.
- Manual Ghost Addresses: EIP-5564 assumes the sender supports the protocol. Opaque allows users to generate âGhost Addressesâ for receive-only flows from legacy or external wallets. These can be retroactively announced on-chain using a deterministic Announcer identity funded by the Gas Tank, ensuring your main
.ethwallet is never the on-chain caller. - The Registry: We utilize the EIP-6538 Registry. Any project (wallets, dApps, or ENSv2 resolvers) can query this registry to enable âPrivacy-by-Defaultâ for their users.
Example Use Cases
- DAO Contributor Privacy: Receive grants or work payments without exposing your cumulative earnings or other DAO participations.
- Merchant Privacy: Accept payments via your ENS name without revealing your storeâs total revenue to competitors or the public.
- One-Time âGhostâ Addresses: Generate a stealth address for a one-off payment from a legacy wallet that doesnât yet support EIP-5564.
Iâm looking forward to hearing your thoughts and honest feedback on the implementation.