Skip to content

BringID/credential-registry

Repository files navigation

BringID Credential Registry

Privacy-preserving credential system built with Semaphore zero-knowledge proofs. Users register credentials via verifier-signed attestations, then prove membership without revealing their identity.

Deployed Contracts

Contract addresses are identical on both chains (same deployer, same nonce).

Base Mainnet (chain ID 8453)

Contract Address
Semaphore 0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D
CredentialRegistry 0x17a22f130d4e1c4ba5C20a679a5a29F227083A62
DefaultScorer 0x6791B588dAdeb4323bc1C3d987130bC13cBe3625
ScorerFactory 0x016bC46169533a8d3284c5D8DD590C91783C8C06

Base Sepolia (chain ID 84532)

Contract Address
Semaphore 0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D
CredentialRegistry 0x17a22f130d4e1c4ba5C20a679a5a29F227083A62
DefaultScorer 0x6791B588dAdeb4323bc1C3d987130bC13cBe3625
ScorerFactory 0x016bC46169533a8d3284c5D8DD590C91783C8C06

Credential Groups

ID Credential Group Family Default Score Validity Duration
1 Farcaster Low 1 2 30 days
2 Farcaster Medium 1 5 60 days
3 Farcaster High 1 10 90 days
4 GitHub Low 2 2 30 days
5 GitHub Medium 2 5 60 days
6 GitHub High 2 10 90 days
7 X (Twitter) Low 3 2 30 days
8 X (Twitter) Medium 3 5 60 days
9 X (Twitter) High 3 10 90 days
10 zkPassport 20 180 days
11 Self 20 180 days
12 Uber Rides 10 180 days
13 Apple Subs 10 180 days
14 Binance KYC 20 180 days
15 OKX KYC 20 180 days

Integrating Proof Consumption (Front-Running Protection)

When a smart contract consumes BringID proofs on-chain (e.g. an airdrop or gating contract), the Semaphore scope is bound to msg.sender + context. This means any transaction routed through the same contract shares the same scope — an attacker can copy proofs from the mempool and front-run the original caller.

Solution: Bind the Semaphore message field to the intended recipient. The @bringid/contracts package provides BringIDGated — an abstract base that handles app ID validation, message binding, and proof submission. Your contract only needs to check the returned score.

Quick start — BringIDGated

import {BringIDGated} from "@bringid/contracts/BringIDGated.sol";
import {CredentialProof} from "@bringid/contracts/interfaces/Types.sol";

contract MyAirdrop is BringIDGated {
    uint256 constant MIN_SCORE = 100; // required reputation threshold

    constructor(address registry_, uint256 appId_)
        BringIDGated(registry_, appId_)
    {}

    // proofs_ are generated off-chain via BringID SDK.
    // Each proof is a zero-knowledge attestation of a verified credential
    // (e.g. GitHub account, Farcaster profile, KYC) — proving ownership
    // without revealing the underlying identity.
    function claim(
        address recipient_,
        CredentialProof[] calldata proofs_
    ) external {
        // Validates proofs, prevents reuse, aggregates score from registry
        uint256 bringIDScore = _submitProofsForRecipient(recipient_, proofs_);

        // Enforce a minimum score
        if (bringIDScore < MIN_SCORE) revert InsufficientScore();

        // Transfer tokens
        ...
    }
}

Off-chain proof generation

When generating proofs for a message-binding-aware contract, set the message to keccak256(abi.encodePacked(recipientAddress)):

import { generateProof } from "@semaphore-protocol/core";
import { ethers } from "ethers";

const recipient = "0x1234...";
const message = ethers.solidityPackedKeccak256(["address"], [recipient]);

const proof = await generateProof(identity, group, message, scope);

See docs/proof-message-binding.md for a full explanation of scope vs. message, why putting the recipient in context breaks sybil resistance, and patterns for custom message semantics. See contracts/examples/SimpleAirdrop.sol for a complete example. For custom message semantics beyond simple recipient binding, compute your own expected message and validate manually.

Usage

Install dependencies

This project uses yarn to install dependencies since soldeer doesn't resolve them correctly.

yarn

Build

$ forge build

Test

$ forge test

Gas Snapshots

$ forge snapshot

Help

$ forge --help
$ anvil --help
$ cast --help

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors