Features
Creating Bubblegum Trees
Last updated February 24, 2026
Summary
Creating a Bubblegum Tree is the first step before minting compressed NFTs. This page covers how to create and fetch the two required on-chain accounts: the Merkle Tree account and the TreeConfigV2 PDA.
- Create a Bubblegum Tree with configurable max depth, max buffer size, and canopy depth
- Choose tree parameters based on your project's cNFT capacity needs (16K to 1B+ cNFTs)
- Fetch merkle tree and tree config account data after creation
- Understand the cost tradeoffs for different tree configurations
Introduction
Whilst the data of Compressed NFTs is stored inside transactions and not onchain accounts, we still need some onchain accounts to keep track of the Merkle Tree and its configuration. As such, before we can start minting Compressed NFTs, we need to create two accounts:
- A Merkle Tree account. This account holds a generic Merkle Tree that can be used to verify the authenticity of any type of data. It is owned by the MPL Account Compression Program forked from the SPL Account Compression Program. In our case, we will use it to verify the authenticity of Compressed NFTs.
- A TreeConfigV2 account. This second account is a PDA derived from the address of the Merkle Tree account. It allows us to store additional configurations for the Merkle Tree that are specific to Compressed NFTs — e.g. the tree creator, the number of minted cNFTs, etc.
With these two accounts, we have everything we need to start minting Compressed NFTs. Note that, we will refer to Merkle Tree accounts with associated Tree Config accounts as Bubblegum Trees.
Creating a Bubblegum Tree
Let's now see how one can create both of these accounts to create a Bubblegum Tree. Fortunately, our libraries make this process easy by providing a Create Tree operation that takes care of everything for us. This operation accepts a variety of parameters — most of them optional — that allow us to customize the Bubblegum Tree to our needs. The most important ones are:
- Merkle Tree: A newly generated signer that will be used to create the Merkle Tree account. The Merkle Tree account will then be accessible at this address.
- Tree Creator: The address of the account that will be able to manage the Bubblegum Tree and mint Compressed NFTs.
- Max Depth and Max Buffer Size: The Max Depth parameter is used to compute the maximum number of leaves — and therefore Compressed NFTs — that the Merkle Tree can hold. This maximum is calculated by
2^maxDepth. The Max Buffer Size parameter indicates the minimum concurrency limit of the Merkle Tree. In other words, it defines how many changes can happen in the tree in parallel. These two parameters cannot be chosen arbitrarily and have to be selected from a predefined set of values as displayed in the table below.
Below are our recommended tree settings for compatibility within the Solana ecosystem.
| Number of cNFTs | Tree Depth | Canopy Depth | Concurrency Buffer | Tree Cost | Cost per cNFT |
|---|---|---|---|---|---|
| 16,384 | 14 | 8 | 64 | 0.3358 | 0.00002550 |
| 65,536 | 16 | 10 | 64 | 0.7069 | 0.00001579 |
| 262,144 | 18 | 12 | 64 | 2.1042 | 0.00001303 |
| 1,048,576 | 20 | 13 | 1024 | 8.5012 | 0.00001311 |
| 16,777,216 | 24 | 15 | 2048 | 26.1201 | 0.00000656 |
| 67,108,864 | 26 | 17 | 2048 | 70.8213 | 0.00000606 |
| 1,073,741,824 | 30 | 17 | 2048 | 72.6468 | 0.00000507 |
The max depths of trees are as follows:
- Public: Whether or not the Bubblegum Tree should be public. If it is public, anyone will be able to mint Compressed NFTs from it. Otherwise, only the Tree Creator or the Tree Delegate (as discussed in Delegating cNFTs) will be able to mint Compressed NFTs.
Here is how one can create a Bubblegum Tree using our libraries:
Create a Bubblegum Tree
import { generateSigner } from '@metaplex-foundation/umi'
import { createTreeV2 } from '@metaplex-foundation/mpl-bubblegum'
const merkleTree = generateSigner(umi)
const builder = await createTreeV2(umi, {
merkleTree,
maxBufferSize: 64,
maxDepth: 14,
})
await builder.sendAndConfirm(umi)
By default, the Tree Creator is set to the Umi identity and the Public parameter is set to false. However, these parameters can be customized as shown in the example below.
const customTreeCreator = generateSigner(umi)
const builder = await createTreeV2(umi, {
// ...
treeCreator: customTreeCreator,
public: true,
})
Fetching a Bubblegum Tree
Since a Bubblegum Tree is composed of two onchain accounts, let's see how to fetch either of them.
Fetching a Merkle Tree
The Merkle Tree account contains various information about the tree such as:
- The Tree Header which stores the Max Depth, the Max Buffer Size, the Authority of the tree and the Creation Slot of when the tree was created.
- The Tree itself which stores low-level information about the tree such as its Change Logs (or roots), its Sequence Number, etc. We talk more about Concurrent Merkle Trees in a dedicated page of this documentation.
- The Canopy as discussed in the Merkle Tree Canopy page.
Here is how one can fetch all of that data using our libraries:
Fetch a Merkle Tree
import {
fetchMerkleTree,
} from "@metaplex-foundation/mpl-account-compression";
const merkleTreeAccount = await fetchMerkleTree(umi, merkleTree)
Fetching a Tree Config
The Tree Config account contains data specific to Compressed NFTs. It stores:
- The Tree Creator of the Bubblegum Tree.
- The Tree Delegate of the Bubblegum Tree, if any. Otherwise, it is set to the Tree Creator.
- The Total Capacity of the Bubblegum Tree which is the maximum number of cNFTs that can be minted from the tree.
- The Number Minted which keeps track of the number of cNFTs minted into the tree. This value is important as it is used as a Nonce ("number used once") value for operations to ensure the Merkle tree leaves are unique. Thus, this nonce acts as a tree-scoped unique identifier of the asset.
- The Is Public parameter which indicates whether or not anyone can mint cNFTs from the tree.
- Is Decompressible is only valid for Bubblegum V1.
- Version is the version of the LeafSchema that can be used.
Here is how one can fetch all of that data using our libraries:
Fetch a Tree Config
import { fetchTreeConfigFromSeeds } from '@metaplex-foundation/mpl-bubblegum';
const treeConfig = await fetchTreeConfigFromSeeds(umi, { merkleTree });
Notes
- Tree parameters (max depth, max buffer size, canopy depth) are immutable after creation. Choose carefully based on your project's needs.
- Larger trees cost more in rent but have a lower per-cNFT cost. See the recommended settings table above for cost estimates.
- The Tree Creator is stored in the TreeConfigV2 account and can delegate minting authority to another account (see Delegating Trees).
- Public trees allow anyone to mint. Private trees restrict minting to the Tree Creator or Tree Delegate.
FAQ
How do I choose the right tree size for my project?
Use the recommended settings table. For small projects or testing, a depth-14 tree holds 16,384 cNFTs at ~0.34 SOL. For large collections, a depth-20 tree holds 1 million cNFTs at ~8.5 SOL. For very large drops, depth-24+ trees hold millions to billions of cNFTs.
Can I change the tree size after creation?
No. The max depth, max buffer size, and canopy depth are all fixed at creation time and cannot be modified. If you need different parameters, you must create a new tree.
What is the relationship between max depth and tree capacity?
The maximum number of cNFTs a tree can hold is calculated as 2^maxDepth. For example, maxDepth=14 supports 16,384 cNFTs, maxDepth=20 supports 1,048,576, and maxDepth=30 supports over 1 billion.
What does the max buffer size control?
The max buffer size determines the minimum concurrency limit — how many modifications can happen to the tree within the same Solana block. Higher values allow more parallel transactions (mints, transfers, burns) but increase the tree's rent cost.
Glossary
| Term | Definition |
|---|---|
| Bubblegum Tree | The combination of a Merkle Tree account and its associated TreeConfigV2 PDA |
| Merkle Tree Account | The on-chain account holding the merkle tree data, owned by the MPL Account Compression Program |
| TreeConfigV2 | A PDA derived from the Merkle Tree address, storing Bubblegum-specific config (creator, delegate, capacity, mint count, public flag) |
| Max Depth | The maximum depth of the merkle tree, determining capacity as 2^maxDepth |
| Max Buffer Size | The number of change log entries stored, determining how many concurrent modifications the tree supports per block |
| Canopy Depth | The number of upper tree levels cached on-chain, reducing proof sizes in transactions |
| Tree Creator | The account that created the tree and has authority to manage it and mint cNFTs |
| Tree Delegate | An account authorized by the Tree Creator to mint cNFTs on their behalf |
