At Cryptonics, we have audited the smart contracts of 22 blockchain projects during the last 12 months. These projects included both fungible and non-fungible tokens, complex exchange protocols, prediction markets, staking systems, and smart contract-based video-games.
In the audited contracts, we discovered a total of 13 critical, 16 major, and 36 minor issues. But what do these numbers demonstrate? As much as we would like to boast, these statistics do not just highlight our auditing capabilities (we like to think they do, of course). They mainly illustrate that writing secure smart contracts is very difficult. They also show that getting an independent audit is a must for any serious blockchain-based project.
In this article, we will explain our auditing process and methodology, clear up some myths about smart contract audits, and also highlight the need to look at security beyond smart contracts.
The Auditing Process
Many projects that come to us expect an audit to consist in a simple code review by an experienced smart contract developer. However, while knowing how to develop good contracts is an important skill for any auditor, the auditing process involves a strict methodology and a well-defined process far beyond simply reviewing the code. Let’s break our process down into individual steps:
1. Source Code Lock-down
Smart contracts to be audited may be delivered to us in a number of ways: a Truffle project in a compressed archive, a link to a source code repository, or even contracts with verified source code already deployed on a test network.
The very first step we do is ensuring the integrity of the audited files can be confirmed after the audit. This means we require a way of a fingerprinting the exact source code version in our audit report. In the case of source code repositories, this is easy and simply involves taking note of the commit number. In other cases, we compute the SHA-256 hash of every file submitted to the audit.
This step is important because projects do not just use audits to verify security, they also use them to demonstrate their users that the code behaves as advertised and documented.
2. Project Familiarization Phase
Before we get into detail of the code, we familiarize ourselves with the purpose of the smart contract architecture. To this end, we ask projects to provide all the documentation they have available. At this stage, we may also have a discussion with the development team, in order for them to explain their design and architecture.
3. Preliminary Code Review
Now it’s time to delve into the code. In this important step, our auditors read through the source code, try to understand the main design decision, look at the libraries used and verify the test coverage.
At this stage, we usually already get a feel for the general quality of the design.
4. Static Code Analysis
We use a number of tools to automatically scan the contracts for certain types of vulnerabilities. Usually, projects use these types of tools themselves during development, but sometimes the automated analysis comes back with some useful finds. Of course, static code analysis has its limitations and false positives are common, which is why we analyze in detail any issue highlighted by the tools.
5. Code Quality Analysis
Next, the quality of the coding is assessed. This analysis verifies that common best security practices for smart contract programming have been followed, as well as more general software engineering guidelines, such as commenting, variable naming, code structure and layout, function visibility and avoidance of replicated code.
6. Known Vulnerability Analysis
This phase is what most people would associate with a smart contract audit. A line by line code analysis is performed against a checklist of known vulnerabilities, including:
- Variable Shadowing
- Storage Pointer Exploits
- Over- and Underflows
- Potential Denial of Service Attacks
- Block Gas Limit Issues
- Timestamp Dependencies
- Insecure Random Number Generation
- Incorrect Cryptographic Signature Validation
- Transaction Ordering Assumptions
Any issues found will be labeled critical, major and minor, according to severity.
7. Functionality Analysis
Many smart contract vulnerabilities can be found in simple programming errors that affect the functionality of the contract. We, therefore, carry out another line by line code analysis to verify the correct behavior of the code.
Often, this step involves verifying the math of the smart contracts. Common errors include rounding impression due to integer arithmetic, or errors in formulas. Another likely cause for errors is access and permission management.
8. Live Testing
The previous two steps often leave unanswered questions in terms of exploitability or correct functioning in edge cases. Depending on the complexity of the issues, we may decide to deploy the contracts on a local test network and run our own test. This may involve developing actual exploits that show how the contract can be attacked.
9. Gas Usage
After the security and functionality of the smart contracts have been confirmed, we look at their efficiency. Gas usage is analyzed, first through an automated gas estimation, and then through another line by line manual code analysis.
10. First Round Audit Report
With all the audit steps completed, a report is written and delivered to the client. The report includes all issues identified and a list of additional recommendations. An example report can be found here.
11. Review of Round One Fixes
It is rare to have an audit in which we find no issues whatsoever. For this reason, our audit process involves at least two rounds. Clients are given the chance to fix the issues identified in the first round and can submit a new version of the code. Usually, the fixing process involves several rounds of direct communication between the auditor and the client. Each fix is reviewed again to ensure it does resolve the issue and does not introduce any additional issues or unwanted side effects.
12. Final Audit Report
Once all fixes have been submitted and reviewed, we update the audit report and produce a final version, which clearly identifies the issues found, the fixes applied and the final verdict.
A Comprehensive Process
As can be seen from the above process, the auditing process follows a strict methodology. For this reason, smart contract audits take time and require resources. They should not be solicited as an afterthought, a few days before the launch date of a project.
For those clients, wishing to deal with security right from the beginning, Cryptonics also offers consulting services throughout the development process. We can guide projects through smart contract development and be involved as security advisors all the way from design through development, testing, and deployment.
Security Beyond Smart Contracts
Decentralized applications and blockchain infrastructures involve many additional layers beyond smart contracts. At the lowest level blockchain nodes have to be configured and deployed. Keys have to be generated, stored and managed. API’s are used to interact with the smart contracts, and web or mobile interfaces are access points for end-users.
While it has become custom to get at least some form of external review for smart contracts, these additional layers are mostly ignored. Cryptonics looks back on 15 years of cybersecurity experience in its parent company, S2 Grupo, and provides compressive full-stack auditing services for decentralized applications. This may include code reviews, black box testing, and white box testing.
In 2018, 1.7 billion USD were lost to digital asset theft in the blockchain industry, according to reports. As far as we know, none of these incidents were due to the breaking of the underlying cryptography, but mainly due to smart contracts vulnerabilities, application bugs, misconfigurations, and poor security policy. Most could probably have been avoided by applying best practice guidelines for cybersecurity and getting a qualified security audit.
Are you building a blockchain-based application? Contact us to speak about security or any other blockchain related topic.