---
sidebar_position: 3
title: Proofs
---

import Tabs from "@theme/Tabs"
import TabItem from "@theme/TabItem"

# Semaphore proofs

Once a user joins their [Semaphore identity](/V3/glossary#semaphore-identity) to a [Semaphore group](/V3/glossary#semaphore-group), the user can signal anonymously with a zero-knowledge proof that proves the following:

- the user is a member of the group,
- the same user created the signal and the proof.

Developers can use Semaphore for the following:

- [**Generate a proof off-chain**](#generate-a-proof-off-chain)
- [**Verify a proof off-chain**](#verify-a-proof-off-chain)
- [**Verify a proof on-chain**](#verify-a-proof-on-chain)

## Generate a proof off-chain

Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/proof) library to generate an off-chain proof.
To generate a proof, pass the following parameters to the `generateProof` function:

- `identity`: the Semaphore identity of the user broadcasting the signal and generating the proof;
- `group`: the group to which the user belongs;
- `externalNullifier`: the value that prevents double-signaling;
- `signal`: the signal the user wants to send anonymously;
- `snarkArtifacts`: the `zkey` and `wasm` [trusted setup files](/V3/glossary/#trusted-setup-files).

#### Install library:

<Tabs
  defaultValue="npm"
  groupId="package-managers"
  values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}
>
  <TabItem value="npm">
    ```bash
    npm install @semaphore-protocol/proof@^3
    ```
  </TabItem>

  <TabItem value="yarn">
    ```bash
    yarn add @semaphore-protocol/proof@^3
    ```
  </TabItem>

  <TabItem value="pnpm">
    ```bash
    pnpm add @semaphore-protocol/proof@^3
    ```
  </TabItem>
</Tabs>

In the voting system use case, once all the voters have joined their [identities](/V3/guides/identities#create-identities) to the ballot [group](/V3/guides/groups),
a voter can generate a proof to vote for a proposal.
In the call to `generateProof`, the voting system passes the unique ballot ID (the [Merkle tree](/V3/glossary#merkle-tree) root of the group) as the
`externalNullifier` to prevent the voter signaling more than once for the ballot.
The following code sample shows how to use `generateProof` to generate the voting proof:

```ts
import { generateProof } from "@semaphore-protocol/proof"

const externalNullifier = group.root
const signal = 1

const fullProof = await generateProof(identity, group, externalNullifier, signal, {
    zkeyFilePath: "./semaphore.zkey",
    wasmFilePath: "./semaphore.wasm"
})
```

:::info
If you are generating the proof on the client side, you can avoid adding the snark artifacts because they are fetched automatically:

```ts
const fullProof = await generateProof(identity, group, externalNullifier, signal)
```

:::

## Verify a proof off-chain

Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/proof) library to verify a Semaphore proof off-chain.
To verify a proof, pass the following to the `verifyProof` function:

- `fullProof`: the Semaphore proof;
- `treeDepth`: the Merkle tree depth.

The following code sample shows how to verify the previously generated proof:

```ts
import { verifyProof } from "@semaphore-protocol/proof"

await verifyProof(fullProof, 20) // true or false.
```

`verifyProof` returns a Promise that resolves to `true` or `false`.

## Verify a proof on-chain

Use the [`Semaphore.sol`](/V3/technical-reference/contracts#semaphoresol) contract to verify proofs on-chain.

:::info
See our [deployed contracts](/V3/deployed-contracts) to find the addresses for your network.
::::

To verify Semaphore proofs in your contract, import `ISemaphore.sol`, pass it the `Semaphore.sol` address and call the `verifyProof` method with following parameters:

- `groupId`: the identifier of the group;
- `merkleTreeRoot`: the root of the Merkle tree;
- `signal`: the signal the user wants to send anonymously;
- `nullifierHash`: a nullifier hash;
- `externalNullifier`: the value that prevents double-signaling;
- `proof`: a Solidity-compatible Semaphore proof.

:::info
You can import `ISemaphore.sol` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/contracts) NPM module.
:::
