From b8e2d801f3575f9d7a91d63839ffe1d136cf0c71 Mon Sep 17 00:00:00 2001 From: patnir Date: Wed, 19 Aug 2026 12:00:15 -0700 Subject: [PATCH] docs: clarify what Base Verify Onchain writes onchain - Add a "What goes onchain" section covering the exact fields a claim publishes, what never touches the chain, and what an observer can infer from a public policy plus a public claim - Note that verify.base.dev shows offchain credentials only, and that onchain claim history lives in the partner app's contract - Mark Base Verify Onchain as Base Sepolia only, not on mainnet --- docs/apps/guides/verify-onchain.mdx | 57 +++++++++++++++++-- .../guides/verify-social-accounts.mdx | 4 ++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/docs/apps/guides/verify-onchain.mdx b/docs/apps/guides/verify-onchain.mdx index 431220e5d..4ed88e0d9 100644 --- a/docs/apps/guides/verify-onchain.mdx +++ b/docs/apps/guides/verify-onchain.mdx @@ -7,10 +7,11 @@ description: "Enforce Sybil resistance and policy gating inside any Base contrac **Base Verify Onchain lets your smart contract enforce "one real person, once" and gate on real-world traits, like an active Coinbase One membership. The check runs in your contract, so you don't run a verification backend.** Base Verify signs a short-lived verification your contract checks in the same transaction as a claim, deposit, or vote. - - Live on Base Sepolia! Try the [demo](https://verify.base.dev/onchain-demo), or [reach + + Base Verify Onchain runs on Base Sepolia only. It is not deployed on Base mainnet, so build and test against it, but + do not put production value behind it. Try the [demo](https://verify.base.dev/onchain-demo), or [reach out](https://forms.gle/WTcuWyKkvUV6gGik6) if you have use cases in mind. - + Integration is three steps: @@ -22,7 +23,7 @@ Integration is three steps: | :--------------- | :------------------------------------------------------------------------------------------------------------------------------ | | `SignerRegistry` | [`0x4f15593fbF7e3491d15080e1610E7AF8deBA1a02`](https://sepolia.basescan.org/address/0x4f15593fbF7e3491d15080e1610E7AF8deBA1a02) | | API base URL | `https://verify.base.dev/v1` | -| Chain | Base Sepolia (`84532`) | +| Chain | Base Sepolia (`84532`), testnet only | | Consumer base | `BaseVerifyConsumer.sol` | Two example consumers to copy from: @@ -41,6 +42,8 @@ Two example consumers to copy from: A single check can do both at once: gate on your policy _and_ dedupe on identity in the same transaction. If your app already enforces this offchain (your own backend and database), start with [Verify Social Accounts](/base-account/guides/verify-social-accounts) instead. This guide is for enforcing it in a contract. +Neither the API response nor your contract carries the user's identity, but a claim is still a public transaction. See [What goes onchain](#what-goes-onchain) for exactly what it publishes. + ## Core concepts ### Verification @@ -79,6 +82,49 @@ A claim moves through your app, the Base Verify API, and your contract: 6. Your app submits the verification to your contract's `enroll` function (or your deposit, borrow, or claim path). 7. Your contract calls `registry.verifyVerification(...)`, which checks the signature and expiry and recomputes `policyHash` from your live policy. Your contract then dedupes on `identityHash` and lets the user participate. +## What goes onchain + +A claim is an ordinary public transaction. Once it is mined, everything below is permanent, world-readable, and outside Base Verify's control. Weigh that when you design your policy and your contract. + +### Written onchain + +| Data | Where it appears | Notes | +| :------------------------------------------ | :---------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------- | +| `identityHash` | Transaction calldata, your contract's storage, and any event you emit with it | Permanently ties the claiming wallet to this identity inside your contract | +| Claiming wallet address | The transaction sender, and any event you emit with it | The wallet that signed the SIWE message and submitted the claim | +| `expiration` and the Base Verify `signature` | Transaction calldata | Public, but bound to your contract and that wallet, and it expires within minutes | +| Your `provider` and `conditions` | Public view functions on your deployed contract | Anyone can read your policy without sending a transaction | + +Whatever your own contract stores or emits alongside a claim is public too. The two example consumers linked above keep a `mapping(bytes32 identityHash => bool)` and emit `Claimed(address indexed user, bytes32 indexed identityHash)`, which makes the wallet-to-hash pairing directly queryable from logs. + +### Never onchain + +- The provider account: no username, handle, account ID, or profile link. +- Trait values: no follower count, subscription state, or other credential data. +- OAuth tokens, or anything else Base Verify holds for the user. +- `policyHash`: the registry recomputes it in memory during verification and never stores or emits it. +- The user's real-world identity: `identityHash` is one-way and cannot be reversed. + +### What an observer can infer + +Your policy is public and your claims are public, so anyone can pair the two. The Coinbase One example consumer declares `provider = "coinbase"` and the condition `coinbase_one_active eq true`, so every wallet in its `Claimed` log is publicly known to have held an active Coinbase One membership at claim time. An observer cannot tell which Coinbase account, but does learn that the wallet had one. + +A narrower policy leaks more. Gating on `followers gte 10000` marks each claiming wallet as a large X account, while gating on `verified eq true` says much less. Your contract name and any action naming leak the same way. + +Because `identityHash` is scoped per contract, the same person claiming in two different contracts produces two unrelated hashes that observers cannot link. Within a single contract, every claim from that person shares one hash, which is exactly what makes the dedupe work. + +### Where claim history lives + +`verify.base.dev` surfaces a user's offchain credentials only: which providers they have verified, and the traits Base Verify stores for them. It has no view of onchain claims and cannot display, edit, or undo them. + +Onchain claim history lives in your contract: your storage, your events, your chain. Users and observers read it through a block explorer or your contract's public getters. If you want your users to see their own claim history, you build that view. + + + Deleting a verification at `verify.base.dev` removes the user's offchain credential and stops Base Verify from + signing new verifications for them. It does not reach anything already written onchain. Claims your contract has + already recorded stay recorded, and the transactions stay in the chain's history. + + ## Implementation @@ -238,7 +284,7 @@ Exchanges a SIWE signature for a signed, short-lived onchain verification. No AP ``` - The SIWE message. Its `statement` must be exactly `Claim eligibility for a Base Verify onchain benefit.`, its `chainId` must be the chain you are claiming on (Base Sepolia `84532` during the test phase), and its `Resources` must include `eip155::`. + The SIWE message. Its `statement` must be exactly `Claim eligibility for a Base Verify onchain benefit.`, its `chainId` must be the chain you are claiming on (Base Sepolia `84532`, the only supported chain), and its `Resources` must include `eip155::`. @@ -370,6 +416,7 @@ When you declare multiple conditions for a provider, **all** must be satisfied ( - Keep your policy (`provider` and `conditions`) immutable. - Dedupe on `identityHash` in your claim path. - Treat a successful check as proof of a unique verified identity, not of any specific account or personal data. +- Tell your users what a claim publishes, and remember that you own any user-facing view of it. See [What goes onchain](#what-goes-onchain). ## Support diff --git a/docs/base-account/guides/verify-social-accounts.mdx b/docs/base-account/guides/verify-social-accounts.mdx index 3c6f9cced..bb44cfb81 100644 --- a/docs/base-account/guides/verify-social-accounts.mdx +++ b/docs/base-account/guides/verify-social-accounts.mdx @@ -873,6 +873,10 @@ Users can delete their verifications at any time: - Invalidates future token generation - Your app's stored tokens become meaningless (user can't re-verify with the same account) + +Deletion covers the offchain credential that Base Verify holds. It cannot reach data an app has already written elsewhere, including anything a contract recorded through [Base Verify Onchain](/apps/guides/verify-onchain). `verify.base.dev` shows offchain credentials only, so onchain claim history is not visible or reversible there. + + ### Caching Cache verification results to reduce API calls: