EIP-712 是一种更高级、更安全的交易签名方法,已在 Uniswap V2 的 Periphery 合约中实现。
原文标题:《一个示例来解释 EIP-712》
撰文:Apurba Pokharel
翻译:ChinaDeFi
在 GitHub 中有许多文章和示例解释和展示了如何使用 EIP-712,但在理解它作为一个整体是如何工作的以及前端代码和智能合约是如何关联的方面有很多困难。这是 EIP-712 的一个示例 (不是解释)。先决条件和使用的版本。
-
Solidity 基础知识
-
npm 7.19.1
-
节点 16.2.0
-
Metamask 9.8.4
-
truffle 5.4.0
EIP-712
EIP-712 是一种更高级、更安全的交易签名方法。使用该标准不仅可以签署交易并且可以验证签名,而且可以将数据与签名一起传递到智能合约中,并且可以根据该数据验证签名以了解签名者是否是实际发送该签名的人要在交易中调用的数据。
EIP-712 提出了数据的标准结构和从结构化消息生成散列的定义过程。然后使用此散列生成签名。通过这种方式,为发送交易生成的签名与为验证身份或任何其他目的生成的签名之间就有了明显的区别。EIP-712 草案将签名方案背后的动机表述为 :
提高链上使用的链下消息签名的可用性。我们看到越来越多的人采用链下消息签名,因为它节省了 gas,减少了区块链上的交易数量。
EIP-712 是类型化结构化数据的哈希和签名的标准,而不仅仅是字节字符串。它包括一个
-
编码函数正确性的理论框架,
-
与 solid 结构相似并兼容的结构化数据规范,
-
安全哈希算法用于这些结构的实例,
-
在可签名消息集中安全包含这些实例,
-
一个可扩展的域分离机制,
-
新的 RPC 调用 eth_signTypedData,
-
EVM 中哈希算法的优化实现。
EIP-712 的实现可以在 Uniswap V2 的 Periphery 合约中看到,它通过许可移除流动性,最终调用 Uniswap V2 Core 中的方法来完成这一操作。
前端的签名被传递给 Periphery 中的方法,签名被用来代表 Core 中使用该方法的用户批准 Router 合约。
示例代码
我们的示例将使用 EIP-721 提案用数据 (地址、storedData 的值和截止日期) 签署交易,这些数据用于更改合约中变量的值。
如果签名和散列给出了签署人的地址,并且没有超过截止日期,则更改 storedData 的值。
这是一个无用的例子,但理解了它将确保您可以在其他地方使用该标准。正确使用 EIP-712 是创建一个 ERC20 许可证,就像 Uniswap 团队所做的那样。
步骤 1
继续克隆 truffle 的 react box。
我们将根据需要简单地调整和添加代码,以使 EIP-712 正常工作。
步骤 2
数据是 EIP-712 中最关键的部分。这些要签名的数据必须符合预定义的格式。它必须有一个 EIP712Domain 和要签名的数据 (在我们的示例中设置)。两者的组合将被签名并发送给智能合约进行验证。
在 EIP-712 下签名的每个数据必须有一个 EIP712Domain 和另一个数据。这两者的结构可以是任何东西,但必须在 JS 代码和 SC 代码上相同。
当使用该提案时,EIP712Domain 的结构是一个被广泛接受的标准。
EIP-712 数据标准
EIP712Domain 有一些参数,这些参数指定在哪个网络和哪个特定合约上将用于验证签名。另一份具有相同代码的合同将无法验证该签名。
步骤 3
让我们添加一个按钮,当单击该按钮时,将弹出元掩码,使用 eth_signTypedData_v3 方法对数据进行签名。
步骤 4
一旦签署了上面定义的数据使用 eth_signTypedData_v3 方法我们得到了签名和签名分割成其 r, s, 和 v 组件并将其发送到智能合约将使用 ercrecover 这些参数和数据哈希恢复签名者的公钥。
拆分签名
步骤 5
编写智能合约。
就像我们定义了包含 EIPdomain 和要签名的数据的 JS 代码一样,智能合约也需要两个变量来表示每个 EIPdomain 的散列数据和我们的数据 (在本例中是设置数据)。
使用 ercrecover
在 UI 端,我们对数据进行签名,并将 r、s 和 v 发送给智能合约。
上面的代码做了两件事,首先它散列数据并生成它们的散列。接下来,它使用该数据的散列 (在 SC 中称为散列) 和签名,使用 ercrecover 方法生成签名者的公钥。
上面显示的数据的两个 kecak 哈希值应该类似于在 out JS 代码中定义的数据结构。如果两者不同,则无法恢复签名者的地址。
签名数据的结构
步骤 6
将 infura 中的助记符添加到 truffle-config.js 文件 (第 3 行),并指定部署者的地址 (第 18 行)。上面的例子使用了 rinkeby testnet,但是任何测试都可以使用,并查看 truffle 文档来部署到其他测试网。
然后部署合同。部署后复制 simplestorage 的地址,替换为 verifyingContract 下 app.js 第 76 行的地址。
部署代码片段
步骤 7
进入 client 目录,运行 npm run start 启动 react 应用。
按下「Press to sign」按钮,然后在元掩码弹出的签名请求上签名。接下来,确认交易以设置智能合约上的值。
交易完成后,刷新 webapp 以查看所反映的变化。
来源链接: medium.com