-
Notifications
You must be signed in to change notification settings - Fork 2k
feat(forge-lint): [claude] check for unwrapped modifiers #10967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat(forge-lint): [claude] check for unwrapped modifiers #10967
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you, makes sense. left some nits, pending @0xrusowsky @DaniPopes review
} | ||
} | ||
|
||
fn is_valid_expr(expr: &solar_ast::Expr<'_>) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be simplified to
fn is_valid_expr(expr: &solar_ast::Expr<'_>) -> bool {
if let ExprKind::Call(func_expr, _) = &expr.kind
&& let ExprKind::Ident(ident) = &func_expr.kind
{
return !matches!(ident.name.as_str(), "require" | "assert");
}
false
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
// If modifier has no contents, skip. | ||
let body = match &func.body { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be simplified to
let Some(body) = &func.body else { return };
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall the PR looks good, however i'd like to hold it back until we merge: and then make it do a fix suggestion |
Motivation
Coauthored by Claude 4 Opus Max
Modifiers in Solidity that contain logic directly in their body can lead to code duplication when used across multiple functions. Since modifiers are inlined at compile time, any logic within them is duplicated for each function that uses the modifier increasing contract size and deployment cost. A common best practice is to extract modifier logic into internal functions that can be called from within the modifier, reducing code duplication and contract size.
Solution
This PR adds a new gas optimization lint
unwrapped-modifier-logic
that detects when modifiers contain logic directly in their body instead of usinginternal/private/public
functions.The lint checks for modifiers that contain any statements other than:
internal/private/public
functions._;
Example of code that triggers the lint:
Recommended pattern:
PR Checklist
testdata/ModifierLogic.sol
andtestdata/ModifierLogic.stderr
with comprehensive test cases