Soulbound Tokens (SBTs): Non-Transferable Credentials for Web3 Identity
Degrees, memberships, KYC indicators, and achievements that stick to a wallet. This lesson explains what SBTs are, when they shine, how to design for consent and revocation, and how to pair them with private verifiable credentials for safer real-world uses.
Introduction: A public, portable way to say “this wallet earned that”
Soulbound tokens (SBTs) are non-transferable NFTs. Unlike ordinary NFTs, you cannot sell or gift an SBT to another address. That simple constraint changes what the token means: it becomes a durable, on-chain signal attached to whichever wallet holds it. SBTs are useful when you want a public, composable claim such as “completed this course,” “is a member in good standing,” “is a project maintainer,” or “has an active KYC check with Issuer X” and you want dapps, DAOs, and dashboards to read that signal without an API gatekeeper.
1) Model and motivation
An SBT is typically an ERC-721-like token where transfers revert. The “soul” is the holder address (which may represent a person, a team multisig, or a service identity). By making tokens non-transferable, we reduce the risk that reputation is bought, sold, or outsourced to a mercenary account. Because SBTs live on chain, they are:
- Discoverable by wallets, explorers, indexers, and dapps without logging into a vendor API.
- Composable in smart contracts: a contract can check “does this address hold token type X or satisfy status Y?” and gate features accordingly.
- Auditable: mints and status changes emit events; indexers can maintain reliable snapshots.
Still, immutability cuts both ways. A permanent ledger is a poor home for sensitive facts. The healthy compromise is to keep on-chain claims minimal and pair them with off-chain verifiable credentials for rich, privacy-preserving detail.
2) Common use cases
Below are patterns that communities and teams adopt when they want tamper-resistant signals that any app can read:
- Education and certification: badges for course completion, continuous education credits, bootcamp graduations, or “passed assessment X.” Keep transcripts private; the SBT only signals completion and optional validity windows.
- Membership and roles: “member,” “maintainer,” “reviewer,” or “core contributor” attached to governance or repository actions. Issuers can require an Active status before administrative functions execute.
- Safelist and allowlist signals: eligibility to mint, to access early betas, or to use higher transaction limits. Unlike a spreadsheet, the signal is readable by aggregators and wallets.
- Compliance indicators (cautious): a “KYC verified by Issuer X” flag where no personal data appears on chain. The token points to an off-chain VC so the user can disclose proofs selectively when required.
- Proof of contribution: bug bounty acknowledgements, hackathon finalists, grant grantee or reviewer status. These support “reputation by doing.”
- Event participation: proof that a wallet attended an event or participated in a workshop, with a locked badge to avoid secondary market trading of presence.
- Institutional controls: hold “upgrade steward” or “auditor attested” roles as prerequisites to call admin functions in protocol contracts.
3) Where SBTs fit: NFTs, verifiable credentials, and attestations
Three families of identity primitives coexist in Web3. Understanding their trade-offs helps you choose the right tool.
A) Transferable NFTs
Great for collectibles, tickets that can be resold, or access passes intended to move between people. Poor for reputation and roles because ownership can change hands without the issuer’s intent.
B) Soulbound tokens (non-transferable NFTs)
Great for public reputation where the claim can be minimal, non-sensitive, and useful to dapps at read time. Ideal when a smart contract must enforce “only holders of X may call Y.” The cost is public traceability and limited flexibility if you later decide the claim should be private.
C) Verifiable credentials (off-chain, signed)
These are JSON-LD or JWT-like objects signed by issuers and presented peer-to-peer. They support selective disclosure, revocation lists, and privacy preserving proofs. Best for sensitive facts (real names, ages, addresses, training transcripts, medical eligibility). Downside: dapps must implement verification logic or use a gateway.
4) Design principles: consent, mint, status, and UX
SBTs can become spam or harassment vectors if anyone can mint sticky labels to your wallet. Good designs give recipients agency, make status readable, and minimize what is public.
Consent before mint
- Signed consent (recommended): the recipient signs an EIP-712 message authorizing mint of a particular token or class. The contract verifies this signature on mint.
- Claim flow: the issuer allowlists addresses; recipients call
claim()
to mint to themselves. This ensures an opt-in act on chain. - Opt-out window: for mass issuance (for example, graduation), publish a pre-mint list and allow opt-outs before the mint window closes.
Revocation and expiry
- Issuer burnable: the issuer can burn a token to rescind a badge. Emit an event so indexers and UIs update quickly.
- Status registry: keep token state on chain (
Active
,Suspended
,Revoked
) so history remains visible but validity is unambiguous. - Expiry: add a
validUntil
attribute and require reissue on expiry. Authentication flows can check current validity in O(1).
Metadata minimization
- Store only what must be public: a short label and a pointer (content hash or URL) to a description.
- Do not put names, emails, government IDs, or birthdates on chain.
- For sensitive descriptions, host behind a privacy preserving gateway you control; include a digest or integrity hash so readers can verify immutability without seeing details.
UX that communicates “locked” semantics
Wallets and explorers increasingly distinguish non-transferable tokens. Use a minimal “locked” interface so UIs render the difference between a tradeable NFT and an SBT. In human terms: the token should look like a badge, not a marketplace listing.
5) Privacy, linkage, and harassment resistance
Public ledgers are excellent at correlation. Seemingly harmless badges can still enable profiling if combined. Think ahead about how your design impacts users.
- Pairwise identities: encourage people to hold SBTs in a dedicated “identity” wallet separate from trading. This reduces cross-linking to financial history.
- Anonymous possession proofs: for private access gates, publish a Merkle root of valid token IDs and let holders prove membership with a zero-knowledge proof plus a nullifier to prevent double use without revealing their address.
- Do not encode sensitive facts: never put health, legal, employment, or financial specifics on chain. If you must commit to something, store a salted hash so it cannot be reversed.
- Spam defenses: require consent signatures or self-claims, allow holders to reject unsolicited mints, and consider a holder burn right only for unwanted or defamatory tokens.
6) Implementation patterns
You can implement an SBT by extending a familiar NFT standard and preventing transfers. Many wallets recognize a minimal “locked” interface so the token displays as non-transferable.
// Minimal pattern: non-transferable ERC-721 with locked signal and status interface ILocked { event Locked(uint256 tokenId); function locked(uint256 tokenId) external view returns (bool); } enum Status { Active, Suspended, Revoked } contract Soulbound is ERC721, ILocked { mapping(uint256 => Status) public status; address public issuer; constructor(string memory name, string memory symbol, address _issuer) ERC721(name, symbol) { issuer = _issuer; } modifier onlyIssuer() { require(msg.sender == issuer, "not issuer"); _; } // Mint with recipient consent (EIP-712 typed data verified off-chain/on-chain) function mintWithConsent(address to, uint256 tokenId, bytes calldata consentSig) external onlyIssuer { require(_verifyConsent(to, tokenId, consentSig), "no consent"); _safeMint(to, tokenId); status[tokenId] = Status.Active; emit Locked(tokenId); } // Transfers always revert (non-transferable) function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal override { require(from == address(0) || to == address(0), "non-transferable"); super._beforeTokenTransfer(from, to, tokenId, batchSize); } function locked(uint256) external pure returns (bool) { return true; } // Optional: issuer can change status or burn function setStatus(uint256 tokenId, Status s) external onlyIssuer { status[tokenId] = s; } function issuerBurn(uint256 tokenId) external onlyIssuer { _burn(tokenId); } }
Metadata should be compact, content addressed, and free of personal data. Include integrity fields so clients can verify resources.
{ "name": "Course Completion — Smart Contracts 101", "description": "Issuer: University X. No personal data on chain.", "image": "ipfs://bafy.../badge.png", "attributes": [ {"trait_type": "issuer", "value": "University X"}, {"trait_type": "status", "value": "Active"}, {"trait_type": "validUntil", "value": "2027-12-31"} ], "image_integrity": "sha256-BASE64..." }
Read paths for dapps should be simple and cacheable:
- Resolve “does address A hold token type X?”
- If yes, read
status
and optionalvalidUntil
to decide whether to unlock a feature. - Cache positive results briefly (honor TTL) and invalidate on relevant events.
7) Blueprints: practical patterns you can copy
A) Education badge with renewal
Goal: signal “completed course X” with a validity window (for example, three years). Flow: student signs consent, issuer mints SBT with validUntil
, indexers watch Locked
and status events. Renewal: complete refresher, issuer sets status to Active and extends validUntil
. Privacy: syllabus and grades remain off chain.
B) DAO role badge
Goal: let maintainers call upgrade functions only if they hold an Active “maintainer” SBT. Flow: governance accepts a proposal adding address A as maintainer; issuer mints SBT to A; protocol checks presence and status before executing admin actions. De-risking: status can be Suspended in emergencies without burning history.
C) KYC indicator (public flag, private details)
Goal: show that a user passed a compliance check with Issuer X without revealing identity on chain. Flow: issuer conducts KYC off chain and issues a verifiable credential; an SBT with label “Verified by Issuer X” points to a revocation list URL and a policy. Apps read the SBT for quick gating; when deeper checks are needed, the user presents the VC privately.
D) Event participation
Goal: gift attendees a non-transferable memento that also unlocks private forum access. Flow: attendees scan a code, sign consent, and self-claim the SBT. The forum checks for the badge at login. Abuse controls: one claim per wallet, rate limit by IP/device, and optional proof-of-presence data kept off chain and discarded after claims close.
8) Operations and recovery: treat SBTs like production infrastructure
Issuers and holders both need clear runbooks. The contracts may be small, but the signals they control are powerful.
- Issuer key hygiene: protect issuer roles with multisig or MPC. Document which functions are guarded by timelocks and which are emergency switches. Rotate keys on staff changes.
- Versioning: if you upgrade the contract, emit mapping events or publish a discovery registry so indexers know where to read status for old and new tokens.
- Recovery for holders: publish a reissue policy. For example, the holder proves control of a linked DID or presents out-of-band evidence, issuer marks old token Revoked and mints a new token to the recovery address. Emit events so apps recognize the handover.
- Monitoring: alert on unusual mint rates, bursts of revocations, or changes to issuer roles. If you integrate SBT checks into admin paths, treat those alerts like protocol health signals.
- Legal and policy docs: publish human-readable policies for consent, revocation, appeals, and data retention. This builds trust and provides predictability for users.
9) Case studies and anti-patterns
University program. A university issues “Completed Smart Contracts 101” SBTs. Students must sign consent; tokens include validUntil
three years out. Alumni can complete a refresher to renew. The contract exposes statusOf(tokenId)
for easy verification. Lesson: expiry handles stale knowledge without deleting history.
DAO maintainers. A DAO replaces spreadsheet role tracking with on-chain “Maintainer” SBTs. Protocol admin functions check for an Active badge. In an incident, governance sets status to Suspended for affected addresses and later restores. Lesson: status beats permanent burns for emergency response.
Hackathon recognition. A hackathon offers locked badges to finalists and winners. Teams can link their badge to a project page hosted on IPFS. Recruiters and grant programs can filter by badge presence. Lesson: public, minimal signals unlock discovery without doxxing.
Anti-patterns to avoid
- Minting without consent: unsolicited labels can become harassment. Always implement opt-in or explicit consent.
- Putting PII on chain: even “first name, last initial” can combine with other clues. Keep personal facts out of token metadata.
- No status model: if the only control is “burn or not,” you will hesitate to act in emergencies. Add
Active
/Suspended
/Revoked
. - Using SBTs for secrets: if the claim must be private, use verifiable credentials and cryptographic proofs instead of on-chain facts.
- Single issuer key: do not let one hot wallet control mint and status. Use multisig, publish admin addresses, and log changes.
10) Frequently asked questions
Can I move an SBT to a new wallet if I rotate keys?
By design, SBTs are non-transferable. Good issuer policies support reissue: the issuer revokes the old token and mints a new one to your new wallet after you prove continuity (for example, with a DID link or off-chain verification). Apps rely on emitted events to track the handover.
What if someone mints a defamatory SBT to my address?
This is why consent is crucial. As a holder, prefer systems that require your signature or self-claim. If an unwanted token appears, some wallets let you hide it; you can also lobby indexers to ignore contracts that do not respect consent. Issuers should implement reject windows and moderation.
Do SBTs improve sybil resistance?
They can help when the cost to obtain a badge is tied to real work (contributions, time, or verification) rather than money. Alone, SBTs are not a silver bullet. Combining multiple signals and private credentials, plus rate limits and reputation decay, works better than any single marker.
Is it safe to put KYC results on chain?
No. Keep identity documents and personal attributes off chain. If you must publicly signal that a check happened, mint a minimal SBT that references a policy and a revocation list. Present the real details privately with a verifiable credential when required.
Which wallet should hold my SBTs?
Use a dedicated identity wallet that you are comfortable connecting to dapps, separate from large value holdings. For organizations, consider holding role badges on a multisig and using subaccounts for operational roles.
11) Glossary
- Soulbound token (SBT): a non-transferable NFT used as a public, composable signal.
- Consent signature: an EIP-712 message signed by the recipient authorizing a mint.
- Status registry: on-chain mapping from token ID to state such as Active, Suspended, Revoked.
- Verifiable credential (VC): an off-chain signed claim that supports selective disclosure and revocation.
- Anonymous membership proof: a zero-knowledge proof that you are in a set without revealing which member.
- Nullifier: a one-time marker used in privacy systems to prevent double use of a proof.
Quick check
- Why does non-transferability matter for credentials or role badges?
- Name two ways to ensure recipient consent before minting.
- When should you choose an SBT versus a verifiable credential?
- How can a holder prove they have a valid SBT without revealing their address?
- What status model would you implement to handle emergencies without destroying history?
Show answers
- It prevents selling or outsourcing the badge, keeping the signal tied to the intended identity.
- Recipient EIP-712 consent signature, or a self-initiated claim flow after allowlisting (opt-in).
- Use SBTs for public, non-sensitive, contract-readable signals; use VCs for sensitive or private attributes.
- Use a zero-knowledge inclusion proof against a published Merkle root, with a nullifier to prevent reuse.
- Active/Suspended/Revoked with optional expiry (
validUntil
) and issuer-burnable controls.
Go deeper
- Token design: consent formats, replay protection, status registries, and event schemas for indexers.
- Privacy techniques: inclusion proofs, nullifiers, rate limits, and wallet separation strategies.
- Operations: issuer key management, timelocks, reissue policies, and public documentation.
- Practice: run tabletop exercises, compromised controller, mass revocation, contract upgrade, before launch.
Next: decentralized identifiers and verifiable credentials for private, portable identity.