forge_lint/sol/gas/
keccak.rs1use super::AsmKeccak256;
2use crate::{
3 linter::{LateLintPass, LintContext},
4 sol::{Severity, SolLint, analysis::is_builtin},
5};
6use solar::{
7 interface::kw,
8 sema::{
9 Gcx,
10 hir::{self, ExprKind, StmtKind},
11 },
12};
13
14declare_forge_lint!(
15 ASM_KECCAK256,
16 Severity::Gas,
17 "asm-keccak256",
18 "high-level `keccak256` call is a candidate for gas optimization"
19);
20
21impl<'gcx> LateLintPass<'gcx> for AsmKeccak256 {
22 fn check_stmt(&mut self, ctx: &LintContext, gcx: Gcx<'gcx>, stmt: &'gcx hir::Stmt<'gcx>) {
23 let expr = match stmt.kind {
24 StmtKind::DeclSingle(var_id) => gcx.hir.variable(var_id).initializer,
25 StmtKind::Expr(expr)
26 | StmtKind::Emit(expr)
27 | StmtKind::Revert(expr)
28 | StmtKind::DeclMulti(_, expr)
29 | StmtKind::If(expr, ..)
30 | StmtKind::Return(Some(expr)) => Some(expr),
31 _ => None,
32 };
33 if let Some(expr) = expr
34 && let ExprKind::Call(callee, args, _) = &expr.kind
35 && args.len() == 1
36 && is_builtin(gcx, callee, kw::Keccak256)
37 {
38 ctx.emit(&ASM_KECCAK256, expr.span);
39 }
40 }
41}