Beilpre-launchOpen app
Beil documentation

A privacy layer
for everything you do on BNB Chain

Beil gives your wallet a private balance. Shield BNB or any BEP-20 into it, then send, trade, lend and withdraw without the chain linking any of it back to you. Your keys never leave your browser.

0.3%to shield
0%Beil fee on private sends
0.3%to withdraw
2²⁶notes the tree can hold
Audit pending. Beil's contracts and circuit have not been externally audited yet, and the proving key comes from a single-operator trusted setup run by the Beil team (not a multi-party ceremony). Deposits will be capped per token and raised gradually. See Security for the current status.

How it works

Value enters through a public shield, lives as sealed notes, and leaves through a public exit. Everything in between is proven, not revealed. Tap a stage.

MetaMask, Trust Wallet or Binance Wallet stays your public identity on BNB Chain. It signs exactly one kind of thing for Beil: a shield. Beil never holds or sees its private key.

The three pieces

Notes

Each note commits to a token, an amount and its owner. Only your viewing key can open it; only your spending key can spend it.

Proofs

Groth16 zero-knowledge proofs, built in your browser, convince the pool contract that balances add up and that you own what you spend.

Relayers

A relayer submits your proof and pays the gas. It can't change where funds go: the recipient and its own fee are bound into the proof.

Quick start

  1. Connect your wallet. MetaMask, Trust Wallet, Binance Wallet or any wallet that speaks BNB Chain. It stays your public entry and exit.
  2. Create your vault and save the recovery key. A random key generated in your browser, encrypted with your passphrase. Write the 24-word recovery key down: it is the only way back if this browser is lost.
  3. Shield a token. One wallet transaction moves it behind the privacy wall (BEP-20s need a one-time approval first).
  4. Use it privately. Send to a beil1… address, trade or lend. No wallet signatures, no public link.
  5. Withdraw. To any address, by default a fresh one-time address only your vault controls.

Shield

Moves BNB or any registered BEP-20 from your wallet into the Beil pool. BNB is wrapped to WBNB and unwrapped on the way out automatically. Your wallet pays the amount plus the 0.3% Beil fee and the gas; the new note is sealed in your browser before the transaction is sent.

Any token can be added: registerAsset is permissionless and costs only gas. Tokens that charge a fee on transfer or rebase are refused on-chain, because the pool checks it received exactly what it was promised. Each token has a per-deposit limit and a total cap, raised gradually.

Crowd size matters. A token few people use is easier to trace from entry to exit. The app shows each token's crowd and warns when it's small.

Send privately

Pay any Beil address (beil1…, bech32m, so its checksum catches a typo) in any token. There's no wallet signature and no Beil fee, only the relayer's network fee. When you hold private WBNB, Beil pays that fee in WBNB and the transaction doesn't name the token you sent.

Every transaction spends exactly four notes and creates exactly three, padding with dummies, and every output carries a ciphertext of the same 168 bytes. The recipient's app finds the payment by trying to open every new note with its viewing key, so nobody (not even the indexer) learns which notes are whose.

Trade

Swap inside your private balance through PancakeSwap V2 or V3. On-chain, the Beil pool is the trader. Your proof spends the input notes, the pool hands the input to an allowlisted adapter, the route runs, and the pool measures what it actually received and seals it as a new note for you, all in one transaction.

You set a minimum output. If the market can't meet it, the whole transaction reverts and your notes are untouched: on the EVM there's no escrow and no refund step to wait for. Quotes and the suggested minimum come from the relayer, so the app compares them with the market price before you approve.

Earn

Lend from your private balance on Venus. Supplying turns, for example, USDT into a private note of vUSDT, which grows as Venus' exchange rate rises with interest. Redeem turns it back into the underlying token, privately. BNB is supplied to vBNB through automatic unwrapping.

Lending has its own risks: smart contracts, borrowers, and withdrawal limits when a market is fully utilised. Beil hides who lends; it doesn't insure the market.

