All Articles

How to Setup Linters, Surya, and Test Your Code Coverage in Solidity

Introduction

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.

Let’s Get Started!

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.

Using Solhint and Solium

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

Results from Ethlint and Solhint

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)

Surya

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.

Solidity-Coverage

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.

red-coverage-solidity-example

Congratulations!

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

Extra bonus: It is best practices to include these in your CI/CD pipeline,

For more information on how to do this, please see the Ethereum.org tutorial here.

Published Jul 14, 2021

security researcher, etc.