A certification you cannot sell, but an authority can revoke.
In Web2, credentials follow a specific lifecycle. A coding bootcamp issues you a certificate of completion. You cannot sell it or give it to someone else — it belongs to you. But the issuing institution retains the right to revoke it if they discover fraud or if the credential expires. Professional licenses, employee badges, verified status markers on social platforms — they all work the same way. They are yours to hold, but someone else controls whether they remain valid.
Solana's Token Extensions Program lets you encode this exact pattern at the protocol level using two extensions: non-transferable and permanent delegate.
How it works
The non-transferable extension locks tokens in place. Once minted to a wallet, they cannot be moved, sold, or traded. The permanent delegate extension gives your authority keypair the ability to burn tokens from any holder's account without their signature. Combined, they create a credential that is soulbound to the holder but revocable by the issuer.
Building it
Here is the exact sequence I ran:
# Step 1: Create the mint with all three extensions
# --enable-non-transferable locks tokens in place
# --enable-permanent-delegate lets the authority burn from anywhere
# --enable-metadata reserves space for the credential name
spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
create-token \
--decimals 0 \
--enable-non-transferable \
--enable-permanent-delegate \
--enable-metadata
# Step 2: Give the credential a name and symbol
spl-token initialize-metadata [MINT_ADDRESS] \
"Solana Dev Credential" "CRED" \
"https://example.com/credential.json" \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
# Step 3: Create a recipient account and mint 1 credential
RECIPIENT=$(solana-keygen pubkey ~/recipient-wallet.json)
spl-token create-account [MINT_ADDRESS] --owner $RECIPIENT \
--fee-payer ~/.config/solana/id.json \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
spl-token mint [MINT_ADDRESS] 1 --recipient-owner $RECIPIENT \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
# Step 4: Try to transfer — this FAILS (soulbound enforced)
spl-token transfer [MINT_ADDRESS] 1 [THIRD_PARTY] \
--owner ~/recipient-wallet.json \
--fee-payer ~/.config/solana/id.json \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
# Error: "Transfer is disabled for this mint"
# Step 5: Revoke the credential using permanent delegate
spl-token burn [RECIPIENT_TOKEN_ACCOUNT] 1 \
--owner ~/.config/solana/id.json \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
# Step 6: Verify balance is now 0
spl-token balance [MINT_ADDRESS] --owner $RECIPIENT \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
# Output: 0
The critical moment is Step 4. The CLI returns:
Transfer is disabled for this mint
This is the non-transferable extension enforcing the soulbound constraint. No smart contract code was written. No custom program was deployed. It is a protocol-level rule that the Solana runtime applies to every transfer involving this mint.
Then in Step 5, I burned the token from the recipient's account using only my authority signature — not the recipient's. This is the permanent delegate extension in action.
Inspecting the final mint
spl-token display [MINT_ADDRESS] \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
The output shows all three extensions:
Extensions
Permanent delegate: 2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164
Non-transferable
Metadata Pointer: ...
Metadata:
Name: Solana Dev Credential
Symbol: CRED
What surprised me
The permanent delegate cannot be changed. Once you enable it, that authority is locked for the life of the mint. You cannot transfer it to a multisig later, you cannot revoke it, you cannot rotate the key. If the permanent delegate key is compromised, the attacker can burn every token in existence. This is the most dangerous extension in the Token Extensions suite — use it deliberately and secure the key.
The combination maps perfectly to real-world credentials. The non-transferable extension prevents secondary markets (no selling certifications). The permanent delegate enables revocation (no lifetime credentials). The metadata makes the credential self-describing (anyone can inspect what it represents without an external database).
Where to go deeper
This pattern is immediately useful for DAOs issuing membership badges, protocols granting contributor status, or education platforms distributing certificates:
If you are building a credential system on Solana, this combination of extensions is the closest thing to a "standard" pattern the protocol offers. Use it. But protect that permanent delegate key like a root password.
Top comments (0)