Elysian Veil Docs Launch App →

Introduction

What is Elysian Veil?

Elysian Veil is a zero-knowledge privacy pool for HYPE on Elysium. You deposit from one wallet and later withdraw to a fresh wallet, and nobody on-chain can tell which deposit paid for which withdrawal.

It runs on the open-source, audited Privacy Pools protocol by 0xbow (Apache-2.0). Elysian Veil deploys those contracts without an owner, adds an on-chain Association Set Provider that keeps stolen funds out, and gives you an app where every secret stays on your device.

Status. Elysian Veil is live on Elysium mainnet. Its own ASP contract and app are not audited yet: start with small amounts. See Status.

Why privacy matters

A blockchain is a public ledger. The moment someone links your name to one address (an exchange withdrawal, an ENS name, a payment to a friend), they can read:

  • your balance, today and at any time in the past;
  • every payment you made and received, and with whom;
  • your other wallets, by following the money between them.

That is the equivalent of publishing your bank statement. Elysian Veil breaks the on-chain link between an old, known wallet and a new one, so the new one starts clean.

How it works

Picture a box full of sealed envelopes, each holding the same kind of coin. When you put an envelope in, you keep a secret that only fits your envelope. Later you prove to the box, with math, that one of the envelopes is yours, without pointing at which one, and it pays you out to any address you name.

  1. Deposit. Your browser creates a secret and a nullifier from your Veil Key and sends only their hash, the commitment, with your HYPE. The commitment joins a public Merkle tree of all deposits.
  2. Wait. The ASP screens the deposit (about 30 minutes). Others deposit too. Every approved deposit is part of your anonymity set.
  3. Withdraw. Your browser builds a Groth16 proof that says: "I know the secret of some commitment in the pool tree, its deposit is in the approved set, and here is its nullifier hash." The relayer submits it; the contract checks the proof, records the nullifier so the note can't be spent twice, and pays the recipient.

The nullifier hash and the commitment are different hashes of different inputs, so no one can connect them. The proof reveals the amount, the recipient and the nullifier hash, and nothing else.

Partial withdrawals. You can withdraw part of a deposit. The proof creates a new hidden note for the rest (same deposit lineage), which you can withdraw later.

Clean funds: the ASP

A plain mixer lets hackers hide stolen money among honest users. Privacy Pools adds an Association Set Provider (ASP): a list of deposits that passed screening. Your withdrawal proof also proves your deposit is on that list, still without saying which one it is.

On Elysian Veil the ASP is a contract, Veil ASP, and it is the only address allowed to publish the approved set. No server decides who gets in:

  • Queue. Each deposit is queued on-chain, which starts a 30-minute window so hacks can be reported first. Anyone can queue; Elysian Veil's keeper does it automatically.
  • Screen. Inside the window, a guardian can deny the deposit. Elysian Veil's keeper denies depositors on the OFAC sanctions list and on a short list of wallets identified as scams. The guardian can do nothing else, and nothing after the window. See what gets denied.
  • Approve. After the window, anyone can approve the deposit: the contract adds it to its Merkle tree and posts the new root to the Entrypoint. The keeper does this automatically.
  • Final. An approval cannot be revoked; the set only grows.
If the keeper is offline, your deposit still gets approved: queue it in the app, wait 30 minutes, then approve it yourself. Do this from the wallet that made the deposit, never from a fresh wallet, or you link the two.

The app rebuilds the whole set from the contract's events and checks it against the on-chain root, so nobody learns which deposit a visitor owns.

What gets denied

Only one thing is checked, and it is the wallet that sent the deposit. Not the amount, not the timing, not where you later withdraw to. Two lists are used:

  • The OFAC sanctions list. The addresses the US Treasury publishes on its SDN list, refreshed every day from the public mirror at 0xB10C/ofac-sanctioned-digital-currency-addresses. It is the same list exchanges use, we add nothing to it, and you can read it yourself before you deposit.
  • A short blocklist of wallets identified as scams, such as the deployer of 81%-fee trap pools. It currently holds a single address. We do not publish the entries: a listed wallet would simply move to a new one, and the list would stop working.

A deposit from any other wallet passes. There is no risk score, no chain-analysis vendor and no profile of you.

What this does not catch

Sanctions lists name addresses months after the fact, if ever, and a 30-minute window is not long enough for a fresh hack to be reported. Money stolen today will pass. Screening raises the cost of using Elysian Veil for known-bad funds; it does not make the pool clean, and we will not claim it does.

Denials are public

Every denial is an on-chain Denied(label, reason) event carrying the reason in plain text, so a denial can never be quiet. A denied deposit is not frozen: ragequit returns every wei to the wallet that sent it.

Live counts for both lists are on the status page.

Ragequit

