Giter VIP home page Giter VIP logo

solhint's Introduction

By Protofire

Donate with Ethereum NPM version Coverage Status MIT licensed

This is an open source project for linting Solidity code. This project provides both Security and Style Guide validations.
VISIT OUR WEBSITE
JOIN OUR DISCORD SERVER

Installation

You can install Solhint using npm:

npm install -g solhint

# verify that it was installed correctly
solhint --version

Usage

First initialize a configuration file, if you don't have one:

solhint --init

This will create a .solhint.json file with the default rules enabled. Then run Solhint with one or more Globs as arguments. For example, to lint all files inside contracts directory, you can do:

solhint 'contracts/**/*.sol'

To lint a single file:

solhint contracts/MyToken.sol

Run solhint without arguments to get more information:

Usage: solhint [options] <file> [...other_files]

Linter for Solidity programming language

Options:

  -V, --version                           output the version number
  -f, --formatter [name]                  report formatter name (stylish, table, tap, unix, json, compact, sarif)
  -w, --max-warnings [maxWarningsNumber]  number of allowed warnings
  -c, --config [file_name]                file to use as your .solhint.json
  -q, --quiet                             report errors only - default: false
  --ignore-path [file_name]               file to use as your .solhintignore
  --fix                                   automatically fix problems and show report
  --noPrompt                              do not suggest to backup files when any `fix` option is selected
  --init                                  create configuration file for solhint
  --disc                                  do not check for solhint updates
  --save                                  save report to file on current folder
  -h, --help                              output usage information

Commands:

  stdin [options]                         linting of source code data provided to STDIN
  list-rules                              display covered rules of current .solhint.json

Notes

  • Solhint checks if there are newer versions. The --disc option avoids that check.
  • --save option will create a file named as YYYYMMDDHHMMSS_solhintReport.txt on current folder with default or specified format

Fix

This option currently works on:

  • avoid-throw
  • avoid-sha3
  • no-console
  • explicit-types
  • private-vars-underscore
  • payable-fallback
  • quotes
  • contract-name-camelcase
  • avoid-suicide



Configuration

You can use a .solhint.json file to configure Solhint for the whole project.

To generate a new sample .solhint.json file in current folder you can do:

solhint --init 

This file has the following format:

Default

{
  "extends": "solhint:default"
}

Note

The solhint:default configuration contains only two rules: max-line-length & no-console

Sample

  {
    "extends": "solhint:recommended",
    "plugins": [],
    "rules": {
      "avoid-suicide": "error",
      "avoid-sha3": "warn"
    }
  }

A full list of all supported rules can be found here.

To ignore files that do not require validation you can use a .solhintignore file. It supports rules in the .gitignore format.

node_modules/
additional-tests.sol

Extendable rulesets

The default rulesets provided by solhint are the following:

  • solhint:default
  • solhint:recommended

Use one of these as the value for the "extends" property in your configuration file.

Configure the linter with comments

You can use comments in the source code to configure solhint in a given line or file.

For example, to disable all validations in the line following a comment:

  // solhint-disable-next-line
  uint[] a;

You can disable specific rules on a given line. For example:

  // solhint-disable-next-line not-rely-on-time, not-rely-on-block-hash
  uint pseudoRand = uint(keccak256(abi.encodePacked(now, blockhash(block.number))));

Disable validation on current line:

  uint pseudoRand = uint(keccak256(abi.encodePacked(now, blockhash(block.number)))); // solhint-disable-line

Disable specific rules on current line:

   uint pseudoRand = uint(keccak256(abi.encodePacked(now, blockhash(block.number)))); // solhint-disable-line not-rely-on-time, not-rely-on-block-hash

You can disable a rule for a group of lines:

  /* solhint-disable avoid-tx-origin */
  function transferTo(address to, uint amount) public {
    require(tx.origin == owner);
    to.call.value(amount)();
  }
  /* solhint-enable avoid-tx-origin */

Or disable all validations for a group of lines:

  /* solhint-disable */
  function transferTo(address to, uint amount) public {
    require(tx.origin == owner);
    to.call.value(amount)();
  }
  /* solhint-enable */

Rules

Security Rules

Full list with all supported Security Rules

Style Guide Rules

Full list with all supported Style Guide Rules

Best Practices Rules

Full list with all supported Best Practices Rules

Docker

Solhint has an official Docker Image

Go to docker folder and follow this instructions.

Documentation

Related documentation you may find here.

IDE Integrations

