Using Remix Analyzer For Solidity Syntax Analysis.
Tags: blockchain, ethereum, hardhat, solidity
Published: 2023-01-11 04:25:16

[Remix Analyzer](https://github.com/ethereum/remix-project/tree/master/libs/remix-analyzer) is the underlying library for the Remix IDE Solidity Static Analysis plugin. This means that it can be also used for other projects, not just for Remix IDE.

Since Hardhat is a popular contract development tool nowadays, it would be nice to make Remix Analyzer work with it. In the Remix code repository, [this test file](https://github.com/ethereum/remix-project/blob/master/libs/remix-analyzer/test/analysis/staticAnalysisIssues-test-0.5.0.ts) shows its basic usage, the key code:

```ts
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() }])
```

The logic is simple: compile code > apply rules > output report.

> Note that.
>
> The Module in the code above is Remix Analyzer Rule class, all rules currently supported can be found in: [this file](https://github.com/ethereum/remix-project/blob/master/libs/remix-analyzer/src/solidity-analyzer/modules/index.ts).

Multiple Module objects can be passed to `runWithModuleList`, if you want to apply multiple rules what you need to do is to initialize multiple Module instances.

## Making a Hardhat Task

Using Remix Analyzer in Hardhat is a piece of cake: calling the script above from a Hardhat task. However, there are some tricky things if you just copy it as it is. If you look closely at the code above, you can see it first goes to download a Solidity compiler and then uses it to complete the contracts. In test `setup`, there is a script like the following:

```ts
test('setup', function (t) {
  solc.loadRemoteVersion('v0.5.0+commit.1d4f565a', (error, compiler) => {
    ...
```

Of course, there is no way to stop you from copying all code lines to your task script. But it is not a Hardhat style:

1. Hardhat comes with a compiler, you should use it directly when you can, rather than downloading a new one.
1. Following the previous step, it would be nice to get `CompilationResult` data from the compiled files directly. Then, we don't have to do any data transformation jobs.

As for `1`, Hardhat supports calling tasks within a task script, the code example:

```ts
await hre.run(TASK_COMPILE, { quiet: true });
```

As For `2`, it's simple too. Hardhat exposes fields to allow developers to access the artifacts in a project, including the compiled files. One thing to note here is that syntax analysis does not use the final artifacts but a middle one. That is, it needs `artifacts/build-info` rather than `artifacts/contracts`.

Also, a json file in `artifacts/build-info` is not expected by Remix Analyzer which only uses part of it. By comparing the `CompilationResult` type with the contents of the json, it is easy to see the connection: the `output` field. 

So, the code snippet for the task is like:

```ts
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);
  ...
})
```

The main logic here is:

1. compile
1. generate a report for each compiled file: parse json > compute rules > apply rules

## Making a Hardhat Plugin

Syntax analysis is a highly reusable task and there is no reason why it cannot be a plugin.

As a dapp developer, you should really read [its documentation](https://hardhat.org/hardhat-runner/docs/advanced/building-plugins) if you still don't know what a Hardhat plugin is. With a plugin you can easily share configurations between projects, including custom tasks of course.

The steps recommended in the documentation: first testing the logic of a task in a Hardhat project; then moving it into a plugin project and wrapping it as a plugin. Now, we have completed the first step.

The documentation is very clear on how to build the plug-in, so I won't go into it again here: fork the [plug-in template](https://github.com/NomicFoundation/hardhat-ts-plugin-boilerplate/) project and make some changes.

Here, I only highlight two things.

### Dependencies

Following [the rules in the documentation](https://hardhat.org/hardhat-runner/docs/advanced/building-plugins#notes-on-dependencies).

### Extending Configuration

The documentation does not show too many details on this topic, rather gives a link to an example file. But I found that I have to read [this file](https://github.com/NomicFoundation/hardhat-ts-plugin-boilerplate/blob/master/src/type-extensions.ts) together to understand the logic.

After reading the code, I summarized the following rules:

1. Extending both `XxxUserConfiguration` and `XxxConfig`, where:
   - The fields added to the former are optional and the latter are required.
   - Generating the latter based on the former during initialization. Or giving a default if the former is missing.
1. When adding a new field to Hardhat existing configuration items, follow what the example did: use the corresponding Types. In the example, they are `ProjectPathsUserConfig` and `ProjectPathsConfig`.
1. To add a new top-level configuration item to Hardhat, use `HardhatUserConfig` and `HardhatConfig` like below:

```ts
declare module "hardhat/types/config" {
  interface HardhatUserConfig {
    analyzerRules?: AnalyzerConfiguration;
  }

  interface HardhatConfig {
    analyzerRules: AnalyzerConfiguration;
  }
}
```

As for the rest, there's not much more to say. If you're interested, you can visit [hardhat-remix-analyzer](https://github.com/DTeam-Top/hardhat-remix-analyzer) for more details.

## Final Words

There are two other similar tools: [slither](https://github.com/crytic/slither/tree/master/slither) and [solhint](https://github.com/protofire/solhint).

After comparing among them, I personally recommend focusing on the latter two, as they offer more rules and are updated more frequently. Meanwhile, Hardhat has a plugin for solhint.