{"id":"ERC-5114","name":"Soulbound Badge","status":"Last Call","chain":"both","category":{"id":"identity","name":"Identity & Privacy","description":"Who you are on-chain, and what you choose to reveal"},"journeyStages":[{"id":"asset-display","name":"Asset Discovery & Display","description":"Seeing tokens, NFTs, and balances"},{"id":"management","name":"Asset Management","description":"Managing assets over time"}],"uxImpact":"ERC-5114 defines an immutable soulbound badge binding to a specific NFT and content-addressable badge metadata. It does not define an issuer registry, revocation function, identity verification, or validity status; show those as separate issuer or application policy when present.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-5114","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-5114","specConstraints":[{"id":"erc-5114-single-mint-event","constraint":"A badge's Mint event must not fire twice for the same badgeId.","appliesTo":"infrastructure","normativity":"normative","specQuote":"this event **MUST NOT** be fired twice for the same `badgeId`","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Treat badge identity as one immutable minted instance in history and do not duplicate a badge when an indexer sees repeated or replayed logs."},{"id":"erc-5114-parent-binding-resolution","constraint":"ownerOf rejects an unminted badge and, after minting, returns a stable parent NFT binding equal to the original Mint event.","appliesTo":"application","normativity":"normative","specQuote":"// returns the NFT that this badge is bound to.\n\t// this function **MUST** throw if the badge hasn't been minted yet\n\t// this function **MUST** always return the same result every time it is called after it has been minted\n\t// this function **MUST** return the same value as found in the original `Mint` event for the badge\n\tfunction ownerOf(uint256 badgeId) external view returns (address nftAddress, uint256 nftTokenId);","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Show the badge's parent collection and token ID from the on-chain binding, and distinguish an unminted or unresolved badge from a valid attached badge."},{"id":"erc-5114-collection-uri-immutable","constraint":"collectionUri must be immutable.","appliesTo":"infrastructure","normativity":"normative","specQuote":"the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Cache collection metadata only when the URI and implementation support immutability. Show the URI scheme and avoid implying mutable web content is a permanent badge record."},{"id":"erc-5114-collection-uri-content-addressed","constraint":"collectionUri must be content addressable.","appliesTo":"infrastructure","normativity":"normative","specQuote":"the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Label content-addressed metadata separately from ordinary URLs and give users a clear unavailable or unverified state when the content cannot be resolved."},{"id":"erc-5114-collection-links","constraint":"External links referenced by collectionUri content must follow the same immutable, content-addressed rules.","appliesTo":"infrastructure","normativity":"normative","specQuote":"any external links referenced by the content at `collectionUri` also **MUST** follow all of the above rules","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Do not make a badge appear permanent while its nested media or links remain mutable. Surface unresolved or non-content-addressed dependencies."},{"id":"erc-5114-badge-uri-immutable","constraint":"The badgeUri section repeats `collectionUri` when stating its immutable-URI rule; treat that source wording as an implementation-verification issue rather than silently claiming a separate badgeUri field requirement.","appliesTo":"infrastructure","normativity":"normative","specQuote":"// returns a censorship resistant URI with details about this badge instance\n\t// the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)\n\t// the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)\n\t// data from this takes precedence over data returned by `collectionUri`\n\t// any external links referenced by the content at `badgeUri` also **MUST** follow all of the above rules\n\tfunction badgeUri(uint256 badgeId) external view returns (string badgeUri);","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Keep the per-badge metadata snapshot stable and distinguish badge-specific content from collection defaults."},{"id":"erc-5114-badge-uri-content-addressed","constraint":"The badgeUri section repeats `collectionUri` when stating its content-addressable rule; preserve that source ambiguity and do not present an independently verified badgeUri permanence guarantee without implementation evidence.","appliesTo":"infrastructure","normativity":"normative","specQuote":"// returns a censorship resistant URI with details about this badge instance\n\t// the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)\n\t// the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)\n\t// data from this takes precedence over data returned by `collectionUri`\n\t// any external links referenced by the content at `badgeUri` also **MUST** follow all of the above rules\n\tfunction badgeUri(uint256 badgeId) external view returns (string badgeUri);","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Treat a badge's instance metadata as a verifiable content reference, not as a mutable profile endpoint."},{"id":"erc-5114-badge-links","constraint":"External links referenced by badgeUri content must follow the same immutable, content-addressed rules.","appliesTo":"infrastructure","normativity":"normative","specQuote":"any external links referenced by the content at `badgeUri` also **MUST** follow all of the above rules","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#specification","designImplication":"Audit nested badge media and links before presenting an immutable or censorship-resistant badge claim."},{"id":"erc-5114-legacy-scope","constraint":"The new badge type is not backward compatible with existing tokens except viable souls identifiable by address and id.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"This is a new token type and is not meant to be backward compatible with any existing tokens other than existing viable souls (any asset that can be identified by `[address,id]`).","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#backwards-compatibility","designImplication":"Keep badge support and legacy NFT support visibly distinct. Do not infer soulbound badge semantics from an arbitrary NFT that happens to have an address and token id."},{"id":"erc-5114-implementation-verification","constraint":"A client must verify that a claimed ERC-5114 implementation actually follows the rules rather than trusting a superficial API probe.","appliesTo":"application","normativity":"security-considerations","specQuote":"Users of badges that claim to implement this EIP must be diligent in verifying they actually do.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#security-considerations","designImplication":"Show verification status and the checks performed before calling a badge soulbound or permanent. Do not treat a matching interface as proof that transfers are impossible."},{"id":"erc-5114-persona-not-human","constraint":"A soulbound badge is bound to a persona, not proof of one permanent human identity.","appliesTo":"application","normativity":"security-considerations","specQuote":"It should also be made clear that soulbound badges are not bound to a human, they are bound to a persona.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#security-considerations","designImplication":"Use persona language and retain the underlying NFT/account context. Do not turn badge ownership into an unqualified human identity claim."},{"id":"erc-5114-loop-detection","constraint":"Software walking chains of badges bound to badges needs an exit strategy when it detects a loop.","appliesTo":"application","normativity":"security-considerations","specQuote":"Software that tries to walk such a chain should take care to have an exit strategy if a loop is detected.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-5114#security-considerations","designImplication":"Bound recursive badge resolution and show a cycle state rather than hanging or presenting an incomplete chain as verified."},{"id":"badge-metadata-format","constraint":"The collectionUri and badgeUri data format is intentionally unspecified; metadataFormat should inform callers what type, format, or version to parse.","appliesTo":"application","normativity":"rationale","specSection":"Rationale > No Specification for badgeUri Data Format","specUrl":"https://eips.ethereum.org/EIPS/eip-5114#no-specification-for-badgeuri-data-format","designImplication":"Read metadataFormat before parsing badge data, retain an unsupported-format state, and do not infer a schema from the URI alone.","specQuote":"The format of the data pointed to by `collectionUri()` and `badgeUri(uint256)`, and how to merge them, is intentionally left out of this standard in favor of separate standards that can be iterated on in the future.\nThe immutability constraints are the only thing defined by this to ensure that the spirit of this badge is maintained, regardless of the specifics of the data format.\nThe `metadataFormat` function can be used to inform a caller what type/format/version of data they should expect at the URIs, so the caller can parse the data directly without first having to deduce its format via inspection."}],"summary":"ERC-5114 defines an immutable soulbound badge binding to a specific NFT and content-addressable badge metadata. It does not define an issuer registry, revocation function, identity verification, or validity status; show those as separate issuer or application policy when present.","partialDeployment":{"body":"ERC-5114 is Last Call. Show badge binding only when the target NFT contract, metadata resolver, and client support are verified; issuer trust, revocation, identity, and validity remain external policy."},"applicability":{"whenToUse":["A product needs to display a badge bound to a specific NFT collection and token ID.","The client can resolve the badge's content-addressable metadata and show the parent NFT context.","The product can separate the on-chain binding from any issuer trust, moderation, or identity policy."],"whenToAvoid":["The product needs wallet-bound credentials rather than an NFT-bound badge.","The UI promises issuer verification, revocation, or validity status without an external source.","The client cannot make the parent NFT and badge relationship clear."]},"designerTakeaways":["Show each badge together with its parent NFT collection and token ID.","Explain that the on-chain binding and content-addressable metadata are separate from issuer trust or personhood claims.","Warn before transferring the parent NFT when the product wants users to understand the badge's resulting association.","Label any issuer, moderation, or revocation status as external policy with a named source."],"problemsSolved":[{"problem":"Credentials need a visible NFT binding","oldWay":"A badge appears beside a wallet without showing what it references.","newWay":"The UI shows the parent NFT collection and token ID with the badge metadata.","impact":"critical"},{"problem":"Badge context is fragmented","oldWay":"Users browse an unscoped list of badge tokens.","newWay":"A client can render badges in the context of their referenced NFT.","impact":"high"},{"problem":"Transfer consequences are unclear","oldWay":"Users move the parent NFT without reading its attached badges.","newWay":"A product can explain that the badge binding follows the referenced NFT, subject to the parent NFT's transfer behavior.","impact":"high"},{"problem":"Issuer trust is conflated with binding","oldWay":"A badge card calls an on-chain reference a verified credential.","newWay":"Show immutable binding/metadata separately from external issuer or moderation evidence.","impact":"high"}],"uxPatterns":[{"name":"Badge-on-NFT Display","description":"Show an immutable badge binding in parent NFT context.","userFlow":["User views a parent NFT","Client resolves attached badge references","Shows collection, token ID, and metadata source","Labels any external issuer evidence separately"]},{"name":"Badge Issuance to NFT","description":"Issue a badge that references a specific NFT when the badge implementation supports it.","userFlow":["Issuer selects the parent collection and token ID","Client shows the immutable binding terms","Issuer submits the badge creation path","UI confirms the reference after settlement"]},{"name":"Parent NFT Selection","description":"Choose the NFT that a badge will reference; identity framing is optional product policy.","userFlow":["User reviews eligible NFTs","Selects a collection and token ID","Confirms the reference and issuer terms","Client shows the attached badge context"]},{"name":"Badge Evidence Panel","description":"Display binding, content-addressed metadata, and separate issuer or moderation evidence.","userFlow":["Enter a badge or parent NFT reference","Fetch attached metadata","Show on-chain binding and content source","Show external evidence only when its source is available","Label unknown, revoked, or unsupported states honestly"]}],"uiComponents":[{"name":"BadgeOnNFT","description":"Visual overlay showing badges on parent NFT","states":["no-badges","has-badges","loading"],"props":["parentNFT","badges[]","maxDisplay","onBadgeClick"]},{"name":"ParentNFTSelector","description":"Choose the parent NFT to which the immutable badge reference will be attached.","states":["selecting","selected","confirming"],"props":["ownedNFTs[]","currentParent","onSelect"]},{"name":"BadgeAttachmentForm","description":"Form for issuing badge to specific NFT","states":["selecting-nft","confirming","issuing","complete"],"props":["badge","recipientNFTs[]","onIssue"]},{"name":"AttachedBadgeCard","description":"Display parent NFT binding and content-addressable metadata; external issuer status is optional","states":["bound","metadata-loaded","metadata-unavailable","external-status-unknown"],"props":["badge","parentNFT","issuer","issuedDate"]},{"name":"NFTBadgeProfile","description":"Show an NFT and its attached badges; do not imply identity or personhood.","states":["loading","loaded","empty"],"props":["nft","badges[]","owner"]}],"antiPatterns":[{"pattern":"Showing badges without their parent NFT","why":"Users cannot understand the immutable reference.","instead":"Show collection and token ID in the parent NFT context.","severity":"critical"},{"pattern":"Hiding parent transfer consequences","why":"Users may not know which NFT a badge follows.","instead":"Show the parent reference and an explicit transfer explanation when applicable.","severity":"critical"},{"pattern":"Issuing to a wallet while calling it NFT-bound","why":"An address-bound badge and an NFT-bound badge have different semantics.","instead":"Require a specific parent NFT reference and show the binding before signing.","severity":"high"},{"pattern":"Calling issuer status protocol verification","why":"ERC-5114 defines no issuer registry, revocation function, or validity status.","instead":"Show external issuer or moderation evidence separately, with its source and unknown state.","severity":"high"},{"pattern":"Hiding metadata source and immutability","why":"Users cannot distinguish content-addressed metadata from mutable app labels.","instead":"Show the metadata source and on-chain binding separately.","severity":"medium"}],"keyTakeaways":["ERC-5114 binds an immutable badge reference to a specific NFT.","Show the parent collection and token ID with content-addressable metadata.","Issuer trust, revocation, moderation, and personhood are external policy unless separately implemented.","Explain the parent NFT transfer consequence when relevant."],"technicalNotes":"ERC-5114 defines an immutable binding to an NFT (collection address plus token ID) and content-addressable badge metadata. It does not define an issuer registry, revocation function, validity status, or human-identity proof. Unlike ERC-5192, which binds to an address, this extension references another token; show the on-chain binding separately from external issuer or moderation evidence.","lastUpdated":"2026-09-18","sources":[{"label":"ERC-5114 official specification","url":"https://ercs.ethereum.org/ERCS/erc-5114","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5114","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-5114","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-5114","markdown":"https://www.eipsfordesigners.com/standards/ERC-5114/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-5114/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-5114","official":"https://ercs.ethereum.org/ERCS/erc-5114","discussion":"https://ethereum-magicians.org/search?q=ERC-5114"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}