As NFTs have flourished on the Solana blockchain, there’s been an increasing need for NFTs to be as ubiquitous as any digital asset on the Internet: every single item in your game’s inventory, proof-of-engagement in your favorite consumer app, or even a profile for every human on the planet.

So far, though, these types of products have been held back by the cost of rent for NFTs on Solana, which is relatively cheap (◎0.012) but scales linearly; a billion NFTs would cost ◎12,000,000! From 10,000 NFTs at ◎3.5 (34x), 1 million NFTs at ◎5 (2,400x), and 1 billion NFTs at ◎500 (24,000x), compression for NFTs drastically reduces the cost of on-chain storage of NFTs to enable creators to be as expressive with the technology as they wish.

Solana Lab’s Concurrent Merkle Tree program (Gummyroll) and Metaplex Foundation’s Compressed NFTs program (Bubblegum) work in tandem to allow Metaplex NFTs to be encoded into the Solana ledger. NFT metadata is hashed into on-chain Merkle trees and supplemented by off-chain indexers (e.g., Metaplex’s Digital Asset Validator Plugin) that observe modifications of the tree via the ledger. These indexers serve the proofs and data needed for dApps and smart contracts to interact with compressed NFTs.

These compressed NFTs maintain backwards-compatibility with Metaplex NFTs and can be transferred, delegated, and even decompressed into account space for interoperability with existing smart contracts.

<aside> ❗ Compression for NFTs is currently in alpha; contracts have not been audited and implementation details may change—proceed at your own risk. uses a prototype indexer that is not intended for production use. See more information about the rollout here.


How Compression for NFTs works

<aside> 💡 We will be assuming you have working knowledge of what Merkle trees are. Here’s a short recap that explains the essentials!


Compressed NFTs are stored in Merkle trees via the Gummyroll program where:

The on-chain buffer of Merkle roots ensures that the Gummyroll program can facilitate *concurrent write requests *****to a single Merkle tree. Given the nature of how Merkle trees work, any updates to the tree cause the root to change, so the program ensures that even stale requests to update the tree would still be valid if they would have successfully updated a previous version of the tree.

<aside> 💡 Interested in how Gummyroll handles concurrent writes to the Merkle tree? Check out this whitepaper that goes through the nitty-gritty details:

Concurrent Merkle Tree Whitepaper.pdf