🛠️ We're partnering with Alchemy to bring you a free Ethereum Developer Bootcamp! Get started here 🛠️
Unlike most use cases of more traditional programming languages, Solidity contracts tend to transfer substantial amounts of value as one of their core functions, and as a result are exposed to a variety of high-risk attacks from attackers seeking to drain funds from these immutable actors.
As a result, it’s highly recommended that developers audit or hire an auditing agency prior to launching smart contracts to the mainnet - once it’s been published, it can be very difficult to retroactively fix security vulnerabilities!
The types of potential vulnerabilities, and ways in which these attacks can be executed, are an entire course by itself. Let’s do a quick overview of major vulnerabilities so you’ll have an idea of what to keep an eye out for:
This type of attack is both extremely dangerous, allowing a vulnerable smart contract to be drained of all its ether, and extremely easy to accidentally commit. Reentrancy attacks occur because of two critical features of Solidity:
Therefore, when a vulnerable contract A makes an external call to another untrusted contract B, it’s possible that the other contract B can be maliciously changed to make a recursive call back to the original contract A. If the call from contract A to B involves sending any amount of Ether, this infinite loop can effectively drain contract A of all its resources before the function finishes.
Here’s a simple example:
Typically, the msg.sender is a regular user, such as a Metamask account. In this case, the withdraw() function will simply withdraw some money, update the balances, and conclude. However, if the msg.sender is a malicious contract B, when contract A runs msg.sender.call, contract B can be set up such that it will immediately call contract A again. In that situation, the withdraw() function will be repeatedly called until contract A has no resources or the EVM stack fills up. Pretty dangerous, right?
For some examples on how to prevent this, take a look at this article here.
Interestingly enough, smart contracts and transactions become fully public not when they’re confirmed on the blockchain, but the second that you submit them to the network as a pending transaction. These pending transactions are shared throughout the network in the mempools of Ethereum nodes, allowing the miner of a block to select the transactions with the highest gas fees.
One side effect of this design is that the intended outcome of a smart contract is visible to all for a period of time before it’s confirmed into the blockchain. Say you have a smart contract that when run, will execute an arbitrage that will earn you 1 ETH, and that costs 0.05 ETH to deploy. Malicious actors watching the mempool may see this transaction, recognize the opportunity, and copy your smart contract, submitting it with a gas fee of 0.06 ETH. Then, they’ve successfully “front-run” your contract, stealing your arbitrage opportunity by submitting their transaction first.
In practice, these attacks are often carried out by the miners themselves, resulting in a phenomenon known as MEV (miner extractable value) that is worth thousands of ETH on a daily basis. Unfortunately, they’re fairly difficult to avoid, but a variety of cutting-edge practices are described in this article here.
This is a common attack in many programming languages! Here’s the general gist of how this type of attack might happen in Solidity:
As you can see, this hack is easily exploitable for any smart contract that internally tracks address balances. To avoid this, simply make sure you’re using a 0.8 version of the Solidity compiler, which automatically checks for overflows and underflows.
Unfortunately, dozens of other major exploits. As many developers have said, “It takes a week to learn Solidity, and three years to avoid writing critical vulnerabilities on a regular basis”.
It’s sufficient to recognize that it’s highly likely you’ll end up with security issues on any moderately-complicated smart contract that you write, and that if you plan on storing any significant value in the contract you should absolutely have the code audited by a professional agency.