-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add detector for msg.value usage unreachable from payable entry points
#2867
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?
Conversation
Co-Authored-By: Claude Opus 4.5 <[email protected]>
ep0chzer0
left a comment
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.
Review: Implementation Feedback
Thanks for working on this, the core detection logic is correct! However, I found a few issues that need to be addressed:
1. Output Format Issue (Critical)
The _build_info method uses strings instead of Slither objects, which breaks the JSON/SARIF output format:
Current (incorrect):
info = [
"msg.value used in non-payable context\n",
f" Location: {func.source_mapping.filename.short}:{func.source_mapping.lines[0]}\n",
...
]Expected (per Slither conventions):
info: DETECTOR_INFO = [
func,
" uses msg.value but is not reachable from any payable function\n",
]
if non_payable_callers:
info.append("\tNon-payable entry points that can reach this function:\n")
for caller in non_payable_callers:
if caller != func:
info.extend(["\t- ", caller, "\n"])The Output class expects Slither objects (Function, Node, etc.) which it converts to proper source mappings for IDE integration and SARIF output.
2. Missing Import
You need to import DETECTOR_INFO from the abstract detector:
from slither.detectors.abstract_detector import (
AbstractDetector,
DetectorClassification,
DETECTOR_INFO,
)3. Include the Function Itself as Entry Point
In _get_entry_point_callers, you should include the function itself if it's public/external:
if function.visibility in ("public", "external"):
if function.payable:
payable_callers.append(function)
else:
non_payable_callers.append(function)4. Missing is_implemented Check
Add a check to skip functions that aren't implemented:
if not func.is_implemented:
continue5. Missing Test Cases
The PR needs test data. Note that in Solidity 0.8+, the compiler prevents direct msg.value use in non-payable public/external functions, so tests should focus on internal functions that use msg.value but are only reachable from non-payable entry points.
Happy to help with any questions!
|
Hi @ep0chzer0 , I’ve now addressed the points you raised:
Here is the updated detector output now when running on the I will also be adding the
|
3f29cb8 to
7c0d32e
Compare

Summary
This PR resolves #2781 and introduces a new Slither detector,
msg-value-in-nonpayable, which identifies uses ofmsg.valuein functions that can never be reached from any payable public or external entry point.In such cases,
msg.valueis provably meaningless:This detector helps developers catch logic errors, dead code, and incorrect assumptions about ETH flow early.
Detection Logic
The detector:
msg.value(including via modifiers)Only the function that uses
msg.valueis reported; callers are included for explanatory context.Example
Here,
subscribe()is not payable and cannot receive ETH.As a result,
msg.valueis always zero and therequirestatement always fails.Notes
The detector follows the semantics discussed in #2781 and reports only
msg.valueusages that are provably unreachable from any payable execution path.