General
Soulbound Assets in MPL Core
Soulbound NFTs are non-fungible tokens that are permanently bound to a specific wallet address and cannot be transferred to another owner. They are useful for representing achievements, credentials, or memberships that should remain tied to a specific identity.
Overview
In this guide, we'll explore how to create soulbound assets using MPL Core and the Umi Framework. Whether you're a developer looking to implement soulbound NFTs in TypeScript or just want to understand how they work, we'll cover everything from basic concepts to practical implementation. We'll examine different approaches for making assets soulbound and walk through creating your first soulbound NFT within a collection.
In MPL Core, there are two main approaches to create soulbound NFTs:
1. Permanent Freeze Delegate Plugin
- Makes assets completely non-transferrable and non-burnable
- Can be applied at either:
- Individual asset level
- Collection level (more rent efficient)
- Collection-level implementation allows thawing all assets in a single transaction
2. Oracle Plugin
- Makes assets non-transferrable but still burnable
- Can also be applied at:
- Individual asset level
- Collection level (more rent efficient)
- Collection-level implementation allows thawing all assets in a single transaction
Creating Soulbound NFTs with the Permanent Freeze Delegate Plugin
The Permanent Freeze Delegate Plugin provides functionality to make assets non-transferrable by freezing them. When creating a soulbound asset, you would:
- Include the Permanent Freeze plugin during asset creation
- Set the initial state to frozen
- Set the authority to None, making the frozen state permanent and immutable
This effectively creates a permanently soulbound asset that cannot be transferred or thawed. In the following code snippet it is shown where to add those three options:
await create(umi, {
asset: assetSigner,
collection: collection,
name: "My Frozen Asset",
uri: "https://example.com/my-asset.json",
plugins: [
{
type: 'PermanentFreezeDelegate', // Include the Permanent Freeze plugin
frozen: true, // Set the initial state to frozen
authority: { type: "None" }, // Set the authority to None
},
],
})
Asset-Level Implementation
The Permanent Freeze Delegate Plugin can be attached to individual assets to make them soulbound. This provides more granular control but requires more rent and separate thaw transactions per asset in case it ever should not be soulbound anymore.
Collection-Level Implementation
For collections where all assets should be soulbound, applying the plugin at the collection level is more efficient. This requires less rent and enables thawing the entire collection in one transaction.
Creating Soulbound NFTs with the Oracle Plugin
The Oracle Plugin provides a way to approve or reject different lifecycle events for an asset. To create soulbound NFTs, we can use a special Oracle deployed by Metaplex that always rejects transfer events while still allowing other operations like burning. This differs from the Permanent Freeze Delegate Plugin approach since assets remain burnable even though they cannot be transferred.
When creating a soulbound asset using the Oracle Plugin, one would attach the plugin to the asset. This can be done on creation or afterwards. In this example we are using a default Oracle that will always reject and has been deployed by Metaplex.
This effectively creates a permanently soulbound asset that cannot be transferred but burned. In the following code snippet it is shown how:
const ORACLE_ACCOUNT = publicKey(
"GxaWxaQVeaNeFHehFQEDeKR65MnT6Nup81AGwh2EEnuq"
);
await create(umi, {
asset: assetSigner,
collection: collection,
name: "My Soulbound Asset",
uri: "https://example.com/my-asset.json",
plugins: [
{
// The Oracle plugin allows us to control transfer permissions
type: "Oracle",
resultsOffset: {
type: "Anchor",
},
baseAddress: ORACLE_ACCOUNT,
lifecycleChecks: {
// Configure the Oracle to reject all transfer attempts
transfer: [CheckResult.CAN_REJECT],
},
baseAddressConfig: undefined,
},
],
})
Asset-Level Implementation
The Oracle Plugin can make individual assets non-transferrable while preserving the ability to burn them. This provides flexibility for cases where assets may need to be destroyed.
Collection-Level Implementation
Applying the Oracle Plugin at the collection level makes all assets in the collection non-transferrable but burnable. This is more rent efficient and allows managing permissions for the entire collection at once.