Based on in-depth analyses of the previous vulnerabilities, we identified 14 tips on how to make your NFT project even more secure.
Since NFTs have gained more and more attention, it has also grown in trading volumes as well as value. This fact was patently noticed by actors intending to use those in a malicious way. Thus, it is highly necessary to implement protocols according to best practices.
NFT best security practices
Digital wallets set some default maximum gas limit. Inform users to adjust the gas limit (give the specific amount) depending on how many NFTs they want to mint. Otherwise, their ether could be wasted for reverted tx’s, and your project launch will be ruined.
Remember that the standard safeMint function calls the onERC721Receiver function on the receiver address. Make sure that you mitigate the reentrancy attacks by following the Checks-Effects-Interactions pattern or using the nonReentrant modifier.
In the case of NTFs sales where metadata is publicly accessible during the sale, divide the process into 2 separate transactions where the randomness is created in the second one. It’s the only way to prevent users from rerolling tx’s until they get a token with desirable id/metadata.
The off-chain oracles, like Chainlink VRF, help to deliver truly pseudo-random data within 2 transactions or you can simply use the data from future blocks (e.g., future block hash) as source of “randomness”.
If you limit the amount of NFTs a single user can purchase, be aware that every user can bypass this limit either by creating multiple EAOs or deploying multiple contracts and each of them would mint tokens within the mentioned threshold in a single transaction. By the time of writing, you can restrict smart contracts from interacting with your NTF minting function - e.g. by simply adding the following require statement:
require(msg.sender == tx.origin, “Smart contracts are not allowed)
BUT, when EIP-3074 introduces AUTHCALL this approach will become insufficient. So before going live, perform risk analysis and take into account the fact that your NFTs can be purchased by other contracts, as well as multiple EOAs.
Do not ever use predefined solidity methods (like block.timestamp, block.coinbase or blockhash) as a source of entropy for generating instant random numbers. If you rely on block-derived values, it can always be easily revealed by malicious smart contracts or malicious miners/validators.
Instead, use oracles as an external source of randomness (Chainlink VRF or RANDAO), Commitment Schemes or future blocks’ attributes.
The metadata of NFTs should be permanent, reliable, and unmodifiable. For that sake, make use of InterPlanetary FileSystem (IPFS) to store all the data on-chain. Data persistence should be your protocol’s design.
Think of the verifiability of your token contracts. Source code submitted to Etherscan is much easier to audit by the end-users than a bytecode. Let them confirm that your NFT project is neither buggy nor malicious.
If you implemented a Merkle Tree for the purpose of NFTs whitelisting, make sure you predefined the root hash as a state variable. If users are able to define an arbitrary root hash value (e.g. pass it as a function parameter), they would also be able to grant themselves unintended access to the presale.
When implementing a function that verifies signatures, instead of using eth_sign or personal_sign standards, use the EIP-712. This type of signature contains all required configuration data (chain id, version, address, data type, and the actual data itself). To prevent replay attacks and ensure execution in a specific timeframe, add a nonce and deadline values. When verifying the signatures, use OpenZeppelin’s ECDSA library to protect it from signature malleability.
If your NFT contract has to be compliant with ERC721 standard, confirm that all necessary functions and events are presented with corresponding, consistent types, all functions emit the proper event and the derived contracts don’t break the conformance. For this purpose use slither-check-erc tool.
We all love gas optimization.
- If you want to make it cheaper for your users to send multiple NFTs, use ERC-1155. The batchTransfer function allows them to perform this operation in a single transaction.
- Drop Counter library for token ids enumeration - replace it with a regular integer incrementation. What’s more, if you are just incrementing a token id, opt out from Solidity’s native overflow/underflow checks by using an unchecked statement.
- Instead of using old revert strings, employ custom errors.
Aware users that a lot of attacks don’t completely take place on the blockchain. They would be targets for various malicious actions and scams, such as phishing or token copies. All social media associated with your NFT project could be subject to scams and social engineering attacks.
Remember, that many of the most common Web2 vulnerabilities are equally applicable to decentralized applications. Thus, the web page where the NFT sale is carried out should be properly protected. Take mitigating steps following the OWASP Cheat Sheet.
- Always validate and sanitize user input by allowing only desired characters,
- String data coming from the contract should be escaped, not to modify DOM objects,
- Make use of security headers, such as X-Frame-Options, Content-Security-Policy, Referrer-Policy, etc.
- Cross Site Scripting is a key thread of your front-end security. Read and introduce mitigations described in the OWASP XSS Prevention Cheat Sheet.
To build a secure protocol, you need to consider the security of its business logic. The majority of vulnerabilities in NFTs implementation are related to logical bugs. Introduce the threat modeling to your SDLC process. Always perform a smart contract security audit, run by a third-party company, before going live.
Like any other digital asset, NFTs can be implemented with serious flaws. Thus, it is important to understand the risks and the process of how to mitigate them and protect yourself and your community from being rekt.
I strongly encourage you to adhere to the guidelines outlined in this article to ensure the proper care and protection of your NFTs. Implementing best practices and conducting thorough security audits are crucial steps in safeguarding your assets.
If your project requires the expertise of a professional audit, please do not hesitate to contact us.
We would be honored to assist you in securing your assets.
About the author
White Hat and smart contract security researcher. Participant of the first edition of Secureum Bootcamp. Professionally dealing with security since 2021. Passionate about DeFi.