ERC-8277: Persistent Identity Token (PIP)

Summary

This ERC proposes a standard interface for Persistent Identity Tokens — ERC-721 tokens that represent human-readable, on-chain identities bound to EVM addresses. The standard defines three interface layers: Identity (registration and binding), Resolution (name-to-address lookup), and Policy (namespace governance).

The core mechanism is a bind-to-lock model: tokens are freely tradable when unbound, but become soulbound when a user binds the identity to their address. This protects active identities from transfer while allowing a secondary market for unclaimed names.

PR: ethereum/ERCs#1776
Protocol Repository (CC0): persistent-identity-protocol
Reference Implementation: PEG ID on Pentagon Chain at 0xf97EB9f8293D1FD5587a809Eb74518c300738d07 (2,200+ identities minted)

Problem

Web3 has wallet ownership but no standardized identity layer. Existing approaches each solve part of the problem:

  • ENS resolves names to addresses but wasn’t designed as a login system, doesn’t define lifecycle governance, and doesn’t serve autonomous agents alongside humans
  • ERC-5192 (SBTs) makes tokens permanently non-transferable, which prevents any secondary market for names
  • Web2 usernames are human-readable but platform-controlled, non-portable, and non-ownable

Applications that need persistent identity — games with characters, social platforms with reputation, AI agents that need to be addressable — currently build bespoke systems. There’s no composable standard.

Three Interface Layers

The standard deliberately separates identity from policy:

1. Identity Layer (IPersistentIdentity)

  • Name registration: one name per token, unique within namespace
  • Address binding: bind(tokenId) locks the token to msg.sender, making it soulbound
  • URL records: on-chain forwarding
  • Tier classification: Reserved / Standard / Basic with different tradability rules
function nameRegistered(string calldata name) external view returns (bool);
function tokenOfName(string calldata name) external view returns (uint256);
function nameOf(uint256 tokenId) external view returns (string memory);
function boundAddress(uint256 tokenId) external view returns (address);
function bind(uint256 tokenId) external;
function setUrlRecord(uint256 tokenId, string calldata url) external;

2. Resolution Layer (IPersistentIdentityResolver)

function resolveAddress(string calldata name) external view returns (address);
function resolveUrl(string calldata name) external view returns (string memory);
function resolveIdentity(string calldata name) external view returns (
    uint256 tokenId, address owner, address boundAddr, bool bound, string memory url, uint8 tier
);

3. Policy Layer (IPersistentIdentityPolicy)

Governance: pricing, renaming, unbinding, reserved name lists. Separated from identity so different namespaces can apply different rules while sharing the same core standard.

Key Design Decisions

Bind-to-lock vs permanent SBT: Unlike ERC-5192, tokens start transferable. They become soulbound only when actively bound. This lets names trade on secondary markets while protecting active identities.

Separation of identity and policy: The identity layer is fixed. The policy layer is namespace-specific. Different communities can deploy their own policy without modifying the core.

Agent-compatible: Human users and AI agents use the same namespace and resolution primitives. Designed to work alongside ERC-8170 (AI-Native NFT) and ERC-8171 (Token Bound Account Agent Registry).

No expiry: Unlike ENS’s rental model, persistent identities don’t expire. Spam resistance comes from economic pricing in the policy layer, not time-based reclaim.

Compatibility

  • ERC-721: PIP tokens are valid ERC-721
  • ERC-165: Implementations register IPersistentIdentity support
  • ERC-5192: Related but distinct (conditional vs permanent non-transferability)
  • ERC-6551: Complementary — identities can have Token Bound Accounts
  • ENS: Can coexist; PIP operates at identity/username layer, not DNS layer

Open Questions

  1. Should the standard define a canonical name normalization rule (e.g., lowercase-only), or leave that to the policy layer?
  2. Is the three-tier system (Reserved/Standard/Basic) too opinionated for a protocol-level standard, or is it useful to standardize?
  3. Should cross-chain resolution be specified, or handled by a separate extension ERC?

Looking forward to feedback from the community.