> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.prividium.com/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

Selective disclosure is a privacy feature that allows contract owners to make specific pieces of information publicly
accessible while maintaining the confidentiality of all other contract data.

The following contract information can be disclosed:

* Account data (bytecode, balance, nonce and account metadata).
* Token total supply.
* Token holder balance.

:::warning[WARNING]
When enabled, dedicated RPC endpoints become available to access this data without authentication.
:::

Selective disclosure is **disabled by default**. To enable it, set `DISCLOSURE_METHODS_ENABLED=true` on the Permissions
API and `VITE_DISCLOSURE_METHODS_ENABLED=true` on the Admin Panel.

:::warning[Security Consideration]
Token supply and balance disclosures should be trusted only when the disclosed contract's code is itself trusted —
this is why the feature is off by default. Before enabling it, read
[Selective Disclosure Integrity Limits](/developers/applications/security-limitations#5-selective-disclosure-integrity-limits-eth_call-disclosures).
:::

## Step-by-Step Process

### 1. Enable Disclosure

Disclosure settings are managed directly on the contract configuration form:

1. Go to the **Contracts** page in the **Admin Dashboard**.
2. Click **Create Contract** to register a new one, OR click on an existing contract to edit it.
3. In the contract form, expand the **Data disclosure** section:
   * Check **Disclose account data** to expose the address's full account-properties record (bytecode, balance, nonce
     and account metadata).
   * Check **Disclose Erc 20 Supply** to expose total supply (requires the contract to be an ERC-20).
   * Optionally set **Disclosure start block** to restrict disclosure queries to blocks at or after a specific block
     number. Requests for earlier blocks are rejected with an error. Defaults to `0` (no minimum).
4. Click **Save** (or Create).

:::warning[Enabling supply or balance disclosure makes **every storage slot read during execution** publicly visible.]
For example, enabling `totalSupply()` disclosure will expose all storage slots the EVM touches while computing the
result, not just the final value. Admins should understand the contract's storage layout before enabling disclosure to
ensure no sensitive data is unintentionally revealed.
:::

### 2. Configure Disclosed Addresses (ERC-20 only)

If **ERC-20 Supply Disclosure** is enabled, you can specify addresses whose token balances may be queried publicly via
`prividium_tokenBalanceDisclosure`.

1. Navigate to the contract details page.
2. Look for the **Disclosed Addresses** section.
3. Add addresses to allow public balance queries for each.
4. Save your changes.

### 3. Request Data

Once configured, users can query the data using specific JSON-RPC methods without needing an authentication token.

## Available Disclosure Types

### 1. Account Data Disclosure

Reveals a single address's account-properties record, which includes bytecode, balance and nonce, along with the full
cryptographic proof material needed to verify that record against the L1 state commitment. Works for both contracts and
EOAs.

:::note[At the moment there is no way to expose only one of those properties.]
Bytecode, balance, and nonce needs to be disclosed all together.
:::

**Purpose:**

* Verify a contract's deployed bytecode matches expected values.
* Provide verifiable transparency for an address's balance and nonce without exposing unrelated state.
* Enable auditors and third parties to confirm an account's on-chain state against L1 without private RPC access.

**RPC Endpoint:** `prividium_accountDataDisclosure`

**Request:**

```json
{
  "method": "prividium_accountDataDisclosure",
  "params": ["0x1234567890123456789012345678901234567890", "0x1a2b3c"]
}
```

**Parameters:**

* `params[0]` (required): Address to query (contract or EOA).
* `params[1]` (required): Hex-encoded block number. Must be at or after the contract's disclosure start block.

