Greetings, dear readers! Today we would like to start a series of articles on what we call the audit methodology. At first, we want to say that in this series we will focus only on those aspects that can be really useful for auditing and bug bounty hacking and that are not described anywhere.
❗️ Other articles in the series will be coming out at blog.pessimistic.io - hope you enjoy!
We can confidently say that such tips can be read publicly in a few places, and our blog is one of those places! Please follow us right now so you won’t miss the new article, and let’s get started!
In their work, auditors use different tools and methods — there are a lot of them. Just look at this selection and separately at this ultra-specific tool; there is no doubt that there are so many of them. According to this research, a higher degree of collaboration (e.g., for maintenance efforts) is observed among users in tools than those in the application repos, but there are some tools, that are a kind of gold standard — we will discuss them first — namely about Slither, SmartCheck and separately discuss fuzzing with Echidna.
First, a few words about our tool, SmartCheck — which can serve as a reinforcement of what we will talk about next. Even in its raw form, it shows good results, and second place in ToB’s article is not bad for a tool we stopped supporting three years ago. We’ll do a separate performance comparison of the two tools in the future. However, let’s move on to Slither.
We rely on Slither — a static analysis tool from Trail of Bits to maintain the quality of our audits. Considering the ease of use, it’s a good idea to try it out.
Besides its excellent analysis capabilities, it also includes a bunch of printers that summarize different aspects of the contract in a digestible form. One can use them to quickly build a mental contract model before diving deeply into the code.
Using printers, one can get a contract summary, check inheritance and contract storage layout, and see utilized modifiers and implemented checks. Besides, some printers can output in *.dot format, so you can see the graph properly. However, multiple printers lose their value for more complex projects since their output becomes unmanageable.
Another interesting thing is that it has a Python API that allows instrumentation of the static analysis engine. This means that the engine can be used to derive specific information from contracts automatically, and in general, can be used to suit the user’s needs. You can also explore machine learning (ML) approaches to automatically improve the performance of Slither via Slither-simil!
That’s why we get its results on all projects. Going back to what we were talking about — we want to make this article useful primarily for those who want to start a journey into Web3.o security, so below you will see a kind of list of tips with which you can achieve amazing results in your business!
❕ Important:
Very few developers strictly follow the safety standards according to this study, and it can not help but be alarming.
That’s why you must never forget about safety when you prepare your workplace — our employees clearly adhere to the rules and therefore no accidents occur.
Slither does not support some less commonly used Solidity features and may fail even on a high-quality contract. We recommend adjusting the problematic lines until the tool works correctly. Note that it might affect the output if the line numbers change. In our experience, Slither provides enough value to accept these code-style restrictions.
1. Make sure there is a python version 3.6+
python3 --version
2. Install Slither via pip:
pip3 install slither-analyzer
3. Make sure you are using the latest version of Slither before you run it. You can check the slither repository on github for release versions.
slither --version
Sometimes Slither will not update to the correct version or will not install for some reason. In this case, create a new python virtual environment and install Slither there:
set up a new environment: python3 -m venv /path/to/venv
activate the environment: source /path/to/venv/bin/activate
Then install Slither according to the instructions above. Activate the environment each time you use Slither.
Typically, we run Slither on all project files (except npm dependencies) and save the results to json, which is then converted to a csv table. To do this at the root of the project, execute:
slither . –-filter-path “node_modules” --json result.json
Other examples:
- slither .
- slither path/to/my_contract.sol
- slither . --exclude-informational
❕Important:
Slither does not run on a separate file that has development environment imports (e.g., truffle, hardhat npm module imports, or brownie pm imports). In this case, you need to manually resolve dependencies — you need to fix the imports to absolute or relative paths in the target file.
In the case of brownie package dependencies, it is worth installing the same module via npm and resolving dependencies as described above. Do not use the brownie pm clone, as it sometimes does not include some files.
You can add a slither.config.json file to filter files or exclude certain detectors. See the Slither documentation for a list of detectors or watch this good old video and this tutorial.
Run on each file separately. Most likely, the problem will not be in all files.
Find a similar problem in slither issues and apply a solution if there is one. “Upvote” is an issue (you can put an emoji on it) if it’s not solved, to get the developers to pay attention to it.
Slither Plugins
Plugins are one of the most important aspects of properly setting up and running Slither because they significantly increase the functionality. Also, keep in mind that it is the most convenient way to add your own detectors. Below are the basics of working with them. Try to understand the analogy of the work and further build your own methodology based on this.
A) Upgradeability checks plugin guide:
B) Check ERC plugin guide:
Run if you want to check the contract for compliance with one of the specified EIP:
❕ Important:
If “Contract not found: name.” — you need to rename the contract so that the name in the project is unique.
You can add a slither.config.json file to filter files or exclude certain detectors. See the slither documentation for a list of detectors.
slither-read-storage
retrieves storage slots from source code by using information from Slither’s underlying type analysis (e.g., whether an array is fixed or dynamic) to inform slot calculations. The tool can retrieve the storage slot(s) of a single variable or of entire contracts, and storage values can be retrieved by providing an Ethereum RPC.
Check out:
Additionally, one can modify storage values using the Ethereum node RPC, eth_call
, by passing in the storage slot and desired value and simulating how transactions applied to the modified state are affected. Details on how to accomplish this can be found in this tutorial.
Command example:
slither-read-storage Privacy.sol 0xFdaF948A66903a0050ed051508c7C26D137E76C4 --variable-name data --rpc-url https://rinkeby.infura.io/v3/{project-id}
If the source code is on Etherscan, you can omit the contract name (Privacy.sol).
In conclusion, we would like to say that we hope that this article was informative and useful for you! In future articles, we’ll write about how our favorite SmartCheck and Slither differ-the differences are quite significant!
The most important thing we wanted to tell you and show you is that a new instrument does not mean good and an old instrument does not mean bad. It’s all about knowing how to use it and being willing to look for something new. I hope we’ve got you interested in that.
What instruments should we review? What would you be interested in reading about? Please leave your comments, we will be happy to answer them, and the best answers and questions may be included in the next article!
By the way, there are some vacancies now so if your project needs an audit — feel free to write to us, visit our public reports page here.