If a deposit is denied, still pending, or you simply want out, the original depositing wallet can ragequit: it proves ownership of the note and gets the remaining balance back. This is public (it shows the money returned to the same wallet), but it means the ASP can never freeze or take your funds.

User guide

Getting started

  1. Install a browser wallet: MetaMask, Rabby or OKX. If you have several, the app lets you choose one.
  2. Open the app. It checks the network, the contracts and the ZK circuits before you start.
  3. Click Connect wallet. The app adds and switches to the right network.
  4. Create a Veil Key (next section).
This is mainnet with real HYPE. Start with a small deposit to learn the flow.

Your Veil Key

Your Veil Key is 12 words, separate from your wallet's seed. Every deposit's secret and nullifier are derived from it, so these 12 words are the only thing that can withdraw your deposits.

  • Back it up on paper. The app asks you to type two of the words back before you continue.
  • In this browser it is stored encrypted with your password (PBKDF2 with 310,000 iterations, then AES-GCM). It is never sent anywhere.
  • Restore on any device by pasting the 12 words. The app rescans the chain and rebuilds every deposit.
  • Never type it into a site other than Elysian Veil, and never share it. Anyone who has it can withdraw your funds.

Depositing

  1. Unlock your Veil Key and connect your wallet.
  2. Enter an amount (minimum 0.1 HYPE). Prefer round amounts.
  3. Confirm in your wallet. The deposit appears under My deposits with a countdown.
  4. After about 30 minutes it shows Approved (or Denied with the reason).