**Response:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "accountProperties": {
      "versioningData": "0x0101010000000000",
      "nonce": "0x01",
      "balance": "0x0de0b6b3a7640000",
      "bytecodeHash": "0xabcd...",
      "unpaddedCodeLen": 1024,
      "artifactsLen": 16,
      "observableBytecodeHash": "0x1234...",
      "observableBytecodeLen": 1024
    },
    "address": "0x1234567890123456789012345678901234567890",
    "bytecode": "0x6080604052...",
    "batchNumber": 175,
    "stateCommitmentPreimage": {
      "nextFreeSlot": "0x430",
      "blockNumber": "0x1da",
      "last256BlockHashesBlake": "0x7e2e68a1633628cf4ee6416a444a6af248e7cf975b3b744b6068beb14f8e98e4",
      "lastBlockTimestamp": "0x69dda64c"
    },
    "l1VerificationData": {
      "batchNumber": 175,
      "numberOfLayer1Txs": 0,
      "priorityOperationsHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      "dependencyRootsRollingHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "l2ToL1LogsRootHash": "0x692f35c99f9c698852289ffecf07f6dd45770904521149d79aa85aae598fa375",
      "commitment": "0x9dbc02b99ea4c385ef2835c23affe9cf84004b946b107b2351eee54f2c641f9b"
    },
    "storageProof": {
      "type": "existing",
      "index": 742,
      "value": "0x...",
      "nextIndex": 903,
      "siblings": ["0xa1b2c3d4...", "0xe5f6a7b8...", "..."]
    }
  }
}
```

**Implementation Details:**

* ZKsync OS stores the hash of account data in a virtual system contract with address
  `0x0000000000000000000000000000000000008003`.
* The method returns all the data needed to reconstruct this hash.
* Storage proofs are also returned, so this data can be verified against the data posted to L1.

**Verifying account data using Prividium SDK:**

**disclosure-account-data.ts**

```typescript
import { selectiveDisclosureActions, verifyAccountPropertiesProof } from 'prividium';
import type { Address } from 'viem';
import { createPublicClient, http } from 'viem';

const PRIVIDIUM_RPC_URL = process.env.PRIVIDIUM_RPC_URL || 'http://localhost:8000/rpc';
const L1_RPC_URL = process.env.L1_RPC_URL || 'http://localhost:5010';
const L1_DIAMOND_PROXY_ADDRESS = (process.env.L1_DIAMOND_PROXY_ADDRESS ||
    '0x7eb50663f054e1c4316f3dc93c4fadb21eb24445') as Address;

export async function verifyAccountData(address: Address, blockNumber: bigint) {
    const prividium = createPublicClient({ transport: http(PRIVIDIUM_RPC_URL) }).extend(selectiveDisclosureActions);
    const l1Client = createPublicClient({ transport: http(L1_RPC_URL) });

    const disclosure = await prividium.accountDataDisclosure(address, blockNumber);
    const expectedBytecode = disclosure.bytecode === '0x' ? undefined : disclosure.bytecode;
    const ok = await verifyAccountPropertiesProof(
        disclosure,
        l1Client,
        L1_DIAMOND_PROXY_ADDRESS,
        expectedBytecode,
        address
    );
    return ok;
}
```

### 2. Token Supply Disclosure

Reveals an ERC-20 token's total supply along with cryptographic storage proofs, enabling independent verification
against the ZKsync state commitment.

**Purpose:**

* Provide verifiable transparency for token total supply without exposing individual holder balances.
* Enable auditors, DEXs, and aggregators to confirm supply figures on-chain.

**What's Disclosed:**

* `result`: Hex-encoded total supply value returned by `totalSupply()`
* `callData`: The ABI-encoded call used to retrieve the value
* `batchNumber`: The L1 batch number at which the proof was generated
* `stateCommitmentPreimage`: ZKsync state commitment data for verification
* `l1VerificationData`: Data required for L1 proof verification
* `proofs`: Storage proofs for each contract slot read during execution

**RPC Endpoint:** `prividium_tokenSupplyDisclosure`

**Request:**

```json
{
  "method": "prividium_tokenSupplyDisclosure",
  "params": ["0x1234567890123456789012345678901234567890", "0x1a2b3c"]
}
```

**Parameters:**

* `params[0]` (required): ERC-20 token contract address
* `params[1]` (required): Hex-encoded block number. Must be at or after the contract's disclosure start block.

**Response:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "result": "0x00000000000000000000000000000000000000000000000000000000000006e4",
    "callData": "0x18160ddd",
    "batchNumber": 175,
    "stateCommitmentPreimage": {
      "nextFreeSlot": "0x430",
      "blockNumber": "0x1da",
      "last256BlockHashesBlake": "0x7e2e68a1633628cf4ee6416a444a6af248e7cf975b3b744b6068beb14f8e98e4",
      "lastBlockTimestamp": "0x69dda64c"
    },
    "l1VerificationData": {
      "batchNumber": 175,
      "numberOfLayer1Txs": 0,
      "priorityOperationsHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      "dependencyRootsRollingHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "l2ToL1LogsRootHash": "0x692f35c99f9c698852289ffecf07f6dd45770904521149d79aa85aae598fa375",
      "commitment": "0x9dbc02b99ea4c385ef2835c23affe9cf84004b946b107b2351eee54f2c641f9b"
    },
    "proofs": [
      {
        "address": "0x7859dcea64a8f60d9ec8f31521574618d8ae8fe1",
        "storageProofs": [
          {
            "key": "0x0000000000000000000000000000000000000000000000000000000000000003",
            "proof": {
              "type": "existing",
              "index": 691,
              "value": "0x00000000000000000000000000000000000000000000000000000000000006e4",
              "nextIndex": 1056,
              "siblings": ["0xf213959a...", "0x355510938b...", "..."]
            }
          }
        ]
      }
    ]
  }
}
```

