How to prepare for a Security Audit
DeFi space is growing strong, TVL is growing even faster, and the stolen value from DeFi protocols.
According to DeFi Pulse, the Total Value Locked in DeFi projects is roughly $80.78B. $80.7B... That’s $15B more since I brought that number up in my article 11 days ago.
Hacks keep happening even though more projects are getting audited. For me, who audits smart contracts every day, I see how different projects approach an audit and applying the recommendation. I decided to write a guide to inform others how I see good preparation for an audit and what would make my life easier as an auditor.
Define the Scope and set a goal
Having a list of the files or functions that need to be tested is a must. There’s nothing worse when a client, after a week of auditing, updates the scope. Below is a list of things I would like to see when before I start a new audit.
- Have a well-defined and thought-out scope. List all files/functions which need to be checked.
- Create a separate branch just for audit and send the final commit hash.
- Perform a code freeze where no new functionality is added, or existing code is changed after the scope is defined.
- Don’t deploy onto mainnet and then ask for an audit without the willingness to re-deploy / upgrade smart contracts if the code is vulnerable, and there are things to improve.
- If you are willing to re-deploy / upgrade deployed smart contracts, please provide a repository and etherscan link. We, auditors, have our toolsets and like to check things locally; I know I do.
Above is still a must, but sometimes projects want to see if the changes they made introduced any vulnerabilities. In this case:
- Please provide two commit hashes for comparison
- Document the changes and list all the places the changes affect the rest of the code. It has no purpose to check only updated code without validating other places in the system the updated code affects.
Any security auditor needs to understand the design and architecture of a system before they dive deep into the client’s codebase. For a security audit, the most important thing is for clients to create clear and comprehensive documentation that explains how their systems work. All documentation should be easily readable with accurate and up-to-date information so that auditors can understand the exact intention behind the code.
You don’t always need documentation like Uniswap's has, but more often than it should, I was dealing with the uncommented code base, README file with six lines, or only a short description of what the project is all about.
- Create a comprehensive README file with the description of the project and its module.
- Technical document with an overview of the system/protocol and the intended functionalities for different system components. I can then validate if the codebase represents the documentation correctly or vice versa
- NatSpec comments. I can’t stress enough how important it is. Good comments can tell the auditor what the code aims to accomplish or potential problems it may contain.
The efficiency of the entire audit process can be affected by the quality of the code. I don’t want to deal with poorly written code and scratch my head why someone uses
tmp variable in the middle of a crucial function or when formatting of the code is all over the place.
Having a streamlined process of auditing where code quality doesn’t get into your way helps me focus entirely on finding the issues and not thinking, “why in the name of god someone did that to this code?!”.
- Enforce a Consistent Style of Code.
- Remove Dead Code and Comments, which were purely created during development—having to deal with the code parts where it was only for debugging, or functionality no longer gave me a headache.
- Don’t reinvent the wheel and use well trusted and up-to-date code dependencies, like OpenZeppelin framework.
- Please, stop using solidity version 0.4.X. Leave it where it should be, back in 2016/2017.
Perform the first round of testing
Write unit tests and integration tests. It’s not only helpful for me but also for you, the client. It helps eliminate the fundamental issues with the code and ensure mechanisms within the systems are working as intended. I don’t have much more to say apart from writing all the tests you can before sending code for an audit.
All this preparation is time-consuming, but the security of the product and the funds of your users are at stake. It’s worth it to take your time and do your diligence in preparation for an audit. It makes my life easier and yours. Remember, the end product is for users, and users' money will be compromised if anything wrong happens.
No audit will make your product 100% secure and audits are no silver bullets. It only helps you make a comprehensive sanity check of the quality of your code.