Intro to Solidity Linting and Formatting
A developer workflow for Solhint, Prettier-Solidity and Git Hooks
The Ethereum developer community is starting to develop some pretty awesome tools that get us closer to the automated workflow and developer “cockpit” that we have in more mature languages like Javascript or Go.
Two of those tools touch the most core part of a developer’s workflow: writing code:
- Linters automatically analyze code for possible programmatic and styling errors (popular example: ESLint for Javascript)
- Formatters automatically format code according to predefined rules and indentation defaults (popular example: gofmt for go)
This tutorial goes over one of the many ways to set them up. We cover these tools in this context of a repo using the Truffle framework, but the steps can be adapted for any framework (or none).
Part 1: Linter
Solhint and Ethlint (formerly Solium) are two fantastic community linters for the Solidity language. They’re like automatic code reviewers who flag up security errors and instills best practices across the team.
For this tutorial, we’ll focus on Solhint, though I highly recommend you take Ethlint out for a spin as well.
Solhint
First, make sure you are in the project root directory and then use NPM or Yarn to add the solhint module.
> npm install --save-dev solhint
Configuring Solhint
Initialize solhint
with a basic configuration file.
> ./node_modules/.bin/solhint init-config
This should create a ./solhint.json
file in your project’s root directory. This file specifies exactly which rules you want Solhint to lint for. Solhint has a pretty amazing coverage of Security Rules, Style Guide rules, and Best Practice rules.
One big gotcha: very few of the rules are turned on by default. After some trial and error, I found that solhint:recommended
was slightly better (vs. solhint:default
that Solhint lists in the documentation.
I’d highly recommend going through the rule lists and adding the ones you want to ./solhint.json
. I’ve personally found the security rules and best practices very useful.
Solhint ignores
Similar to .gitignore
, you can get solhint
to ignore files and folders
node_modules/
migrations/
Solhint Script
Edit your package.json
to include a new script to run Solhint.
"solhint": "./node_modules/.bin/solhint -f table contracts/**/*.sol"
The command above has a couple of things to note:
Solhint
runs on globs that match a file pattern. In the above, it runs on all**/*.sol
files in thecontracts
directory-f table
presents the findings in a table format. You can choose from other options (e.g.unix
,tap
)
Solhint in action
> npm run solhint
You’ll likely see a bunch of errors, especially indentation and styling errors. You don’t need to fix these manually! Our next tool (the formatter) will help a lot with this.
Step 2: Formatter
Prettier is a fantastic tool that automatically formats the codebase according to a predefined style guide. Just agree on the rules beforehand at the team level, and then Prettier will then autoformat everyone’s code in the same way.
Prettier-solidity is a Prettier for solidity files that works hand-in-hand with Solhint. It helps to automatically fix many of the errors that Solhint finds, especially simple ones like indentation and code style.
It’s a work in progress with an active Gitter community and has progressed very quickly in the last few months.
Installing Prettier
> npm install --save-dev prettier prettier-plugin-solidity
Configuring Prettier
You can configure Prettier using a .prettierrc
file. Most of the rules work out of the box with Solhint but you may want to add or turn off a couple of them. I’d recommend keeping it short.
You can read the Prettier documentation for more details. You can also specify files that you want to ignore in .prettierignore
.
{
"printWidth": 100,
"singleQuote": true
}
Configuring Solhint to work with Prettier
Install solhint-plugin-prettier, that allows Solhint to play nicely with Prettier-Solidity.
> npm install --save-dev solhint-plugin-prettier
Then update ./solhint.json
to add the Prettier as a plugin and a rule.
Running Prettier-Solidity
Add the prettier command to your package.json
.
The --write
flag will format and overwrite your existing files. As per the Prettier documentation, it’s a good idea to commit your code first.
"prettier:solidity": "./node_modules/.bin/prettier --write contracts/**/*.sol"
Then at the command line
> npm run prettier:solidity
Step 3: Git Hooks (optional)
In an ideal world, we’d always remember to run our linter and formatter before pushing code to our team’s codebase.
Fortunately for us, we can automate this process with Git Hooks. These are tiny scripts that always run before or after Git events like commits, pushes, or receives.
Setting up Husky
We’ll use a Husky, a very helpful npm module that takes care of the ugly internals of git hooks.
npm install --save-dev husky
Then, add a few lines to your package.json
. In the example below, we use the pre-push
hook to run our Prettier formatter.
// package.json
{
"husky": {
"hooks": {
"pre-push": "npm run prettier:solidity"
}
}
}
Your formatter now runs every time any of the developers on your team pushes to Github.