Poking around in the world of NFTs you will primarily come into contact with NFTs on Ethereum Virtual Machine (EVM) based blockchains. Now that Opensea Solana has integrated NFTs on its trading platform or well-known marketplaces such as NBATopshot have been implemented on Flow, it is worth to take a closer look at both of them. Not at least in order to avoid expensive mistakes, caused by bad decisions for a certain technology.
To get a practical understanding of both Blockchains, we have deployed the identical implementation of a rudimentary NFT marketplace including the implementation of the associated NFT smart contracts on each of them. The experiences and lessons learned are shared with you in this blog series.
In this part, you will learn how Solana offers a steep learning curve for writing highly performant smart contracts.
In Case you've missed Part 1, click here:
Table of Contents:
- Introduction to Solana
- Solana Concepts
- Summary Findings
Introduction to Solana
Solana is a high-performance, Proof of Stake blockchain that attempts to overcome the limitation of classic blockchain networks, by introducing Proof of History - a proof to verify the order and passage of time between events. Having timestamps that nodes can rely on, means that Solana can leverage concepts from modern distributed systems to increase network performance.
At any given time, one of the system nodes is designated as leader, randomly selected through PoS. The leader orders the user messages, generates a Proof of History sequence using a verifiable delay function and publishes it to the Verifiers, who will broadcast their confirmations. Each Verifier is equipped with the same high-performance hardware capabilities and can be elected Leader through PoS based elections. Solana employs scheduled Leader Rotation to minimize the effects of a malicious leader, censoring votes or transactions.
Solana's transaction flow from the Solana white paper
Instead of publishing a concluded block to the validators, the leader node streams entries as quickly as he can batch valid transactions into an entry. The validators already start processing the entries before the last entry is received, which reduces the delay between receiving the rest of the block and voting on its validity. Proof of History is implemented by having the leader "timestamp" each block with a cryptographic proof that some duration has passed since the last proof.
Proof of History (PoH)
PoH uses a collision resistant cryptographic hash function to create a continuous hash sequence, where every hash function has the output of the previous hash function as input, similar to how in a regular blockchain each block contains the hash of the previous block. Solana uses this PoH sequence to prove the passage of time by appending events to the output of the previous hash. Table 1 shows an example of a PoH sequence that proves that photograph1 must have been created sometime before photograph2. The insertion of photograph1 changes all subsequent values in the sequence, and thereby it is computationally impossible to pre-compute a future sequence.
|1||sha256(”any random starting value”)||hash1|
|326||sha256(append(hash335, photograph1 sha256))||hash326|
|600||sha256(append(hash599, photograph2 sha256))||hash600|
Example of a PoH Sequence from the Solana white paper
The verification of the PoH sequence can occur in significantly less time than it took to generate it, by splitting up the sequence of hashes and distributing their verification on the multiple cores of a modern GPU. Likewise, the generation of a PoH sequence can be horizontally scaled by periodically appending the hash output of parallel sequences to each other.
To prevent concurrency related issues and improve the scalability of Solana programs, executable code and state were separated. In Solana, all programs are stateless and any data they work with must be passed in from the outside. In turn, Solana programs can be invoked in parallel, as long as they don't try to write on the same data.
All data on Solana is stored in accounts, since accounts in Solana are essentially memory buffers that are addressable by a public key. Solana accounts can be separated into three types:
- Native Accounts,
- Data accounts that store state, and
- Program accounts that store executable code.
Associated Token Account
Each user's System account address comes with an account for the default Solana token, but each custom token requires its own token account called the Associated Token Account. Their address is deterministically derived from the mint address and the user's main System account address. The deterministic and unique associated token address for each token allows also for external accounts to fund the creation of a new account for the receiver.
Program Derived Addresses (PDAs)
To securely read and write data, the always stateless Solana programs make use of Program Derived Addresses. PDAs are accounts controlled by Solana programs and serve as the foundation for Cross-Program Invocation. A PDA is deterministically generated using a program's ID and seeds. Only the program from which the PDA was derived, can sign for the PDA, using the seed and bump. Solana programs can generally have multiple data accounts to store necessary states.
Solana Program Library (SPL) Token Program
Every type of token on Solana is created using the Solana Program Library Token Program. SPL tokens are comparable to token standards such as ERC-20 or ERC-721, but instead of creating a new contract for each token, the Token Program creates and mints the token according to the instructions it receives.
Deployment of Solana programs uses the Upgradeable BPF Loader that supports three different types of state accounts to deploy a program.
The program account is the main account of an on-chain program and is referred to with the "program id" used to invoke the program. Program accounts are immutable once deployed, but only represent a proxy account to the accounts storing the byte-code and states.
The program data account stores the executable byte-code of the program. Buffer accounts are used to temporarily store the byte-code while the program is deployed throughout a series of transactions.
The CLI breaks up the byte-code into ~1 KB chunks that are sent to the buffer account at a rate of 100 transactions per second. After the final transaction, the byte-code written to the buffer account is copied into a program data account and verified.
The marketplace prototype starts with a home screen that shows the NFTs of the logged-in user, which can only be accessed after authenticating with a wallet provider.
The listed NFTs can be opened in a detail view, giving additional information and allowing transfer and burning of the NFT.
The minting page allows the user to mint their own NFT, while showing a preview of the final result.
The marketplace uses the Solana network for minting and managing NFTs. The tokens are represented as SPL tokens and associated with a metadata account using Metaplex, their metadata is saved on the Arweave network using Bundlr. When receiving or minting a new token, a new token account is generated using the user's address and the token's mint address. The token account is part of the user's storage until the token is transferred out or burned.
General overview of the components used in the Marketplace implementation
The Metaplex protocol was developed as an NFT standard to support developers with their NFT projects. Metaplex is a collection of tools and smart contracts to simplify minting and selling NFTs on Solana.
Simplified presentation of the link between SPL Token and Metaplex metadata
NFT Structure on Solana
Mint accounts are responsible for storing the global information of a Token, such as the current supply and its authorities, but require a Metadata account to store additional information. To make a digital asset out of a simple token, a Metadata account is attached using a program derived address. The metadata account holds additional information, such as an off-chain JSON object. In our case, this is stored on the Arweave network.
There are additional NFT formats supported by Metaplex, which are available here.
The Metaplex storefront is a protocol that provides smart contracts to create/mint NFTs, start a variety of auctions or direct sales as well as visualize NFTs in a standard way. It is separated into an on-chain program and a self-hosted front-end that can be replaced or modified at will.
It supports the creation of NFTs that pay royalty percentages, creator splits to the original artists, and master editions with limited prints. NFTs can be sold in instant sales or auctions with various adjustments regarding timing, pricing, tick size and tiered auctions.
Metaplex Candy Machine
The Metaplex Candy Machine is an on-chain NFT distribution program, named after its unpredictable distribution of NFTs, allowing for a fair distribution of rarer items. After the configuration of the Candy Machine, uploading the assets and setting up the minting website, users can connect their Solana wallet to the website and buy a random NFT from the collection. To protect against bots, the candy machine can be configured with a gatekeeper challenge.
We have compiled the most important findings and experiences from our example implementation in the following two tables. We have contrasted these with the more developed and widespread Ethereum world. It should be noted that these are experiences from the first half of 2022.
|Developer Documentation||Official documentation and some community tutorials||Extensive documentation and few community created tutorials||Extensive documentation and community created tutorials|
|Development Community||Smaller but growing community||Smaller Community||Many third party tutorials and forums|
|Development Tools||Limited but under development: Metaplex, Anchor, regular Rust tools||Limited but under development: Flow Playground, Cadence IDE extensions||Larger choice of tools: IDEs, frameworks, languages,|
|Contract Security Analysis||Some auditing tools by solana-labs||No tools found||
Various security analysis tools: Mythril, MythX, Echidna ...
Contract auditing firms available
|Smart Contract Language||Rust||Cadence||Solidity, Vyper, Yul|
|Smart Contract Type||Stateless, Account-based||Stateful, Resource-oriented||Stateful|
|Converting Contracts from Solidity||Requires bigger changes due to statelessness||Requires some changess but also enables different designs||-|
|Subjective Assessment||Steep learning curve for writing highly performant smart contracts||Lower barriers of entry||De facto standard for smart contract development|