CTZN Token¶
CTZN is a soulbound (non-transferable) identity token module built on the Citizen WASM execution engine. Once minted to a recipient, a CTZN token is permanently bound to that identity - the transfer operation is always rejected.
Location: citizen-protocol/modules/ctzn-token/
Features¶
| Feature | Description |
|---|---|
| Multi-issuer authority | Configure authorized issuer DIDs with N-of-M signature thresholds. Initial configuration requires governance approval - no one can self-appoint as admin. |
| Custom metadata schemas | Each token has a schema_type (e.g., degree, reputation, identity) and free-form JSON metadata. |
| Hierarchical tiers | Tokens are assigned bronze (0), silver (1), or gold (2). Per-tier supply is tracked independently. |
| Time-locked / revocable | Optional expiry_block makes tokens expire at a future block height. Issuers can revoke tokens at any time. |
| Attribute-based access control | check_access verifies token ownership with tier/schema requirements. Supports direct token lookup or enumeration of a DID's holdings. |
Governance Gate¶
The initial configure call requires a proposal_id that passes host_check_governance_approval. This means:
- No one can self-appoint as admin by simply calling
configurefirst - The admin keypair must be established through a governance-approved proposal
- Subsequent reconfiguration calls require the admin's signature
This prevents unauthorized privilege escalation at the protocol level.
Operations¶
| Operation | Parameters | Purpose |
|---|---|---|
configure |
admin_did, admin_sig, proposal_id, issuers, threshold |
Set authorized issuers and minimum signature count. Initial call requires governance-approved proposal_id; subsequent calls require admin signature. |
mint |
issuer_dids, signatures, token_id, recipient_did, tier?, schema_type?, metadata?, expiry_block? |
Mint a new CTZN token (backward-compatible with singular issuer_did/signature_hex) |
owner_of |
token_id |
Get owner and full token status (burned, revoked, expired) |
total_supply |
- | Get global and per-tier supply counts |
get_metadata |
token_id |
Get token metadata, tier, schema, and revocation/expiry status |
burn |
issuer_did, signature_hex, token_id |
Permanently destroy a token |
revoke |
issuer_did, signature_hex, token_id |
Issuer-revoke a token (keeps record, marks invalid) |
transfer |
(any) | Always rejected - CTZN tokens are non-transferable |
check_access |
did, token_id?, required_tier?, required_schema? |
Verify a DID holds a qualifying token |
Minting Flow¶
Minting requires signatures from authorized issuers meeting the configured threshold:
{
"operation": "mint",
"issuer_dids": ["did:key:ed25519:issuer-a", "did:key:ed25519:issuer-b"],
"signatures": ["sig_a_hex", "sig_b_hex"],
"token_id": "degree-2026-001",
"recipient_did": "did:key:ed25519:student",
"tier": "gold",
"schema_type": "degree",
"metadata": {"university": "Example U", "degree": "BSc Computer Science"},
"expiry_block": 500000
}
The module supports both multi-issuer (issuer_dids / signatures array) and singular (issuer_did / signature_hex) formats for backward compatibility.
Access Control¶
The check_access operation supports two modes:
Direct token lookup¶
{
"operation": "check_access",
"did": "did:key:ed25519:user",
"token_id": "degree-2026-001",
"required_tier": "silver",
"required_schema": "degree"
}
Enumeration (find any qualifying token)¶
{
"operation": "check_access",
"did": "did:key:ed25519:user",
"required_tier": "gold",
"required_schema": "reputation"
}
When token_id is omitted, the module scans all tokens held by the DID and returns the first match that satisfies the tier and schema requirements.
State Keys¶
| Key Pattern | Content |
|---|---|
config:admin |
Admin DID |
config:issuers |
Authorized issuer DID list |
config:threshold |
Minimum signature count |
owner:{token_id} |
Recipient DID |
meta:{token_id} |
JSON metadata blob |
tier:{token_id} |
Numeric tier (0/1/2) |
schema:{token_id} |
Schema type string |
expiry:{token_id} |
Expiry block height |
burned:{token_id} |
Burn marker |
revoked:{token_id} |
Revocation marker |
supply:{tier} |
Per-tier minted count |
total_supply |
Global minted count |
held:{did} |
Comma-separated token IDs |
Building¶
cd citizen-protocol/modules/ctzn-token
RUSTFLAGS="-C link-arg=--allow-undefined" cargo build --release --target wasm32-unknown-unknown
Testing¶
The integration test suite includes 22 CTZN-specific tests covering minting, multi-issuer threshold verification, governance gating, tiers, schemas, expiry, revocation, and access control.