Back to Foundry

Literal instead of constant

crates/lint/docs/literal-instead-of-constant.md

1.8.11.9 KB
Original Source

Literal instead of constant

Severity: Info ID: literal-instead-of-constant

Flags literal values appearing more than once in the executable bodies of a contract.

What it does

Reports every occurrence of a number, address or hex string literal whose value appears more than once in the bodies a contract declares: functions, constructors, modifiers, receive and fallback. The modifier and base-constructor arguments of a function header are executable expressions too, so a value repeated between a header and a body counts as a repetition. Values are compared semantically, so 100, 0x64 and 1e2 are one value, and 1 ether equals 1e18; Aderyn's detector of the same name compares the source spellings instead. Out of scope: 0, 1 and 2 (structural values), bare literals indexing an array-like value, bounding a slice or giving a shift amount (positional or structural), fixed array sizes in parameter and return types (type annotations rather than executable expressions), string and bool literals, single occurrences, and repetitions split across two contracts. Mapping keys count, they are configuration data rather than positions, and so do Yul case labels, shifted literal values and literals inside a computed shift amount.

Why is this bad?

A repeated literal is a configuration value the contract never named: each copy can drift independently on the next edit, and the reader has no word for what the value means. A named constant gives it one definition and one meaning.

Example

Bad

solidity
function deposit(uint256 amount) external {
    require(amount >= 500, "too small");
    ...
}

function fee() public pure returns (uint256) {
    return 500;
}

Good

solidity
uint256 private constant MIN_DEPOSIT = 500;

function deposit(uint256 amount) external {
    require(amount >= MIN_DEPOSIT, "too small");
    ...
}

function fee() public pure returns (uint256) {
    return MIN_DEPOSIT;
}