paint-brush
应用 EIP-712 使用以太坊无 Gas 元转让 过@thebojda
1,802 讀數
1,802 讀數

使用 EIP-712 进行以太坊无 Gas 元交易

路过 Laszlo Fazekas12m2023/10/17
Read on Terminal Reader

太長; 讀書

在元交易的情况下,用户创建一个描述交易的结构,然后用他们的私钥对其进行数字签名。这类似于为某人写支票。然后,经过数字签名的交易被发送到中继节点,中继节点将其提交给智能合约。合约验证签名,如果有效,则执行交易。中继节点为合约的执行付费。
featured image - 使用 EIP-712 进行以太坊无 Gas 元交易
Laszlo Fazekas HackerNoon profile picture
0-item


我最近写了一篇关于Karma Money的文章,这是一种基于独特的 ERC-20 代币的替代货币系统。我将 Karma Money 设想为一个封闭的系统,用户还可以用 karma 支付交易费用。构建我们自己的区块链将是实现这一目标的一种方法,但这是一项具有挑战性的任务。为了保证区块链的安全性和可信性,我们需要建立必要的基础设施和足够大的社区。使用现有的区块链会简单得多。有诸如或之类的链,它们与以太坊完全兼容,并且交易费用非常低。这些链上的 ERC20 交易费用通常低于 1 美分。问题是这笔费用必须用链本身的加密货币支付,这可能会使用户使用链变得复杂。幸运的是,有一个桥接解决方案,即金属交易。


在元网上成交的的情况下,业主搭建一位说明网上成交的结构特征,进而用顾客的私钥对其通过大金额签字。这相似于为某某人写现金支票。进而,要经过大金额签字的网上成交被发送邮件到中继进程,中继进程将其审核给智能化合同规定。合同规定查证签字,一旦有郊,则继续来执行网上成交。中继进程为合同规定的继续来执行收取费用。


例如,在 karma 交易中,用户提供交易金额(例如 10 karma 美元)、他们想要发送该金额的以太坊地址以及他们愿意提供的交易费用(以 karma 美元为单位)用于交易。该结构经过数字签名并发送到中继节点。如果节点认为交易费用可以接受,则会将数字签名的结构提交给 karma 合约,该合约验证签名并执行交易。由于交易费用是由中继节点以区块链的本机货币支付的,因此在用户看来,他们好像是用业力美元来支付交易,而不需要自己的区块链。


基础理论收场后,我们公司分析看实践性。


EIP-712 要求规范理解了怎么才能以要求规范化手段对构造化资料包实施签名图片。 MetaMask 以粉丝可读的形式表明这样的构造化资料。非常符合 EIP-712 的构造,如 MetaMask 上如图是()下列如图是:


符合 EIP-712 的结构


