How to Protect a Solana Candy-Machine Against Mint Bots

5 min readJan 23, 2022


This post describes the approach we have adopted to protect our mints for PixTapes and its sister collections. Our P!Guard server is more generic though, it can be more generally be used for other collections, and even for non-NFT related dapps. So feel free to drop us a line at if you are interested!

Minting Bots, waiting in line for your candy-machine to open. (Photo by Chela B. on Unsplash)

If you want to launch a collection of NFTs on the Solana blockchain, you’ll find yourself configuring a Candy-Machine, namely the smart contract (a.k.a. the program in Solana vocabulary) and associated web front-end where the members of your community will find the big “Mint” button, emitting a new NFT at each click.

Assuming that you have succeed at building a dynamic community during your pre-mint period, it will be on fire at the very moment of the mint and the collection will sold out very quickly… Maybe too quickly to be true actually! Around each well-hyped mint lie herds of bots, lurking in the shadows, or seating steadily in their sniping spot, ready to spring. Especially if we’re talking about a free mint.

Why is this a problem, you may ask. Well, your true community members will hate seeing their true dedication doubled by script kiddies, and remember that the true value of an NFT collection starts in the trust of its community. You may well lose that, plus from an economic standpoint, it is better to have many holders with few NFTs than a few holders with many NFTs.

Fig 1. In a traditional web2 application, the back-end is protected from bots by a Captcha.

How does one defend a server from bots in the web2 realm? They use Captchas, or any variant of the concept. Can we do the same in the web3 world? Short answer is: yes, but pay attention.

In a traditional web2 application, the front-end is the only door to the back-end, so the model of the Captcha is quite straightforward: the backend sends a challenge to the front-end, then the front-end (well, the user, assuming it is a human) solves it, and the back-end checks that the answer is correct prior to accepting the request (Fig 1).

Fig 2. In a web3 application, the back-end is the blockchain, which is open to everybody.

But with a web3 application, the backend is the blockchain. Thus the front-end is just one convenient shiny door to access it, but actually anyone can access the backend (to build an alternative front-end for instance). It is not possible to “install” a Captcha in an on-chain program (Fig. 2), so one could be tempted to do add a proxy — a regular web2 server — that’d check the Captcha and then route valid requests to the blockchain (Fig. 3). This is a bad idea! Remember, the blockchain is accessible to anybody. Once your smart contract is live on chain, bots, humans, aliens, anything can interact with it, be it with or without the help of your front-end.

Fig 3. Attempting to naively adopt the web2 approach to a web3 application fails because the front-end is not the only door to the back-end so a proxy can easily be bypassed.

The only true native safety tool that a blockchain features — and the only one it actually needs, really –is cryptography and the fact that an on-chain program can reject instructions if they are not digitally signed by one or several wallets of its choice. Usually this is used to ensure that the wallet that spends some tokens and/or pays transaction fees actually gave its consent to the transaction. But this mechanism can also be used to safely off-load the Captcha verification process on a third party server (Fig. 4).

Fig 4. Our P!Guard service transforms the traditional Captcha response into a Solana digital signature certifying the request. The on-chain program then checks that this signature is valid.

Our such server, named P!Guard, receives the human answer to a Captcha and the transaction to sign. It holds both the Captcha’s secret, and a Solana secret key. If the Captcha is correct, the P!Guard signs the transaction and returns it to the front-end, which then sends it to the blockchain. Finally, the on-chain program only accepts transactions signed with the P!Guard’s secret account. Only a human can obtain a transaction signed by the P!Guard’s secret account, so only a human can perform the transaction, success! Note that to prevent some malicious use of our service, the P!Guard server also checks that the transaction follows the an expected template.

In the end, the main constraint with this approach is that it requires to configure the on-chain program to check for the P!Guard’s signature. If you write your own program, it is dead simple, just look at account.is_signer in the instruction’s processor. But the thing is, most people don’t write their own program, they rather use existing ones. For minting NFTs, it is not much a problem: adding the P!Guard address as a verified creator (with 0% of royalties) will make the on chain program check for the P!Guard signature! For other program, well let’s expect developers who want to enable this kind of third-party verification to add an extra signature check.

A note about decentralization. This kind of verification mechanism is needed to build web3 applications that don’t become the new email and its spam-verse. That being said, a service like P!Guard, or anything similar, reconcentrates the trust in a way, because you must trust that it checks the Captchas correctly, that it does not censor some transactions by claiming that the Captcha is wrong even if it is correct, etc. When using P!Guard, you must trust that. In practice you can use multiple P!Guard-like services and check all the signatures. Now how many people will actually do it? Don’t forget the spirit of web3!

Alt144, for the PixTapes team.

Don’t forget to check out our collection!




PixTapes is an evolutionary collection of NFTs representing music titles, as well as a community which drives its dynamics.