Withdrawing privately

  1. In My deposits, pick an approved deposit and click Withdraw privately.
  2. Enter the amount and a fresh recipient address that has never been used.
  3. The app shows the relayer fee (currently none: Elysian Veil's relayer pays the gas). Click Generate proof & withdraw.
  4. Your browser builds the proof (a few seconds), the relayer submits it, and the recipient receives the HYPE. The recipient needs no gas.

You don't need to connect a wallet to withdraw; nothing is signed.

Privacy meter

While you fill in a withdrawal, the app rates it Weak, Fair or Good from public data only: the list of deposits that everyone can read. Nothing about you is sent anywhere to compute it.

  • Deposits that could be the source: approved deposits at least as large as your withdrawal. An observer can't tell which one is yours; this is your crowd.
  • Same amount: taking out exactly what you put in, when few deposits used that amount, points straight at you.
  • Time: how long ago you deposited, and how many deposits came in after yours.

The deposit amount buttons show how many approved deposits already used each amount. Picking a common one puts you in a bigger crowd.

Split withdrawals

Open Split into several withdrawals over time in the withdraw form. Choose the number of parts (2 to 10), a window (6 to 72 hours) and one fresh recipient per part. The app makes equal round parts and picks random times inside the window, at least 10 minutes apart.

Each part is a normal private withdrawal, and its proof is made in your browser, so keep the tab open and unlocked. If you close it, parts that came due run when you come back and unlock. The plan is stored in this browser only, encrypted with a key derived from your Veil Key, because it links your deposit to its recipients. Track or cancel it under My deposits.

Privacy checklist

The math is solid. Most leaks come from habits. Before you withdraw:

  • Wait. Let time pass and let others deposit after you. Withdrawing minutes after depositing narrows the crowd.
  • Round amounts. Deposit 1, not 0.937. Withdraw in several parts at different times if your amount is unusual (the app can split it for you).
  • Read the meter. The privacy meter tells you when the crowd is too small or the timing too close.
  • Fresh recipient. Never your depositing wallet, never a wallet you used before.
  • Don't fund the recipient yourself. The relayer pays gas; sending gas from your old wallet links them.
  • Don't send it back. Moving funds from the new wallet to the old one undoes everything.
  • Different behaviour. If the new wallet buys the same rare token at the same time as the old one, it can be matched.
  • Network privacy. Your IP is visible to this site and to the RPCs you use, and your internet provider sees that you came here. Opening Elysian Veil in the Tor Browser, or over a VPN you trust, hides both.

Footprint

Footprint is a read-only exposure scan. Paste any wallet and see what an observer sees: where its money came from (exchanges, bridges, other wallets) and where it went, across Robinhood, Ethereum, BNB Chain, Base and Solana. Bridge hops are re-checked on both chains where possible.

Use it before depositing to see what is already linked to you, and after withdrawing to confirm your fresh wallet shows nothing but the relayer. It also follows the money up to two hops and shows token launches and launch-block bundle patterns it finds on the way.

Privacy. The scan service never sees your IP. This site keeps no visit record. Results are public chain data, cached for up to 6 hours. Every scan ends with what Footprint cannot see.

Troubleshooting

"ASP set does not match the on-chain root yet"
The ASP just published a new root. Wait a minute and try again.
"This deposit is not approved by the ASP (yet)"
Check the countdown in My deposits. Denied deposits can only ragequit.
My deposit still says "waiting" long after 30 minutes
The keeper may be offline. Approve it yourself in My deposits, from the wallet that made the deposit,.
The relayer fee is above the 0.5% cap
The pool never lets a relayer take more than 0.5%. Use another relayer or withdraw a larger amount.
Ragequit fails with OnlyOriginalDepositor
Connect the exact wallet that made the deposit.
My deposits are missing
Make sure you unlocked the right Veil Key. Restore with your 12 words; the app rescans the chain.
The wrong wallet extension opens
Click the wallet button again and pick your wallet from the list.

Developers

Architecture

browser app + Privacy Pools SDK (keys, proofs: all local)
   │  /rpc (read-only allow-list)   /relayer/*   /asp/stats
   ▼
web server (static files, strict CSP, same-origin proxies)
   ├─► chain RPC
   └─► relayer          submits Entrypoint.relay(), pays the gas
keeper (guardian key)   queues, screens and approves deposits on Veil ASP
chain: Entrypoint (proxy, owner renounced) → PrivacyPoolSimple (HYPE)
                                            → WithdrawalVerifier, CommitmentVerifier
       Veil ASP (the Entrypoint's only ASP postman) → posts association-set roots

The pool contracts and circuits are upstream Privacy Pools, unmodified. Elysian Veil adds the ASP contract, a deploy script that renounces the owner, the keeper, a relayer launcher and the app.

Networks & contracts

ContractElysium

Addresses are read from this site's deployment.

Circuits & trusted setup

  • Proof system: Groth16 over BN254, circuits written in Circom.
  • withdraw: proves the existing note's commitment is in the state tree, its label is in the ASP tree, the withdrawn amount fits (128-bit range checks), the new nullifier differs from the old one, and outputs the new commitment hash and the spent nullifier hash. The withdrawal context (recipient, fee data, pool scope) is bound into the proof.
  • commitment: used by ragequit; proves knowledge of a note's value, label, nullifier and secret.
  • Hashes: commitment = Poseidon(value, label, Poseidon(nullifier, secret)); trees are Lean incremental Merkle trees (Poseidon), max depth 32.
  • Trusted setup: proving keys come from the public 0xbow ceremony. The SDK checks the SHA-256 of every circuit file against pinned hashes before using it.

Contract interface

// Entrypoint
function deposit(uint256 precommitment) payable returns (uint256 commitment);
function relay(Withdrawal withdrawal, WithdrawProof proof, uint256 scope);
function latestRoot() view returns (uint256);          // current ASP root
function assetConfig(address asset) view returns (pool, minimumDepositAmount, vettingFeeBPS, maxRelayFeeBPS);

// PrivacyPoolSimple (HYPE)
function ragequit(RagequitProof proof);                // original depositor only
function currentRoot() view returns (uint256);         // state tree root
event Deposited(address indexed depositor, uint256 commitment, uint256 label, uint256 value, uint256 precommitmentHash);
event Withdrawn(address indexed processooor, uint256 value, uint256 spentNullifier, uint256 newCommitment);
event Ragequit(address indexed ragequitter, uint256 commitment, uint256 label, uint256 value);

A withdrawal proof must use one of the pool's last 64 state roots and the latest ASP root.

ASP contract

Veil ASP is the only address with the Entrypoint's ASP postman role. Labels come from the pool's Deposited events.

function queue(uint256 label);                        // anyone: starts the window
function queueMany(uint256[] labels);                 // skips unknown or queued labels
function deny(uint256 label, string reason);          // guardian only, inside the window
function approve(uint256[] labels) returns (uint256); // anyone, after the window; posts the root
function status(uint256 label) view returns (Status); // None, Waiting, Ready, Approved, Denied
function isApproved(uint256 label) view returns (bool);
function root() view returns (uint256);
function size() view returns (uint256);
function guardian() view returns (address);           // address(0) once renounced
function WINDOW() view returns (uint256);             // 1800 seconds
function transferGuardian(address to);                // guardian only
function renounceGuardian();                          // guardian only, for good
event Queued(uint256 indexed label, address indexed depositor, uint256 at);
event Denied(uint256 indexed label, string reason);
event Approved(uint256 indexed label, uint256 index);
event RootPosted(uint256 root, uint256 size);

The approved set is the Approved events in index order; rebuild the LeanIMT (Poseidon) from them and compare with Entrypoint.latestRoot(). The "CID" posted with each root is the root's own 64 hex digits, since the set lives on-chain. The keeper also serves read-only counts at GET /asp/stats.

Relayer API

The Privacy Pools relayer, configured to charge only its base fee (currently 0) and pay the gas itself. Base path /relayer.

EndpointPurpose
GET /relayer/details?chainId=&assetAddress=Fee receiver, minimum withdrawal, max gas price.
POST /relayer/quote{ chainId, amount, asset, recipient } → feeBPS and a signed feeCommitment (valid 60 s) whose withdrawalData you bind into the proof.
POST /relayer/request{ withdrawal, publicSignals, proof, scope, chainId, feeCommitment } → { success, txHash }

The relayer cannot change the recipient or the fee: both are inside the proof's context. At worst it can refuse; use another relayer or submit relay() yourself.

Fees & limits

Protocol / vetting fee0%
Relayer fee0 (the relayer pays the gas); capped on-chain at 0.5%
Minimum deposit0.1 HYPE
Minimum relayed withdrawal0.01 HYPE
ASP window30 minutes, fixed in Veil ASP
AssetHYPE only

These parameters were set at deploy and cannot be changed: the owner role that could change them is renounced.

Verify a deployment

  1. Open the Entrypoint on the explorer and call hasRole(keccak256("OWNER_ROLE"), deployer): it must be false.
  2. Check the RoleRevoked event from the deploy transaction.
  3. Compare the verifier bytecode with the upstream build of WithdrawalVerifier and CommitmentVerifier.
  4. Read Veil ASP's Approved events, rebuild the LeanIMT with Poseidon and compare with latestRoot(). Check that only the ASP contract holds ASP_POSTMAN.
  5. In the app, open DevTools → Network during a withdrawal: the only outgoing payload is the proof, amount and recipient. The Verify page runs the live checks for you.

Security

Trust model

PartyCanCannot
Elysian Veil teamRun the keeper, relayer and websiteUpgrade, pause or drain the contracts; see your keys
Guardian (keeper key)Deny a deposit for private withdrawal, inside its 30-minute windowApprove, revoke, move or freeze funds; act after the window (ragequit always works)
RelayerSee proof, amount, recipient and your IP; refuse to relayChange the recipient or fee; link you to a deposit
WebsiteServe the app codeRead your Veil Key, unless the served code is malicious; see Risks
SequencerDelay or censor transactionsForge proofs or steal funds

Audits

  • Privacy Pools core (contracts, circuits, Entrypoint upgrade): audited by Oxorio and Auditware. Reports are in the upstream repository's audit/ folder.
  • Elysian Veil additions (Veil ASP, deploy script, keeper, app, CLI): not audited yet. They are tested (contract tests and end-to-end runs on a fork of Elysium), but start with small amounts.

Risks

  • Smart contract or circuit bugs could lose funds. Mitigation: the pool is unmodified audited code; Veil ASP is small and tested but not audited.
  • Malicious front-end. A compromised website could steal Veil Keys. Mitigation: strict CSP, no third-party scripts, no outside requests from the page; reproducible builds and an IPFS mirror are planned.
  • Losing your Veil Key loses your funds. Nobody can recover it.
  • Small anonymity set. Privacy depends on how many others use the pool.
  • Censorship. The sequencer could delay withdrawals; ragequit and direct contract calls remain.
  • Regulatory risk. Rules about privacy tools differ by country and change.

Live status

/status shows the chain, the pool, the ASP screening, the keeper and relayer (and the gas they have left), refreshed every 30 seconds. The ASP root is also re-checked in your browser against the chain. None of these services can touch funds: if one is down, the app still works.

Status

Live on Elysium mainnet since 9 November 2026.

  • Unmodified audited pool contracts and circuits
  • Owner renounced at deploy, verified on-chain
  • On-chain ASP: 30-minute guardian window, OFAC + blocklist screening, approval by anyone
  • Browser-side proofs, encrypted Veil Key, restore from 12 words
  • End-to-end tests on a fork of Elysium
  • Privacy meter, split withdrawals, live status page
  • Independent audit of Veil ASP, keeper and app
  • Hardware or multisig guardian key
  • More relayers and a relayer fee policy
  • IPFS front-end mirror and reproducible builds
  • Bug bounty
  • Legal review for the jurisdictions served

Resources

Glossary

Commitment
A hash of your note (value, label, nullifier, secret) stored in the pool tree. Reveals nothing.
Nullifier
A secret whose hash is published when a note is spent, so it can't be spent twice. Unlinkable to the commitment.
Label
An ID tied to a deposit and inherited by its change notes; the ASP approves labels.
Anonymity set
The approved deposits your withdrawal could have come from.
ASP
Association Set Provider: publishes the set of approved (clean) deposits.
Ragequit
A public exit that returns a deposit to the wallet that made it.
Relayer
A service that submits your withdrawal and pays the gas, so the recipient needs no funding.
Veil Key
Your 12-word phrase that derives all your notes' secrets.
Groth16
The zero-knowledge proof system used; proofs are small and cheap to verify on-chain.