Verified cross-chain events become a Creditcoin passport, then a credit line.
A Sepolia transaction is proved with Attestcoin (Merkle inclusion + continuity). Creditcoin’s native verifier at 0x0000000000000000000000000000000000000FD2 must return true or CreditPassport.stamp reverts. Verified repayments open PassportLine. Anything else is refused, with a sentence.
Track: AI (an attestor that processes cryptographically verified cross-chain data). DeFi is the consumption surface, not the product.
Live: https://agent3-passport-production.up.railway.app
Repo: https://github.com/agent3-666/agent3-passport
- Wait for attestors —
ProofBuilder.waitUntilHeightAttested(or skip when on-chain latest height already covers the tx). - Build the proof —
ProofBuilder.getProofathttps://prover.cc3-testnet.creditcoin.network(/api/v1/proof-by-tx/{chainKey}/{tx}). - Verify — SDK
PrecompileBlockProver.verifySingle→ precompileverify/verifyAndEmitat0x0FD2. - Stamp —
CreditPassport.stampcallsverifier.verifyAndEmit(...)andrequire(verified, "Attestcoin: inclusion proof rejected"). - Line —
PassportLine.quote/borrowread only those stamps.
Source chain: Ethereum Sepolia. chainKey is Creditcoin’s internal id, not the EVM chainId. Confirmed via PrecompileChainInfoProvider.getSupportedChains(): Sepolia is chainKey 1 (chainId 11155111). Ethereum mainnet is chainKey 3 on this testnet.
npm installat repo root and inapps/passport.npm run attestor(port 4201).npm run dev(Next.js on 4200).- Open
http://localhost:4200. The booklet is the product. - Prove → use the filled public Sepolia tx (already attested) → inspector explains Merkle vs continuity.
- Hire the attestor with the same hash. It runs the same rail and stamps on Creditcoin when the proof verifies.
- Line page quotes from verified repayments and can borrow. Anything else is refused, with a sentence.
# Proof rail (no funds). Calls 0x0FD2 via eth_call.
npx tsx scripts/prove-tx.ts
npx tsx scripts/prove-tx.ts 0x<sepolia_tx>
# Contracts
forge test -vv
# App
npm run attestor
npm run dev --prefix apps/passport| Piece | Chain | Role |
|---|---|---|
RepaymentLedger |
Ethereum Sepolia | recordRepayment(bytes32,uint256) emits RepaymentRecorded |
CreditPassport |
Creditcoin CC3 testnet | stamp only if 0x0FD2 returns true |
PassportLine |
Creditcoin CC3 testnet | credit = sum of verified repay amounts; explicit refuse otherwise |
| Native verifier | Creditcoin | 0x0000000000000000000000000000000000000FD2 |
Addresses: contracts/ADDRESSES.md. Deploy (needs faucet keys, never committed):
forge script script/Deploy.s.sol:DeploySepolia --rpc-url sepolia --broadcast
forge script script/Deploy.s.sol:DeployCreditcoin --rpc-url creditcoin --broadcastPublic Sepolia tx 0x975051aef8615c48573c5b6cd270c3aad3101325511da54943e85ea15d74b7e4 (height 11442024). The public Sepolia node prunes receipts this old, so the UI says so rather than asserting a status it cannot read.
- chainKey 1 (confirmed)
- Merkle siblings: 7
- Continuity roots: 77
verifySingle→ true against0x0FD2(eth_call)
Run it yourself against the live deployment:
curl -s -X POST https://agent3-passport-production.up.railway.app/api/prove \
-H 'Content-Type: application/json' \
-d '{"txHash":"0x975051aef8615c48573c5b6cd270c3aad3101325511da54943e85ea15d74b7e4"}'
# → "attested": true, "verified": trueA verification that always passes proves nothing, so the same proof is resubmitted with one byte of txBytes flipped:
npm run negative-control
# 1. Genuine proof -> accepted
# 2. Tampered proof -> rejected (execution reverted: "Merkle proof validation failed")The precompile refuses the forged proof. Script: scripts/negative-control.ts.
| Step | Chain | Transaction |
|---|---|---|
| Repayment recorded | Sepolia | 0x8234a9e3331ab9ce8407e9922afc4ef44b1e01938f388aeb379db254ba589465 |
| Passport stamped | Creditcoin | 0x01f1efc1c4bf8beb7d47c8be1f576ce4260def7f5c815105a45d060dad8b1d8b |
| Line drawn | Creditcoin | 0x65a19ca2abc996cf83364324e4e61e31f2bfdf2b31bf4b84776cec623d2447a4 |
Deployed: CreditPassport 0x88FEB78da56beB5Fd3af6655160907de0fAF09Fd and
PassportLine 0x11C9c3d5f400735387ACBA51aeeC03566eaE77FC on Creditcoin CC3,
RepaymentLedger 0x88FEB78da56beB5Fd3af6655160907de0fAF09Fd on Sepolia.
Read the resulting credit line without a wallet:
curl "https://agent3-passport-production.up.railway.app/api/credit?address=0x8e5830D9Cc2c88A330698A6B334ACF9c07c2acD4"- Creditcoin CC3 testnet RPC:
https://rpc.cc3-testnet.creditcoin.network(chainId 102031) - Explorer: https://creditcoin-testnet.blockscout.com/
- Proof API: https://prover.cc3-testnet.creditcoin.network/
- Sepolia RPC:
https://ethereum-sepolia-rpc.publicnode.com - Official decoder (tutorial env; passport does not require it):
0x731c345d79Fb8BbDC541f9DF3b6317585F849F9f
Copy .env.example to .env for optional keys. Do not commit keys.