Withdraw & one-time addresses

Withdraw sends funds to any BNB Chain address, minus the 0.3% fee. By default the app sends them to a one-time address derived from your vault (a fresh secp256k1 account per index), so nothing ties it to your wallet. Your recovery key restores every one of them. WBNB arrives as native BNB.

Because a withdrawal goes through a relayer, the recipient needs no BNB for gas: the relayer's fee is paid from your private balance.

Gasless shield

For tokens that support EIP-2612 permits, you can shield without holding any BNB. Your wallet signs two messages (no transactions): the permit, and a Beil intent that binds the exact deposit, its notes and a nonce. A relayer submits shieldWithPermit, pays the gas and takes its fee out of the deposit.

  1. Sign the permit for the amount plus the 0.3% fee.
  2. Sign the intent: an EIP-712 message over the deposit's hash, its three note commitments, a nonce and a deadline, so nobody can replay it with different notes.
  3. The relayer submits it. If the permit was already used, the pool relies on the allowance instead, so a front-run permit can't block you.

What is public, what is private

Pick an action to see exactly what the chain records and what stays sealed.

What BNB Chain sees

  • That a valid private transaction happened
  • The relayer, its fee and the fee token (WBNB when you hold private BNB)
  • Four nullifiers and three new commitments, always: real or dummy, they look the same

What stays private

  • Sender
  • Recipient
  • Amount
  • Which token moved, when the fee is paid in WBNB
  • How many notes you really spent

With no private WBNB, the relayer is paid in the token you send, which names that token. The app tells you before you confirm.

Good habits

  • Don't withdraw the exact amount you shielded to the same wallet right away.
  • Keep a little private WBNB so transfers can hide their token.
  • Prefer tokens with a big crowd; wait a while between shielding and withdrawing.
  • Reach the relayer through a network-level privacy tool if your IP address matters to you.

Fees

Beil's fee is 0.3% each time value crosses the privacy wall: when you shield, trade or withdraw. Private sends between Beil users have no Beil fee. The contract enforces the rates and caps each one at 1%; protocol fees are kept apart from user funds and can only be paid to the treasury.

ActionBeil feeRelayer fee
Shield0.3%, on topNone: your wallet pays the gas (gasless shield: taken from the deposit)
SendNoneGas × gas price × margin, in WBNB or the token
Trade / Earn0.3% of the inputGas × gas price × margin
Withdraw0.3% of what you withdrawGas × gas price × margin

Try it

Action
Beil fee0.3% · 0.3
ResultYour wallet pays 100.3; 100 lands privately.

Default rates (30 bps). The pool is not deployed yet.

Keys & recovery

Your vault holds one random 32-byte root. From it your browser derives a spending key (to spend notes), a viewing key (to find and open them, x25519) and every one-time address. It's encrypted with your passphrase (PBKDF2-SHA256, 600,000 rounds → AES-256-GCM) and stored only in this browser.

  • The recovery key (24 words, shown once at creation) restores everything on any device. Anyone who has it can spend your private balance.
  • It is not derived from your wallet, so a wallet compromise doesn't expose your Beil balance, and vice versa.
  • Your beil1… address encodes your shielded public key and your encryption key; share it freely. Your beilview1… viewing key is read-only; share it only with someone who should see your history.
Lose both this browser and the recovery key and the funds are unrecoverable. Nobody, including the Beil team, can restore them.

Security model

  • Non-custodial: only proofs from your keys move your notes. The admin can pause, set fees, caps and allowlisted adapters, but no function lets it move anyone's funds.
  • Immutable: the pool is not upgradeable. What is deployed is what runs; changes mean a new deployment that users choose to move to.
  • Bound to the proof: recipient, fees, swap terms and the chain id are hashed into each proof by the contract itself; a relayer that changes anything gets an invalid proof.
  • Atomic integrations: swaps and lending run through allowlisted adapters inside one transaction; the pool measures its own balance and enforces your minimum output.
  • Multisig admin: a Safe multisig, handed over in two steps (Ownable2Step). It can pause, never move funds.

