If you've ever written anything (which I'm sure you have), you know that typos happen. In the writing world, it will make you look quite silly once it's exposed. In the programming world, if mistakes like this are deployed to your software, not only will it make you look silly, but it can also leave your platform susceptible to dangerous hacks. This is where auditing comes in. However, auditors don't just check for typos, they meticulously review a codebase and its documentation to make sure there are no unexpected behaviors or side effects that result from how it was written.
Any broadly used code should always be audited before it goes live, but this rings even stronger for smart contracts. A hack on a smart contract can have an immediate financial impact on the governing organization and/or its end-users, while a website defacement hack, for example, will probably "only" lead to reputation damage for the governing organization. Additionally, due to blockchain's inherent immutability, if a smart contract is deployed with a bug, that bug stays even after it's discovered because it literally can't be changed.
Maybe you're saying ‘well, it won't happen to me, my contract is a toy / joke / totally secure / not relevant'. Maybe you don't have a budget allocated for an audit. Unfortunately, when your contract handles funds, skipping this step can prove to be exponentially more expensive in the long run.
According to an article in Bleeping Computer, Oyente found 34,200 vulnerable Ethereum smart contracts in 2016 alone. Quantstamp, a leader in the blockchain audit space, estimates that over $8B USD have been lost to vulnerabilities and exploits in smart contracts. Both the infamous DAO and Yam Finance, received a far greater investment than anticipated. $50 million USD worth of ether was stolen from The DAO and a critical bug in Yam Finance led to the crash in the value of its token. When it comes to blockchain, it's not ‘better late than never', it's often either early or never.
Slight tangent — While there are ways to introduce a certain level of upgradeability to smart contracts, that doesn't mean they're not still susceptible to the pitfalls that we will discuss here. Also, allowing upgradeability comes with its own set of dangers that could lead to a hostile takeover not unlike Devops199's ‘I accidentally killed it'.
The most recent craze on Ethereum (since I checked Twitter this morning, at least) is #DeFi. Due to the nature of many of the participants, compounded with the frenetic pace of the markets and speed of innovation, a norm of poorly-vetted protocols has emerged. Many of us have heard of the infamous Yam implosion. While it was an unfortunate turnout, it wasn't an unforeseeable one considering this quote from their announcement:
This is a very dangerous trend — Yam lost ~650K USD due to a bug in their code and imploded after less than 36 hours live. If you want to learn more about what happened, you can read the full article.
There is also a more sinister danger that can occur when communities don't demand formal audits. In the SushiSwap saga, at the peak of its valuation, its mysterious creator Chef Nomi took $14 million dollars in $SUSHI from the dev fund. Chef Nomi promptly sold it all and disappeared — effectively crashing the price for all token holders.
Due to its lack of thorough checks, nobody in the community called out that Chef Nomi could drain the dev fund of SushiSwap arbitrarily (while some community members did notice, they decided to trust him). Audits can help uncover these dirty little secrets and bring them to the forefront.
For the whole SushiSwap story, check this great writeup in The Defiant.
If you're looking at audits from a developer side, (hopefully) you don't have to worry too much about internal bad actors like Chef Nomi. However, there's a growing number of ways that external hackers might still be able to manipulate a smart contract for their use. It would be exhaustive to list them all, however, we've highlighted some common attacks that have led to the biggest downfalls in the past.
This is an overarching system's behavior that defines when events do not occur in the intended order. Many attacks on smart contracts derive from a form of race condition. These conditions become dangerous when external smart contracts are called as they may take over the flow and make changes that the calling function wasn't expecting. Both of the major bugs that led to the DAO's collapse were bugs of this sort. (The DAO hack was a major event in the more formative years of Ethereum. If you'd like to learn more about the general story, This is an article The Story of the DAO — Its History and Consequences that gives a good overview.) The specific types of race conditions will be explored more in-depth.
This a form of a race condition. A reentrancy attack can occur when a function calls external contracts before they resolve any effects. If an attacker manages to control the external contract, they can make a recursive call back to the original function. This allows the attacker to repeat interactions that would have originally not run after the effects were resolved. One of the DAO attack bugs resulted from this.
A Simple Example
If the vulnerable contract exposes a withdraw function, the attacker can recursively call the withdraw function and effectively drain the contract of all its funds. No bueno.
The key solution to preventing reentrancy is to block concurrent calls, especially external calls, from happening in certain functions. Contracts should always minimize external code or complete all internal work before calling external contracts.
For a more in-depth discussion on re-entrancy attacks, please check out this article.
Front running is another race condition that allows one user to benefit from a manipulated transaction order at the expense of another user. Since all transactions are visible in the mempool for a short while before being executed, observers of the network can see and react to an action before it is included in the block.
A Simple Example
This vulnerability could be exploited in a decentralized exchange where a buy order transaction can be seen by the attacker, and a second order can be broadcast and executed before the first transaction is included.
Smart contract audits are usually conducted by a third party or parties to ensure that the code is reviewed as thoroughly as possible. As a development agency, we always suggest our clients perform an audit with Quantstamp before deploying.
An audit will first begin with a code analysis. There are two fundamental approaches to the analysis— Manual and Automatic.
A manual code analysis is exactly what it sounds like. A dedicated team will examine each line of the code to scrutinize for the aforementioned mistakes. This approach is still the best approach and significantly more feasible when you have a large development team or use a third party.
The automatic code analysis naturally saves teams and developers significant amounts of time when checking their code. Smart contract developers can use tools like Slither and Mythril to check their code. However, while this is a good first step, developers do need to remember that this approach misses the vulnerabilities related to business logic. It only catches low-hanging fruit and it outputs a lot of false positives. An estimated 80% of findings are false positives on average, and a manual analysis is still always recommended after.
A thorough audit will then run performance tests to make sure the contract is optimized before deployment.
Validation will include checking for errors that may slow down the contract's performance and increase gas costs. The main concern is ensuring that the way in which the contract executes fulfils all the agreements that both parties have decided on.
Next, the contract will undergo fuzz testing for quality assurance. This test involves inputting a large amount of random data (fuzz) into the system to see if it will crash. Since there can be a large range of triggers when a contract is deployed to the real world, proper validation will include stress testing of these variables to make sure the smart contract can handle it.
Since gas prices charged on the Ethereum network are directly related to how computationally complex the contract is, prices will be significantly lower for a fully optimized contract. We all know how bad gas prices are right now — don't make it even worse for your contract at run time.
While companies with large development teams may be able to handle the audit internally, it is always advisable to use a dedicated third party to check your codebase. While outsourcing may be slightly pricier than working in-house, the chances of identifying vulnerabilities are exponentially higher under the eyes of unbiased experts.
To combat this, a new form of assurance is being developed. Quantstamp has led this by recently creating ChainProof - a smart contract warranty for their clients. If a client implements all the suggested adjustments, Quantstamp will stake a certain amount of funds to act as an assurance in the event of a hack. This model operates in a P2P manner also allowing interested investors to stake and potentially earn profits on secured projects.
The DeFi space often simulates the wild wild west, where anything goes and anything can happen. We're thankful for audits and innovations like these to protect our community and continue moving the industry forward in a safe manner. We're sure this is only the beginning of the advancements, and excited to see how it evolves over time.
If you're interested in building a safe smart contract of your own, please feel free to reach out to us and book a free consultation. We've guided dozens of companies and founders from ideation, development, 3rd party audit, to finally, public deployment. To learn more about us at Linum Labs, please visit our website.
To book a free consultation on your next project or chat about the wild history of DeFi attacks please set up a time with us.
Special thanks to William Schwab.