Table of Contents

  • Roadmap: The core project's roadmap - what the core team is looking to work on in the near future.
  • Contributing: The core Solhint team ❤️ contributions. This describes how you can contribute to the Solhint Project.
  • Shareable configs: How to create and share your own configurations.
  • Writing plugins: How to extend Solhint with your own rules.

Plugins

Who uses Solhint?

OpenZeppelin POA Network - Public EVM Sidechain 0x GNOSIS

Projects

Acknowledgements

The Solidity parser used is @solidity-parser/parser.

Licence

MIT

Back us

Solhint is free to use and open-sourced. If you value our effort and feel like helping us to keep pushing this tool forward, you can send us a small donation. We'll highly appreciate it :)

Donate with Ethereum

Related projects

  • eth-cli: CLI swiss army knife for Ethereum developers.

solhint's People

Contributors

0xvolosnikov avatar akersof avatar cruzdanilo avatar dbale-altoros avatar dependabot[bot] avatar eshaan7 avatar fernandomg avatar fiction-code avatar florblue avatar fqlx avatar fvictorio avatar habdelra avatar hackartists avatar idrabenia avatar juanpcapurro avatar kaypee90 avatar kevsul avatar llllvvuu avatar mariano-aguero avatar maurelian avatar mgarciap avatar nventuro avatar pablofullana avatar paulrberg avatar pcowgill avatar pycckuu avatar think-in-universe avatar touhonoob avatar unjapones avatar zouguangxian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

solhint's Issues

func-order confused by modifiers and constructors.

Running solhint over this contract

pragma solidity ^0.4.18;


contract TestThing {

    modifier validSender() {
        require(msg.sender != 0x0);
        _;
    }

    function statusIsOkay() external view returns(bool) {
        return true;
    }

    function TestThing() public validSender() {
        // does something
    }
}

gives error

11:5  error    Function order is incorrect, external constant function can not go after  function  func-order

what does two-lines-top-level-separator mean?

Thanks for creating this. Very helpful.

I couldn't find this in the style guide:

two-lines-top-level-separator | Definition must be surrounded with two blank line indent

What does this mean?

Add option to force storage type to be explicit

It would be nice if I could specify an option that enforced explicit declaration of storage type.

For example

function something(string foo) public { ... }

should specify a storage type of memory or storage for the parameter foo.

The `byte` keyword is not recognized as a keyword in inline assembly.

0.1.7

The byte keyword is not recognized as a keyword in inline assembly.

    function toByte(uint addr, uint8 index) internal pure returns (byte b) {
        require(index < 32);
        uint8 n;
        assembly {
            n := byte(index, mload(addr))
        }
        b = byte(n);
    }

line 102:17 mismatched input 'byte' expecting {'return', 'address', DecimalNumber, HexNumber, HexLiteral, Identifier, 'byte', StringLiteral}

Additionally, I know this was the problem because when commenting the asm section out, the linting worked (in fact i got a warning that 'addr' was never used).

no-empty-blocks should not run on default-functions

When a default-function is used, its common to not do anything in the function itself.

    function() public payable {
        // got money
    }

Solhint currently gives the warning Code contains empty block no-empty-blocks.

[Bug] Unable to satisfy indentation rules for functions with multiple return values

I have a particular line in our contract that is unable to pass the linters indentation rules:

(bytes32 r, bytes32 s, uint8 v) = SomeLibrary.splitSignature(signature);

Error:

Expected indentation of 12 spaces, but found 13 [indent]

If you remove a space from before the first bracket, it replaces 13 with 11 in the error message. Seems to be an issue with any function that has multiple return values.

Scientific notation is not supported

solhint ./contracts/Test.sol for next contract

pragma solidity ^0.4.18;


contract Test {
    uint256 constant public MAX_POSSIBLE_AMOUNT = 1e9 ether;
}


//Works
contract Test2 {
    uint256 constant public MAX_POSSIBLE_AMOUNT = 1000000000 ether;
}

returns:

line 5:51 missing ';' at 'e9'
line 5:54 mismatched input 'ether' expecting {'from', 'constant', 'public', 'internal', 'private', Identifier}

./contracts/Test.sol
1:17 warning Compiler version must be fixed compiler-fixed
5:52 error Expected indentation of 4 spaces but found 51 indent
5:52 warning Explicitly mark visibility of state state-visibility

✖ 3 problems (1 error, 2 warnings)

Expected:
No errors for Test contract

Add gcc format

I tried to integrate solhint with Ale (a lint engine for vim that takes advantage of vim 8 async features), but I wasn't able to do it because none of the formatters is supported by Ale, at least right now. There is support for the unix format, but it can't tell warnings from errors.