Testing, review status and live on-chain checks are on the Security page.

Limits & risks

  • Anonymity set: privacy grows with the number of people using Beil, per token for shields and exits.
  • Issuer controls: some BEP-20s (for example bridged stablecoins) can be frozen or blacklisted by their issuer, and that applies to the pool's balance too. The app labels them.
  • Emergency pause: the multisig can pause deposits, transfers and swaps; withdrawals stay open. In an incident it can also pause everything leaving the pool for at most 3 days (it ends by itself, and a new one can start only 7 days after the last ended).
  • Trusted setup: Groth16 needs a per-circuit setup. Phase 1 is the public PSE Perpetual Powers of Tau; phase 2 was run by the Beil team as a single operator and sealed with a public drand beacon. Anyone who knew the operator's randomness could forge proofs, so you are trusting that it was destroyed. The transcript is at /circuits/ceremony.json.
  • Early software: no external audit yet. Caps stay low until that changes. A browser extension is planned after mainnet, not before.

SDK

@beil/sdk does everything the app does: keys, sync, proofs, and talking to the relayer. Proofs are generated client-side with snarkjs; nothing secret is ever sent. @beil/crypto holds the pure primitives (Poseidon, notes, note encryption, addresses, the Merkle tree).

import { BeilClient } from '@beil/sdk'
import { deriveKeys, randomRoot } from '@beil/crypto'
import { createPublicClient, http } from 'viem'
import { bsc } from 'viem/chains'

const publicClient = createPublicClient({ chain: bsc, transport: http() })

const beil = new BeilClient({
  chainId: 56, pool: POOL_ADDRESS, publicClient,
  indexerUrl: 'https://indexer.example', relayerUrl: 'https://relayer.example',
  circuit: { wasm: '/circuits/transaction.wasm', zkey: '/circuits/transaction_final.zkey' },
})

beil.unlock(deriveKeys(randomRoot()))  // keep the 32-byte root safe: it is the vault
await beil.sync()                      // download every note, find yours by trial decryption
console.log(beil.rootStatus)           // 'ok': matches the pool's own getLastRoot() on-chain

Relayer & indexer API

Both are plain HTTP, keep no access logs and store no IP addresses. Anyone can run their own. Large numbers are decimal strings. What the app may connect to, checked live in your browser: API.

EndpointWhat it does
GET /v1/infoRelayer address, chain, pool, allowlisted adapters (PancakeSwap V2/V3, Venus), fee rates, accepted fee tokens
GET /v1/fee?token&inputs&kindRelayer fee for a fee token and kind (transfer, withdraw, swap): gas × price × margin, converted to the token
POST /v1/relaySubmit a proof (transfer, withdrawal, trade, lend). Checked off-chain and simulated before it is sent
POST /v1/sponsorGasless shield: submits a permit + intent signature + proof, after strict checks
GET /v1/status/:txHashpending, success or reverted
GET /v1/quote?kind&tokenIn&tokenOut&amountInSwap or lending quote after the Beil fee, with a minimum output (0.5% default slippage) and the adapter route
GET /v1/positionsVenus markets: vToken, underlying, supply APY, exchange rate
GET /v1/commitments?from&limitIndexer: every note commitment and ciphertext, in order. Everyone downloads all of them
GET /v1/nullifiers · /v1/rootIndexer: spent markers, and the Merkle root cross-checked against the pool's getLastRoot()
GET /v1/tokens · /v1/statsIndexer: registered tokens with their crowd size, and public pool totals

Contracts

