Slang v1:一种可靠的分析Solidity代码的方法

  • Nomic
  • 发布于 2天前
  • 阅读 199

Slang v1是一套为以太坊开发者提供的Solidity代码分析和工具的模块化编译器API。它能够支持80多种版本的Solidity,并提供高效的错误容忍解析器和符号追踪分析,旨在简化开发工具的构建。Slang的独特之处在于,它不仅是编译器,而是为开发者工具打造的API,极大提高了Soliditiy工具的开发效率。

我们很高兴分享经过多年开发和社区反馈后的 Slang v1 正式版本。Slang 的代码分析 API 现在已经准备好上线,且功能齐全。

什么是 Slang?

Slang 是一组模块化的编译器 API,旨在为以太坊开发者提供下一代 Solidity 代码分析和工具支持。它是用 Rust 编写的,目前主要通过 TypeScript API 进行访问。

构建可靠的 Solidity 工具始终具有挑战性。通过 Nomic 基金会多年来关于 Hardhat 套件的建设和维护工作,我们从第一手经验中了解到,可靠和准确地分析 Solidity 代码的多个版本需要大量的工程努力。

这就是为什么我们将 Slang 构建为一个以开发工具为中心的 API,以应对这些复杂性,从而使以太坊生态系统构建先进的 Solidity 开发工具变得更简单。

你可以用 Slang 构建什么?

Slang 是从底层构建的编译器 API,供其他开发工具使用。这为所有其他 Solidity 工具,如 IDE、格式化工具、代码风格检查器、代码验证器、测试运行器、代码生成器、模糊测试器、静态代码分析器、执行模拟器、区块浏览器、钱包等,提供了一个坚实的基础,从而显著降低开发和维护这些工具的成本和难度。

它与其他 Solidity 编译器有什么不同?

Slang 设计为构建开发者工具的 API,而市场上大多数其他 Solidity 编译器是为 Solidity 开发者设计,专注于生成用于部署的字节码。这具体意味着 Slang 将代码分析工具开发者所需的用例视为一等公民,首先提供程序化 API 作为使用编译器的主要接口。

Slang v1 包含哪些功能?

Slang v1 版本涵盖了 Solidity 编译器 API 的前端接口。

全版本支持

分析 Solidity 代码时,你将面临分析不同 Solidity 版本的挑战。像 solc 这样的编译器每个版本只处理一个版本的 Solidity,这意味着为了优雅地分析多个 Solidity 版本,你需要有临时逻辑来使用适当的编译器版本,并处理编译器在不同 Solidity 版本之间提供的输出结构差异。

Slang 支持 80 多个版本的 Solidity(从 0.4.110.8.28),API 一致。无需特定版本的代码路径。仅需编写一次工具,便可同时支持所有版本。输出(CST、绑定图等)在各版本之间保持稳定,完美适用于版本比较和迁移。你可以专注于构建功能,而不是处理版本间的重大变化。

这一点已在超过 1,350,000 个来自Sanctuary 数据集的合约上进行测试,并在所有语言版本中保持 100% 的准确率。我们还在考虑将更多链/网络添加到我们的测试中,以确保我们的 API 始终是最新的。

容错解析器

Slang 的解析器可以优雅地处理语法错误,同时仍然生成完整的语法树。这在实际软件开发场景中是至关重要的,其中活跃编写的代码需要在编程编辑器中进行分析。这种容错能力确保工具在存在语法错误或缺失依赖项时仍能正常工作。

Slang v1 的解析器迄今为止专注于完整性和正确性。性能比目前在生态系统中许多项目中使用的 @solidity-parser/parser 快 4 倍,我们的目标是在接下来的几个季度大幅提高性能。

符号追踪的绑定分析

构建工具通常需要超越语法模式理解代码。识别语义意义以追踪代码中的符号并进行导航对于许多用例至关重要。Slang 的绑定分析 API 允许例如获取变量的引用列表或查找函数的定义。它也设计为容错,即使有缺失的依赖或不完整代码,也能提供有用的结果。这使其非常适合现实场景,你可能会与部分代码库或外部依赖(NPM)工作,而这些在本地不可用。Slang 是今天唯一提供此功能的 Solidity 编译器 API。

树查询语言

Slang 将类似于 CSS 选择器的体验带入代码分析。它的树查询语言使从合约中提取信息变得轻而易举,能够以最小的努力搜索和过滤 Solidity 代码。通过声明性和简洁的语法,Slang 可以用有效的查询替代数百或数千行代码,在 CST 上运行,以保留每一个细节。

基本提取 uint 变量定义的常见方法是:

function findVariables(node: Node) {
    if (node.kind === NonterminalKind.VariableDeclaration) {
        // 必须手动检查子节点
        for (const child of node.children) {
            if (child.kind === NonterminalKind.TypeName) {
                // 处理类型名称...
            }
            if (child.kind === TerminalKind.Identifier) {
                // 处理标识符...
            }
        }
    }
    // 递归检查所有子节点
    for (const child of node.children()) {
        findVariables(child);
    }
}

而 Slang 让它变得简单得多:

const query = Query.create(`
  [VariableDeclaration\
    @typeName [TypeName ["uint"]]\
    @id [Identifier]\
  ]
`);
for (const match of cursor.query([query])) {
  const {typeName, id} = match.captures;
    // 轻松得多...
}

提取的代码模式越复杂,使用 Slang 的查询语言的回报就越高。

完全保真语法树

Slang 生成的具体语法树(CST)保留代码的每一个细节,包括注释、空格和格式。这使得分析和转换代码的精确工具得以实现,而不丢失原有风格。

Slang 的代码分析 API 如何被使用?

Slang 拥有一些早期采用者,可以作为特定用例的有价值代码参考:

  • Nomic 基金会自己的 Solidity VSCode 插件,下载量超过 30 万次,正利用它提供高级语言功能,如语义高亮和文档大纲/符号。它将在不久的将来完全迁移到 Slang。
  • 即将发布的 prettier-solidity v2 版本,提升代码格式化速度和准确性,面向生态系统中数万个 Solidity 项目。
  • OpenZeppelin Upgrades 使用 Slang 来分析 NatSpec 注释,以实现命名空间存储布局(ERC-7201)。
  • sspec 是 Foundry 项目的 Solidity 规范生成器。通过测试名称,它为智能合约及其函数生成可读的描述,并方便在测试中导航,提供链接到测试文件中的函数。
  • lintspec 是一个寻找 Solidity 文档中常见错误的工具。它是 natspec-smells 的 Rust 移植版,基于 Slang,据报道速度提升了 214 倍(查看公告)。

如果你对在你的项目中使用 Slang 感兴趣,我们很乐意听取你的意见!请通过我们的 Telegram 群组GitHub 问题 联系我们。

Slang 的下一步发展路线图是什么?

我们将在下一个迭代中推出一个 pragma 版本提取 API,并开始着手后端开发,以便为 Solidity 构建可靠的调试体验。

我们的长远愿景包括以相同的方式构建编译器后端,暴露特定于工具的 API。我们旨在提供高性能、强类型的 API,不仅用于分析源代码,还用于转换、注释、验证和优化代码。

了解更多

视频 Slang’s Query API: a better way to analyse Solidity code by Antony Blakey | Devcon SEA

  • 原文链接: blog.nomic.foundation/sl...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Nomic
Nomic
Nomic Foundation, a non-profit organization dedicated to Ethereum’s developer platform