Expand description
§Linter (lint)
Solidity linter for identifying potential errors, vulnerabilities, gas optimizations, and style guide violations. It helps enforce best practices and improve code quality within Foundry projects.
§Supported Lints
forge-lint includes rules across several categories:
- High Severity:
incorrect-shift: Warns against shift operations where operands might be in the wrong order.unchecked-call: Low-level calls should check the success return value.erc20-unchecked-transfer: ERC20transferandtransferFromcalls should check the return value.rtlo: Flags Unicode bidirectional override characters (“Trojan Source”, CVE-2021-42574) that can hide malicious code.reentrancy-unlimited-gas: Flags uncapped ETH-transferring low-level calls followed by writes to state that was read before the call.
- Medium Severity:
boolean-cst: Flags misuse of boolean constants.divide-before-multiply: Warns against performing division before multiplication in the same expression, which can cause precision loss.incorrect-erc20-interface: Flags ERC20 interfaces and implementations with non-compliant function signatures.incorrect-erc721-interface: Flags ERC721 interfaces and implementations with non-compliant function signatures.incorrect-strict-equality: Dangerous strict equality check on an externally-influenced value (ETH balance, ERC-20 balance).tx-origin: Flags use oftx.originin authorization-like predicates.uninitialized-local: Local variable is read before being explicitly initialized.unsafe-typecast: Typecasts that can truncate values should be checked.unused-return: Return value of an external call is not used.weak-prng: Flags randomness-like expressions derived from predictable on-chain values.
- Low Severity:
block-timestamp: Warns whenblock.timestampis used in a comparison, as it may be manipulated by validators.calls-loop: External calls inside loops can cause denial-of-service if a call reverts or exhausts gas.delegatecall-loop: Payable functions should not usedelegatecallinside a loop.missing-zero-check: Address parameter is used in a state write or value transfer without a zero-address check.return-bomb: External calls with a gas limit should not consume unbounded return data.
- Informational / Style Guide:
boolean-equal: Boolean comparisons to constants should be simplified.too-many-digits: Numeric literals with 5+ consecutive zeros are error-prone.pascal-case-struct: Flags for struct names not adhering toPascalCase.mixed-case-function: Flags for function names not adhering tomixedCase.mixed-case-variable: Flags for mutable variable names not adhering tomixedCase.screaming-snake-case-const: Flags forconstantvariable names not adhering toSCREAMING_SNAKE_CASE.screaming-snake-case-immutable: Flags forimmutablevariable names not adhering toSCREAMING_SNAKE_CASE.unused-import: Unused imports should be removed.unaliased-plain-import: Use named imports{A, B}or aliasimport ".." as X.named-struct-fields: Prefer initializing structs with named fields.unsafe-cheatcode: Usage of unsafe cheatcodes that can perform dangerous operations.multi-contract-file: Prefer having only one contract, interface, or library per file.interface-file-naming: Interface file names should be prefixed withI.interface-naming: Interface names should be prefixed withI.pragma-inconsistent: Flags projects whose source files declare different Solidity pragma version requirements.redundant-base-constructor-call: Flags explicit empty base-constructor arguments (e.g.is A()) when the base requires no arguments.missing-inheritance: Flags contracts that implement every external function of an interface without explicitly inheriting from it.low-level-calls: Direct use of low-level calls should be avoided.event-fields:addressand id-like (uint256/bytes32namedid/*Id) event parameters should beindexedfor efficient log filtering.
- Gas Optimizations:
asm-keccak256: Recommends using inline assembly forkeccak256for potential gas savings.cache-array-length: Recommends caching dynamic array orbyteslengths used inforloop conditions.costly-loop: Flags storage variable writes inside loops; accumulate into a local variable and write once after the loop instead.could-be-immutable: Recommends declaring constructor-only state variables asimmutable.could-be-constant: Recommends declaring never-written state variables with a compile-time-constant initializer asconstant.custom-errors: Recommends using custom errors instead of strings and plain reverts for potential gas savings.external-function:publicfunctions never called internally should be declaredexternalto avoid copying reference-type arguments into memory.unused-state-variables: State variables that are never used should be removed.var-read-using-this: Reads of state variables (or otherview/purefunctions) viathiscause an unnecessarySTATICCALL; access them directly.
- Code Size:
unwrapped-modifier-logic: Recommends wrapping modifier logic to reduce contract code size.
§Configuration
The behavior of the SolidityLinter can be customized with the following options:
| Option | Default | Description |
|---|---|---|
with_severity | None | Filters active lints by their severity (High, Med, Low, Info, Gas, CodeSize). None means all severities. |
with_lints | None | Specifies a list of SolLint instances to include. Overrides severity filter if a lint matches. |
without_lints | None | Specifies a list of SolLint instances to exclude, even if they match other criteria. |
with_description | true | Whether to include the lint’s description in the diagnostic output. |
with_json_emitter | false | If true, diagnostics are output in rustc-compatible JSON format; otherwise, human-readable text. |
§Contributing
Check out the foundry contribution guide.
Guidelines for contributing to forge lint:
§Opening an issue
- Create a short concise title describing an issue.
- Bad Title Examples
Forge lint does not work Forge lint breaks Forge lint unexpected behavior - Good Title Examples
Forge lint does not flag incorrect shift operations
- Bad Title Examples
- Fill in the issue template fields that include foundry version, platform & component info.
- Provide the code snippets showing the current & expected behaviors.
- If it’s a feature request, specify why this feature is needed.
- Besides the default label (
T-Bugfor bugs orT-featurefor features), addC-forgeandCmd-forge-fmtlabels.
§Fixing A Bug
- Specify an issue that is being addressed in the PR description.
- Add a note on the solution in the PR description.
- Add a test case to
lint/testdatathat specifically demonstrates the bug and is fixed by your changes. Ensure all tests pass.
§Developing a New Lint Rule
Check the dev docs for a full implementation guide.
Modules§
Macros§
- declare_
forge_ lint - Macro for defining lints and relevant metadata for the Solidity linter.
- register_
lints - Registers Solidity linter passes that can have both early and late variants.