Solana Programs Part 4
Metaplex Candy Machine
May 29, 2022

The Metaplex Candy Machine is among the most popular smart contracts used for NFT minting on Solana. Recently, it has even implemented sophisticated logics for detecting and taxing bots.

How does the candy machine program work internally? What are its intended use cases and dependencies? How does it detect bots? This article elaborates on these technical details.

What Is Metaplex Candy Machine?

The Candy Machine is a distribution program used by

  1. NFT creators to set up a collection of NFTs (e.g., 10,000 diverse Okay Bears) to be distributed
  2. Users to mint the NFTs created in Step 1 (note: bots can mint NFT too!)

For 1, the distributor must first call the InitializeCandyMachine instruction to create a candy machine:

A candy machine has a few important pieces of information:

  • authority: who is authorized to update the candy machine, withdraw funds, etc
  • wallet: the wallet for receiving payment from NFT minters
  • token_mint: an optional SPL token mint for the wallet (if payment is in SPL token)
  • items_redeemed: total number of NFTs minted so far
  • data: the NFT metadata (of type CandyMachineData)
  • additional configs for each NFT (e.g., name and uri)

The CandyMachineData includes the necessary attributes for NFT minting:

price is the price paid by users to mint an NFT, with optional discount configured in whitelist_mint_settings.

creators specifies the list of creators of the NFT collection.

items_available is number of NFTs in the collection.

For 2, any one can mint NFTs through a candy machine created in Step 1, by calling the MintNFT instruction. MintNFT is a fairly complex instruction (over 600 lines of source code in Rust). We next explain MintNFT in detail.

Mint NFT

To mint an NFT on Metaplex, there are several essential steps (see Part 3: Metaplex Token Metadata):

  1. create a new token mint (a unique identifier for the to-be-minted NFT), and mint one token to the user’s token account
  2. create a new metadata account for the NFT (this will call the token metadata program’s CreateMetadataAccountV2 instruction)
  3. create a master edition account of the NFT (this will call the token metadata program’s CreateMasterEditionV3 instruction)
  4. set metadata’s update_authority to a user-supplied account (or candy_machine.authority if candy_machine.data.retain_authority is true); this will call the token metadata program’s UpdateMetadataAccountV2 instruction

The MintNFT instruction depends on the token metadata program and it includes all the above four steps and, additionally, a logic for users to pay for the minted NFT and logics for detecting and taxing bots.

How Does a User Mint an NFT on Candy Machine?

To process the MintNFT instruction, the function handle_mint_nft is invoked with a number of input accounts, e.g., candy_machine , candy_machine_creator , wallet , metadata , mint , mint_authority , etc.

The user has to pay a price to mint each NFT. The price is specified in the candy machine in the amount of either a SPL token or Sol:

When SPL token is used, the token mint is specified by candy_machine.token_mint and the payment is transferred from the source token account to the candy_machine.wallet account by spl_token_transfer (line 468):

Otherwise, the price amount of Sol is transferred from the payer account to the wallet account directly via system_instruction::transfer (line 482):

The distributor can also offer a discount price for users through configuring whitelist_mint_settings in candy_machine.data:

Which NFT to Mint From a Collection?

For every NFT in the collection, the candy machine maintains a ConfigLine containing the NFT’s name and uri:

If candy_machine.data.hidden_settings is set, the minted NFT name is ordered by a mint_number (e.g. Okay Bear #1756):

The mint_number is incremented by one upon each successful MintNFT call.

Otherwise if hidden_settings is not set, the MintNFT instruction uses an index calculated from recent_slothashes.data to determine which NFT to mint from the collection:

The get_config_line function takes the modded index as input and traverses through the remaining NFTs in the collection (using a bit mask):

Finally, after checking all constraints and setting up the CPI account data to call the token metadata program, the following three functions are invoked in the written order to complete the NFT minting process:

config_line contains the information of the minted NFT

Note that the candy_machine_creator account (PDA created by the candy machine program) is also specified as a creator of the NFT:

Why Not Use the Token Metadata Program Directly?

Readers may wonder, to mint an NFT, why should we use a candy machine instead of calling the token metadata program directly?

These two programs have different use cases:

  • for candy machine, users mint from a collection of NFTs created by the distributor (i.e., the distributor represents the original NFT creators)
  • for token metadata, users create their own NFTs one by one

How Does Candy Machine Detect and Tax Bots?

The candy machine program detects bots and charges a fee (BOT_FEE: 0.01 Sol) for each bot call to the MintNFT instruction:

The bot detection logic is implemented in the handle_mint_nft function, considering a good number of different scenarios:

Step 1. bots calling handle_mint_nft via CPI. Only CPI called by the Gumpdrop program is not considered as bots. GUMDROP_ID: gdrpGjVffourzkdDRrQmySw4aTHr8a3xmQzzxSwFD1a

Step 2. bots missing set collection during the mint instruction (for candy machine with collection set):

Step 3. bot transactions containing any CPI from an unknown program:

The known programs include the System program, SPL Token program, Associated Token program, and the Candy Machine program itself. Transactions containing any CPI not from the known programs are considered as bots.

Step 4. bots calling MintNFT after minting has stopped (after a certain timestamp):

Step 5. bots calling MintNFT after all available NFTs have been redeemed:

Step 6. bots missing gateway token when the candy machine’s gatekeeper is set

Step 7. bots calling MintNFT before the candy machine’s go_live_date:

Step 8. bots calling MintNFT with incorrect whitelist_token_mint:

Step 9. bots calling MintNFT with whitelist_token_account while the candy machine has no discount and no presale (i.e., it has a forced whitelist):

Update and Configure Candy Machine

The authority can make changes to the candy machine through a few additional instructions: UpdateCandyMachine, AddConfigLines, SetCollection, RemoveCollection, SetCollectionDuringMint, as well as WithdrawFunds. These instructions are permissioned (signed by candy_machine.authority) otherwise will abort the transaction.


About sec3 (Formerly Soteria)

sec3 is a security research firm that prepares Solana projects for millions of users. sec3’s Launch Audit is a rigorous, researcher-led code examination that investigates and certifies mainnet-grade smart contracts; sec3’s continuous auditing software platform, X-ray, integrates with GitHub to progressively scan pull requests, helping projects fortify code before deployment; and sec3’s post-deployment security solution, WatchTower, ensures funds stay safe. sec3 is building technology-based scalable solutions for Web3 projects to ensure protocols stay safe as they scale.

To learn more about sec3, please visit https://www.sec3.dev