Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 120 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ To install the latest release version:
forge install succinctlabs/sp1-contracts
```

Add `@sp1-contracts/=lib/sp1-contracts/contracts/src/` in `remappings.txt.`
Add `@sp1-contracts/=lib/sp1-contracts/contracts/src/` in `remappings.txt`.

### Usage
## Usage

Once installed, you can import the `ISP1Verifier` interface and use it in your contract:

Expand All @@ -22,7 +22,8 @@ pragma solidity ^0.8.20;
import {ISP1Verifier} from "@sp1-contracts/ISP1Verifier.sol";

contract MyContract {
address public constant SP1_VERIFIER = 0x3B6041173B80E77f038f3F2C0f9744f04837185e;
/// @dev Use the gateway address for your chain from the deployments/ folder.
address public SP1_VERIFIER;

bytes32 public constant PROGRAM_VKEY = ...;

Expand All @@ -32,72 +33,160 @@ contract MyContract {
}
```

You can obtain the correct `SP1_VERIFIER` address for your chain by looking in the [deployments](./contracts/deployments) directory, it's recommended to use the `SP1_VERIFIER_GATEWAY` address which will automatically route proofs to the correct verifier based on their version.
You can obtain the correct `SP1_VERIFIER` address for your chain by looking in the [deployments](./contracts/deployments) directory. Use the `SP1_VERIFIER_GATEWAY` address which automatically routes proofs to the correct verifier based on their version.

You can obtain the correct `PROGRAM_VKEY` for your program calling the `setup` function for your ELF:
You can obtain the correct `PROGRAM_VKEY` for your program by calling the `setup` function for your ELF:

```rs
let client = ProverClient::new();
let (_, vk) = client.setup(ELF);
println!("PROGRAM_VKEY = {}", vk.bytes32());
let client = ProverClient::new();
let (_, vk) = client.setup(ELF);
println!("PROGRAM_VKEY = {}", vk.bytes32());
```

### Deployments
## Deploy Your Own Verifiers

To deploy the contracts, ensure your [.env](./contracts/.env.example) file is configured with all the chains you want to deploy to.
This section walks through deploying your own SP1 verifier gateway and verifiers. This is useful for testing on testnets or deploying to a chain not yet supported by the canonical deployments.