**Implementation Details:**

* **Data Retrieval**: Debug-traces a `totalSupply()` call, collects touched storage slots, and gathers `zks_getProof`
  for each slot.
* **Authorization**: Permissions API's `checkErcTokenSupply` verifies supply disclosure is enabled for the contract.

**Verifying a token supply disclosure using Prividium SDK:**

**disclosure-token-supply.ts**

```typescript
import { selectiveDisclosureActions, verifyEthCallDisclosure } from 'prividium';
import { type Address, createPublicClient, http } from 'viem';

const PRIVIDIUM_RPC_URL = process.env.PRIVIDIUM_RPC_URL || 'http://localhost:8000/rpc';
const L1_RPC_URL = process.env.L1_RPC_URL || 'http://localhost:5010';
const L2_RPC_URL = process.env.L2_RPC_URL || 'http://localhost:5050';
const L1_DIAMOND_PROXY_ADDRESS = (process.env.L1_DIAMOND_PROXY_ADDRESS ||
    '0x7eb50663f054e1c4316f3dc93c4fadb21eb24445') as Address;

export async function verifyTokenSupplyDisclosure(tokenAddress: Address, blockNumber: bigint) {
    const prividium = createPublicClient({ transport: http(PRIVIDIUM_RPC_URL) }).extend(selectiveDisclosureActions);
    const l1Client = createPublicClient({ transport: http(L1_RPC_URL) });
    const l2Client = createPublicClient({ transport: http(L2_RPC_URL) });

    const disclosure = await prividium.tokenSupplyDisclosure(tokenAddress, blockNumber);
    const bytecodes = { [tokenAddress.toLowerCase()]: (await l2Client.getCode({ address: tokenAddress }))! };
    const ok = await verifyEthCallDisclosure({
        disclosure,
        l1Client,
        l2Client,
        diamondAddress: L1_DIAMOND_PROXY_ADDRESS,
        contractBytecodes: bytecodes,
        batchNumber: disclosure.batchNumber
    });
    return ok;
}
```

### 3. Token Balance Disclosure

Reveals the token balance of a specific holder address along with cryptographic storage proofs.

**Purpose:**

* Allow public verification of balances for pre-approved addresses (e.g., disclosed treasury or vesting wallets).
* Enable third parties to confirm a specific holder's balance without accessing private RPC.

**What's Disclosed:**

* `result`: Hex-encoded balance value returned by `balanceOf(holderAddress)`
* `callData`: The ABI-encoded call used to retrieve the value
* `batchNumber`: The L1 batch number at which the proof was generated
* `stateCommitmentPreimage`: ZKsync state commitment data for verification
* `l1VerificationData`: Data required for L1 proof verification
* `proofs`: Storage proofs for each contract slot read during execution

**RPC Endpoint:** `prividium_tokenBalanceDisclosure`

**Request:**

