crytic/slither

Custom error imported from library is converted to high level call

ejolanix opened this issue · 2 comments

Got this error running newly released slither v0.8.2 on https://github.com/primitivefinance/rmm-manager commit 2fdeeb2648c3c7fc580abfaa07f1474b97c38093
Any suggested fix?

Slither run output:

$ slither .
'npx hardhat compile --force' running
Compiling 62 files with 0.8.6
Generating typings for: 62 artifacts in dir: typechain for target: ethers-v5
Successfully generated 100 typings!
Compilation finished successfully

Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
  --> contracts/PositionRenderer.sol:15:21:
   |
15 |     function render(address engine, uint256 tokenId) external view override returns (string memory) {
   |                     ^^^^^^^^^^^^^^


Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
  --> contracts/PositionRenderer.sol:15:37:
   |
15 |     function render(address engine, uint256 tokenId) external view override returns (string memory) {
   |                                     ^^^^^^^^^^^^^^^


Warning: Function state mutability can be restricted to pure
  --> contracts/PositionRenderer.sol:15:5:
   |
15 |     function render(address engine, uint256 tokenId) external view override returns (string memory) {
   |     ^ (Relevant source part starts here and spans across multiple lines).




Multicall.multicall(bytes[]) (contracts/base/Multicall.sol#11-27) has delegatecall inside a loop in a payable function: (success,result) = address(this).delegatecall(data[i]) (contracts/base/Multicall.sol#14)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop

IERC20 is re-used:
        - IERC20 (node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol#9-82)
        - IERC20 (contracts/interfaces/external/IERC20.sol#6-26)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused
Traceback (most recent call last):
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 743, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 84, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 69, in process_single
    return _process(slither, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 110, in _process
    detector_results = slither.run_detectors()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slither.py", line 203, in run_detectors
    results = [d.detect() for d in self._detectors]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slither.py", line 203, in <listcomp>
    results = [d.detect() for d in self._detectors]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/abstract_detector.py", line 152, in detect
    for r in [output.data for output in self._detect()]:
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy_eth.py", line 93, in _detect
    super()._detect()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 302, in _detect
    self.detect_reentrancy(c)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 289, in detect_reentrancy
    self._explore(function.entry_point, [])
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  [Previous line repeated 1 more time]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 267, in _explore
    contains_call = fathers_context.analyze_node(node, self)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 159, in analyze_node
    if detector.can_callback(ir):
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 228, in can_callback
    return isinstance(ir, Call) and ir.can_reenter()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slithir/operations/library_call.py", line 25, in can_reenter
    return self.function.can_reenter(callstack)
AttributeError: 'NoneType' object has no attribute 'can_reenter'
None
Error in .
Traceback (most recent call last):
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 743, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 84, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 69, in process_single
    return _process(slither, detector_classes, printer_classes)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/__main__.py", line 110, in _process
    detector_results = slither.run_detectors()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slither.py", line 203, in run_detectors
    results = [d.detect() for d in self._detectors]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slither.py", line 203, in <listcomp>
    results = [d.detect() for d in self._detectors]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/abstract_detector.py", line 152, in detect
    for r in [output.data for output in self._detect()]:
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy_eth.py", line 93, in _detect
    super()._detect()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 302, in _detect
    self.detect_reentrancy(c)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 289, in detect_reentrancy
    self._explore(function.entry_point, [])
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 282, in _explore
    self._explore(son, visited)
  [Previous line repeated 1 more time]
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 267, in _explore
    contains_call = fathers_context.analyze_node(node, self)
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 159, in analyze_node
    if detector.can_callback(ir):
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/detectors/reentrancy/reentrancy.py", line 228, in can_callback
    return isinstance(ir, Call) and ir.can_reenter()
  File "/home/ejolanix/.local/lib/python3.9/site-packages/slither/slithir/operations/library_call.py", line 25, in can_reenter
    return self.function.can_reenter(callstack)
AttributeError: 'NoneType' object has no attribute 'can_reenter'

Minimal test case. Maybe related to #1115

library CustomErrors {
     error LibraryError();
}

contract Bar { 
    function baz() external {
            revert CustomErrors.LibraryError();
    }
}

Add assertion assert isinstance(ir.function, Function) here and it's more clear where the issue arises

elif isinstance(ir, LibraryCall):
assert isinstance(ir.destination, Contract)
self._high_level_calls.append((ir.destination, ir.function))
self._library_calls.append((ir.destination, ir.function))