所诉消费是采用下述简单易行编码出现的:


 async function main() { if (!window.ethereum || !window.ethereum.isMetaMask) { console.log("Please install MetaMask") return } const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); const chainId = await window.ethereum.request({ method: 'eth_chainId' }); const eip712domain_type_definition = { "EIP712Domain": [ { "name": "name", "type": "string" }, { "name": "version", "type": "string" }, { "name": "chainId", "type": "uint256" }, { "name": "verifyingContract", "type": "address" } ] } const karma_request_domain = { "name": "Karma Request", "version": "1", "chainId": chainId, "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" } document.getElementById('transfer_request')?.addEventListener("click", async function () { const transfer_request = { "types": { ...eip712domain_type_definition, "TransferRequest": [ { "name": "to", "type": "address" }, { "name": "amount", "type": "uint256" } ] }, "primaryType": "TransferRequest", "domain": karma_request_domain, "message": { "to": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", "amount": 1234 } } let signature = await window.ethereum.request({ "method": "eth_signTypedData_v4", "params": [ accounts[0], transfer_request ] }) alert("Signature: " + signature) }) } main()


eip712domain_type_definition是一般结构的描述,其中包含元数据。 name 字段是结构的名称,version 字段是结构的定义版本,chainId 和 verifyingContract 字段确定消息针对哪个合约。执行合约验证此元数据,以确保签名的交易仅在目标合约上执行。


karma_request_domain包含 EIP712Domain 结构定义的元数据的具体值。


我们发送到 MetaMask 进行签名的实际结构包含在Transfer_request变量中。 types 块包含类型定义。这里,第一个元素是强制性的 EIP712Domain 定义,它描述了元数据。接下来是实际的结构定义,在本例中是 TransferRequest。这是将在 MetaMask 中为用户显示的结构。域块包含元数据的特定值,而消息包含我们要与用户签名的特定结构。


当说起了业力钱时,元成交怎么样才能组合式消息队列带到自动化合約的举例给出如下:


 const types = { "TransferRequest": [ { "name": "from", "type": "address" }, { "name": "to", "type": "address" }, { "name": "amount", "type": "uint256" }, { "name": "fee", "type": "uint256" }, { "name": "nonce", "type": "uint256" } ] } let nonce = await contract.connect(MINER).getNonce(ALICE.address) const message = { "from": ALICE.address, "to": JOHN.address, "amount": 10, "fee": 1, "nonce": nonce } const signature = await ALICE.signTypedData(karma_request_domain, types, message) await contract.connect(MINER).metaTransfer(ALICE.address, JOHN.address, 10, 1, nonce, signature) assert.equal(await contract.balanceOf(ALICE.address), ethers.toBigInt(11))


types变量定义事务的结构。 “发件人”是发件人的地址,“收件人”是收件人的地址。该金额代表要转移的代币数量。费用是我们向中继节点提供的代币“数量”,以换取执行我们的交易并支付链上本机货币的成本。 “随机数”作为计数器来确保交易的唯一性。如果没有这个字段,一笔交易可能会被执行多次。然而,由于存在随机数,签名的交易只能执行一次。


提供的signTypedData函数可以轻松签署EIP-712 结构。它与前面介绍的代码执行相同的操作,但用法更简单。


metaTransfer是 karma 合约执行元交易的方法。让我们看看它是如何工作的:


 function metaTransfer( address from, address to, uint256 amount, uint256 fee, uint256 nonce, bytes calldata signature ) public virtual returns (bool) { uint256 currentNonce = _useNonce(from, nonce); (address recoveredAddress, ECDSA.RecoverError err) = ECDSA.tryRecover( _hashTypedDataV4( keccak256( abi.encode( TRANSFER_REQUEST_TYPEHASH, from, to, amount, fee, currentNonce ) ) ), signature ); require( err == ECDSA.RecoverError.NoError && recoveredAddress == from, "Signature error" ); _transfer(recoveredAddress, to, amount); _transfer(recoveredAddress, msg.sender, fee); return true; }


考虑到安全验证亲笔签名,我们的必定第一绘制设备构造的哈希值。 图解描绘了实行此使用的中应布骤,其中的以及和。


上述情况表明,存在论只是当我门实用abi.encode将TYPEHASH(即组成部分体描叙的哈希值)与组成部分体的字段名结合事实上了。然而转化成 keccak256 哈希值。哈希值被转递给 _hashTypedDataV4 的方式,该的方式承继自 Karma 合同协议中的 EIP712 OpenZeppelin 合同协议。该变量将元数据报告填加到当我门的组成部分中并转化成不可能的哈希值,使组成部分确认觉得很轻松和黑色。最外卖的变量是 ECDSA.tryRecover,它成功从哈希和个人签字图片中恢复功能个人签字图片者的具体联系地址。如果你与“from”参数表的具体联系地址相配,则个人签字图片合理。在编码的最后一个,进行事实上的寄售,与此同时进行寄售的中继端点发送到相应费用。


EIP-712 是签名结构的通用标准,使其成为实现元交易的众多用途之一。由于签名不仅可以通过智能合约进行验证,它在非区块链应用程序中也非常有用。例如,它可用于服务器端身份验证,其中用户使用其私钥来标识自己。这样的系统可以提供通常与加密货币相关的高级别安全性,从而允许仅通过硬件密钥使用网络应用程序。此外,单个 API 调用也可以借助 MetaMask 进行签名。


我期望 EIP-712 标的简单详述对一些人有所作为体会,如果您将就能在系统设计区快链和非区快链的内容中适用它。


每个码都能够以在上寻找。
바카라사이트 바카라사이트 온라인바카라