Adding a gcc formatter to solhint seems to me like the easiest way to do it.

import library from node_module

I'm trying to use import "zeppelin-solidity/contracts/token/ERC20/MintableToken.sol";
but solhint is giving me an error because it can't find the file. How can I indicate a folder for libraries ?
Using a fully relative path works but is quite ugly

Switch from Blacklisting to Rulesets + Whitelisting

Blacklisting is quite a tricky and tedious process. Requires many iterations and isn't straightforward at all.
Proposal is to evaluate switching this approach in favor of Rulesets + Whitelisting. Guess it that this will make Solhint setup simpler and more intuitive.

Support latest version solc

Actually solhint doesnt support:

  • event emit : emit eventName()
  • constructor keyword in place of function name equal to contract name

Support of stateMutability keywords (pure, view, etc.)

Version 1.1.6, (according to package.json file, but solhint --version says 1.1.5)

Using pure or other state mutability keywords is currently not supported by the linter, but it is supported by the compiler.

Using pure will result in a line like the following:

line 15:55 extraneous input 'pure' expecting {';', '{', 'returns'}

Eventually, the line numbers in errors/warnings and other things will be jumbled and will not work properly. Replacing pure with constant will remove the error.

Plugins support

This may require a lot of changes, but allowing Solhint to be pluggable will bring nothing but great potential to the table.

Just a few things, off the top of my head, to be defined:

  1. Configuration. How Solhint will be configured to run plugins.
  2. Execution model. Standard API to be implemented by each plugin.

Comments should not be counted in the function-max-lines rule

May I suggest ignoring comments when counting the number of lines in a function to check whether it exceeds function-max-lines?

i.e. the following should only count as 2 lines of code:

uint foo = 0; // comment
// comment
Event(bar);

This will prevent solhint from giving function-max-lines errors for functions which exceed 50 lines but are mainly comprised of comments. IMO, it's good practice to comment smart contract code and this shouldn't be penalised by the tool. Thanks!

Disable rules using "off" instead of "false"

In order to make solhint more compatible with eslint, we should allow disabling rules using the value "off" instead of using false. We can make this change backward-compatible and, ideally, show a deprecated message for configurations that use false.

func-order error always shown for external functions

I always get Function order is incorrect, external constant function can not go after function. (func-order) solhint error for external functions.

(using solhint in Atom)

pragma solidity 0.4.18;


contract SolhinTest {
    function get() external view returns (uint ct) { // solhint error: func-order on this line
        return 1;
    }
}

Addition of emit keyword when logging an event

Solidity 0.4.20+ now recommends using 'emit' keyword to creating an event. e.g.
emit Transfer(msg.sender, _to, _tokens);

This creates 2 issues in solhint:

  • Parsing produces something like line 26:21 mismatched input '(' expecting {';', '='}
  • Indentation message 26:22 error Expected indentation of 8 spaces but found 21 indent

Use solidity-parser-antlr?

Not sure if there was a licensing issue (solidity-parser-antlr is GPL, which would force this project to be GPL?) or something, but a quick look over a diff of the antlr grammars in this package and solidity-parser-antlr make it seem like the differences are trivial, and hence unnecessary to maintain two copies.

The only non-trivial differences seem to be a few extra rules here for some assembly items, namely subAssembly, datasize, and linkerSymbol and one potentially wrong rule for expression (AFAIK you can only use an identifier after a .).

Add 'How to Contribute' section

Add 'How to Contribute' section to README file, covering:

  • Contributing process: Fork, branch, commit, PR and so on.
  • Adding new rules.
  • (optional?) Supporting new output formats.

[Feature Request] Watch mode

Hello, It would be nice to have the option "--watch" or a kind of watch mode, where you can see errors and problems in real time.

Thanks in advance

improvement: warn/err on missing and unnecessary semicolons

common mistakes I make when copy-paste:

/* Calling set() works fine on javascriptVM, fails on testrpc/ganache-cli 6.0.3 */
pragma solidity ^0.4.18;

contract Test {

  uint public counter = 1;
  
  function set() public  {
      counter = 0 // missing a semicolon
  }; // having an unnecessary semicolon
  
}

would be great to show warnings/errors

Solhint is not installed exception

Exception
I am getting the following exception if anyone can help me out.
"Solhint is not installed: For correct run of Solidity Solhint Plugin you need to install Solhint."

Installed
I have the latest NodeJs installed.
I also have Solidity and Solhint (1.1.8) installed via Browse Repository

