Oct 31, 2021

Seven Security Considerations for Smart Contracts

It may not feel necessary to focus on security when it comes to crypto and NFT, but it absolutely is. Security processes will mitigate the risk of fraud, ensure no bots and whales, ensure no breakdowns or outages, and ensure users don’t lose money.

Real money is involved and we must be sure we can provide the best experience at the lowest gas price. In this blog, we go through seven security considerations you should think about.

1. Use a framework

A smart contract is a set of functions required by an ERC-721 standard and functions for desired logic implementation. In order to make your contract, you can either write the it yourself from scratch or you can use a framework.

We prefer the latter because it saves time and makes our contract more secure, and it means that there is a wide community working on contract frameworks and constantly improving them. We use the OpenZepplin framework which provides all the necessary functions and is also easy to use.

2. Restrict direct minting

It has almost become a standard across different NFT contracts to restrict direct minting and allow access only through a selected node. This is because letting users mint directly can create user inequality. Some will know more than others and will have the tools to do it bulk, meanwhile others won’t know much at all and will just watch gas prices rise due to those in the know.

Disabling direct mint ensures all users are equal and that there is more control of the minting process. This means you can have more checks on your contracts and will ultimately reduce gas prices. Click here to learn how it works.

How does it work?

We have a pair of "private key" and "public key". On a back-end, we use a "private key" that lets us sign data. In a contract, we use a "public key" that lets us verify data. When a user clicks on a “mint” button on our website next things happen:

1. We send a request to our back-end to generate a hash, a nonce, and a signature

A hash is a keccak256 encrypted address, nonce, and quantity.

A nonce is a random 8 characters length string. This will help us prevent encrypted data to be used again.

A signature is encrypted with a "private key" hash.

2. Once a hash, a nonce, and a signature are received we then send a request with all these parameters (plus quantity) to the contract.

3. In a contract, we decrypt the signature and match it against the hash.

4. If they match then we can proceed to a next check

5. If they don’t match we throw an exception because it means not our "private key" was used to creating a signature

6. Then we check that nonce wasn’t used. If it was used this means that someone tries to use hash & signature for the second time.

If all the checks passed we finally mint a token. If there is a problem at any step we revert the transaction therefore we don’t spend any gas on errors.

So, in general, it’s a standard cryptography protocol of sending a private message from Alice to Bob in a public-key cryptosystem.

3. Securing access on a client-side

We don’t want bots or whales to drop the project value by purchasing huge sets of tokens. Therefore, they should not be allowed to use our website as a proxy, change identities, or send multiple requests to the contract. Only real users should be able to submit mint requests and there are different ways to ensure this. The simplest and easiest solution is to use a captcha. Together with UUID, this can help to make it harder to bulk mint for those who just want to exploit the contract.

4. Limit access to public functions

A smart contract has some system functions (e.g. set token base URI, toggle public sale, etc.). Access to those functions should be limited to a contract owner or some chosen roles. Again, an OpenZepplin framework provides a standard way to secure access to such system function. You can read more about the access control here.

5. Add validations for the mint request

Before trying to execute a mint function we will run a set of standard validations like:

  • do you have enough free tokens left?
  • is public sale active?
  • does a hash match your signature?
  • do you have enough funds to mint desired number of tokens?

All these checks will help avoid spending gas without being sure that you can mint successfully.

6. Set up servers properly

We have a back-end that generates signatures required for minting. Therefore, we should keep our servers secured and make sure they can run under a heavy load.

These are basic things that must be done:

  • Disallow password access
  • Use a separate (not root) user to access your server
  • Use SSH keys to access your server
  • Set up a firewall
  • Set up 2-way SSL
  • Set up caching
  • Keep things (packages) updated
  • Don’t let one the latest versions, use stable ones
  • Use load balancers
  • Use multiple servers + backups

Note — with our current configuration, we can handle ~4k requests/second which is pretty good. And we can easily increase this number in case we have to.

7. Use third parties for a better security

If a third party service can help to improve your security/performance why not use it? Cloudflare is an example of one such service, which can help:

  • Another layer of caching and speeding up the website
  • A richer DDoS protection
  • Hiding servers real IP.

For us using Cloudflare already become a standard.


originally posted on medium.com

CV