Remix Analyzer 是 Remix IDE Solidity 静态分析插件的底层支撑库。这意味着它不仅可以用于 Remix IDE 同时也能用于其他项目。
既然 Hardhat 是现在流行的合约开发工具,如果能够跟它结合话,那当然再好不过了。在 Remix 的代码仓库中,这个测试文件显示了它的基本使用,关键代码摘录如下:
const res: CompilationResult = compile('functionParameters.sol')
const Module: any = checksEffectsInteraction
const statRunner: StatRunner = new StatRunner()
...
const reports = statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }])
代码逻辑一目了然:编译代码 > 应用规则 > 输出报告。
注意:
上面代码中的 Module 对应 Remix Analyzer 的检查规则,目前支持的所有规则可以在:这个文件中找见。
由于 runWithModuleList
中可以接收多个 Module 对象,如果想应用多个规则的话,只需要初始化多个 Module 实例就行了。
在 Hardhat 中使用 Remix Analyzer 的办法很简单:将上面的那段脚本封装成一个 Task 就行了。但直接照搬的话有个问题。如果仔细看上面的测试代码,你会发现它会先去下载一个 Solidity 的编译器,然后使用它来完成编译。在测试准备阶段有类似下面的代码:
test('setup', function (t) {
solc.loadRemoteVersion('v0.5.0+commit.1d4f565a', (error, compiler) => {
...
当然,直接闷头照抄并非不行,但整个过程不太美观:
CompilationResult
类型的数据就更完美了。这样避免了手工适配的过程。对于 1
,好办,Hardhat 直接支持在任务中调用任务,代码如下:
await hre.run(TASK_COMPILE, { quiet: true });
对于 2
,也不复杂。Hardhat 暴露了属性可以方便的让开发者访问其内部各种制品(Artifact),当然也包括编译后的产物。只是这里有一点需要注意,语法分析用的并不是最终制品,而是编译后的制品。即它需要的是 artifacts/build-info
而不是 artifacts/contracts
。
并且,artifacts/build-info
下的 json 文件不能直接被 Remix Analyzer 所用,只是其中的一部分。通过对比 CompilationResult
类型和 json 的内容很容易发现其中关联:output
属性。因此,整个任务的逻辑框架代码如下:
const runner = new staticAnalysisRunner();
await hre.run(TASK_COMPILE, { quiet: true });
console.log("√ compiled contracts.\n");
const compileResults = await hre.artifacts.getBuildInfoPaths();
compileResults.forEach((result) => {
const compiled = JSON.parse(fs.readFileSync(result).toString());
const source = Object.keys(compiled.input.sources)[0];
const modules = calculateRules(source, rulesConfig).map((Module: any) => {
return { name: new Module().name, mod: new Module() };
});
const reports = runner.runWithModuleList(compiled.output, modules);
...
})
即:
语法分析是一个高度可复用的任务,没有理由不进一步将其封装成一个插件。
身为 dapp 开发,如果还不清楚 Hardhat 插件为何物,那真应该好好读读文档了。利用插件,你可以方便地在项目间共享配置,当然也包括自定义的 task。
按照文档推荐的步骤:先在 Hardhat 工程中测试完任务的逻辑;再将其挪到插件工程封装成插件。现在,我们已经完成了第一步。
关于如何构建插件的过程,文档中已经说的很清楚,这里不再赘述:基于插件模板工程进行改造就行了。在实际开发过程中,个人发现有两点需要强调一下。
按照文档中总结的几条规则操作就行了。
在文档中并没有特别说明,而只是给出了一个示例文件的链接,但我发现需要搭配这个文件一起看才能明白其中的逻辑。读完代码,规则总结如下:
declare module "hardhat/types/config" {
interface HardhatUserConfig {
analyzerRules?: AnalyzerConfiguration;
}
interface HardhatConfig {
analyzerRules: AnalyzerConfiguration;
}
}
至于其余的,没啥可说的了,照着模板工程来就行了。有兴趣的话可以访问 hardhat-remix-analyzer 的代码仓库了解详情。
除了 Remix Analyzer,还有其他两个类似工具可以关注:slither 和 solhint。对比之后,个人建议关注后面两个,原因在于后者提供了更多的规则,而且更新更频繁,并且 Hardhat 也提供了针对 solhint 的插件。
觉得有帮助的话,不妨考虑购买付费文章来支持我们 🙂 :
付费文章