Overview
JAMID is written in Rust using ink!, and defines a self-contained smart contract for on-chain identity in the Polkadot JAM ecosystem. Its purpose is to provide a trust-minimized, cryptographically verifiable, and DAO-ready registry for JAM Identities (JIDs).
Core Data Model
Each JID is represented by a record stored on-chain. The design keeps the record minimal and efficient, optimized for trustless environments:
pub struct JIDRecord {
pub owner: AccountId,
pub registered_at: Timestamp,
pub updated_at: Timestamp,
pub metadata: Vec<u8>,
pub is_active: bool,
pub expires_at: Timestamp,
}- •Fixed-size hash keys instead of variable strings → better storage performance.
- •Metadata limited to 256 bytes to avoid DoS or bloat (larger data via IPFS pointer).
- •Revocation & expiration natively supported for lifecycle management.
Storage Structure
#[ink(storage)]
pub struct Jamid {
jid_registry: Mapping<Hash, JIDRecord>,
hash_to_jid: Mapping<Hash, String>,
account_to_jid: Mapping<AccountId, Hash>,
nonces: Mapping<(AccountId, u8), u64>,
owner: AccountId,
paused: bool,
blacklist: Mapping<Hash, bool>,
total_jids: u64,
registration_fee: Balance,
total_fees_collected: Balance,
total_fees_withdrawn: Balance,
chain_id: String,
genesis_hash: Hash,
}Why this design:
- •Mapping-based storage ensures O(1) lookup and avoids dynamic iteration.
- •Hash-based privacy hides JIDs in events and logs.
- •Nonce namespacing ensures replay protection per action (Register/Transfer).
- •Genesis hash binding prevents cross-chain replay attacks.
Security Layers
JAMID implements multiple layers of protection:
| layer | description |
|---|---|
| Nonce System | Prevents transaction replay by maintaining per-account nonces. |
| Genesis Hash Binding | Guarantees signatures are valid only on the intended chain. |
| Pause Mechanism | Allows safe contract halting during migration or audits. |
| Blacklist System | Protects against abusive registrations (squatting, offensive names). |
| Length & Character Rules | Prevent malformed JIDs and parsing vulnerabilities. |
Signature Verification
Signatures follow this format:
fn verify_signature(&self, account: &AccountId, jid: &str, nonce: u64, signature: &[u8]) -> Result<()>and include:
- •1 byte → signature type (0x00 = sr25519, 0x01 = ed25519)
- •64 bytes → signature
- •32 bytes → public key
<JAMID>:{genesis_hash}:register:{jid}:{nonce}:{contract_address}This model ensures deterministic verification and compatibility across wallets.
Design Choice: JAMID doesn't trust off-chain verifiers. All proofs are verified directly in the contract through sr25519_verify or future JAM runtime primitives.
Registration Flow
Steps:
#[ink(message, payable)]
pub fn register(&mut self, jid: String, signature: Vec<u8>, nonce: u64, expires_at: Timestamp)Why this order? Cheaper checks first reduce gas cost for failed transactions. Expensive cryptographic checks run only if all early conditions pass.
- •Validate format, blacklist, and uniqueness.
- •Check sufficient payment (registration_fee).
- •Verify nonce and signature.
- •Record identity → emit event.
Events & Transparency
Events are emitted for every change, but only hashed JIDs are exposed publicly — preserving privacy while maintaining transparency.
#[ink(event)]
pub struct JIDRegistered {
#[ink(topic)]
jid_hash: Hash,
owner: AccountId,
registered_at: Timestamp,
}Governance Hooks & Fees
All fees are accounted internally via:
registration_fee: Balance,
total_fees_collected: Balance,
total_fees_withdrawn: Balance,In future versions, withdraw() will be removed and replaced by direct Treasury redirection, so all fees automatically flow to the Polkadot Treasury DAO.
Admin Functions
Temporarily included for testnet and migration control:
These will be burned in v2.0 once governance integration is finalized.
- •set_paused()
- •blacklist_jid() / unblacklist_jid()
- •set_registration_fee()
- •withdraw()
- •transfer_ownership()
Testing & Validation
The contract includes over 35 ink! tests covering:
Each test uses ink! test environment mocks for reproducibility.
- •Registration, revocation, and resolution
- •Fee accounting
- •Blacklist and metadata validation
- •Nonce overflow and replay edge cases
- •Case normalization
- •Paused state enforcement
Future Changes
| version | feature |
|---|---|
| v1.1 | Treasury fee redirection |
| v1.2 | DAO integration via OpenGov |
| v2.0 | Burned admin, full autonomy |
| v2.1 | Multi-chain JID resolution via JAM messaging |
Conclusion
JAMID is designed for security, transparency, and neutrality. It minimizes trust assumptions, enforces chain integrity, and paves the way for a community-owned identity standard within JAM and Polkadot.