Reclaim zkTLS Integration
End-to-end architecture, privacy model, sybil resistance, and CCA behavior for Umia's Reclaim integration
This page is the implementation-level companion to Umia zkTLS Extension. It explains how Umia integrates Reclaim proofs into Tailored Auctions, how the privacy model works in practice, how sybil resistance is enforced, and what this changes for the Continuous Clearing Auction (CCA).
Why We Use Reclaim
Tailored Auctions need a way to make statements like "this round is for GitHub contributors" or "this bucket is for a specific community" without turning the auction into a centralized KYC flow.
Reclaim gives Umia a way to:
- gate early auction steps by offchain credentials;
- bind a proof to the bidder's wallet so it cannot be replayed by someone else;
- preserve public onchain execution of the auction itself;
- add provider-scoped sybil resistance for gated rounds;
- keep the CCA's price discovery and settlement logic unchanged.
What Umia Actually Integrates
At a high level, Umia combines five layers:
| Layer | Role |
|---|---|
| Reclaim provider + witnesses | Produce and attest to a zkTLS proof about some offchain account or activity |
| Umia docs/hub frontend | Requests proofs, stores them locally, and attaches them to bids as hookData |
| Umia API | Creates proof-request configs, verifies proofs off-chain, stores proofs, computes identity hashes, and serves eligibility |
UmiaValidationHook | Verifies wallet binding, provider compatibility, monotonic eligibility, and on-chain identity ownership |
| CCA / Validation Router | Calls the hook on every bid; accepts or rejects the bid based on verification state |
The important design choice is that Reclaim is the proof system, while Umia is the auction-specific policy layer. Reclaim proves something about offchain data. Umia decides which proofs are accepted for which auction step and how that affects bid eligibility.
Architecture Diagram
Sequence Diagram
Current default Hub flow
Today, the main user flow is: verify off-chain, store the proof in the backend, then send that proof inline in hookData when the user bids. The contract also supports permissionless pre-submission via submitProof(), and the keeper has a route for it, but that is not the primary Hub path right now.
How We Integrate Reclaim Into an Auction
1. We deploy and pair the hook
Each gated auction gets a UmiaValidationHook. The hook is paired to a single CCA via setCCA(address).
That pairing matters because the hook caches the CCA's step ranges and resolves the current step from block number during validate().
2. We configure allowed Reclaim providers per step
Auction steps are configured with Reclaim providerHash values, plus human-readable providerId labels for UI/indexing.
In practice, the CLI computes or accepts provider hashes and then calls:
enableStepBatch(stepIndices, providerHashesPerStep, providerIdsPerStep)during deployment;addStepProviders(...)orsetStepProviders(...)for later updates.
This is how a founder says, for example, "step 0 accepts GitHub provider X" while later steps may accept a broader or different set.
3. We expose readable requirements to the Hub
The API/indexer layer stores a human-readable description per provider and per step. That is what powers the lock-requirements UI in the Hub.
4. We mint proof requests server-side
The Hub never gets the Reclaim app secret directly.
Instead, the API creates the proof request using Reclaim credentials and returns a serialized config to the frontend. During that step, Umia binds the bidder wallet into the proof context:
ReclaimProofRequest.init(appId, appSecret, providerId)
proofRequest.setContext(walletAddress, "Auction verification")That wallet binding is critical. It means the proof is not just "someone has this credential". It is "this credential was issued for this wallet context".
5. We verify off-chain before the user bids
When the extension returns a proof, the API validates the proof off-chain and applies Umia-specific policy checks:
- the auction must actually use a zkTLS hook;
- the requested step must be enabled;
- the proof's
providerHashmust match one of the step's accepted providers; - the proof's
contextAddressmust equal the authenticated wallet; - the proof must pass Reclaim verification;
- the proof is normalized to the earliest step that accepts that provider.
That last point is important for monotonic access. If a proof qualifies a user for an earlier locked step, Umia records the earliest valid step so later bids can reuse that stronger eligibility.
6. We store the proof and reuse it at bid time
After off-chain verification, the proof is stored in the API database and cached locally in the browser. On bid submission, the frontend prefers, in order:
- an in-memory freshly verified proof;
- a locally cached stored proof;
- a backend-stored proof fetched for the wallet;
- a server permit, if that step supports permits;
- empty
hookDataif the wallet is already on-chain verified.
What Goes On-Chain
The bid path still ends at the CCA's normal submitBid(...) call, but now hookData may carry verification material.
For Reclaim proofs, Umia encodes:
hookData = abi.encodePacked(uint256 proofStep) ++ abi.encode(Reclaim.Proof)The validation hook then:
- resolves the current auction step;
- checks whether that step is gated;
- checks whether the wallet is already verified from an earlier step;
- if not, decodes
hookDataand verifies the proof forproofStep; - stores
verifiedFromStepfor monotonic access.
This means verification is part of bid admission, not part of price formation.
How This Affects CCA
Reclaim changes who can submit a valid bid in a given step, but it does not change the core economic mechanics of the auction.
| CCA surface | Effect of Reclaim integration |
|---|---|
| Bid entry | A bid may require valid hookData before it is accepted |
| Clearing price | Unchanged |
| Fill logic | Unchanged |
| Settlement and liquidity seeding | Unchanged |
| Auction step timing | Same CCA steps, but some steps are gated |
| User state | Once verified from step N, the user stays eligible for N and later steps |
In other words, Reclaim adds an admission-control layer around the auction. It does not fork or replace the CCA itself.
The Privacy Model in Practice
What is private
Umia does not require public KYC and does not need a real-world legal identity to gate an auction. The bidder proves eligibility through a signed Reclaim proof that is bound to their wallet.
What is intentionally bound
The wallet address is intentionally inserted into the proof context. That is how the system prevents replay across wallets.
What is not guaranteed by Umia alone
Privacy depends on what the Reclaim provider includes in the signed context and extractedParameters fields.
If the provider emits a privacy-preserving pseudonymous identifier, Umia can enforce one-wallet-per-identity without learning a raw username. If the provider emits a raw handle, then that handle may be present in the proof payload and privacy is correspondingly weaker.
Important privacy nuance
Umia's integration is privacy-preserving by architecture, but not magically data-free. The actual privacy level depends on provider design. The safest provider design is to expose only the minimum fields needed for wallet binding, provider selection, and sybil resistance.
The Privacy-Preserving OPRF Piece
The sybil-resistance design is built around a provider-scoped stable identity, represented in Umia as:
identityHash = keccak256(providerHash || extractedParameters_substring)Two details matter here:
providerHashnamespaces the identity by provider/version, so the same source account under two different providers does not collide;extractedParameters_substringis taken verbatim from the signed Reclaim context both off-chain and on-chain, so both layers compute the sameidentityHashbyte-for-byte.
Why this is useful:
- if Reclaim provides an OPRF-derived pseudonymous identifier, the same real-world account maps to the same stable provider-scoped identity without exposing the raw account identifier;
- Umia only needs the stable pseudonym to enforce one-wallet-per-identity;
- the contract and API never need a traditional user database keyed by a Web2 username.
What Umia does not do is run the OPRF ceremony itself. Umia consumes the signed output that comes back inside the Reclaim proof context and then derives identityHash from it.
Sybil Resistance
Umia enforces sybil resistance in two places.
Off-chain gate
When the API stores a proof, it computes identityHash and tries to claim that identity for the current hook.
It uses:
- a transaction-level advisory lock on
(hookId, identityHash); - a unique database index on
(hook_id, identity_hash); - same-wallet re-verification logic that replaces older proof rows.
If a different wallet already claimed that identity, the API rejects the proof with a conflict instead of letting the user proceed to bid.
On-chain gate
The validation hook independently enforces the same identity claim on-chain:
_identityToUser[providerHash][identityHash]stores the wallet that owns that provider-scoped identity;- first claim wins;
- re-verification by the same wallet is idempotent;
- a different wallet reverts with
IdentityAlreadyClaimed(...).
This means the backend improves UX and reduces wasted bid attempts, while the contract remains the final enforcement layer.
Submission Modes
Umia supports three verification modes in the same hook:
| Mode | How it works | Typical use |
|---|---|---|
| Pre-submitted Reclaim proof | Someone calls submitProof(user, stepIndex, proofData) before bidding | Relayed or keeper-driven flow |
| Inline Reclaim proof | Bid carries proofStep + Reclaim.Proof in hookData | Current default Hub UX |
| Server permit | Bid carries an EIP-712 permit or user pre-submits one | Admin-curated or fallback allowlists |
The same auction can mix Reclaim steps and permit-enabled steps.
Why the Monotonic Model Matters
Verification is monotonic: if a wallet verifies for step 0, it is also valid for steps 1, 2, 3, and so on.
That matters because Tailored Auctions often want a funnel like:
- early blocks reserved for a narrow cohort;
- later blocks widened to a broader cohort;
- final blocks fully open.
Without monotonic registration, users would need to re-prove eligibility at every step transition. With monotonic registration, one strong proof unlocks the rest of the auction path that should logically include that user.
Tradeoffs and Design Intent
This integration intentionally chooses:
- on-chain enforcement over trust in the frontend;
- wallet-bound proofs over reusable anonymous bearer credentials;
- provider-scoped sybil resistance over fully open one-wallet-many-wallet behavior;
- optional backend prechecks for UX, while keeping the contract as the source of truth.
The tradeoff is that privacy quality depends on provider design, and the first gated bid carries more verification data than a fully open bid.
Summary
Reclaim gives Umia a way to add offchain audience targeting to an otherwise fully onchain auction.
- Reclaim proves eligibility.
- Umia decides which providers are allowed for which auction steps.
- The API binds proofs to wallets, stores proofs, and blocks obvious sybil reuse early.
- The validation hook enforces the same rules on-chain during
validate(). - The CCA keeps its native auction mechanics; only bid admission changes.
For the user-facing overview, see Umia zkTLS Extension. For the contract-level interface, see Validation Hook.