```json
{
  "method": "prividium_tokenBalanceDisclosure",
  "params": ["0x1234567890123456789012345678901234567890", "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x1a2b3c"]
}
```

**Parameters:**

* `params[0]` (required): ERC-20 token contract address
* `params[1]` (required): Holder address to query
* `params[2]` (required): Hex-encoded block number. Must be at or after the contract's disclosure start block.

**Response:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "result": "0x0000000000000000000000000000000000000000000000000000000000000064",
    "callData": "0x70a0823100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8",
    "batchNumber": 175,
    "stateCommitmentPreimage": {
      "nextFreeSlot": "0x430",
      "blockNumber": "0x1da",
      "last256BlockHashesBlake": "0x7e2e68a1633628cf4ee6416a444a6af248e7cf975b3b744b6068beb14f8e98e4",
      "lastBlockTimestamp": "0x69dda64c"
    },
    "l1VerificationData": {
      "batchNumber": 175,
      "numberOfLayer1Txs": 0,
      "priorityOperationsHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      "dependencyRootsRollingHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "l2ToL1LogsRootHash": "0x692f35c99f9c698852289ffecf07f6dd45770904521149d79aa85aae598fa375",
      "commitment": "0x9dbc02b99ea4c385ef2835c23affe9cf84004b946b107b2351eee54f2c641f9b"
    },
    "proofs": [
      {
        "address": "0x7859dcea64a8f60d9ec8f31521574618d8ae8fe1",
        "storageProofs": [
          {
            "key": "0x000000000000000000000000000000000000000000000000000000000000000a",
            "proof": {
              "type": "existing",
              "index": 742,
              "value": "0x0000000000000000000000000000000000000000000000000000000000000064",
              "nextIndex": 903,
              "siblings": ["0xa1b2c3d4...", "0xe5f6a7b8...", "..."]
            }
          }
        ]
      }
    ]
  }
}
```

**Implementation Details:**

* **Data Retrieval**: Debug-traces a `balanceOf(holderAddress)` call, collects touched storage slots, and gathers
  `zks_getProof` for each slot.
* **Authorization**: Permissions API's `checkBalanceDisclosure` verifies that the holder address is in the contract's
  disclosed addresses list.

**Verifying a token balance disclosure using Prividium SDK:**

**disclosure-token-balance.ts**

```typescript
import { selectiveDisclosureActions, verifyEthCallDisclosure } from 'prividium';
import { type Address, createPublicClient, http } from 'viem';

const PRIVIDIUM_RPC_URL = process.env.PRIVIDIUM_RPC_URL || 'http://localhost:8000/rpc';
const L1_RPC_URL = process.env.L1_RPC_URL || 'http://localhost:5010';
const L2_RPC_URL = process.env.L2_RPC_URL || 'http://localhost:5050';
const L1_DIAMOND_PROXY_ADDRESS = (process.env.L1_DIAMOND_PROXY_ADDRESS ||
    '0x7eb50663f054e1c4316f3dc93c4fadb21eb24445') as Address;

export async function verifyTokenBalanceDisclosure(tokenAddress: Address, holderAddress: Address, blockNumber: bigint) {
    const prividium = createPublicClient({ transport: http(PRIVIDIUM_RPC_URL) }).extend(selectiveDisclosureActions);
    const l1Client = createPublicClient({ transport: http(L1_RPC_URL) });
    const l2Client = createPublicClient({ transport: http(L2_RPC_URL) });

    const disclosure = await prividium.tokenBalanceDisclosure(tokenAddress, holderAddress, blockNumber);
    const bytecodes = { [tokenAddress.toLowerCase()]: (await l2Client.getCode({ address: tokenAddress }))! };
    const ok = await verifyEthCallDisclosure({
        disclosure,
        l1Client,
        l2Client,
        diamondAddress: L1_DIAMOND_PROXY_ADDRESS,
        contractBytecodes: bytecodes,
        batchNumber: disclosure.batchNumber
    });
    return ok;
}
```

:::note[NOTE]
This differs from [the permissions system](/configuring/contracts/permissions) which controls **who** can call
functions.
Selective disclosure controls **what** data is publicly visible.
:::