BeilPool · BNB Smart ChainNot deployed yet
FunctionPurpose
transactShield, private transfer, withdrawal or swap/lend, with a Groth16 proof (4 notes in, 3 out)
shieldWithPermitGasless shield: EIP-2612 permit + EIP-712 intent signature, submitted by a relayer
registerAssetOpen the pool to a new BEP-20 (anyone; default caps until the multisig tunes them)
collectFeesSweep accrued protocol fees to the treasury (anyone can call; treasury only receives)
setFees · setAssetConfig · setDefaultCaps · setAdapter · setTreasuryMultisig governance: fees (each ≤ 1%), caps, adapter allowlist, treasury
setPaused · emergencyExitPause · liftExitPausePause deposits / transfers / swaps (never withdrawals); an exit pause lasts at most 3 days, 7 days apart
getLastRoot · isKnownRoot · nullifierSpent · nextIndexPublic views: the tree, its last 2^20 roots, and spent markers

Circuit: Transaction(26, 4, 3), Groth16 over BN254, 13 public inputs (root, public amount and asset, fee asset and fee, the external-data hash, 4 nullifiers, 3 commitments), verified with the EVM's BN254 precompiles (ecAdd, ecMul, ecPairing). Notes live in a Poseidon Merkle tree of 226 leaves.

FAQ

Does Beil ever hold my keys?

No. Your vault is generated and encrypted in your browser, and proofs are built there too. The relayer and indexer never get your keys. Like any server they see your IP address, and the relayer sees the transactions it submits for you, which are public on-chain anyway.

Can the Beil team freeze or take my funds?

The contracts have no function that moves a note without its owner's proof, and they are not upgradeable: there is no proxy and no admin path to replace the code. The multisig can pause deposits, transfers and swaps (withdrawals stay open), pause everything leaving the pool for at most 3 days with 7 days between two such pauses, set fees up to 1%, set caps, and choose which adapters are allowed. Disabling a token stops new deposits into it, never its withdrawals.

What if the relayer goes down?

Your notes stay in the pool, untouched. Anyone can run a relayer, and transact is permissionless: you can also submit a proof from any wallet yourself (that wallet then pays the gas and is visible as the sender).

Is Beil anonymous?

Beil hides the link between your wallet and your private activity. How well depends on the crowd and your habits: amounts, timing and tokens. No tool makes you 100% anonymous, and we won't claim one does.

Which tokens work?

BNB (as WBNB) and any standard BEP-20 that has been registered, which anyone can do. Fee-on-transfer and rebasing tokens are refused automatically: the pool checks that it received exactly the amount it was promised.

I lost my recovery key and my browser data.

Then the funds can't be recovered by anyone. Keep the recovery key offline and private.

Why does a send sometimes show the token?

The relayer has to be paid in something public. When you hold private WBNB, it is paid in WBNB and the token you send stays hidden. With none, it is paid in the token itself, which names it. Shield a little BNB to keep sends fully hidden.

Why WBNB and not BNB?

Inside the pool every asset is a BEP-20, so native BNB is wrapped on the way in and unwrapped on the way out. You send and receive plain BNB; the wrapping is automatic.

Glossary

Note
A sealed record of a token amount you own. Your private balance is your notes.
Commitment
The public fingerprint of a note, Poseidon(npk, asset, amount), added to the Merkle tree. Reveals nothing about the note.
Nullifier
Published when a note is spent, so it can't be spent twice. Unlinkable to the note's commitment without your keys.
Merkle root
One hash that commits to every note in the tree. Proofs show your notes are in it; the pool remembers the last 2^20 (about a million) roots.
Relayer
A server that submits proofs and pays gas. It can't alter what the proof allows, including its own fee.
Indexer
A server that serves public pool data (commitments, ciphertexts, nullifiers) to everyone alike.
Anonymity set
The crowd your activity blends into: other users of the same pool and token.
One-time address
A fresh BNB Chain address derived from your vault, used once for an exit or a payment.
Viewing key
A read-only beilview1… key that can find and open your notes and see when they are spent, but never spend.
Adapter
An allowlisted contract that runs one swap or lending action for the pool: PancakeSwap V2, V3 or Venus.

Security & testing →