Skip to main content

forge_lint/sol/gas/
keccak.rs

1use 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}