Then you can use the `forge script` command and specify the specific contract you want to deploy. For example, to deploy the SP1 Verifier Gateway for PLONK you can run:
> For canonical Succinct-managed deployments, see [Deployed Addresses](#deployed-addresses).

### Prerequisites

- [Foundry](https://book.getfoundry.sh/getting-started/installation)
- Node.js 18+
- Git

### Setup

```bash
git clone https://github.com/succinctlabs/sp1-contracts.git
cd sp1-contracts/contracts
forge install
```

Copy and configure the environment file:

```bash
FOUNDRY_PROFILE=deploy forge script ./script/deploy/SP1VerifierGatewayPlonk.s.sol:SP1VerifierGatewayScript --private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
cp .env.example .env
```

or to deploy the SP1 Verifier Gateway for Groth16 you can run:
Fill in the following values in `.env`:

| Variable | Description |
|----------|-------------|
| `PRIVATE_KEY` | Deployer EOA private key |
| `CREATE2_SALT` | Salt for deterministic deployment (e.g. `0x0000000000000000000000000000000000000000000000000000000000000001`) |
| `OWNER` | Address that will own the gateway (your deployer address for testing) |
| `CHAINS` | Target chains, comma-separated (e.g. `SEPOLIA`) |
| `RPC_<CHAIN>` | RPC endpoint for each chain (e.g. `RPC_SEPOLIA=https://...`) |
| `ETHERSCAN_API_KEY_<CHAIN>` | Etherscan API key for contract verification |
| `ETHERSCAN_API_URL_<CHAIN>` | Etherscan API URL for each chain |

Then load the environment:

```bash
source .env
```

> **Note**: The deploy scripts read RPC endpoints from environment variables (`RPC_<CHAIN>`), not from the `--rpc-url` CLI flag.

### Step 1: Deploy Gateways

Deploy the verifier gateways. The `OWNER` address will be the only address able to add and freeze routes.

```bash
FOUNDRY_PROFILE=deploy forge script ./script/deploy/SP1VerifierGatewayGroth16.s.sol:SP1VerifierGatewayScript --private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
# Groth16 gateway
FOUNDRY_PROFILE=deploy forge script \
./script/deploy/SP1VerifierGatewayGroth16.s.sol:SP1VerifierGatewayScript \
--private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast

# Plonk gateway
FOUNDRY_PROFILE=deploy forge script \
./script/deploy/SP1VerifierGatewayPlonk.s.sol:SP1VerifierGatewayScript \
--private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
```

### Adding Verifiers
Gateway addresses are written to `deployments/<chainId>.json`.

You can use the `forge script` command to specify which verifier you want to deploy and add to the gateway. For example to deploy the PLONK verifier and add it to the PLONK gateway you can run:
### Step 2: Deploy Verifiers & Register Routes

Deploy verifiers and register them with the gateway in a single step. Since you own the gateway, set `REGISTER_ROUTE=true`:

```bash
FOUNDRY_PROFILE=deploy forge script ./script/deploy/v3.0.0/SP1VerifierPlonk.s.sol:SP1VerifierScript --private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
# Groth16 verifier
REGISTER_ROUTE=true FOUNDRY_PROFILE=deploy forge script \
./script/deploy/v6.0.0-beta.1/SP1VerifierGroth16.s.sol:SP1VerifierScript \
--private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast

# Plonk verifier
REGISTER_ROUTE=true FOUNDRY_PROFILE=deploy forge script \
./script/deploy/v6.0.0-beta.1/SP1VerifierPlonk.s.sol:SP1VerifierScript \
--private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
```

or to deploy the Groth16 verifier and add it to the Groth16 gateway you can run:
> Change `v6.0.0-beta.1` to the desired SP1 version. Available versions are in `script/deploy/`.

Verify the deployment:

```bash
FOUNDRY_PROFILE=deploy forge script ./script/deploy/v3.0.0/SP1VerifierGroth16.s.sol:SP1VerifierScript --private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast
cat deployments/<chainId>.json | jq .
```

Change `v3.0.0` to the desired version to add.
### Step 3: Verify On-chain

Check that routes are registered on the gateway:

```bash
GATEWAY=$(cat deployments/<chainId>.json | jq -r '.SP1_VERIFIER_GATEWAY_GROTH16')
VERIFIER=$(cat deployments/<chainId>.json | jq -r '.V6_0_0_BETA_1_SP1_VERIFIER_GROTH16')

### Freezing Verifiers
SELECTOR=$(cast call $VERIFIER "VERIFIER_HASH()" --rpc-url $RPC_SEPOLIA | cut -c1-10)
cast call $GATEWAY "routes(bytes4)" $SELECTOR --rpc-url $RPC_SEPOLIA
# Should return the verifier address (non-zero)
```

> [!WARNING]
> **BE CAREFUL** When a freezing a verifier. Once it is frozen, it cannot be unfrozen, and it can no longer be routed to.
### Multi-chain Deployment

To freeze a verifier on the gateway, run:
To deploy across multiple chains, set `CHAINS` to a comma-separated list:

```bash
FOUNDRY_PROFILE=deploy forge script ./script/deploy/v3.0.0/SP1VerifierPlonk.s.sol:SP1VerifierScript --private-key $PRIVATE_KEY --verify --verifier etherscan --multi --broadcast --sig "freeze()"
CHAINS=SEPOLIA,HOLESKY
```

Change `v3.0.0` to the desired version to freeze.
Each chain requires its own `RPC_<CHAIN>`, `ETHERSCAN_API_KEY_<CHAIN>`, and `ETHERSCAN_API_URL_<CHAIN>` entries in `.env`. See [`.env.example`](./contracts/.env.example) for all supported chains.

## Deployed Addresses

Succinct Labs maintains canonical verifier gateways across all major chains. You can find the full list of deployed addresses at:

- **Docs**: https://docs.succinct.xyz/docs/sp1/verification/contract-addresses
- **This repo**: [`contracts/deployments/`](./contracts/deployments/) (JSON files keyed by chain ID)

For production gateway management, see the [production deployment guide](./docs/PRODUCTION_DEPLOYMENT.md).

## Freezing Verifiers

> [!WARNING]
> Once frozen, a verifier cannot be unfrozen and can no longer be routed to.

```bash
FOUNDRY_PROFILE=deploy forge script \
./script/deploy/v6.0.0-beta.1/SP1VerifierPlonk.s.sol:SP1VerifierScript \
--private-key $PRIVATE_KEY --multi --broadcast --sig "freeze()"
```

## For Developers: Integrate SP1 Contracts
## Architecture

This repository contains the EVM contracts for verifying SP1 PLONK EVM proofs.
The SP1 verification system uses a gateway pattern:

You can find more details on the contracts in the [`contracts`](./contracts/README.md) directory.
- **SP1VerifierGateway** routes proof verification calls to the correct versioned verifier. The first 4 bytes of the proof are a selector derived from the verifier's `VERIFIER_HASH`, which the gateway uses to look up the registered route.
- Each SP1 version has both **Groth16** and **Plonk** verifier variants, deployed behind separate gateways.
- The gateway owner can **add routes** (register new verifier versions) and **freeze routes** (permanently disable a verifier version).

Note: you should ensure that all the contracts are on Solidity version `0.8.20`.
See [`contracts/`](./contracts/README.md) for more details on the contract structure.

## For Contributors

To update the SP1 contracts, please refer to the [`update`](./UPDATE_CONTRACTS.md) file.
To update the SP1 contracts with a new version, see the [update guide](./UPDATE_CONTRACTS.md).

## Security

Expand Down
1 change: 1 addition & 0 deletions contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RPC_OPTIMISM=
RPC_OPTIMISM_SEPOLIA=
RPC_SCROLL=
RPC_SCROLL_SEPOLIA=
RPC_HOODI=
RPC_HYPEREVM=

# Etherscan API keys for each chain ID
Expand Down
19 changes: 13 additions & 6 deletions contracts/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# SP1 Contracts

This repository contains the smart contracts for verifying [SP1](https://github.com/succinctlabs/sp1) EVM proofs.
Smart contracts for verifying [SP1](https://github.com/succinctlabs/sp1) EVM proofs.

## Overview
- [`SP1Verifier`](./src/SP1Verifier.sol): The main contract for verifying SP1 EVM proofs.
- [`SP1MockVerifier`](./src/SP1MockVerifier.sol): A mock contract for testing SP1 EVM proofs.
- [`ISP1Verifier`](./src/ISP1Verifier.sol): Interface for SP1Verifier.
- [`PlonkVerifier`](./src/PlonkVerifier.sol): Core logic for verifying Plonk EVM proofs.
## Contracts

- [`SP1VerifierGateway`](./src/SP1VerifierGateway.sol) — Routes proofs to the correct versioned verifier based on a 4-byte selector derived from `VERIFIER_HASH`.
- [`ISP1Verifier`](./src/ISP1Verifier.sol) — Interface for SP1 verifier contracts.
- [`ISP1VerifierGateway`](./src/ISP1VerifierGateway.sol) — Interface for the gateway.
- [`SP1MockVerifier`](./src/SP1MockVerifier.sol) — Mock verifier for testing.

Versioned verifier implementations (Groth16 and Plonk) are in `src/v*/` directories.

## Deployments

Per-chain contract addresses are in [`deployments/`](./deployments/) as JSON files keyed by chain ID (e.g., `1.json` for Ethereum mainnet).
Loading
Loading