This EIP proposes a standard interface for non-transferable, multi-owner Soulbound tokens. Previous account-bound token standards face the issue of users losing their account keys or having them rotated, thereby losing their tokens in the process. This EIP provides a solution to this issue that allows for the recycling of SBTs.
This EIP was inspired by the main characteristics of the ERC-1155 token standard and by articles in which benefits and potential use cases of Soulbound/Accountbound Tokens (SBTs) were presented. This design also allows for batch token transfers, saving on transaction costs. Trading of multiple tokens can be built on top of this standard and it removes the need to approve individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Smart contracts implementing this ERC MUST implement all of the functions in the ERC-5516 interface.
Smart contracts implementing this ERC MUST implement the ERC-165 supportsInterface function and MUST return the constant value true if 0xe150bdab is passed through the interfaceID argument.
For a given issuer (msg.sender) and a given metadataURI, the resulting tokenId MUST be deterministic. Implementations are RECOMMENDED to compute it as:
A subsequent call to issue from the same msg.sender with the same metadataURI MUST resolve to the same tokenId and MUST extend the holder set under that tokenId rather than create a new token. Implementations MUST reject any issue call that targets an existing tokenId from a msg.sender other than the original issuer.
The value returned by uri(tokenId) MUST be fixed at first issuance. Implementations MUST NOT mutate it on re-issuance or via any other operation.
A successful call to renounce(tokenId) MUST clear the caller's ownership of tokenId and MUST be permanent for the caller's address: implementations MUST reject any subsequent issue call that includes that address in recipients[] for the same tokenId.
Implementations MUST emit exactly one Issued event per call to issue, including re-issuance calls. The recipients field of the event MUST contain the addresses added in that call only, not the cumulative holder set.
Implementations MUST emit exactly one Renounced event per call to renounce.
We implement a standard method of obtaining metadata (uri) similar to the one defined in ERC-1155:
The URI value allows for ID substitution by clients. If the string {id} exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for a large number of tokens to use the same on-chain string by defining a URI once, for that large number of tokens.
[0-9a-f] with no 0x prefix.https://token-cdn-domain/{id}.json would be replaced with https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json if the client is referring to token ID 314592/0x4CCE0.The original idea for this proposal arose from a necessity of emitting on-chain certificates to multiple people. We thought that having to emit one token per account was redundant, and we originally developed a ERC-1155 partial-compatible implementation.
After revisiting our proposal, we thought that it would be cleaner to have a more minimal interface that just serves this purpose only, so we decided to drop the partial backwards compatibility with ERC-1155.
A common real-world use case for on-chain credentials is reusing the same conceptual credential across cohorts of recipients (for example, a university issuing the same "Knows Python" credential to successive classes of students). To support this without introducing a separate "extend" function or making issuers manage opaque counter-derived identifiers, this EIP specifies that issue is the single entry point for both creation and re-issuance.
The deterministic, issuer-bound derivation of tokenId from (msg.sender, metadataURI) (see Specification > Token ID derivation) gives the standard several useful properties:
issue with the same metadataURI always lands on the same tokenId. The second cohort, third cohort, and so on each emit a fresh Issued event under that tokenId while extending the holder set. No counter, registry, or cohort id is required.tokenId mixes in the caller's address, an adversary observing a pending issue transaction in the mempool cannot pre-claim that tokenId; their copy would derive a different identifier under their own address. Verifiers should check issuerOf(tokenId) against the expected issuer rather than trusting metadata alone (see Security Considerations).uri(tokenId) at first issuance, and an issuer wanting to publish revised metadata mints a new tokenId under a different metadataURI.issue appends to the holder set for that tokenId and emits its own Issued event, allowing off-chain indexers to reconstruct the full holder set (and any subsequent renunciations) from event logs.Renunciation interacts with re-issuance deliberately: once an address has renounced a tokenId, the issuer cannot re-attach it via a subsequent issue call. This preserves holder agency over which credentials remain bound to their soul, even in the face of a cooperative or compelled issuer. The cost is that a renouncer who later changes their mind must receive a new tokenId under a different metadataURI; this is considered acceptable given the strong semantics it preserves around the word "renounce".
We saw the vision of the ERC-1155 and tried to apply it to Soulbound/Accountbound tokens: We think that having the ability to prove that you own a token, not a particular identifier is valuable, and that it has real world use cases.
The ERC-5516 standard guarantees that event logs emitted by the smart contract will provide enough data to create an accurate record of all current token balances. A database or explorer may listen to events and be able to provide indexed and categorized searches of every ERC-5516 token in the contract.
Given the non-transferability property of SBTs, if a user's keys to an account get compromised or rotated, such user may lose the ability to associate themselves with the token.
Given the multi-owner characteristic of this EIP, SBTs will be able to bind to multiple accounts, providing a potential solution to the issue.
Multi-owner SBTs can also be issued to a contract account that implements a multi-signature functionality (As recommended in ERC-4973).
The multi-token functionality permits the implementation of multiple token types in the same contract. Furthermore, all emitted tokens are stored in the same contract, preventing redundant bytecode from being deployed to the blockchain. It also facilitates transfer to token issuers, since all issued tokens are stored and can be accessed under the same contract address.
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]).
You can find an implementation of this standard here.
Because tokenId is a hash of (msg.sender, metadataURI) and the contract enforces no global ownership of a metadataURI, anyone can call issue with arbitrary metadataURI values, including values that imitate or duplicate a legitimate issuer's metadata. The resulting tokenId will differ from the legitimate one (since msg.sender differs) and issuerOf(tokenId) will return the impostor's address.
Verifiers should therefore treat metadata content as untrusted on its own. To trust a credential, a verifier should:
tokenId.issuerOf(tokenId) and compare the returned address against the expected issuer (e.g., a known university wallet, a multisig, or an address recorded in an out-of-band registry).tokenId as keccak256(abi.encodePacked(expectedIssuer, expectedMetadataURI)) and confirming it matches.Indexers and UIs displaying ERC-5516 credentials should surface the issuer prominently and should not imply authenticity from metadata alone.
The deterministic, issuer-bound tokenId derivation is intentionally designed to make front-running ineffective. An adversary who observes a pending issue transaction cannot pre-claim the resulting tokenId, because submitting their own issue from a different address yields a different identifier. They can, however, mint a token with the same metadataURI under their own address; this collapses to the impersonation case above, mitigated by issuerOf verification.
Renunciation under this standard is irreversible: once an address has called renounce(tokenId), implementations refuse any subsequent issue call that includes the same address among recipients[] for that tokenId (see Specification > Renunciation). This protects holders from coerced or unilateral re-attachment by a cooperative or compromised issuer. Holders should be aware that this finality is per (tokenId, address); if the issuer mints a new tokenId (under a different metadataURI) and includes the renouncer, that is a new credential and is allowed. UIs surfacing renunciation should not misrepresent it as also blocking new credentials from the same issuer.
If an issuer's key is compromised, the attacker can extend any existing credentials they originally minted (since they control msg.sender for re-issuance). They cannot, however, retroactively rewrite issuerOf(tokenId) for tokens minted by other addresses, nor can they re-attach renounced credentials. Issuers handling credentials of consequence (academic, professional, regulatory) are encouraged to use multisig or smart-contract wallets as the msg.sender for issue so that the issuer identity is governance-bound rather than tied to a single externally-owned account, consistent with the Exception handling rationale above.
The multi-owner property of this EIP is the standard's primary mitigation for holder key loss: a credential may be issued to multiple addresses controlled by the same person (or to a smart-contract wallet that implements key rotation). Verifiers checking ownership via has(who, tokenId) should not assume that a single address represents the totality of a holder's identity for that credential.
The event semantics described in the Specification (one Issued event per issue call, including re-issuance, and one Renounced event per renounce call) are load-bearing for off-chain indexers. Indexers reconstructing holder sets must process both event types and must not assume that the most recent Issued event represents the full holder set for a tokenId; it represents only the recipients added in that call.
Copyright and related rights waived via CC0.