本文介绍了如何构建一个基本的多签钱包(Multisig wallet),详细讲解了硬帽(hardhat)的使用及智能合约的测试流程。文章通过对多签钱包的生命周期、核心合约的结构以及测试框架的使用进行了深入的分析与实现,便于读者掌握多签钱包的原理和构建方法。
本文最初发布于 BuildBear Tutorials。
在本文中,我们将学习如何构建自己基本的 Multisig 钱包。我们将了解 hardhat 及使用 hardhat 测试智能合约。
这将是一个较长的帖子,因此建议你慢慢来,跟随本教程,以最大限度地获得收益。如果有任何疑问,请随时与我联系。
你可以将 Multisig 钱包视为一个联合银行帐户,其中需要多个方的签名以发起帐户的交易。类似地,multisig 钱包是一个基于智能合约的钱包,由多个不同的帐户维护。这些帐户被称为 multisig 钱包的所有者或管理员。
提交
该交易到钱包的交易池中。批准
该交易,如果他们同意该交易。撤销
他们的批准。执行
该交易。足够的理论,现在让我们深入构建自己实现的 Multisig 钱包。我们将在这个过程中使用 hardhat 和 typescript。首先,我们将设置一个基本的 starter 项目,幸运的是,这一步的大部分工作都可以通过 hardhat 的启动脚本自动完成。接下来,我们将编写 IMultisigCore
和 MultisigCore
智能合约,这些合约将拥有上述文章中提到的 multisig 钱包的核心功能。其他合约将继承 MultisigCore
以将核心功能添加到它们的 multisig 钱包实现。我们还将在我们的 Multisig
合约中继承该合约,以遵循相同的模式。
让我们开始 hardhat starter 项目的设置。导航到你想要创建此项目的文件夹。然后输入以下命令 yarn init
并按照说明按回车以保持默认设置。这将创建一个 package.json
文件,即它将在该目录中创建一个节点项目。现在,要将 hardhat 作为开发依赖项之一进行安装,请运行命令 yarn add --dev hardhat
。我们使用 --dev
标志,因为 hardhat 是一个开发依赖项。在成功执行上述命令后,你可以看到 hardhat 添加为 package.json
中的开发依赖项之一。现在要运行 hardhat 命令,运行 yarn hardhat
,当你第一次运行此命令时,会出现欢迎提示。使用箭头键选择 创建一个 TypeScript 项目
,然后按回车以保持默认设置。它将安装一些其他依赖项,以便更轻松地在 typescript 中使用类型等。完成后,你可以看到脚本已创建一个带有 typescript 的样板代码。你将在合约和测试目录中看到 Lock.sol
、Lock.ts
,以及在脚本目录中的 deploy.ts
。你可以安全地删除这些文件,因为在下一节中我们将编写自己的合约文件。
IMultisigCore
接口现在我们完成了基本环境的设置,让我们开始从零构建我们的 Multisig 钱包库。在项目的 contracts
文件夹中,创建一个名为 MultisigLib
的子文件夹。该项目的所有代码都可以在文章末尾链接的仓库中找到。现在我们将为我们的 Multisig 核心库合约创建一个接口 IMultisigCore
。该接口文件将包含从我们的 Multisig 合约发出的错误和事件的声明。你可以从下面的代码片段看到,我们的合约将发出 5 个事件 Deposit
、Submit
、Approve
、Revoke
和 Execute
。阅读代码中的注释,以了解这些事件的更多信息。
自 v0.8.4 以来,Solidity 支持自定义错误。以下是一个代码片段,包含 Multisig 核心在不同点抛出的自定义错误。你可以阅读注释以了解何时 revert 使用特定错误。
这就是 IMultisigCore
接口,它描述了 MultisigCore
合约发出的事件和抛出的错误。
MultisigCore
合约现在让我们看看 MultisigCore
合约,在这里所有的 multisig 奇迹发生。我们将从交易结构体和其他状态变量声明开始。
如上面的代码片段所示,交易有四个属性 to
地址、value
、data
和 isExecuted
布尔值。除此之外,我们有一个地址的 admins
数组、一个 isAdmin
映射以快速检查给定地址是否为管理员,我们还有类似的映射 isApprover
来检查,对于给定的交易,给定的管理员是否已被批准。我们还有 minApprovals
,这是执行任何交易所需的最低批准数。availableBalance
是 Multisig 可用于交易的余额。接下来,让我们看看合约中的一些函数修饰符。
onlyAdmin
仅允许管理员调用该函数。notExecuted
检查并允许函数调用,如果给定交易尚未执行。类似地,notApproved
仅在给定交易尚未被调用者批准时检查并允许函数调用,即如果已被调用者批准则 revert。isApproved
是 notApproved
修饰符的反值。现在我们将查看构造函数和合约的其他函数,其中使用了这些修饰符。
在该合约的构造函数中,我们设置 admins
和 minApprovals
,并更新所有给定管理员的 isAdmin
映射。在 _submit
函数中,我们将新交易推送到 transactions
数组,更新 availableBalance
并发出 Submit
事件。在 _approve
和 _revoke
函数中,我们更新 isApprover
映射并相应地发出 Approve
或 Revoke
事件。在 _execute
函数中,我们检查交易的批准数量,然后如果我们获得了最低所需的批准,我们将更新存储中的交易并执行交易,代码如下。
通过 txn.to.call{value: txn.value}(txn.data)
,我们将交易的值和数据传递给 txn.to
中的地址的调用。这就是 MultisigCore
合约,创建一个 multi-sig 钱包所需的一切。
Multisig
钱包合约在最后一节中,我们编写了 MultisigLib
合约,即 MultisigLib/IMultisigCore
和 MultisigLib/MultisigCore
。在本节中,我们将使用该合约构建我们的 multisig 钱包。在合约文件夹中,即在 MultisigLib
文件夹外,创建一个新的文件 Multisig.sol
。
如上所示,submit
、approve
、revoke
、execute
函数及该合约的构造函数相当简单。该合约中唯一的新内容是 receive
和 fallback
函数,这些函数允许该合约在没有调用任何函数调用的情况下接收资金。
接下来,我们将编写部署脚本以部署此 Multisig 合约。该脚本类似于 hardhat启动的默认脚本。以下是 deploy.ts
脚本的内容。
我们现在已经有了一个 Multisig 钱包合约,接下来我们将测试该合约的功能。Hardhat 使用 mocha 和 chai 进行智能合约的测试。所有这些测试遵循 describe-it 书写测试的格式。
这样的 describe 块中也可以嵌套其他描述。这样我们可以使用这些描述和嵌套描述来描述我们的合约,以测试合约的不同部分。
Hardhat 允许使用 fixtures,这是一种让多个测试具有相同初始条件的方式。fixture 基本上是一种将网络恢复到某个特定状态的方法。第一次当 loadFixture
以函数形式调用时,它会运行该函数,而每次之后调用时,hardhat 会将网络重置为首次运行该函数时的状态。这使我们能够为测试提供相同的初始条件。对于我们的测试,我们主要将使用三个 fixtures deployMultisigFixture
、depositFixture
和 submitFixture
,每个 fixture 都建立在彼此之上。你可以查看下面的代码片段。
deployMultisigFixture
顾名思义是部署 fixture,提供已部署合约、合约工厂和其他部署参数。depositFixture
在 deployMultisigFixture
的基础上构建,所有三个管理员向 Multisig 合约转账一个以太。submitFixture
在 depositFixture
的基础上构建,所有三个管理员各自提交一笔交易。
上面是 execute 功能的测试代码片段,所有其他测试均以类似方式编写。你可以在与本帖相关的仓库的测试目录中的 Multisig.test.ts
文件中找到并阅读所有测试。本文到此结束,感谢你一直阅读到最后,希望你从中学到了东西。
仓库:ts-multisig
https://github.com/BuildBearLabs/Tutorials
作者:Nisarg Chaudhari ( @nisargsc)
关于 BuildBear :
BuildBear 是一个为团队提供大规模测试 dApps 的平台。它为用户提供自己的私有测试网络,以测试他们的智能合约和 dApps,可从任何 EVM 链中分叉。它还提供水龙头、区块浏览器和用于测试的 RPC。
BuildBear 旨在为团队构建一个工具生态系统,以大规模测试 dApps。
- 原文链接: medium.com/buildbear/lea...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!