以太坊开发者文档06 测试智能合约
测试智能合约
测试智能合约是提高智能合约安全性的最重要措施之一。与传统软件不同,智能合约通常在启动后无法更新,因此在以太坊网络上部署合约之前必须进行严格测试。
什么是智能合约测试?
智能合约测试是指对智能合约进行详细的分析和评估,以在开发周期内评估其源代码的质量。测试智能合约可以更容易地识别错误和漏洞,并减少可能导致代价高昂的漏洞利用的软件错误的可能性。
智能合约测试有多种形式,不同的方法有着对应的好处。测试以太坊智能合约的策略可以分为两大类:自动测试和手动测试。
自动测试
自动测试涉及使用自动化工具对智能合约进行脚本测试。该技术依赖于可以执行重复测试以发现智能合约缺陷的自动化软件。
与手动分析相比,自动化测试是高效的,使用的资源更少,并且覆盖率更高。自动化测试工具也可以配置测试数据,允许他们将预测的行为与实际结果进行比较。
手动测试
手动测试是人工辅助的,涉及手动执行测试步骤的个人。代码审计,开发人员和/或审计人员检查每一行合约代码,是智能合约手动测试的一个例子。
智能合约的手动测试需要相当高的技能和大量的时间、金钱和精力投入。此外,手动测试有时容易受到人为错误问题的影响。
然而,对智能合约应用手动测试也是有益的。代码审计利用人类智能来发现合同代码中可能在自动化测试期间未被发现的缺陷。
手动测试你的智能合约也可以揭示代码之外存在但仍会影响它的漏洞。例如,智能合约审计可以发现因与链下组件的有缺陷的交互而产生的漏洞。
为什么测试智能合约是重要的?
测试智能合约很重要,原因如下:
1. 智能合约是高价值的应用
智能合约经常处理高价值金融资产,尤其是在去中心化金融 (DeFi) 等行业,以及诸如不可替代代币 (NFT) 等有价值的物品。因此,智能合约中的小漏洞可能而且通常会给用户带来巨大的、不可挽回的损失。然而,综合测试可以暴露智能合约代码中的错误并降低部署前的安全风险。
2. 智能合约是不可变的
默认情况下,部署在以太坊虚拟机 (EVM) 中的智能合约是不可变的。虽然传统开发人员可能习惯于在启动后修复软件错误,但一旦智能合约在区块链上运行,以太坊开发就几乎没有修补安全漏洞的空间。
虽然智能合约有可升级机制,例如代理模式,但这些可能难以实施。除了降低不变性和引入复杂性之外,升级通常需要复杂的治理流程。
在大多数情况下,升级应被视为最后的手段,除非必要,否则应避免。在预发布阶段检测智能合约中的潜在漏洞和缺陷可减少对逻辑升级的需求。
智能合约的自动测试
1. 功能测试
功能测试验证智能合约的功能,并确保代码中的每个功能都按预期工作。功能测试需要了解您的智能合约在特定条件下的行为方式。然后,您可以通过使用选定值运行计算并将返回的输出与预期输出进行比较来测试每个功能。
功能测试包括三种方法:单元测试、集成测试和系统测试。
单元测试
单元测试涉及测试智能合约中的各个组件的正确性。单元测试简单、快速运行,并且可以清楚地了解测试失败时出了什么问题。
单元测试对于智能合约开发至关重要,尤其是当您需要向代码添加新逻辑时。您可以验证每个函数的行为并确认它按预期执行。
运行单元测试通常需要创建断言(assertions) —— 指定智能合约要求的简单、非正式的语句。然后可以使用单元测试来测试每个断言,看看它在执行时是否成立。
与合约相关的断言示例包括:
i. “只有管理员可以暂停合约”
ii. “非管理员不能铸造新代币”
iii. “合约因错误而恢复”
集成测试
集成测试是在测试层次上比单元测试更高的测试。在集成测试中,智能合约的各个组件被一起测试。
这种方法检测由合约的不同组件之间或跨多个合约的交互引起的错误。如果您有一个具有多个功能的复杂合约或一个与其他合约交互的合约,您应该使用此方法。
集成测试对于确保继承和依赖注入之类的东西正常工作很有用。
系统测试
系统测试是智能合约功能测试的最后阶段。系统将智能合约评估为一个完全集成的产品,以查看它是否按照技术要求中的规定执行。
您可以将此阶段视为从用户的角度检查智能合约的端到端流程。对智能合约执行系统测试的一种好方法是将其部署在类似生产的环境中,例如测试网或开发网络。
在这里,终端用户可以进行试运行并报告合约业务逻辑和整体功能的任何问题。系统测试很重要,因为一旦合约部署在主 EVM 环境中,您就无法更改代码。
2. 静态/动态分析
静态分析和动态分析是评估智能合约安全质量的两种自动化测试方法。然而,这两种技术都使用不同的方法来查找合约代码中的缺陷。
静态分析
静态分析在执行前检查智能合约的源代码或字节码。这意味着您可以在不实际运行程序的情况下调试合约代码。静态分析器可以检测以太坊智能合约中的常见漏洞并帮助遵守最佳实践。
动态分析
动态分析技术需要在运行时环境中执行智能合约来识别代码中的问题。动态代码分析器在执行期间观察合约行为,并生成已识别漏洞和财产违规(property violations)的详细报告。
Fuzzing 是测试合约的动态分析技术的一个例子。在模糊测试期间,模糊器向您的智能合约提供格式错误和无效的数据,并监控合约如何响应这些输入。
与任何程序一样,智能合约依赖于用户提供的输入来执行功能。而且,虽然我们假设用户会提供正确的输入,但情况并非总是如此。
在某些情况下,向智能合约发送不正确的输入值可能会导致资源泄漏、崩溃,或者更糟糕的是,导致意外的代码执行。 Fuzzing 活动预先识别出此类问题,从而使您能够消除漏洞。
智能合约的手动测试
1. 代码审计
代码审计是对智能合约源代码的详细评估,以发现可能的故障点、安全漏洞和不良的开发实践。虽然代码审计可以自动化,但我们在这里指的是人工辅助代码分析。
代码审计需要攻击者的思维方式来绘制智能合约中可能的攻击向量。即使您运行自动审计,分析每一行源代码也是编写安全智能合约的最低要求。
您还可以委托进行安全审计,为用户提供更高的智能合约安全保证。审计受益于网络安全专业人员执行的广泛分析,并检测可能破坏智能合约功能的潜在漏洞或错误。
2. 漏洞赏金
漏洞赏金是给予在程序代码中发现漏洞并向开发人员报告的个人的经济奖励。漏洞赏金类似于审计,因为它涉及要求其他人帮助发现智能合约中的缺陷。主要区别在于漏洞赏金计划对更广泛的开发人员/黑客社区开放。
漏洞赏金计划通常会吸引一大批具有独特技能和经验的道德黑客和独立安全专业人士。与主要依赖可能拥有有限或狭窄专业知识的团队的智能合约审计相比,这可能是一个优势。
测试 vs. 形式验证
虽然测试有助于确认合约返回某些数据输入的预期结果,但它不能最终证明测试期间未使用的输入相同。测试智能合约不能保证“功能正确性”,这意味着它不能表明程序的行为符合所有输入值和条件集的要求。
因此,鼓励开发人员将形式验证纳入其评估智能合约正确性的方法中。形式验证使用形式方法 —— 用于指定和验证软件的数学上严格的技术。
形式验证被认为对智能合约很重要,因为它可以帮助开发人员正式测试与智能合约相关的假设。这是通过创建描述智能合约属性的正式规范并验证智能合约的正式模型是否与规范匹配来完成的。这种方法增加了对智能合约将仅执行其业务逻辑中定义的功能而不执行其他任何功能的信心。
测试工具和库
单元测试工具
Solidity-Coverage - Solidity 代码覆盖工具,可用于测试智能合约。
Waffle - 高级智能合约开发和测试框架(基于 ethers.js)。
Remix Tests - 用于测试 Solidity 智能合约的工具。在 Remix IDE “Solidity Unit Testing”插件下工作,该插件用于编写和运行合同的测试用例。
OpenZeppelin Test Helpers - 用于以太坊智能合约测试的断言库。确保您的合约按预期运行!
Truffle smart contract test framework - 自动化测试框架,让您的合约测试变得轻而易举。
Brownie unit testing framework - Brownie 使用 Pytest,这是一个功能丰富的测试框架,让您可以用最少的代码编写小型测试,可以很好地适应大型项目,并且具有高度可扩展性。
Foundry Tests - Foundry 提供 Forge,这是一个快速灵活的以太坊测试框架,能够执行简单的单元测试、gas 优化检查和合约模糊测试。
Etheno - All-in-one 的以太坊测试工具,包括 JSON RPC 多路复用器、分析工具包装器和测试集成工具。 Etheno 消除了在大型、多合约项目上设置分析工具(如 Manticore 和 Echidna)的复杂性。
动态分析工具
Echidna - 快速合约模糊器,用于通过基于属性的测试来检测智能合约中的漏洞。
Harvey - 自动模糊测试工具,可用于检测智能合约代码中的财产违规(property violations)行为。
Manticore - 用于分析 EVM 字节码的动态符号执行框架。
智能合约审计服务
ConsenSys Diligence - 智能合约审计服务可帮助整个区块链生态系统中的项目确保其协议已准备好启动并构建以保护用户。
CertiK - 率先在智能合约和区块链网络上使用尖端的形式验证技术的区块链安全公司。
Trail of Bits - 网络安全公司,将安全研究与攻击者心态相结合,以降低风险并强化代码。
PeckShield - 区块链安全公司,为整个区块链生态系统的安全性、隐私性和可用性提供产品和服务。
QuantStamp - 审计服务通过安全和风险评估服务促进区块链技术的主流采用。
OpenZeppelin - 为分布式系统提供安全审计的智能合约安全公司
漏洞赏金平台
Immunefi - 用于智能合约和 DeFi 项目的漏洞赏金平台,安全研究人员在这里审查代码、披露漏洞、获得报酬并让加密更安全。
HackerOne - 漏洞协调和漏洞赏金平台,将企业与渗透测试人员和网络安全研究人员联系起来。
相关教程
- Solidity and Truffle Continuous Integration Setup – 如何设置 Travis 或 Circle CI 以进行 Truffle 测试以及有用的插件。
- Testing products overview – 不同测试产品的概述和比较。
- How to use Echidna to test smart contracts
- How to use Manticore to find smart contract bugs
- How to use Slither to find smart contract bugs
- How to mock Solidity contracts for testing
- How to migrate from Truffle Tests to OpenZeppelin Test Environment
- How to test contracts after they have been deployed on a network
- Learn Blockchain, Solidity, and Full Stack Web3 Development with JavaScript (YouTube)
- Solidity, Blockchain, and Smart Contract Course (YouTube)
延伸阅读
- An In-Depth Guide to Testing Ethereum Smart Contracts - Ben Hauser
- How to Test Ethereum Smart Contracts - Alex Roan