• 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

active
last call
hasCredential(subject, MERCHANT_VERIFIED) → true
attestation 0x7a4c…6690 · schema closed by RegistryOnlyResolver

How it works

One writer, one schema, any reader.

  • Issue. A wallet holding ISSUER_ROLE calls issue(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.
Issuer walletISSUER_ROLEChainCredID.solissue · revoke · hasCredentialEASattestationsRegistryOnlyResolverattester == registry?Any verifierdApp · backend · agent toolissue / revokeattestonAttesthasCredentialgetAttestation

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.

agent · verify_credential

merchant

0x7099…79C8

not issued

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.

issuedday 0expires day 30

0x7a4c…6690

not issued

 

re-issue
issuer console

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

not issued
attempt 
0limit 1,000 USDC
payments backend

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

0x7099…79C8
Agent registered
AGENT_REGISTERED
not issued

uid 0x7a4c…6690

reader B · cast (Foundry)
waiting for chain events

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