Smart Contract
The VouchHub contract is the on-chain source of truth for identities, delegations, and agent registrations. This page covers deployed addresses, key functions, and fee behavior.
Deployed Addresses
Base Sepolia (testnet — current)
| Contract | Address |
|---|---|
| VouchHub | 0x4483508dE005fCD42B1060dB69556d2b8e2Cd18E |
| TrustedForwarder | 0x98239780251e763F404d9F000A37978B0F029D65 |
Chain ID: 84532 · Deployment version: v5 (USDC fee gate)
Base Mainnet (production)
Mainnet deployment is not yet live. Contract addresses will be published here when available.
Architecture
VouchHub is a single, non-upgradeable contract built on OpenZeppelin’s audited libraries:
- EIP-712 — domain-separated typed data signing (
"Vouch", version"1") - ERC-2771 — meta-transaction support via the TrustedForwarder (gasless relaying)
- Ownable — admin functions restricted to contract owner
- SafeERC20 — safe USDC fee collection for direct callers
Solidity version: ^0.8.24 (checked arithmetic, no overflow/underflow risk).
Key Functions
Identity
| Function | Description |
|---|---|
linkIdentity() | Link an X, GitHub, or DNS identity to your wallet. Requires an oracle attestation signed by the Vouch oracle. |
revokeIdentity() | Revoke an identity link. Always free (no USDC fee). |
updateProviderLabel() | Update the display label for a linked identity (e.g., after a handle change). Requires a fresh oracle attestation. |
Delegation
| Function | Description |
|---|---|
delegateKey() | Delegate a runtime key to sign on behalf of your wallet. Max expiry: 30 days. Rate limited: 5 per 60 seconds per wallet. |
revokeKey() | Revoke a runtime key delegation. Always free (no USDC fee). |
Agent Directory
| Function | Description |
|---|---|
publishAgent() | Register or update an agent endpoint and capabilities in the on-chain directory. |
View Functions (free, no gas)
| Function | Description |
|---|---|
isIdentityActive(wallet, provider) | Check if a wallet has an active identity for a provider |
hasAnyActiveIdentity(wallet) | Check if a wallet has at least one active identity |
getIdentity(wallet, provider) | Get the full identity record for a wallet + provider |
getIdentities(wallet) | Get all active identities for a wallet |
isDelegateActive(wallet, runtimeKey) | Check if a delegation is active |
getAgent(wallet) | Get the agent record for a wallet |
keyToWallet(runtimeKey) | Resolve a runtime key to the delegating wallet |
Identity Providers
| Constant | Value | Provider |
|---|---|---|
PROVIDER_X | 1 | X (Twitter) |
PROVIDER_GITHUB | 2 | GitHub |
PROVIDER_DNS | 3 | DNS domain |
Each wallet can link one identity per provider. The providerId is the keccak256 hash of the raw provider identifier (e.g., X user ID, GitHub user ID, or domain name).
Fee Behavior
VouchHub uses a dual fee model depending on how you interact with it:
| Call Path | Fee | Details |
|---|---|---|
| Via relay (API/CLI) | No on-chain fee | Calls through the TrustedForwarder skip the USDC fee — already billed via Stripe (see Pricing) |
| Direct call | $0.05 USDC | Caller pays the fee + their own gas. Fee token: USDC on Base Sepolia (0x036CbD53842c5426634e7929541eC2318f3dCF7e) |
| Revocations | Always free | revokeKey and revokeIdentity have no USDC fee regardless of call path |
| View functions | Free | Read-only calls cost nothing (standard eth_call) |
The fee amount and treasury address are configurable by the contract owner via setFee() and setTreasury().
Reading from the Contract
All VouchHub state is public and readable via standard RPC calls. The CLI uses direct eth_call invocations — no indexer or subgraph required.
# Check if a wallet has an active identity (via cast)cast call 0x4483508dE005fCD42B1060dB69556d2b8e2Cd18E \"hasAnyActiveIdentity(address)(bool)" 0xYOUR_WALLET \--rpc-url https://sepolia.base.org# Get all identities for a walletcast call 0x4483508dE005fCD42B1060dB69556d2b8e2Cd18E \"getIdentities(address)" 0xYOUR_WALLET \--rpc-url https://sepolia.base.org
Or use the CLI, which wraps these calls with JSON output:
vouch lookup --json --wallet 0xYOUR_WALLET
On-Chain Rate Limits
The contract enforces a delegation rate limit directly in storage:
| Limit | Value |
|---|---|
| Max delegation expiry | 30 days |
| Delegation rate limit | 5 per 60 seconds per wallet |
The rate limit uses a ring buffer of 5 timestamps. When all 5 slots are within the 60-second window, the transaction reverts with DelegateRateLimited().
Source Code
The contract is verified on Basescan. You can view the full source code and interact with it directly: