Portal Deposit Addresses
A portal is a reusable, public deposit address — like a centralized-exchange deposit address, but self-custodial. The owner publishes one fixed addressE;
any number of senders fund it with ordinary ERC-20 transfers (no Privacy Boost
software, no per-deposit ceremony); and the funds are later swept into the
owner’s shielded balance. Sweeping is permissionless and crediting is submitted
by an allowed relay, both decoupled from the deposit, so the recipient does not
have to be online for any individual deposit.
Public observers see the portal address, token, amount, timing, and sender — but
never which Privacy Boost account receives the funds.
How it works
A portal addressE is a normal Ethereum EOA that the owner controls, upgraded
via EIP-7702 so it can do three
things: bind its recipient record once (a second binding reverts), sweep
supported tokens into the pool (wrapping plain ETH for the configured
wrapped-native token), and let the owner withdraw funds resting at it. It can
never spend from the pool.
E use its owner’s direct withdrawal path without the
pool’s cancellation delay.
- Create. The owner derives a fresh portal address
Efrom their nullifying key, delegates it to the shared portal implementation, and registers a public on-chain bindingHthat commits to their account without revealing it. - Publish. The owner publishes a private registry entry (
E → (recipientMPK, blind), where the client supplies onlyblind) so the server’s indexer can credit deposits to the right account. A missing or wrong entry only delays crediting — it can never send funds to the wrong account. - Fund. Anyone sends standard ERC-20 to
E. This is an ordinary token transfer; the sender needs nothing from Privacy Boost. - Sweep. Anyone calls the permissionless sweep, which measures the actual received balance and escrows it in the pool. Deployments typically run a keeper so owners do not have to.
- Credit. The relay submits an epoch proof that credits the net amount
after the recorded sweep fee to the owner’s shielded balance as a new note.
The owner’s identifying key stays private throughout — the proof binds the
credit to the public
Hwithout revealing the account. - Reclaim / withdraw. If a swept deposit is never credited, anyone can
cancel it after the delay. The contract returns the full gross amount to
E, regardless of who calls. Funds that were never swept (e.g. an unsupported token) can be withdrawn directly fromE.
requestBlock + cancelDelay, where
requestBlock is recorded at the sweep and cancelDelay() gives the pool’s
configured delay in blocks.
For the configured wrapped-native token, a sweep can wrap native ETH above the
portal’s 0.001 ETH reserve. Receiving ETH alone does not wrap or credit it.
Ordinary ERC-20 sweeps leave native ETH untouched.
SDK API shape
The SDK exposes the same high-level portal lifecycle across TypeScript, CLI, WASM, iOS, Android, and React Native:create/createPortalderivesE, gaslessly delegates and registers it, and publishes discovery.listPage/listPortalsPage,depositsPage/listPortalDepositsPage, andstatus/getPortalStatusexpose portal and deposit state.sweep/sweepPortaltriggersrequestPortalDepositfrom the connected wallet when an app needs a self-sweep backstop.reclaim/reclaimPortalDepositreclaims an uncredited swept deposit after the cancel delay.withdraw/withdrawPortalsigns an escape-hatch transaction fromEfor raw funds resting at the portal.
E’s key inside core; it never crosses
the binding boundary. Low-level generatePortalEoa and encodePortalWithdraw
remain only as custodial escape hatches for integrations that intentionally
manage their own portal EOA key.
Trust and privacy
The portal is a deposit-only extension: it can only add notes to the shared note tree, never spend or alter existing notes, and it grants no new capability to the relay or TEE.
A portal note joins the same shared note tree as every other deposit and
transfer, so its anonymity set is the full mixed pool. The portal hides who
receives, not that
E was funded. Because a reusable public address makes
the sender ↔ E link public, use one portal per counterparty or rotate
portals when unlinkability between funders matters — these are product-layer
mitigations, not cryptographic guarantees. The discovery registry (E → (recipientMPK, blind)) is privacy-load-bearing and should be treated as
confidential. Preserve recipientMPK and blind for recovery.
Current limitations
These are known constraints of the current implementation; design around them:status.delegatedalways reportsfalse. A portal you created is delegated regardless; gate readiness onregisteredandpublished.deposit.cancellableAtBlockis always0. Treat it as unknown, not “reclaimable now” — the chain still enforces the delay on reclaim.- The sweep fee is one global rate, not per-token.
requestPortalDepositis permissionless: the caller is recorded as the fee payee, and the rate is snapshotted into the record at sweep time so a later rate change cannot alter an already-escrowed sweep. The credited amount isgross - floor(gross * feeBps / 10000); cancellation returns the gross amount. The rate is a single owner-set value capped at 10%, so a deployment running it at zero credits the full gross amount. If fee payment fails at settlement, the sweeper can claim the deferred fee later. - Registration is write-once per
E. A portal binding cannot be changed after it is set; derive a new portal instead. - Not every network has a
PortalDelegate. Portals need the shared EIP-7702 delegate deployed on the target chain and advertised by the server. In TypeScript and React,sdk.portal.delegateAddress()returns nothing when it is absent, as doesportalDelegateAddress()on the other platforms. See Contract Addresses. - Same-chain credit. Portals credit the pool on the portal’s chain. Moving funds between chains requires a separate bridge flow; multi-chain portals are a planned additive extension.