In this post, we’ll go over how to setup solhint, ethlint, and, as a bonus, surya and solidity-coverage for your Solidity project. This is a basic overview of these packages’ functionality. For deeper dives, please visit the respective project repos.
First, let’s open a terminal, cd into your project repo with contracts, and install solhint and ethlint and surya all at once.
npm i -g solhint ethlint surya
To check that they are installed properly, do the following: Please pay attention to the capitalizations in these commands as they are important.
(1) Check that ethlint was installed by running:
solium -V
(2) Check that solhint was installed by running:
solhint -V
(3) Check that surya was installed by running:
surya -v
If all of these return a version of the respective package, then they have been properly installed.
Inside your Solidity project, run the following to get solhint and solium up and running:
solhint init-config
solium --init
Once this has been completed, you can run solhint and ethlint (solium) on your contracts for linting!
To do this, simply run:
solhint contracts/ExampleContract.sol
and
solium -f contracts/ExampleContract.sol
These run solhint and solium (ethlint) on your file ExampleContract.sol
.
You should see some results like this for solium:
ExampleContract.sol
22:4 warning Line contains trailing whitespace no-trailing-whitespace
29:12 error Only use indent of 8 spaces. indentation
30:12 error Only use indent of 8 spaces. indentation
31:12 error Only use indent of 8 spaces. indentation
32:12 error Only use indent of 8 spaces. indentation
33:12 error Only use indent of 8 spaces. indentation
34:0 error Only use indent of 4 spaces. indentation ....
✖ 23 errors, 25 warnings found.
You should see results like this for solhint:
ExampleContract.sol
116:2 error Line length must be no more than 120 but current length is 125 max-line-length
118:2 error Line length must be no more than 120 but current length is 124 max-line-length
131:2 error Line length must be no more than 120 but current length is 138 max-line-length
✖ 3 problems (3 errors, 0 warnings)
Now, for bonus, you can get the whole layout of your ExampleContract in an markdown report by running the following surya command:
surya mdreport example.md contracts/ExampleContract.sol
If you open the example.md in your project directory, it will display something like this:
## Sūrya's Description Report
### Files Description Table
| File Name | SHA-1 Hash |
|-------------|--------------|
| ExampleContract.sol | 91d6db4960e5f32864a40994853093479d950080 |
### Contracts Description Table
| Contract | Type | Bases | | |
|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|
| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** |
||||||
| **ERC20Interface** | Interface | |||
| └ | transfer | External ❗️ | 🛑 |NO❗️ |
| └ | transferFrom | External ❗️ | 🛑 |NO❗️ |
| └ | balanceOf | External ❗️ | |NO❗️ |
| └ | approve | External ❗️ | 🛑 |NO❗️ |
| └ | allowance | External ❗️ | |NO❗️ |
| └ | totalSupply | External ❗️ | |NO❗️ |
||||||
| **ERC20Token** | Implementation | ERC20Interface |||
| └ | <Constructor> | Public ❗️ | 🛑 |NO❗️ |
| └ | transfer | Public ❗️ | 🛑 |NO❗️ |
| └ | transferFrom | Public ❗️ | 🛑 |NO❗️ |
| └ | approve | Public ❗️ | 🛑 |NO❗️ |
| └ | allowance | Public ❗️ | |NO❗️ |
| └ | balanceOf | Public ❗️ | |NO❗️ |
| └ | totalSupply | Public ❗️ | |NO❗️ |
||||||
| **ICO** | Implementation | |||
| └ | <Constructor> | Public ❗️ | 🛑 |NO❗️ |
| └ | start | External ❗️ | 🛑 | onlyAdmin icoNotActive |
| └ | buy | External ❗️ | 💵 | icoActive |
| └ | release | External ❗️ | 🛑 | onlyAdmin icoEnded tokensNotReleased |
| └ | withdraw | External ❗️ | 🛑 | onlyAdmin icoEnded tokensReleased |
### Legend
| Symbol | Meaning |
|:--------:|-----------|
| 🛑 | Function can modify state |
| 💵 | Function is payable |
This can be useful for documenting your contracts in a README.md file. Public functions are listed with a red exclamation point to remind developers to be especially careful of these methods. Red octagons mean that the function can change a state variable. Modfiiers are listed last, i.e. “onlyAdmin”, “icoEnded”, etc.
We will now use solidity-coverage to find out how well our code is covered by tests. Best practices is to come as close to 100% as possible for smart contracts.
In order to do this, we must first install solidity-coverage and include it in our truffle-config.js file.
To install run:
npm i --save-dev solidity-coverage
Include the following in your truffle-config.js
file right after networks
:
...
plugins: ["solidity-coverage"],
...
Now, we can run the solidity-coverage by running the following Truffle command:
truffle run coverage
You will see a result such as:
------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
------------|----------|----------|----------|----------|----------------|
contracts/ | 0 | 0 | 0 | 0 | |
ExampleContract.sol | 0 | 0 | 0 | 0 |... 186,190,191 |
------------|----------|----------|----------|----------|----------------|
All files | 0 | 0 | 0 | 0 | |
------------|----------|----------|----------|----------|----------------|
For more information, please go to the /coverage folder created project directory. Inside this folder, you will find an index.html
file. Open this in your preferred web browser for details on the coverage of your contract. Marked in red will be the functions not covered by your tests. Green indicates coverage by your tests. Click into the contracts/ folder and your ExampleContract.sol to see exactly where there is coverage. In this case, we have no tests, so the file looks red.
In conclusion, you’ve learned how to use solhint, ethlint, surya, and solidity-coverage in a basic Truffle project! To dive deeper into these projects, please look at their respective repos here:
solhint
ethlint
surya
solidity-coverage
For more information on how to do this, please see the Ethereum.org tutorial here.