- Credential registry on EAS
- Base Sepolia
- Testnet
Know who you are paying before the money moves.
ChainCredID is an issuer-signed credential registry on the Ethereum Attestation Service. A human, a payments backend, or an AI agent asks one question about a wallet and gets an answer computed from EAS state: not from this app, not from a database.
hasCredential(subject, type) → true | false
Won a top prize at ETH Latam 2024 as a citizen-rights demo. Rebuilt in 2026 around agent and operator credentials: Foundry, 23 tests against real EAS bytecode, Next.js 16, wagmi 3. Not audited, not on mainnet.
subject
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
credential
MERCHANT_VERIFIED
status
How it works
One writer, one schema, any reader.
- Issue. A wallet holding
ISSUER_ROLEcallsissue(subject, credentialType, expirationTime, metadataURI). - Attest. The registry writes a typed, revocable EAS attestation. The schema's resolver rejects any attester that is not the registry, so the schema is closed.
- Verify. Anyone calls
hasCredential. The answer is derived from the attestation's revocation and expiration times on EAS. - Re-issue. A new attestation links to the old one through
refUID, so a credential's history is a chain.
Four credentials, four situations
The contract is type-agnostic. These are the credentials the demo issues, each shown doing its job.
MERCHANT_VERIFIED
An agent pays a merchant only while the merchant's credential is active.
Before an x402 payment, the agent's tool asks the registry one question. The first time the merchant is verified and the payment settles. Then the issuer revokes. Same wallet, same question, different answer, and the payment stops.
The registry answers yes or no. Your payments code decides what to do with it.
merchant
0x7099…79C8
OPERATOR_KYC
Credentials expire on their own, and a re-issue keeps the history.
An issuer grants operator KYC for 30 days. Nothing needs to revoke it: on day 31 the same read returns false because the attestation's expiration time has passed. A fresh issue writes a new attestation that points at the old one through refUID.
Expired attestations stay on EAS. Verifiers see the whole chain, not just the current state.
0x7a4c…6690
not issuedre-issue
SPEND_LIMIT_USDC_1000
A credential can carry a policy the payments backend enforces.
The issuer vouches that this agent may settle up to 1,000 USDC per period and points the attestation's metadata at the policy. The backend reads the credential, then applies its own rule: 900 goes through, 1,200 is held.
The registry stores the claim and who signed it. Amount checks live where the money moves.
agent wallet
0x3C44…93BC
AGENT_REGISTERED
Two readers, one source. Neither of them is this app.
The web page and a plain cast call read the same attestation through the registry. When the issuer revokes, both flip on the next read, because the truth lives on EAS and the registry only stores a pointer to it.
Anything that can read a chain can verify: an indexer, another contract, an MCP tool in an agent's toolbox.
reader A · /verify
uid 0x7a4c…6690
Why this exists in 2026
The new identity problem is agents, not citizens.
Agents now hold wallets and pay. ERC-8004 gives an agent an onchain identity and reputation. x402 lets it pay over HTTP with stablecoins. What neither answers is who vouches for the agent, or for the merchant it is about to pay.
EAS is the substrate that won. It is a predeploy on Base and the OP Stack and already carries Coinbase Verifications and most onchain reputation. A credential written here is readable by every tool that already reads EAS.
Know Your Agent needs a claims layer. Identity says who. Reputation says how they behaved. ChainCredID is the third piece: an issuer-signed, revocable claim that a wallet passed a check, with the evidence linked and the history kept.
Run it
Deploy to anvil in one command, then verify a wallet.
Foundry deploys a local EAS, registers the closed schema, and binds the registry. The web app reads it on chain 31337. Roadmap: an MCP server so agents call verify_credential directly, and a Base Sepolia deployment.
forge test # 23 tests, real EAS bytecode
anvil
forge script script/Deploy.s.sol \
--rpc-url anvil --broadcast \
--unlocked --sender 0xf39F…2266
cd ../web && npm run dev # /verify on chain 31337