The three layers
Identity
A human verifies once (Smile ID hosted flow). Contra issues an Albus credential, signed by a BabyJubJub issuer key. PII never leaves Contra.
Compliance Engine
Workflows + sessions orchestrate the verification recipe (KYC, AML, biometric, phone, address). Outcome → a signed ContraToken.
On-chain Credential
The credential becomes a Groth16 proof, verified on-chain by
KycVerifier.sol. The agent is minted on canonical ERC-8004 IdentityRegistry (0x8004A169…). Any contract can read its tier permissionlessly.The data path
What goes on-chain (and what doesn’t)
| On-chain | Off-chain |
|---|---|
| Agent ID + ZK commitment | Raw name / DOB / document number |
| Issuer key (Ax, Ay) — allowlisted | Smile job ID + raw images |
Tier (1 / 2 / 3) + validUntil | The Albus credential (encrypted, KV) |
keccak256(issuer pubkey) | The session’s expected_details |
Composability
Contra reads + writes are intentionally permissionless:- Any smart contract calls
SSIAgentV2.getEffectiveKycTier(agentId)for free. - Off-chain backends call
GET /v1/compliance/:address(free, on-chain read mirror). - Paid endpoints (verification, on-chain mint) are gated by either
x-api-key(developers) orx402(agents — pay-per-call USDC).