Slither 将 Solidity 转换为中间表示 SlithIR,以通过简单的 API 实现高精度分析。
预定义了很多检测器(detectors),支持自定义:https://github.com/crytic/slither/wiki/Detector-Documentation
slither demo.sol
"
--config-file file.config.json
指定配置文件
--detect detector1,detector2
指定检测器
--exclude detector1,detector2
排除探测器
--filter-paths "Migrations.sol|ConvertLib.sol"
筛选只跟xx文件有关的结果
--checklist
测试结果以md格式输出
--json file.json
测试结果导出为json
--print slithir
输出每个函数的IR
"
# 与编译有关的选项参考:crytic-compile --help
# <https://github.com/crytic/crytic-compile/wiki/Configuration>
"
--solc-remaps @openzeppelin=node_modules/@openzeppelin
指定import依赖路径
"
# 可以基于solc生成的AST文件运行
slither file.ast.json
配置文件
跟编译有关的配置字段参考
crytic_compile:https://github.com/crytic/crytic-compile/blob/master/crytic_compile/cryticparser/defaults.py
{
"detectors_to_run": "detector1,detector2",
"printers_to_run": "printer1,printer2",
"detectors_to_exclude": "detector1,detector2",
"exclude_informational": false,
"exclude_low": false,
"exclude_medium": false,
"exclude_high": false,
"json": "",
"disable_color": false,
"filter_paths": "(mocks/|test/)", # regex
"legacy_ast": false
}
被测合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
// This is the age-old reentrancy attack that should make you squirm when you see it
contract EtherStore {
mapping(address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw() external {
uint256 balance = balances[msg.sender];
require(balance > 0);
(bool success, ) = msg.sender.call{value: balance}("");
require(success, "Failed to send Ether");
balances[msg.sender] = 0;
}
// Helper function to check the balance of this contract
function getBalance() external view returns (uint256) {
return address(this).balance;
}
}
测试结果
Reentrancy in EtherStore.withdraw() (demo.sol#12-18):
External calls:
- (success) = msg.sender.call{value: balance}() (demo.sol#15)
State variables written after the call(s):
- balances[msg.sender] = 0 (demo.sol#17)
EtherStore.balances (demo.sol#6) can be used in cross function reentrancies:
- EtherStore.balances (demo.sol#6)
- EtherStore.deposit() (demo.sol#8-10)
- EtherStore.withdraw() (demo.sol#12-18)
Reference: <https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities>
Pragma version^0.8.9 (demo.sol#2) allows old versions
Reference: <https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity>
Low level call in EtherStore.withdraw() (demo.sol#12-18):
- (success) = msg.sender.call{value: balance}() (demo.sol#15)
Reference: <https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls>
demo.sol analyzed (1 contracts with 84 detectors), 3 result(s) found