ACCOUNT & SECURITY

Compliance & Disclosure

Privacy with accountability. Built-in screening, cooldown periods, and voluntary disclosure — without compromising the privacy of legitimate users.

Privacy ≠ Impunity

Dust V2 is designed to provide privacy for legitimate users while maintaining compliance hooks. Unlike fully anonymous systems, Dust includes mechanisms that deter illicit use without weakening privacy guarantees for everyone else.

On-chain Screening

Sanctioned addresses are blocked at deposit time via the Chainalysis oracle. Tainted funds never enter the pool.

Time-locked Cooldowns

A 1-hour cooldown after deposit gives authorities time to flag suspicious activity before funds can be fully mixed.

Voluntary Disclosure

Users can prove their transaction history to auditors via view keys — without revealing spending keys or compromising future privacy.

Deposit Screening (Chainalysis Oracle)

  1. 01

    User initiates deposit

    When calling DustPoolV2.deposit() or depositERC20(), the contract queries the Chainalysis sanctions oracle at 0x40C57923924B5c5c5455c48D93317139ADDaC8fb via the ChainalysisScreener wrapper.
  2. 02

    Oracle check

    IComplianceOracle.isBlocked(msg.sender) returns true if the address is on the OFAC sanctions list. If blocked, the transaction reverts with DepositBlocked().
  3. 03

    Deposit proceeds

    If the address passes screening, the deposit continues normally. An event DepositScreened(depositor, commitment, blocked=false) is emitted for audit trails.

Updateable oracle

The compliance oracle is updateable. The pool owner can call setComplianceOracle(newOracle) to switch screening providers without redeploying the contract.

Deposit Cooldown (1 Hour)

After depositing, a 1-hour cooldown period begins. During cooldown, withdrawals from that note can only go to the original depositor's address. After cooldown expires, withdrawals can go to any address. This gives compliance systems time to flag suspicious deposits before funds can be fully mixed.

depositTimestamp[commitment] = block.timestamp depositOriginator[commitment] = msg.sender // During withdrawal: if (block.timestamp < depositTimestamp[C] + 1 hour) { require(recipient == depositOriginator[C], "CooldownActive()") }

On-chain, the contract stores depositTimestamp and depositOriginator mappings for each commitment. If a user tries to withdraw to a different address during cooldown, the transaction reverts with CooldownActive(). The frontend shows a countdown timer with the remaining time.

Why 1 hour?

One hour balances usability against compliance needs. It is long enough for off-chain monitoring systems to flag suspicious deposits and short enough that legitimate users experience minimal friction. The pool owner can adjust this parameter if regulations change.

View Keys

A view key allows a third party to verify your full transaction history without gaining the ability to spend your funds. It contains two components:

ownerPubKey

PUBLIC

Poseidon(spendingKey) — appears in every UTXO commitment. Allows the holder to verify which commitments belong to you by recomputing the Poseidon hash with known note parameters.

nullifierKey

SENSITIVE

Computes nullifiers: N = Poseidon(nullifierKey, leafIndex). Allows the holder to determine which notes have been spent by matching against on-chain nullifier records.

Serialized format: dvk1:<hex(ownerPubKey)><hex(nullifierKey)> CAN do: - Verify all note commitments (recompute Poseidon hash) - Compute nullifiers (track which notes are spent) - Generate a complete transaction history CANNOT do: - Spend funds - Create new notes - Modify balances

Unlike Zcash's incoming viewing key model, Dust view keys include nullifier tracking, meaning the holder can see both deposits and spending activity. A Zcash-style ivk only reveals incoming notes.

View key security

A view key reveals your full transaction history — every deposit, transfer, and withdrawal amount. Share only with trusted parties (auditor, tax authority, compliance officer). Once shared, the holder can track all past and future activity until you rotate keys.

Disclosure Reports

  1. 01

    Derive view key

    Go to Settings → Disclosure. Click “Derive View Key”. This computes ownerPubKey = Poseidon(spendingKey) and extracts the nullifierKey from your V2 key material.
  2. 02

    Generate report

    Click “Generate Report”. The browser scans all your notes and verifies each commitment: Poseidon(ownerPubKey, amount, asset, chainId, blinding) == commitment. The report includes total notes, total deposited, total spent, and unspent balance.
  3. 03

    Export

    Export as CSV or JSON. The report is self-authenticating — an auditor can independently verify each commitment using only the view key and the on-chain Merkle tree data. No cooperation from you or the protocol is required after export.

Relayer Screening

The relayer performs an additional screening layer on the withdrawal side. Every recipient address is checked against the Chainalysis sanctions oracle before the relayer submits the withdrawal transaction.

Recipient screening. If the recipient address is sanctioned, the relayer returns HTTP 403 with “Recipient address is sanctioned”. The withdrawal is not submitted.

All endpoints covered. Screening applies to every relayer endpoint: /api/v2/withdraw, /api/v2/split-withdraw, /api/v2/transfer, and /api/v2/batch-withdraw.

Fail-closed. If the compliance screening service is unavailable, the relayer rejects the request rather than allowing it through. No withdrawal proceeds without a successful sanctions check.

Summary

FeatureMechanismWhen
Deposit screeningChainalysis oracle on-chainEvery deposit
Cooldown period1-hour time lockAfter deposit
Recipient screeningChainalysis oracle via relayerEvery withdrawal
View keysPoseidon-based disclosureOn-demand (user generates)
Disclosure reportsCSV/JSON export with commitment verificationOn-demand
Chainalysis OracleDeposit CooldownView KeysPoseidon VerificationSelf-Authenticating Reports