本文介绍了Motsu,一个专为Arbitrum Stylus智能合约设计的Rust原生测试框架,它通过模拟区块链环境,帮助开发者快速、隔离地进行单元测试,类似于Hardhat和Foundry,但更Rust-idiomatic。文章详细讲解了Motsu的设置、基本用法,包括账户管理、合约交互、事件测试、错误处理和合约间交互,并提供了一个ERC-20 token的实例。
随着以太坊扩容解决方案的成熟,Arbitrum Stylus 成为一项引人入胜的创新,它允许开发者使用 Rust 编写智能合约。这提供了显著的性能改进,并将 Rust 强大的类型系统和内存安全保证带到区块链世界。 但正如任何经验丰富的智能合约开发者都知道的那样,彻底的测试是不可协商的。这就是 Motsu 的用武之地 —— 一个专门为 Stylus 合约设计的测试框架,它既让 Rust 开发者感到熟悉,又在概念上类似于 Solidity 开发者熟知的 Hardhat 和 Foundry 等工具。
在本教程中,我们将探讨如何使用 Motsu 有效地测试你的 Stylus 合约。如果你来自 Solidity 背景,并且具有 Foundry 或 Hardhat 等工具的经验,你会发现许多相似之处可以帮助你快速上手。
你可以在我们的 GitHub 存储库中找到包含所有示例的完整工作项目:https://github.com/0xNeshi/motsu-tutorial
Motsu 解决了测试 Stylus 智能合约中的一个核心挑战:模拟区块链环境。正如 Hardhat 提供了一个 JavaScript 环境来测试 Solidity 合约,而 Foundry 提供了一个 Solidity 原生的测试体验一样,Motsu 通过模拟 vm 的辅助功能,为 Stylus 合约提供了一个纯 Rust 测试体验。与 Hardhat 或 Foundry 启动轻量级区块链节点来执行测试不同,Motsu 采用了一种不同的方法,即在 Wasm 级别直接拦截和模拟 Stylus 主机函数。这使得可以进行快速、隔离的测试,而无需完整的区块链运行时,使其成为纯粹在 Rust 中进行 Stylus 合约单元测试的理想选择。
“Motsu”(持つ,日语“持有”)这个名字巧妙地引用了“手持手写笔(holding a stylus in our hand)”—— 这对于一个让你可以控制 Stylus 合约测试的工具来说,是一个恰当的比喻。
在深入研究 Motsu 之前,请确保你的项目已正确配置。以下是本项目所需的依赖项:
让我们在 src/lib.rs 中添加合约:
让我们从一个简单的例子开始。如果你以前用 Rust 编写过测试,那么结构看起来会很熟悉,但有一个关键的区别:我们不使用 #[test],而是使用 #[motsu::test]。
这是我们的 Vault 合约的一个基本测试:
让我们分解一下这里发生了什么:
这在概念上类似于 Foundry 的 setUp() 函数准备你的测试环境的方式,但通过函数参数以更符合 Rust 习惯的方式进行。
Motsu 提供了两种类型来表示区块链账户:
你可以在测试函数中使用任何一种作为参数:
请注意,你需要在 Cargo.toml 的 [dev-dependencies] 中添加 alloy-signer@0.11.1 才能执行签名操作。
除非你需要在测试中访问私钥或底层签名者,否则我们建议使用 Address,因为它更轻量级。
在调试测试时,拥有命名一致的帐户可以帮助跟踪问题。Motsu 提供了一个 FromTag trait,它包含在其 prelude 中,用于从字符串标识符创建确定性地址,并且此 trait 用于注入测试参数:
Motsu 测试的核心围绕着 Contract<T> 类型,它代表了你的智能合约的已部署实例。
要在你的合约上调用函数:
sender() 方法设置交易的调用者,类似于 Hardhat 的 connect() 或 Foundry 的 vm.prank()。
假设我们向 Vault 添加了一个 payable 的 deposit 函数,该函数接受底层的 gas token:
对于 payable 函数,你可以使用 sender_and_value() 发送 ETH。
智能合约经常发出你想要在测试中验证的事件。
首先,让我们更新 deposit 函数,以便在成功存款时发出一个事件:
Motsu 提供了一种优雅的方式来检查发出的事件:
如果事件断言失败,Motsu 会提供格式良好的 panic 消息,其中帐户/合约地址替换为适当的标签(如果标签用于实例化它们)。
测试失败场景与测试成功操作同样重要。让我们向 Vault 添加一个 decrease_balance 函数,该函数会在余额下溢时用错误 revert:
Motsu 提供了几种方法来正确处理 revert:
用于处理 revert 的关键方法是:
这些方法确保在交易失败时正确地 revert 合约状态,类似于真实区块链交易的行为方式。如果上述任何方法 panic,panic 消息将被漂亮地打印以提高清晰度,并且地址将被替换为适当的标签(如果这是它们的实例化方式)。
Motsu 的强大功能之一是能够测试多个合约之间的交互。这对于复杂的 DeFi 应用程序或任何具有多个交互组件的系统至关重要。
让我们设置一个简单的代理合约实现:
Motsu 处理内部合约间连接,允许我们轻松测试上面的代理:
有时你需要模拟特定的区块链条件。Motsu 允许你修改某些环境变量(如链 ID),这使你可以模拟链的分叉。
让我们通过测试 ERC-20 token 实现来将所有内容放在一起。
我们将继承 openzeppelin-stylus 库的 ERC-20 实现,因此让我们将必要的依赖项添加到我们的 Cargo.toml 中:
我们现在可以打开 src/lib.rs 并实现我们的 ERC-20 token 以及一个全面的转移测试:
根据我们探索的模式,以下是一些使用 Motsu 进行测试的最佳实践:
Motsu 为 Arbitrum Stylus 合约提供了一个强大的、Rust 原生的测试环境。虽然在概念上类似于 Hardhat 和 Foundry 等工具,但它利用 Rust 的类型系统来提供更集成的测试体验。
对于来自 Solidity 的开发者来说,思维模型是可以转移的 - 你仍然在使用合约、地址和交易。但是 Motsu 的设计利用了 Rust 的功能,使测试更加简洁且更易于推理。
当你继续使用 Stylus 进行开发时,请继续探索 Motsu 的功能。投入编写全面测试的时间将在智能合约的可靠性和安全性方面获得回报。
测试愉快!
- 原文链接: openzeppelin.com/news/te...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!