# Deposit circuit

> The Deposit circuit proves a deposit is well-formed: the depositor knows a (noteSecret, depositSecret) pair that produces a specific [commitment](/concepts/commitments-and-nullifiers) for a specific value of a specific asset.

The Deposit circuit proves a deposit is well-formed: the depositor knows a (noteSecret, depositSecret) pair that produces a specific [commitment](/concepts/commitments-and-nullifiers) for a specific value of a specific asset.

## Public signals

The Deposit circuit exposes four public signals (one output and three inputs). The contract reads them in this order:

-   `outputCommitment`: the full [note](/concepts/notes) commitment, and the only public output of the circuit.
-   `tokenId`: the asset address (20-byte hex).
-   `value`: the value in the asset's smallest unit.
-   `context`: the deposit context, computed on-chain as `uint256(keccak256(abi.encode(noteData))) % SNARK_SCALAR_FIELD`, which binds the proof to the supplied note data. (The [transact circuit](/protocol/circuits/transact) binds `keccak256(abi.encode(transactParams, noteData))` instead.)

`precommitment` and `label` are **computed in-circuit** from the private inputs and are not public signals.

## Private inputs

The circuit has exactly two private inputs:

-   `depositSecret`: an SDK-generated 32-byte scalar in the BN254 field (produced by `generateSecret`, not raw random bytes), used only by this circuit to compute the label. It is not an input to the ragequit or transact circuits.
-   `noteAddressHash`: `Poseidon(ownerAddress, noteSecret)`, computed outside the circuit and supplied as a private input. The `noteSecret` folded into it never enters the circuit directly, though it is required again to spend the note (transact, withdraw) or to ragequit it.

## Constraints (high level)

1.  `precommitment = Poseidon(noteAddressHash, tokenId, value, 0)` (metadata is hard-coded to 0 in v2.0).
2.  `label = Poseidon(precommitment, depositSecret)`
3.  `outputCommitment = Poseidon(precommitment, label)`
4.  Range checks ensure that tokenId fits in 160 bits and value fits in 128 bits.

## Verifier

Each deployment has its own `DepositGroth16Verifier` contract, and the verification key is locked in at deploy time. If your local zkey comes from a different deployment set, the proof is rejected with `PoolVault_InvalidDepositProof`.

Source: `v2-monorepo/packages/circuits/circuits/main/deposit.circom`
