Skip to main content

forge_guard/security/
checks.rs

1//! Security check definitions — all vulnerability types organized by severity.
2
3/// Metadata for a single security check.
4pub struct SecurityCheckMeta {
5    pub id: &'static str,
6    pub name: &'static str,
7    pub severity: &'static str,
8    pub description: &'static str,
9    pub details: &'static str,
10    pub remediation: &'static str,
11    pub category: &'static str,
12    pub blocks_deployment: bool,
13}
14
15// ─────────────────────────────────────────────────────────────────
16// HIGH severity checks
17// ─────────────────────────────────────────────────────────────────
18
19pub const REENTRANCY: SecurityCheckMeta = SecurityCheckMeta {
20    id: "FA-H-001",
21    name: "Reentrancy",
22    severity: "high",
23    description: "Detects reentrancy vulnerabilities where external calls can recurse into the contract",
24    details: "Functions that make external calls after state changes can be re-entered, allowing attackers to drain funds or manipulate state. Common in withdraw patterns without checks-effects-interactions.",
25    remediation: "Follow checks-effects-interactions pattern. Use ReentrancyGuard from OpenZeppelin. Always update state before making external calls.",
26    category: "Access Control",
27    blocks_deployment: true,
28};
29
30pub const ACCESS_CONTROL: SecurityCheckMeta = SecurityCheckMeta {
31    id: "FA-H-002",
32    name: "Access Control",
33    severity: "high",
34    description: "Detects missing or incorrect access control modifiers",
35    details: "Functions that perform privileged operations without proper access control can be called by anyone. Common issues: missing onlyOwner, incorrect modifier checks, public init functions.",
36    remediation: "Use OpenZeppelin's Ownable or AccessControl. Ensure all privileged functions have proper modifiers. Avoid using tx.origin for authorization.",
37    category: "Access Control",
38    blocks_deployment: true,
39};
40
41pub const DELEGATECALL: SecurityCheckMeta = SecurityCheckMeta {
42    id: "FA-H-003",
43    name: "Delegatecall",
44    severity: "high",
45    description: "Detects unsafe delegatecall usage that can lead to storage corruption or code execution",
46    details: "delegatecall executes code from another contract in the caller's context. Unsafe patterns can lead to storage collisions, unexpected state changes, or malicious code execution in proxy patterns.",
47    remediation: "Validate delegatecall targets. Use a whitelist of allowed implementations. Check storage layout compatibility between proxy and implementation contracts.",
48    category: "Access Control",
49    blocks_deployment: true,
50};
51
52pub const TX_ORIGIN: SecurityCheckMeta = SecurityCheckMeta {
53    id: "FA-H-004",
54    name: "tx.origin Usage",
55    severity: "high",
56    description: "Detects tx.origin usage for authentication which is vulnerable to phishing",
57    details: "Using tx.origin for authorization allows intermediary contracts to impersonate the original caller. This can lead to phishing attacks where users lose funds.",
58    remediation: "Use msg.sender instead of tx.origin for authorization. tx.origin should only be used in very specific cases where you need the original external account.",
59    category: "Access Control",
60    blocks_deployment: true,
61};
62
63pub const CREATE2: SecurityCheckMeta = SecurityCheckMeta {
64    id: "FA-H-005",
65    name: "CREATE2 Vulnerabilities",
66    severity: "high",
67    description: "Detects issues with CREATE2 deterministic address deployment",
68    details: "CREATE2 allows deterministic contract addresses but can lead to address squatting, selfdestruct-recreate attacks, and unexpected contract replacement.",
69    remediation: "Use CREATE2 with salt derived from deployer-specific data. Consider adding deployment timeouts. Verify expected contract code at the computed address.",
70    category: "Deployment",
71    blocks_deployment: true,
72};
73
74pub const DOS: SecurityCheckMeta = SecurityCheckMeta {
75    id: "FA-H-006",
76    name: "Denial of Service",
77    severity: "high",
78    description: "Detects patterns that can lead to denial of service",
79    details: "Loops over dynamic arrays, unbounded gas consumption, reverting on expected external calls, and reliance on specific gas amounts can all be exploited to DoS the contract.",
80    remediation: "Use pull-over-push patterns for payments. Avoid iterating over dynamic arrays. Design for failure. Set reasonable gas limits for external calls.",
81    category: "Logic",
82    blocks_deployment: true,
83};
84
85pub const STORAGE_COLLISION: SecurityCheckMeta = SecurityCheckMeta {
86    id: "FA-H-007",
87    name: "Storage Collision",
88    severity: "high",
89    description: "Detects storage layout collisions in upgradeable contracts",
90    details: "In proxy patterns, changing the storage layout between implementations can cause variable collisions, corrupting contract state and potentially leading to loss of funds.",
91    remediation: "Maintain storage layout compatibility. Always append new variables. Use OpenZeppelin's upgradeable contracts plugin. Never reorder or delete existing state variables.",
92    category: "Upgradeability",
93    blocks_deployment: true,
94};
95
96pub const UNSAFE_ASSEMBLY: SecurityCheckMeta = SecurityCheckMeta {
97    id: "FA-H-008",
98    name: "Unsafe Assembly",
99    severity: "high",
100    description: "Detects unsafe inline assembly usage",
101    details: "Inline assembly bypasses Solidity's safety checks. Common issues: incorrect slot calculations, unsafe memory operations, and missing overflow checks in assembly arithmetic.",
102    remediation: "Minimize assembly usage. Validate all assembly operations carefully. Use Solidity's built-in functions when possible. Add extensive testing around assembly blocks.",
103    category: "Security",
104    blocks_deployment: true,
105};
106
107pub const SELFDESTRUCT: SecurityCheckMeta = SecurityCheckMeta {
108    id: "FA-H-009",
109    name: "Selfdestruct",
110    severity: "high",
111    description: "Detects selfdestruct usage that can destroy contract code",
112    details: "selfdestruct removes contract code and sends remaining ETH to a target address. In proxy patterns, selfdestruct can brick the proxy. Can also be used for CREATE2 address manipulation.",
113    remediation: "Avoid selfdestruct in upgradeable contracts. If necessary, use a timelock and multi-sig. Consider using SELFDESTRUCT only as a last resort with proper access control.",
114    category: "Security",
115    blocks_deployment: true,
116};
117
118pub const PROXY_VULNERABILITIES: SecurityCheckMeta = SecurityCheckMeta {
119    id: "FA-H-010",
120    name: "Proxy Vulnerabilities",
121    severity: "high",
122    description: "Detects proxy-related security issues",
123    details: "Proxy contracts introduce unique vulnerabilities: uninitialized implementations, selector clashes, unsafe delegatecall targets, and storage collisions.",
124    remediation: "Initialize implementations to prevent selfdestruct. Use transparent or UUPS patterns correctly. Verify storage layout compatibility. Test upgrade paths thoroughly.",
125    category: "Upgradeability",
126    blocks_deployment: true,
127};
128
129pub const ORACLE_MANIPULATION: SecurityCheckMeta = SecurityCheckMeta {
130    id: "FA-H-011",
131    name: "Oracle Manipulation",
132    severity: "high",
133    description: "Detects oracle price feed manipulation vulnerabilities",
134    details: "Using a single price oracle or a manipulable DEX price as an oracle can lead to price manipulation attacks, especially in lending, staking, and AMM protocols.",
135    remediation: "Use decentralized oracles like Chainlink. Implement TWAP or median pricing. Use multiple oracle sources and outlier detection. Add price deviation checks.",
136    category: "DeFi",
137    blocks_deployment: true,
138};
139
140pub const SIGNATURE_VULNERABILITIES: SecurityCheckMeta = SecurityCheckMeta {
141    id: "FA-H-012",
142    name: "Signature Vulnerabilities",
143    severity: "high",
144    description: "Detects signature verification vulnerabilities",
145    details: "Common issues: missing nonces allowing replay attacks, no expiry, EIP-2612 permit frontrunning, and signature malleability in ecrecover.",
146    remediation: "Include nonce, deadline, and chain ID in signed data. Use EIP-712 typed signatures. Prevent signature replay across chains. Use OpenZeppelin's SignatureChecker.",
147    category: "Cryptography",
148    blocks_deployment: true,
149};
150
151pub const REPLAY_ATTACKS: SecurityCheckMeta = SecurityCheckMeta {
152    id: "FA-H-013",
153    name: "Replay Attacks",
154    severity: "high",
155    description: "Detects cross-chain replay attack vulnerabilities",
156    details: "Without chain ID and nonce tracking in signatures, the same message can be replayed on different chains or multiple times, leading to unauthorized actions.",
157    remediation: "Include chainId and nonce in all signed messages. Track used nonces to prevent reuse. Use EIP-712 for structured signing with domain separator.",
158    category: "Cross-Chain",
159    blocks_deployment: true,
160};
161
162pub const ERC20_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
163    id: "FA-H-014",
164    name: "ERC20 Issues",
165    severity: "high",
166    description: "Detects ERC20 implementation vulnerabilities",
167    details: "Common issues: missing return values, fee-on-transfer tokens, rebasing tokens, flash minting, and approval race conditions (the approve-frontrun issue).",
168    remediation: "Use OpenZeppelin's ERC20 implementation. Handle non-standard tokens safely. Use increaseAllowance/decreaseAllowance instead of approve. Check return values.",
169    category: "Standards",
170    blocks_deployment: true,
171};
172
173pub const BRIDGE_VULNERABILITIES: SecurityCheckMeta = SecurityCheckMeta {
174    id: "FA-H-015",
175    name: "Bridge Vulnerabilities",
176    severity: "high",
177    description: "Detects cross-chain bridge vulnerabilities",
178    details: "Bridge attacks can lead to catastrophic fund loss. Common issues: validator set manipulation, message relaying flaws, insufficient confirmation thresholds, and signature verification bugs.",
179    remediation: "Use battle-tested bridge architectures. Implement proper validator management. Add rate limiting and circuit breakers. Use fraud proofs or validity proofs where possible.",
180    category: "Cross-Chain",
181    blocks_deployment: true,
182};
183
184pub const FLASH_LOAN_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
185    id: "FA-H-016",
186    name: "Flash Loan Issues",
187    severity: "high",
188    description: "Detects flash loan attack vector vulnerabilities",
189    details: "Protocols using spot prices, insufficient liquidity checks, or manipulable oracles are vulnerable to flash loan attacks that can drain protocol funds.",
190    remediation: "Use TWAP or manipulated-resistant oracles. Implement minimum liquidity requirements. Use time-weighted average prices. Add circuit breakers for abnormal price movements.",
191    category: "DeFi",
192    blocks_deployment: true,
193};
194
195pub const MEV_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
196    id: "FA-H-017",
197    name: "MEV Vulnerabilities",
198    severity: "high",
199    description: "Detects maximal extractable value vulnerabilities",
200    details: "Frontrunning, sandwich attacks, and backrunning can extract value from users. Common issues: public mempool transactions with no slippage protection, visible order details.",
201    remediation: "Use commit-reveal schemes. Implement slippage protection. Use private mempools or MEV protection. Batch operations atomically. Add minimum output amounts.",
202    category: "DeFi",
203    blocks_deployment: true,
204};
205
206pub const CROSS_CHAIN_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
207    id: "FA-H-018",
208    name: "Cross-Chain Issues",
209    severity: "high",
210    description: "Detects general cross-chain interoperability vulnerabilities",
211    details: "Cross-chain operations introduce unique risks: chain reorganization, message ordering, token representation mismatches, and bridge dependency risks.",
212    remediation: "Design for chain reorgs with confirmation requirements. Use canonical token representations. Ensure message atomicity. Add fallback mechanisms for bridge failures.",
213    category: "Cross-Chain",
214    blocks_deployment: true,
215};
216
217pub const DEPENDENCY_VULNERABILITIES: SecurityCheckMeta = SecurityCheckMeta {
218    id: "FA-H-019",
219    name: "Dependency Vulnerabilities",
220    severity: "high",
221    description: "Detects vulnerable or malicious dependencies",
222    details: "Using outdated or compromised dependencies can introduce vulnerabilities. Common issues: pinning to vulnerable versions, no integrity checks, and supply chain attacks.",
223    remediation: "Pin dependency versions. Use integrity verification (e.g., SRI). Keep dependencies updated. Audit dependency changes. Use tools like Dependabot or Snyk.",
224    category: "Dependencies",
225    blocks_deployment: true,
226};
227
228pub const UNSAFE_IMPORTS: SecurityCheckMeta = SecurityCheckMeta {
229    id: "FA-H-020",
230    name: "Unsafe Imports",
231    severity: "high",
232    description: "Detects unsafe or suspicious imports",
233    details: "Importing from untrusted sources, outdated versions, or suspicious-looking contracts can introduce vulnerabilities or malicious code into the project.",
234    remediation: "Use trusted sources only (OpenZeppelin, Solmate, etc.). Pin to specific versions. Verify import integrity. Use forge remappings consistently.",
235    category: "Dependencies",
236    blocks_deployment: true,
237};
238
239pub const UNSAFE_INITIALIZERS: SecurityCheckMeta = SecurityCheckMeta {
240    id: "FA-H-021",
241    name: "Unsafe Initializers",
242    severity: "high",
243    description: "Detects uninitialized upgradeable contracts",
244    details: "Implementation contracts without initialized guards can be selfdestructed. Proxy contracts can have their initializer called multiple times without reinitializer guards.",
245    remediation: "Use OpenZeppelin's Initializable with initializer modifier. Use reinitializer for version upgrades. Call disableInitializers in the implementation constructor.",
246    category: "Upgradeability",
247    blocks_deployment: true,
248};
249
250pub const UNSAFE_UPGRADE_PATHS: SecurityCheckMeta = SecurityCheckMeta {
251    id: "FA-H-022",
252    name: "Unsafe Upgrade Paths",
253    severity: "high",
254    description: "Detects unsafe contract upgrade paths",
255    details: "Upgradeable contracts need carefully managed upgrade paths. Common issues: storage layout breaks, missing reinitializers, and upgradeability without timelocks.",
256    remediation: "Use a timelock for upgrades. Maintain storage layout compatibility. Test upgrade paths. Use UUPS or transparent proxy patterns correctly.",
257    category: "Upgradeability",
258    blocks_deployment: true,
259};
260
261pub const CLONE_VULNERABILITIES: SecurityCheckMeta = SecurityCheckMeta {
262    id: "FA-H-023",
263    name: "Clone/ Minimal Proxy Issues",
264    severity: "high",
265    description: "Detects minimal proxy (EIP-1167) vulnerabilities",
266    details: "Clones share implementation storage and logic. Issues: uninitialized clones, implementation selfdestruct, and immutable variable expectations in proxied contracts.",
267    remediation: "Initialize each clone individually. Protect implementation from selfdestruct. Ensure clones have proper access control. Use Clones with initializer patterns.",
268    category: "Deployment",
269    blocks_deployment: true,
270};
271
272// ─────────────────────────────────────────────────────────────────
273// MEDIUM severity checks
274// ─────────────────────────────────────────────────────────────────
275
276pub const GAS_PROBLEMS: SecurityCheckMeta = SecurityCheckMeta {
277    id: "FA-M-001",
278    name: "Gas Problems",
279    severity: "medium",
280    description: "Detects gas-inefficient patterns",
281    details: "Unbounded loops, redundant storage operations, repeated computations, and high-gas patterns can make contracts expensive or unusable.",
282    remediation: "Optimize storage usage. Use local variables. Minimize on-chain computations. Use appropriate data structures. Consider using ERC-1167 for clones.",
283    category: "Gas",
284    blocks_deployment: false,
285};
286
287pub const UNSAFE_CASTING: SecurityCheckMeta = SecurityCheckMeta {
288    id: "FA-M-002",
289    name: "Unsafe Casting",
290    severity: "medium",
291    description: "Detects unsafe type casting operations",
292    details: "Downcasting without overflow checks can lead to truncation. address payable conversions can fail silently. bytes<T> to string casts can produce invalid UTF-8.",
293    remediation: "Use OpenZeppelin's SafeCast library for downcasting. Validate addresses before payable conversion. Use string(bytes) carefully. Add input validation.",
294    category: "Logic",
295    blocks_deployment: false,
296};
297
298pub const TIMESTAMP_MANIPULATION: SecurityCheckMeta = SecurityCheckMeta {
299    id: "FA-M-003",
300    name: "Timestamp Manipulation",
301    severity: "medium",
302    description: "Detects reliance on block.timestamp for critical logic",
303    details: "block.timestamp can be manipulated by miners within a ~15-second window. Using it for critical randomness or time- sensitive logic is unsafe.",
304    remediation: "Use block.number for time intervals when possible. Don't use timestamp for randomness. Allow reasonable timestamp variance. Use trusted oracles for precise time.",
305    category: "Logic",
306    blocks_deployment: false,
307};
308
309pub const STORAGE_INEFFICIENCIES: SecurityCheckMeta = SecurityCheckMeta {
310    id: "FA-M-004",
311    name: "Storage Inefficiencies",
312    severity: "medium",
313    description: "Detects storage layout and packing inefficiencies",
314    details: "Poor storage layout wastes gas and can lead to slot overflow. Variables that fit in fewer slots should be packed together. Unnecessary storage variables increase costs.",
315    remediation: "Pack related state variables into fewer slots. Use appropriate data types (uint128, uint64, etc.). Delete unused storage. Use mappings for dynamic data.",
316    category: "Gas",
317    blocks_deployment: false,
318};
319
320pub const UNSAFE_EVENTS: SecurityCheckMeta = SecurityCheckMeta {
321    id: "FA-M-005",
322    name: "Unsafe Events",
323    severity: "medium",
324    description: "Detects events missing indexed parameters or emitting sensitive data",
325    details: "Events can leak sensitive information as they are stored on-chain permanently. Missing indexed parameters makes filtering difficult for off-chain services.",
326    remediation: "Index important parameters for efficient filtering. Never emit sensitive data in events. Follow the indexed parameter limit (max 3). Use EIP- standards for event signatures.",
327    category: "Best Practices",
328    blocks_deployment: false,
329};
330
331pub const POOR_VISIBILITY: SecurityCheckMeta = SecurityCheckMeta {
332    id: "FA-M-006",
333    name: "Poor Visibility Definitions",
334    severity: "medium",
335    description: "Detects incorrect or unsafe visibility modifiers",
336    details: "Functions marked as public or external when they should be internal or private can expand the attack surface. State variables exposed publicly may be unintended.",
337    remediation: "Use the most restrictive visibility modifier possible. Audit all public functions. Consider using external for functions only called externally. Mark state variables as private.",
338    category: "Best Practices",
339    blocks_deployment: false,
340};
341
342pub const BAD_MODIFIERS: SecurityCheckMeta = SecurityCheckMeta {
343    id: "FA-M-007",
344    name: "Bad Modifiers",
345    severity: "medium",
346    description: "Detects unsafe or incorrect modifier patterns",
347    details: "Modifiers that perform state changes, external calls, or have incorrect guard conditions can introduce vulnerabilities. Modifier side-effects are often unexpected.",
348    remediation: "Keep modifiers simple and read-only. Avoid external calls in modifiers. Don't create side effects in modifiers. Use functions instead of complex modifier logic.",
349    category: "Best Practices",
350    blocks_deployment: false,
351};
352
353pub const UNSAFE_MATH: SecurityCheckMeta = SecurityCheckMeta {
354    id: "FA-M-008",
355    name: "Unsafe Math Patterns",
356    severity: "medium",
357    description: "Detects math operations without proper overflow protection",
358    details: "While Solidity 0.8+ has built-in overflow checking, unchecked blocks and assembly math bypass these checks. Division before multiplication loses precision.",
359    remediation: "Use checked math by default. Only use unchecked blocks when overflow is impossible. Use FixedPointMath libraries for precision. Add input bounds.",
360    category: "Logic",
361    blocks_deployment: false,
362};
363
364pub const POOR_ACCESS_PATTERNS: SecurityCheckMeta = SecurityCheckMeta {
365    id: "FA-M-009",
366    name: "Poor Access Patterns",
367    severity: "medium",
368    description: "Detects suboptimal access patterns that increase gas or risk",
369    details: "Reading and writing storage repeatedly in loops, accessing storage when memory suffices, and redundant SLOAD operations waste gas and increase execution cost.",
370    remediation: "Cache storage reads in memory. Batch state changes. Minimize SLOAD/SSTORE operations. Use appropriate data structures for access patterns.",
371    category: "Gas",
372    blocks_deployment: false,
373};
374
375// ─────────────────────────────────────────────────────────────────
376// LOW severity checks
377// ─────────────────────────────────────────────────────────────────
378
379pub const NAMING_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
380    id: "FA-L-001",
381    name: "Naming Issues",
382    severity: "low",
383    description: "Detects naming convention violations",
384    details: "Inconsistent naming (mixedCase for functions, UPPER_CASE for constants, etc.) makes code harder to read and audit. Misleading names can hide vulnerabilities.",
385    remediation: "Follow Solidity style guide: camelCase for functions and variables, UPPER_CASE for constants, underscore prefix for private. Use descriptive names.",
386    category: "Style",
387    blocks_deployment: false,
388};
389
390pub const CODE_DUPLICATION: SecurityCheckMeta = SecurityCheckMeta {
391    id: "FA-L-002",
392    name: "Code Duplication",
393    severity: "low",
394    description: "Detects repeated code patterns",
395    details: "Duplicate code increases maintenance burden and audit surface. Changes to one copy may not be applied to all, leading to inconsistency and potential bugs.",
396    remediation: "Extract common logic into internal functions or libraries. Use inheritance for shared functionality. Consider using modifiers for reusable checks.",
397    category: "Architecture",
398    blocks_deployment: false,
399};
400
401pub const OPTIMIZATION_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
402    id: "FA-L-003",
403    name: "Optimization Suggestions",
404    severity: "low",
405    description: "Detects optimization opportunities",
406    details: "Using more gas than necessary due to suboptimal patterns: redundant operations, unnecessary storage, inefficient data structures, or missing compiler optimizations.",
407    remediation: "Enable compiler optimizer. Pack storage variables. Use calldata instead of memory for read-only parameters. Minimize external calls. Use appropriate data types.",
408    category: "Gas",
409    blocks_deployment: false,
410};
411
412// ─────────────────────────────────────────────────────────────────
413// INFORMATIONAL checks
414// ─────────────────────────────────────────────────────────────────
415
416pub const STYLE_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
417    id: "FA-I-001",
418    name: "Style Issues",
419    severity: "informational",
420    description: "Detects style guide violations",
421    details: "Deviations from the Solidity Style Guide: incorrect indentation, missing or extra spaces, ordering of functions (external, public, internal, private), and NatSpec comments.",
422    remediation: "Follow the official Solidity Style Guide. Use forge fmt for automatic formatting. Add NatSpec documentation to all functions. Use consistent layouts.",
423    category: "Style",
424    blocks_deployment: false,
425};
426
427pub const DOCUMENTATION_ISSUES: SecurityCheckMeta = SecurityCheckMeta {
428    id: "FA-I-002",
429    name: "Missing Documentation",
430    severity: "informational",
431    description: "Detects missing or insufficient NatSpec documentation",
432    details: "Contracts, functions, and state variables without NatSpec comments are harder to audit and maintain. Documentation is critical for security review.",
433    remediation: "Add @notice, @param, @return, @dev tags to all functions. Document state variables. Add custom errors documentation. Include usage examples and security assumptions.",
434    category: "Documentation",
435    blocks_deployment: false,
436};
437
438// ─────────────────────────────────────────────────────────────────
439// Master list of all checks
440// ─────────────────────────────────────────────────────────────────
441
442pub const ALL_CHECKS: &[SecurityCheckMeta] = &[
443    // HIGH
444    REENTRANCY,
445    ACCESS_CONTROL,
446    DELEGATECALL,
447    TX_ORIGIN,
448    CREATE2,
449    DOS,
450    STORAGE_COLLISION,
451    UNSAFE_ASSEMBLY,
452    SELFDESTRUCT,
453    PROXY_VULNERABILITIES,
454    ORACLE_MANIPULATION,
455    SIGNATURE_VULNERABILITIES,
456    REPLAY_ATTACKS,
457    ERC20_ISSUES,
458    BRIDGE_VULNERABILITIES,
459    FLASH_LOAN_ISSUES,
460    MEV_ISSUES,
461    CROSS_CHAIN_ISSUES,
462    DEPENDENCY_VULNERABILITIES,
463    UNSAFE_IMPORTS,
464    UNSAFE_INITIALIZERS,
465    UNSAFE_UPGRADE_PATHS,
466    CLONE_VULNERABILITIES,
467    // MEDIUM
468    GAS_PROBLEMS,
469    UNSAFE_CASTING,
470    TIMESTAMP_MANIPULATION,
471    STORAGE_INEFFICIENCIES,
472    UNSAFE_EVENTS,
473    POOR_VISIBILITY,
474    BAD_MODIFIERS,
475    UNSAFE_MATH,
476    POOR_ACCESS_PATTERNS,
477    // LOW
478    NAMING_ISSUES,
479    CODE_DUPLICATION,
480    OPTIMIZATION_ISSUES,
481    // INFO
482    STYLE_ISSUES,
483    DOCUMENTATION_ISSUES,
484];
485
486/// Get the total number of available checks.
487pub const fn check_count() -> usize {
488    ALL_CHECKS.len()
489}