Solidity code linter providing security and style guide validations for smart contract development
—
Comprehensive rule system with 64+ rules across 7 categories for security, style, and best practices validation. The rules system is the core of Solhint's linting capabilities, providing extensive validation of Solidity code.
Creates and returns array of enabled rule checkers based on configuration.
/**
* Creates and returns array of enabled rule checkers
* @param {Reporter} reporter - Reporter instance for collecting issues
* @param {Object} configVals - Configuration values
* @param {string} inputSrc - Source code being linted
* @param {Array} tokens - Parsed tokens
* @param {string} fileName - File name being processed
* @returns {Array} Array of enabled rule checker instances
*/
function checkers(reporter, configVals, inputSrc, tokens, fileName);Usage Examples:
const checkers = require('solhint/lib/rules/index');
const Reporter = require('solhint/lib/reporter');
// Create rule checkers (typically done internally)
const reporter = new Reporter([], {});
const config = { rules: { 'func-visibility': 'error' } };
const ruleCheckers = checkers(reporter, config, sourceCode, tokens, 'test.sol');
console.log(`Enabled rules: ${ruleCheckers.length}`);Rules focused on identifying potential security vulnerabilities and unsafe patterns.
Key Rules:
avoid-call-value - Avoid using .call.value()()avoid-low-level-calls - Avoid low-level calls like call, delegatecall, staticcallavoid-tx-origin - Avoid using tx.origin for authorizationcheck-send-result - Check result of send() callscompiler-version - Enforce specific compiler version constraintsfunc-visibility - Require explicit function visibility declarationsreentrancy - Detect potential reentrancy vulnerabilitiesstate-visibility - Require explicit state variable visibilityConfiguration Examples:
{
"rules": {
"avoid-low-level-calls": "error",
"compiler-version": ["error", "^0.8.0"],
"func-visibility": "error",
"reentrancy": "warn"
}
}Rules for enforcing consistent naming conventions across Solidity code.
Key Rules:
const-name-snakecase - Constants in SCREAMING_SNAKE_CASEcontract-name-capwords - Contracts, structs, enums in CapWordsevent-name-capwords - Events in CapWordsfunc-name-mixedcase - Functions in mixedCasemodifier-name-mixedcase - Modifiers in mixedCasevar-name-mixedcase - Variables in mixedCaseprivate-vars-leading-underscore - Private variables with leading underscoreConfiguration Examples:
{
"rules": {
"contract-name-capwords": "error",
"func-name-mixedcase": "error",
"var-name-mixedcase": "warn",
"private-vars-leading-underscore": ["error", { "strict": false }]
}
}Rules promoting good coding practices, code quality, and maintainability.
Key Rules:
code-complexity - Limit cyclomatic complexityexplicit-types - Require or forbid explicit types (uint256 vs uint)function-max-lines - Limit function lengthmax-line-length - Limit line lengthno-console - Forbid console.log statementsno-empty-blocks - Forbid empty code blocksno-global-import - Require specific imports instead of global importsno-unused-vars - Detect unused variablesreason-string - Require reason strings in require/revert statementsConfiguration Examples:
{
"rules": {
"code-complexity": ["warn", 7],
"function-max-lines": ["warn", 50],
"max-line-length": ["warn", 120],
"no-console": "error",
"reason-string": ["warn", { "maxLength": 64 }]
}
}Rules for code organization and element ordering within contracts.
Key Rules:
imports-on-top - Import statements must be at file topimports-order - Enforce specific import orderingordering - Enforce element ordering within contractsvisibility-modifier-order - Visibility modifier must come firstConfiguration Examples:
{
"rules": {
"imports-on-top": "error",
"ordering": "warn",
"visibility-modifier-order": "error"
}
}General utility rules for various code quality checks.
Key Rules:
comprehensive-interface - Ensure interface completenessduplicated-imports - Prevent duplicate importsimport-path-check - Validate import pathsquotes - Enforce quote style consistencyConfiguration Examples:
{
"rules": {
"quotes": ["warn", "double"],
"duplicated-imports": "error"
}
}Rules for identifying and migrating deprecated language features.
Key Rules:
constructor-syntax - Use new constructor keyword syntaxRules focused on gas optimization and efficient contract design.
Key Rules:
gas-calldata-parameters - Use calldata for read-only function parametersgas-custom-errors - Use custom errors instead of string reasonsgas-indexed-events - Use indexed event parameters appropriatelygas-length-in-loops - Avoid repeated length calculations in loopsgas-struct-packing - Optimize struct field packingConfiguration Examples:
{
"rules": {
"gas-custom-errors": "warn",
"gas-indexed-events": ["warn", { "maxIndexed": 3 }],
"gas-length-in-loops": "warn"
}
}{
"rules": {
"func-visibility": "error", // Block deployment
"max-line-length": "warn", // Show warning
"no-console": "off" // Disabled
}
}Many rules accept configuration options:
{
"rules": {
"compiler-version": ["error", "^0.8.0"],
"code-complexity": ["warn", 10],
"max-line-length": ["warn", 120],
"gas-indexed-events": ["warn", { "maxIndexed": 3 }],
"private-vars-leading-underscore": ["error", { "strict": true }]
}
}{
"extends": "solhint:recommended", // Recommended rules
// OR
"extends": "solhint:all", // All rules enabled
"rules": {
"no-console": "off" // Override specific rules
}
}Each rule follows a consistent pattern:
class RuleChecker {
constructor(reporter, config) {
this.reporter = reporter;
this.config = config;
this.ruleId = 'rule-name';
}
// Visit AST nodes
visitFunctionDefinition(node) {
// Check rule conditions
if (violatesRule(node)) {
this.reporter.error(node, this.ruleId, 'Error message');
}
}
}Rule Metadata:
class RuleChecker {
static get meta() {
return {
type: 'best-practices',
docs: {
description: 'Rule description',
category: 'Best Practices'
},
schema: {
type: 'object',
properties: {
maxLength: { type: 'integer' }
}
}
};
}
}Solhint supports external rule plugins:
{
"plugins": ["prettier", "security"],
"rules": {
"prettier/prettier": "error",
"security/no-hardcoded-secrets": "warn"
}
}Plugin Structure:
// solhint-plugin-security/index.js
module.exports = [
require('./rules/no-hardcoded-secrets'),
require('./rules/safe-math-usage')
];Rules can be categorized by their inspection approach:
Rules should handle edge cases gracefully:
visitFunctionDefinition(node) {
try {
// Rule logic
if (node.body && node.body.statements) {
// Process statements
}
} catch (error) {
// Log but don't crash
console.warn(`Rule ${this.ruleId} failed:`, error.message);
}
}Install with Tessl CLI
npx tessl i tessl/npm-solhint