CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-solhint

Solidity code linter providing security and style guide validations for smart contract development

Pending
Overview
Eval results
Files

rules-system.mddocs/

Rules System

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.

Capabilities

Main Rules Function

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}`);

Rule Categories

Security Rules (16 rules)

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, staticcall
  • avoid-tx-origin - Avoid using tx.origin for authorization
  • check-send-result - Check result of send() calls
  • compiler-version - Enforce specific compiler version constraints
  • func-visibility - Require explicit function visibility declarations
  • reentrancy - Detect potential reentrancy vulnerabilities
  • state-visibility - Require explicit state variable visibility

Configuration Examples:

{
  "rules": {
    "avoid-low-level-calls": "error",
    "compiler-version": ["error", "^0.8.0"],
    "func-visibility": "error", 
    "reentrancy": "warn"
  }
}

Naming Rules (13 rules)

Rules for enforcing consistent naming conventions across Solidity code.

Key Rules:

  • const-name-snakecase - Constants in SCREAMING_SNAKE_CASE
  • contract-name-capwords - Contracts, structs, enums in CapWords
  • event-name-capwords - Events in CapWords
  • func-name-mixedcase - Functions in mixedCase
  • modifier-name-mixedcase - Modifiers in mixedCase
  • var-name-mixedcase - Variables in mixedCase
  • private-vars-leading-underscore - Private variables with leading underscore

Configuration Examples:

{
  "rules": {
    "contract-name-capwords": "error",
    "func-name-mixedcase": "error",
    "var-name-mixedcase": "warn",
    "private-vars-leading-underscore": ["error", { "strict": false }]
  }
}

Best Practices Rules (15 rules)

Rules promoting good coding practices, code quality, and maintainability.

Key Rules:

  • code-complexity - Limit cyclomatic complexity
  • explicit-types - Require or forbid explicit types (uint256 vs uint)
  • function-max-lines - Limit function length
  • max-line-length - Limit line length
  • no-console - Forbid console.log statements
  • no-empty-blocks - Forbid empty code blocks
  • no-global-import - Require specific imports instead of global imports
  • no-unused-vars - Detect unused variables
  • reason-string - Require reason strings in require/revert statements

Configuration Examples:

{
  "rules": {
    "code-complexity": ["warn", 7],
    "function-max-lines": ["warn", 50],
    "max-line-length": ["warn", 120],
    "no-console": "error",
    "reason-string": ["warn", { "maxLength": 64 }]
  }
}

Order Rules (4 rules)

Rules for code organization and element ordering within contracts.

Key Rules:

  • imports-on-top - Import statements must be at file top
  • imports-order - Enforce specific import ordering
  • ordering - Enforce element ordering within contracts
  • visibility-modifier-order - Visibility modifier must come first

Configuration Examples:

{
  "rules": {
    "imports-on-top": "error",
    "ordering": "warn",
    "visibility-modifier-order": "error"
  }
}

Miscellaneous Rules (4 rules)

General utility rules for various code quality checks.

Key Rules:

  • comprehensive-interface - Ensure interface completeness
  • duplicated-imports - Prevent duplicate imports
  • import-path-check - Validate import paths
  • quotes - Enforce quote style consistency

Configuration Examples:

{
  "rules": {
    "quotes": ["warn", "double"],
    "duplicated-imports": "error"
  }
}

Deprecations Rules (1 rule)

Rules for identifying and migrating deprecated language features.

Key Rules:

  • constructor-syntax - Use new constructor keyword syntax

Gas Consumption Rules (11 rules)

Rules focused on gas optimization and efficient contract design.

Key Rules:

  • gas-calldata-parameters - Use calldata for read-only function parameters
  • gas-custom-errors - Use custom errors instead of string reasons
  • gas-indexed-events - Use indexed event parameters appropriately
  • gas-length-in-loops - Avoid repeated length calculations in loops
  • gas-struct-packing - Optimize struct field packing

Configuration Examples:

{
  "rules": {
    "gas-custom-errors": "warn",
    "gas-indexed-events": ["warn", { "maxIndexed": 3 }],
    "gas-length-in-loops": "warn"
  }
}

Rule Configuration Patterns

Severity Levels

{
  "rules": {
    "func-visibility": "error",        // Block deployment
    "max-line-length": "warn",         // Show warning
    "no-console": "off"                // Disabled
  }
}

Rules with Options

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 }]
  }
}

Built-in Rule Sets

{
  "extends": "solhint:recommended",  // Recommended rules
  // OR
  "extends": "solhint:all",         // All rules enabled
  "rules": {
    "no-console": "off"             // Override specific rules
  }
}

Rule Implementation Structure

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' }
        }
      }
    };
  }
}

Plugin System

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')
];

Rule Execution Flow

  1. Initialization: Rules are instantiated based on configuration
  2. AST Traversal: Parser visits each AST node
  3. Rule Checking: Matching rules inspect nodes and report issues
  4. Result Collection: Reporter collects all issues
  5. Output Formatting: Results are formatted for display

Rule Development

Rules can be categorized by their inspection approach:

  • AST Node Visitors: Inspect specific node types (functions, variables, etc.)
  • Token Analyzers: Examine raw token sequences
  • Source Code Processors: Analyze source text directly
  • Cross-Reference Checkers: Track relationships between code elements

Error Handling in Rules

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);
  }
}

Rule Performance

  • Rules execute during AST traversal, so efficiency matters
  • Cache expensive computations when possible
  • Avoid deep object traversals in hot paths
  • Use early returns to skip unnecessary processing

Install with Tessl CLI

npx tessl i tessl/npm-solhint

docs

cli-interface.md

configuration-management.md

core-processing.md

index.md

output-formatting.md

result-reporting.md

rules-system.md

tile.json