Smart contract security is becoming an increasingly important aspect of Web3 development. Not only when writing smart contracts but also when listening to blockchain events as decentralized applications (dapps) rely on accurate on-chain data. As you might already know, the easiest way to monitor smart contract events is by setting up a Moralis Web3 stream. So, how do you protect your streams from malicious actors? Well, the easiest way to do so is with a webhook security function:
const verifySignature = (req, secret) => { const providedSignature = req.headers["x-signature"] if(!providedSignature) throw new Error("Signature not provided") const generatedSignature= web3.utils.sha3(JSON.stringify(req.body)+secret) if(generatedSignature !== providedSignature) throw new Error("Invalid Signature") }
Adding the snippet above to your Web3 streams ensures that only Moralis can send post requests to your webhook URLs. As a result, you can be confident that the data provided by the streams is accurate and relevant!
Check out the webhook security documentation page for more information on how this works. Also, remember to sign up with Moralis if you want to create your own Web3 streams. Creating an account is free and only takes a couple of seconds!
Overview
Today’s article will cover the ins and outs of smart contract security. In doing so, this guide starts by exploring some of the common security issues in smart contracts. From there, we dive straight into best practices for smart contract security. Following this, we will briefly cover some prominent smart contract security tools. Lastly, to top things off, we will take a closer look at how you can secure your Moralis Web3 streams!
In the article’s last two sections, you will familiarize yourself with the Moralis Streams API. This is one of many blockchain development resources offered by Moralis. Along with several enterprise-grade Web3 APIs, Moralis also features amazing blockchain development content on the Web3 blog. For instance, learn about Notify API alternatives, how to import OpenZeppelin contracts in Remix, or tackle our Chainlink NFT tutorial!
Also, did you know you can access all Moralis features for free? All you need to do is sign up with Moralis and immediately leverage these Web3 development resources!
How to Make Smart Contracts More Secure
As the Web3 industry grows, smart contract security is becoming an increasingly important aspect of blockchain development. Malicious actors are looking to exploit this new industry and are seeking flaws in smart contract code for personal gain. For this reason, we’ll take a closer look at smart contract security!
Since Ethereum is the most significant blockchain for Web3 development, we will focus on Ethereum security best practices. Fortunately, most of the tips in this article apply to smart contract development in general.
Nevertheless, to understand why we need these Ethereum security best practices in the first place, the initial section will take a closer look at the root of the problem. As such, let us kickstart this guide by exploring some of the common smart contract security issues!
Are There Security Issues in Smart Contracts?
Smart contract technology is the backbone of the Web3 industry, enabling a higher degree of flexibility and innovation. Unfortunately, the advantages of smart contracts are double-edged, as it also presents opportunities for bad-faith actors to exploit vulnerabilities.
The immutability aspect of public blockchain networks, like Ethereum, further complicates the smart contract security issue. Once a developer deploys a contract, altering its code to deal with security flaws is incredibly challenging. What’s more, assets and funds stolen from smart contracts are next to impossible to recover. This is another adverse effect of the various networks’ immutability characteristics.
Even though conflicting figures are circulating, it is estimated that the total value of stolen assets or losses due to inadequate smart contract security far exceeds the $1 billion mark. This is a result of DAO hacks, wallet hacks, frozen wallets, etc.
The issues above are only a few examples of why developers need to invest resources toward building robust, resilient, and secure smart contracts. Smart contract security must be prioritized and considered a vital task for all Web3 developers. For this reason, we will take the following second to explore best practices for smart contract security!
Best Practices for Smart Contract Security
Smart contract technology has and will continue to transform various sectors of the economy worldwide. This includes industries such as finance, governance, the internet of things (IoT), and many more. Also, as the utilization of smart contract technology continues to grow, it is becoming increasingly important to consider smart contract security.
So, what exactly is smart contract security? To adequately answer this question, the following sub-sections will explore three fundamental best practices all developers should employ!
Smart Contract Audits
In 2023, developers need to consider smart contract security when developing dapps and other Web3 platforms. Unfortunately, developers are still ignoring this and are launching unaudited contracts on various blockchain networks.
Hiring a smart contract auditor costs money and is likely, not cheap. However, it is possible to detect flaws via a thorough auditing process, which can save resources down the line. For instance, millions in DeFi have disappeared in hacks that exploited weaknesses in poorly written smart contract code.
Good smart contract security auditors follow protocols and proven auditing processes to find flaws in a smart contract’s code. In doing so, they can spot errors that go unnoticed during development. In some instances, auditors can also help improve code by advising on optimizing and fixing smart contracts before committing them to the blockchain.
Rigorous Testing
Besides frequently performing smart contract audits, another part of the Ethereum security best practices presented in this tutorial is rigorous testing. When building smart contracts, you need to test your code repeatedly to find vulnerabilities and bugs.
Continuously testing your code is the most effective and easiest method to ensure your contracts perform as intended. One possibility is to use testnets for the various existing blockchain networks to try them in a real environment. Here are a few examples:
- Goerli
- Sepolia
- Mumbai
- The Solana testnet
If you want to utilize these networks, you need testnet tokens; to get those, you need faucets. The Moralis testnet faucet page provides a list of the best faucets for multiple networks. On that page, you can use the Mumbai faucet to get free MATIC, the Goerli faucet to get Goerli ETH, the Solana faucet to get testnet SOL, or use the Fantom testnet faucet, for example!
Add Fail-Safe Protection
When developing Ethereum smart contracts, you must always consider the risk of failure. As such, a good rule of thumb is to be prepared for as many scenarios as possible. However, no matter the amount of testing, it is impossible to cover all bugs in smart contract code. Consequently, a part of Ethereum security best practices is implementing fail-safe mechanisms.
Fail-safe mechanisms can limit the damage of malicious attacks. They are designed to trigger whenever something abnormal happens within a smart contract. Some examples can be:
- Speed Bumps – Speed bumps do not prevent attacks but slow down malicious actors, giving admins enough time to take action.
- Circuit Breakers – Circuit breakers prevent the execution of methods and functions when vulnerabilities and bugs are detected.
- Balance Limits – Balance limits restrict the total amount of tokens that can be locked in a contract.
- Rate Limits – Rate limits control how frequently a function can be called within a given timeframe.
Smart Contract Security Tools
When writing smart contract code, you can also use smart contract security tools to aid your endeavors. Down below, you can find three prominent examples of smart contract security tools:
- Mythril – This is a smart contract security tool developed by ConsenSys. Mythril helps identify smart contract vulnerabilities in Ethereum Virtual Machine (EVM) byte code.
- Octopus – Octopus is a smart contract analytical tool used to deeply understand the internal behavior of a contract’s byte code.
- Oyente – This is an audit tool for identifying common security vulnerabilities in smart contracts. Oyente consists of a validator, explorer, CGF builder, and CoreAnalysis tool.
Combining the tools above with smart contract security best practices will help you build – not only resilient Ethereum smart contracts – but robust smart contracts in general!
Moralis Streams for Smart Contract Developers
As you now know, building robust, resilient, and secure smart contracts is a vital part of blockchain programming. Once deployed, another central aspect of Web3 development is to monitor smart contract events!
All smart contracts generally emit events whenever something of importance happens within them. This can, for instance, be a transfer event whenever a token is exchanged. As you can imagine, listening to and monitoring these events play an important role in creating more compelling user experiences. So, how do you go about listening to smart contract events?
The easiest way to monitor smart contracts is with the Moralis Web3 Streams API! With this interface, you can stream data directly into the backend of your projects via Moralis webhooks. For example, you can set up a Web3 stream to monitor an Ethereum address, get webhooks when an asset is sent, received, staked, etc., or any other smart contract event fires based on your filters!
To set up your own Web3 stream, all you need to do is follow these five steps:
- Provide an address
- Set up filters and choose when to receive webhooks
- Select the chain(s) you want to monitor
- Add a webhook URL
- Receive webhooks based on your filters
Monitoring smart contract events does not have to be more challenging than that when working with Moralis. If you are further interested in creating streams, check out the official documentation page to create a stream!
Unfortunately, even listening to and monitoring a smart contract can pose security risks. Thus, in the coming section, let’s explore security best practices for Moralis and Web3 streams!
Ethereum Security Best Practices and Moralis Streams
When setting up a new Web3 stream with Moralis, you need to provide a webhook URL. This is the location where Moralis sends JSON responses through post requests. Unfortunately, as these webhook URLs are public and come from outside the Moralis ecosystem, they can pose a security risk if not handled correctly!
Without proper countermeasures, anyone with access to your webhook URL can send a post request. As a result, malicious actors can send fake JSON responses mimicking the events you are monitoring. So, how do you avoid this? To answer this question, let us start by looking closer at an example.
In preparation for this tutorial, we set up a Web3 stream listening to Ethereum transfer events with an amount greater than $50,000. If you do not know how to create a stream yourself, check out the official create a stream using the web UI documentation page before continuing.
Next, once we set up a stream, we connect it to a straightforward JavaScript parameter that listens to all the post requests sent to our webhook URL. Here is what the JavaScript code looks like:
const express = require("express"); const app = express(); const port = 3000; app.use(express.json()); app.post("/webhook", (req, res) => { const webhook = req.body; console.log(webhook); return res.status(200).json(); }); app.listen(port, () => { console.log(`Listening to streams`); });
In the example above, nothing prevents a malicious actor from sending fake JSON responses through post requests. Let’s take a look at what that might look like. In the image below, we use the Postman platform to send a post request to an ngrok-generated webhook URL:
As a result, we should get a response containing the ”value”, ”to”, and ”from” variables as parameters:
{ value: '500000000000' from: '0x79d11Bc...' to: '0xF73d13DaB...' }
As you can imagine, this becomes problematic and poses a security risk if your dapps rely on this information. So, how do you prevent this?
Adding Webhook Security
To ensure that all post requests originate from Moralis, you can add this simple webhook security function:
const verifySignature = (req, secret) => { const providedSignature = req.headers["x-signature"] if(!providedSignature) throw new Error("Signature not provided") const generatedSignature= web3.utils.sha3(JSON.stringify(req.body)+secret) if(generatedSignature !== providedSignature) throw new Error("Invalid Signature") }
The function above takes two arguments: the request itself and your Moralis API key. Once executed, the function initially verifies that the post request contains an ”x-signature”. From there, it takes the request body and your API key to generate a signature using the ”web3” package. Lastly, it compares the newly generated signature with the provided signature, ensuring they match.
For this to work with the code from the previous section, you also need to make a few configurations. First, let’s import the ”web3” and ”dotenv” libraries at the top of the file:
const dotenv = require("dotenv"); const web3 = require("web3");
Next, you need to add your Moralis API key as a variable. Displaying the key is a security risk, which is why you should create a ”.env” file and add the key as an environment variable. To get the key, sign up with Moralis, log in to the admin panel, and click on the Web3 APIs tab:
With the key at your disposal, create a new environment variable in the ”.env” file:
MORALIS_API_KEY=”replace_me”
From there, you can now use ”dotenv” to import the key safely into your code through these lines:
dotenv.config(); const apiKey = process.env.MORALIS_API_KEY;
Now, all that remains is calling the ”verifySignature()” function in your route by adding the following:
verifySignature(req, apiKey);
All in all, your complete code should now look something like this:
const express = require("express"); const app = express(); const dotenv = require("dotenv"); const web3 = require("web3"); const port = 3000; app.use(express.json()); dotenv.config(); const apiKey = process.env.MORALIS_API_KEY; app.post("/webhook", (req, res) => { verifySignature(req, apiKey); const webhook = req.body; console.log(webhook); return res.status(200).json(); }); app.listen(port, () => { console.log(`Listening to streams`); }); const verifySignature = (req, secret) => { const providedSignature = req.headers["x-signature"]; if (!providedSignature) throw new Error("Signature not provided"); const generatedSignature = web3.utils.sha3(JSON.stringify(req.body) + secret); if (generatedSignature !== providedSignature) throw new Error("Invalid Signature"); };
By adding the ”verifySignature()” function, you have ensured that only Moralis can send post requests to your webhook URL. As a result, you can now be sure that your Moralis Web3 stream only provides accurate data!
If you have any further questions, check out the official webhook security documentation page or watch the video from the Moralis YouTube channel down below:
Summary – Smart Contract Security
In this article, we explored the intricacies of smart contract security. In doing so, we started off by diving into some common smart contract security issues. From there, we took on some Ethereum smart contract security best practices. Next, we also dove into three prominent smart contract security tools. Lastly, to top things off, we introduced the Moralis Streams API and how to keep your streams safe and secure!
If you found this tutorial helpful, consider checking out more content here on the Moralis blog. For example, read our article on Web3 libraries, where we, among other things, answer the ”what is ethers.js?” question.
What’s more, if you want to get into the Web3 space and become a more proficient developer, consider enrolling in Moralis Academy! For example, check out the course on Ethereum smart contract security!
Also, if you are serious about becoming a blockchain developer, remember that you can sign up with Moralis for free! It only takes a few seconds, and you can start building projects smarter and more efficiently immediately!