OS
Operating System: Windows 10 x64
IDE: IntelliJ

In addition, how do you get started once you have all package installed? What is the run command?

no-simple-event-func-name should have an exception of ERC20 token

ERC 20 is a standard. Unfortunately, they named their Transfer event the same as their transfer function.

You're correct in marking this as a warning if no-simple-event-func-name is being checked, but I think it's a bad idea to do so.

A nieve programmer may change that event name to something else, only to silence the linter, but this will make the token contract non-compliant. In order to remove the warning, the programmer must create an incompatible client.

I would make an exception and not report a warning if the smart contract is an ERC20 token (which may be impossible, but in that case simply don't warn for the Transfer(address indexed, address indexed, uint256) event.

no-simple-event-func-name rule is not case sensitive

I am not sure if this is a bug or a feature but the no-simple-event-func-name rule does not see a difference between a function called claimSatisfied and an event ClaimSatisfied.

Is that rule supposed to be case insensitive?

Error message appears when running files through remote-atom

I'm getting an error message when editing files that are in certain directories:

[Linter] Error running Solhint
See console for more info

...(console)...

C:\Users\patri\.atom\packages\linter\lib\linter-registry.js:177 [Linter] Error running Solhint Error: Invalid or no `directory` provided
    at Object.validateFind (C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\helpers.js:92:11)
    at Object.<anonymous> (C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\index.js:67:13)
    at Generator.next (<anonymous>)
    at step (C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\index.js:145:191)
    at C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\index.js:145:437
    at Object.<anonymous> (C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\index.js:145:99)
    at Object.findCachedAsync (C:\Users\patri\.atom\packages\atom-solidity-linter\node_modules\atom-linter\lib\index.js:86:18)
    at file:///C:/Users/patri/.atom/packages/atom-solidity-linter/lib/helpers.js:15:45
    at Generator.next (<anonymous>)
    at step (file:///C:/Users/patri/.atom/packages/atom-solidity-linter/lib/helpers.js:49:2)

For example, by default, remote-atom creates files in Windows 10 at AppData/Local/Temp. If I move the exact same file to these directories:

AppData/Local
AppData
OneDrive/Documents
(or my home dir)

it doesn't work. However, if I move it to $HOME/OneDrive/Documents/solidity I no longer get those error message. File permissions are exact same, moving the exact same file. I thought maybe it was remote-atom but it seems to happen regardless of whether remote-atom creates a file or I move one.

[Feature request] Add max-warnings option

Add --max-warnings [int] option in formatter option: Number of warnings to trigger nonzero exit code.

Number of warnings to trigger nonzero exit code - default: -1

The motivation comes from an option that EsLint CLI offers, and continue tha idea of issue #5.

[Feature Request] Fix option

Hello, It would be interesting to have the option "--fix" to solve some existing warnings, for example with spaces, quotes, tabs, etc.

This feature would be very helpful

Becoming ESLint-like

Just to get the discussion rolling, I was wondering if it might make sense to conform to some of ESLint's CLI and options given how this project uses a lot of the great ideas that have come out of ESLint.

Some ideas (that may be better as separate issues if agreed upon):

  • Change solhint.json to solhintrc.json (we could use cosmiconfig for this)
  • Change init-config to --init
  • Add support for using 0, 1, and 2 as severity levels (or state that you can only use "off", "warn", "error") (see also #43)
  • Add --quiet to only report errors
  • Add support for a .ignores-type file
  • Add support for custom rulesets, and inheriting from them
  • Add support for custom plugins, and moving the security rules into a solhint-plugin-security-type package

A lot of these features are either present or coming via solium@1, but I don't see much of a point in having both when solhint seems like a cleaner implementation already using antlr4.

small bug with not-rely-on-time

If you have a function like this

function doThing(uint someTimeInDays) public {
    expiry[msg.sender] = now + timelockPeriod days;
}

you get a warning

warning  Avoid to make time-based decisions in your business logic  not-rely-on-time

But if you add // solhint-disable-line not-rely-on-time, i.e.

function doThing(uint someTimeInDays) public {
    expiry[msg.sender] = now + timelockPeriod days; // solhint-disable-line not-rely-on-time
}

you get

extraneous input 'days' expecting ';'

Likewise if you use // solhint-disable-next-line not-rely-on-time, or even if you start the file with

/* solhint-disable not-rely-on-time */

The same error appears.

Similarly if you add

"not-rely-on-time": false,

to the rules in .solhint.json you get this error as well.

This appears to be a bug in comment-directive-parser.js but I am not familiar enough with the code to see where.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.