solidity-conventions — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited solidity-conventions (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
If the repo doesn't define its own tooling, use:
forge, cast, anvil, chisel)sort_imports = true, contract_new_lines = true, bracket_spacing = true)^6.0.0 — linting, run with --max-warnings=0 --noPosterbuild_and_test and linter jobspre-commit hook runs npm run lint:checkDefault to audited, widely-used libraries over hand-rolling your own:
AccessControl, ReentrancyGuard, UUPS/transparent proxies).When neither covers the need, search these curated lists before writing from scratch:
forge test -vvv. No Hardhat/Truffle unless the repo already uses them.test/**/*.t.sol, one contract under test per file, named <ContractOrFeature>.t.sol.function testFoo(uint256 x) public) and let forge generate random inputs. Add vm.assume(...) for invariants, bound inputs with bound(x, min, max) rather than if-guards.forge-std/StdInvariant.sol with handler contracts.forge snapshot for regression tracking when gas matters.forge coverage --report lcov in CI.Default is the strictest available. Extend solhint:all (every rule enabled) and run with --max-warnings=0 so warnings block CI.
Logic (.solhint.json):
{
"extends": "solhint:all",
"rules": {
"compiler-version": ["error", "^0.8.22"]
}
}Tests (test/.solhint.json) — minimum opt-outs for practical Foundry patterns:
{
"extends": "solhint:all",
"rules": {
"compiler-version": ["error", "^0.8.22"],
"one-contract-per-file": "off",
"no-console": "off",
"func-name-mixedcase": "off",
"reason-string": "off"
}
}Relax individual rules in-project only when you hit a real conflict — never pre-emptively.
Events are the on-chain logging primitive; they are public and permanent. Treat them as part of the contract's external API.
Transferred, RegistryUpdated, EpochAnchored), not present tense (Transfer, UpdateRegistry).indexed slot. The cap is three indexed slots per event.emit second. Reversed ordering invites reentrancy / race confusion and breaks downstream consumers that expect the event payload to reflect post-mutation state.test/ files; lint or grep for it in src/./// @inheritdoc IThing rather than restating the @notice / @dev prose inline. The interface is the single source of truth; duplicating the prose in the impl invites drift (one side gets updated, the other does not) and reviewers flag it as "documentation inconsistency". This is the convention in OpenZeppelin, Aave, Compound, and Uniswap.@inheritdoc cannot resolve, so write the prose inline.Add to package.json:
"lint:check": "yarn lint:version && yarn lint:sol-logic && yarn lint:sol-tests && forge fmt --check",
"lint:fix": "forge fmt && yarn lint:sol-tests --fix && yarn lint:sol-logic --fix",
"lint:sol-logic": "solhint -c .solhint.json 'src/**/*.sol' --max-warnings=0 --noPoster",
"lint:sol-tests": "solhint -c test/.solhint.json 'test/**/*.sol' --max-warnings=0 --noPoster",
"lint:version": "solhint --version"(Swap src/ ↔ contracts/ to match the repo's foundry.toml src =.)
NEVER use inline Solidity via `forge script --via-stdin` or heredocs.
For ad-hoc exploration:
chisel) — REPL for one-off expressions and cheatcode checks.script/, run with forge script script/Scratch.s.sol. Comment out previous blocks to keep history. Gitignored — never commit; move to a real script if the code should persist.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.