Ethereum ERC-20 Meta-Transaction – 以太坊ERC-20元事务区块链毕设代写

区块链毕设代写本文提供国外最新区块链项目源码下载,包括solidity,eth,fabric等blockchain区块链,Ethereum ERC-20 Meta-Transaction – 以太坊ERC-20元事务区块链毕设代写 是一篇很好的国外资料

Ethereum ERC-20 Meta-Transaction

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

Meta-Transaction – Background

A meta-transaction is a regular Ethereum transaction which contains another transaction, the actual transaction. The actual transaction is signed by a user and then sent to an operator (e.g. Awl) or something similar; no gas and blockchain interaction required. The operator takes this signed transaction and submits it to the blockchain paying for the fees himself. The contract ensures there’s a valid signature on the actual transaction and then executes it.

In the context of ERC-20 token transfers, we must also be aware of the following important governance layer: Arguably one of the main reasons for the success of ERC-20 tokens lies in the interplay between approve and transferFrom, which allows for tokens to not only be transferred between externally owned accounts (EOA) but also to be used in other contracts under application-specific conditions by abstracting away msg.sender as the defining mechanism for token access control.

However, a limiting factor in this design stems from the fact that the ERC-20 approve function itself is defined in terms of msg.sender. This means that the user’s initial action involving ERC-20 tokens must be performed by an EOA. If the user needs to interact with a smart contract, then they need to make two transactions (approve and the smart contract call which will internally call transferFrom). Even in the simple use case of paying another person, they need to hold ether (ETH) to pay for transaction gas costs.

To resolve this challenge, we extend all deployed ERC-20 tokens with a new function permit, which allows users to modify the allowance mapping using a signed message (via secp256k1 signatures), instead of through msg.sender. Or in other words, the permit method, which can be used to change an account’s ERC-20 allowance (see IERC20.allowance) by presenting a message signed by the account. By not relying on IERC20.approve, the token holder account doesn’t need to send a transaction, and thus is not required to hold ETH at all.

For an improved user experience, the signed data is structured following EIP-712, which already has wide spread adoption in major RPC & wallet providers.

This setup leads us to the following architecture:

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

EIP-712 – Ethereum Typed Structured Data Hashing and Signing

EIP-712 is a standard for hashing and signing of typed structured data.

The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in their contracts using a combination of abi.encode and keccak256.

The smart contract Forwarder.sol implements the EIP-712 domain separator (_domainSeparatorV4) that is used as part of the encoding scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA (_hashTypedDataV4).

The OpenZeppelin implementation of the domain separator was designed to be as efficient as possible while still properly updating the chain ID to protect against replay attacks on an eventual fork of the chain.

The smart contract Forwarder.sol implements the version of the encoding known as “v4”, as implemented by the JSON RPC method eth_signTypedDataV4 in MetaMask.

Forwarder Contract – A Smart Contract for Extensible Meta-Transaction Forwarding on Ethereum

The smart contract Forwarder.sol extends the EIP-2770 and entails the following core functions:

  • verify: Verifies the signature based on the typed structured data.
    function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {         address signer = _hashTypedDataV4(keccak256(abi.encode(             _TYPEHASH,             req.from,             req.to,             req.value,             req.gas,             req.nonce,             keccak256(req.data)         ))).recover(signature);         return _nonces[req.from] == req.nonce && signer == req.from;     }
  • execute: Executes the meta-transaction via a low-level call.
    function execute(ForwardRequest calldata req, bytes calldata signature) public payable whenNotPaused() returns (bool, bytes memory) {         require(_senderWhitelist[msg.sender], "AwlForwarder: sender of meta-transaction is not whitelisted");         require(verify(req, signature), "AwlForwarder: signature does not match request");         _nonces[req.from] = req.nonce + 1;          (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(abi.encodePacked(req.data, req.from));                  if (!success) {             assembly {             returndatacopy(0, 0, returndatasize())             revert(0, returndatasize())             }         }          assert(gasleft() > req.gas / 63);          emit MetaTransactionExecuted(req.from, req.to, req.data);          return (success, returndata);     }

UML Diagram Forwarder.sol Smart Contract

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

Unit Tests

As the project backbone, we use the Truffle development environment. However, since Hardhat implements great features for Solidity debugging like Solidity stack traces, console.log, and explicit error messages when transactions fail, we leverage Hardhat for testing:

npx hardhat test

Test Coverage

This repository implements a test coverage plugin. Simply run:

npx hardhat coverage --testfiles "test/Forwarder.test.js"

The written tests available in the file Forwarder.test.js achieve a test coverage of 100%:

----------------|----------|----------|----------|----------|----------------| File            |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines | ----------------|----------|----------|----------|----------|----------------|  contracts     |      100 |      100 |      100 |      100 |                |   Forwarder.sol |      100 |      100 |      100 |      100 |                | ----------------|----------|----------|----------|----------|----------------| All files       |      100 |      100 |      100 |      100 |                | ----------------|----------|----------|----------|----------|----------------|

Important: A test coverage of 100% does not mean that there are no vulnerabilities. What really counts is the quality and spectrum of the tests themselves.

Security Considerations

In order to assure a replay protection, we track on-chain a nonce mapping. Further, to prevent anyone from broadcasting transactions that have a potential malicious intent, the Forwarder smart contract implements a whitelist for the execute function. Also, the smart contract is Ownable which provides a basic access control mechanism, where there is an EOA (an owner) that is granted exclusive access to specific functions (i.e. addSenderToWhitelist, removeSenderFromWhitelist, killForwarder, pause, unpause). Further, the smart contract function execute is Pausable, i.e. implements an emergency stop mechanism that can be triggered by the owner. Eventually, as an emergency backup a selfdestruct operation is implemented via the function killForwarder.

Note 1: It is of utmost importance that the whitelisted EOAs carefully check the encoded (user-signed) calldata before sending the transaction.

Note 2: calldata is where data from external calls to functions is stored. Functions can be called internally, e.g. from within the contract, or externally. When a function’s visibility is external, only external contracts can call that function. When such an external call happens, the data of that call is stored in calldata.

Note 3: For the functions addSenderToWhitelist and killForwarder we do not implement a dedicated strict policy to never allow the zero address 0x0000000000000000000000000000000000000000. The reason for this is that firstly, the functions are protected by being Ownable and secondly, it can be argued that addresses like 0x00000000000000000000000000000000000001 are just as dangerous, but we do nothing about it.

Remember That ETH Can Be Forcibly Sent to an Account

Beware of coding an invariant that strictly checks the balance of a contract. An attacker can forcibly send ETH to any account and this cannot be prevented (not even with a fallback function that does a revert()). The attacker can do this by creating a contract, funding it with 1 wei, and invoking selfdestruct(victimAddress). No code is invoked in victimAddress, so it cannot be prevented. This is also true for block reward which is sent to the address of the miner, which can be any arbitrary address. Also, since contract addresses can be precomputed, ETH can be sent to an address before the contract is deployed.

Test Deployments

The smart contract Forwarder.sol has been deployed across all the major test networks:

  • Rinkeby: 0xDA9F0524bDbc92443797feA702eDBD10A51cD3Fd
  • Ropsten: 0xeD1d5e84F1d2947509923Ac55AEb538684015cb2
  • Kovan: 0xeb8647302b2F97653452Ce1582E046e205D515bc
  • Goerli: 0x20EC414D11C2C1C9c332083284C1f99C1365A645

Signed User Data (Input Parameters) for permit and execute

For the permit function, there exists a JS script for every token contract repository: e.g. Säntis Gulden. Before running this script, assure the right configurations for the use case (e.g. owner, spender, amount, deadline).

For the execute function, first assure the right configurations for the use case (e.g. toAddress, toContract, network_id) and then run the JS script sign-data.js (assuming Node.js is installed):

node scripts/sign-data.js

Example output:

payableAmount (ether): 0   req (tuple): ["0x3854Ca47Abc62A3771fE06ab45622A42C4A438Cf", "0x0f64069aC10c5Bcc3396b26C892A36D22CdCf5A6", "0", "210000", "0", "0x23b872dd0000000000000000000000003854ca47abc62a3771fe06ab45622a42c4a438cf000000000000000000000000a971eadc6dac94991d3ef3c00bc2a20894cd74f10000000000000000000000000000000000000000000000000000000000000001"]  signature (bytes): 0x3ac63b6929bc4ecde0391551bad4babda3b471dbaadf9994478da2af749021097bd135f5ed41df8119a59357662a38069e1c8c7e66dcefabd46d0f7da7a250681c

The first four bytes of the calldata for a function call specifies the function to be called. It is the first (left, high-order in big-endian) four bytes of the keccak256 hash of the signature of the function. Thus, since 1 nibble (4 bits) can be represented by one hex digit, we have 4 bytes = 8 hex digits.

Example Transaction (Rinkeby Testnet)

  • 1. Transaction (permit): The EOA 0x3854Ca47Abc62A3771fE06ab45622A42C4A438Cf permits the Forwarder contract to spend 1 Saentis Gulden token (SGD). The payer and broadcaster of this transaction is 0x9f3f11d72d96910df008cfe3aba40f361d2eed03.
  • 2. Transaction (execute): The EOA 0x3854Ca47Abc62A3771fE06ab45622A42C4A438Cf transfers the arbitrary amount (maximum possible amount would be 1 SGD) of 0.000000000000000001 SGD to another EOA 0xA971eADc6dac94991d3Ef3c00BC2A20894CD74F1. The payer and broadcaster of this transaction is 0x9f3f11d72d96910df008cfe3aba40f361d2eed03.

References

[1] https://medium.com/coinmonks/ethereum-meta-transactions-101-de7f91884a06

[2] https://soliditydeveloper.com/meta-transactions

[3] https://docs.openzeppelin.com/contracts/4.x/api/metatx

[4] https://docs.opengsn.org

[5] https://eips.ethereum.org/EIPS/eip-2612

[6] https://eips.ethereum.org/EIPS/eip-712


以太坊ethERC-20元事务

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

元事务-背景

元事务是一个常规的以太坊eth事务,它包含另一个事务,即实际事务。实际交易由用户签名,然后发送给操作员(例如Awl)或类似的东西;无需气体和区块链blockchain交互。运营商将这个签名的交易提交给自己支付费用的区块链blockchain。合同确保在实际交易上有一个有效的签名,然后执行它

在ERC-20代币转让的背景下,我们还必须意识到以下重要的治理层:可以说,ERC-20代币成功的主要原因之一在于批准和转让之间的相互作用,通过提取msg.sender作为令牌访问控制的定义机制,它不仅允许令牌在外部拥有的帐户(EOA)之间传输,而且允许令牌在特定于应用程序的条件下用于其他合同

然而,这种设计中的一个限制因素源于这样一个事实,即ERC-20 approve函数本身是根据msg.sender定义的。这意味着用户涉及ERC-20令牌的初始操作必须由EOA执行。如果用户需要与智能合约交互,那么他们需要进行两个事务(approve和智能合约调用,智能合约调用将在内部调用transferFrom)。即使是在向另一个人付款的简单用例中,他们也需要持有乙醚(ETH)来支付交易气体成本

为了解决这个问题,我们使用新的功能许可证扩展了所有部署的ERC-20令牌,允许用户使用签名消息(通过secp256k1签名)而不是通过msg.sender修改余量映射。或者换句话说,permit方法,可以通过显示由帐户签名的消息来更改帐户的ERC-20限额(参见IERC20.allowance)。通过不依赖IERC20.approve,令牌持有者帐户不需要发送交易,因此根本不需要持有ETH

为了改善用户体验,签名数据的结构遵循EIP-712,EIP-712已经在主要RPC&amp;中广泛采用;钱包提供商

此设置将我们引入以下体系结构:

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

EIP-712-以太坊eth类型的结构化数据哈希和签名

EIP-712是类型化结构化数据的哈希和签名标准

EIP中规定的编码是非常通用的,这样的通用实现是不可行的,因此本合同不实现编码本身。协议需要使用abi.encode和keccak256的组合来实现其契约中所需的特定于类型的编码

smart contract Forwarder.sol实现用作编码方案一部分的EIP-712域分隔符(_domainseptorv4),以及编码的最后一步,以获得消息摘要,然后通过ECDSA(_hashTypedDataV4)签名

域分隔符的OpenZeppelin实现设计得尽可能高效,同时仍然正确地更新链ID,以防止对链的最终分支的重放攻击

smart contract Forwarder.sol实现了被称为“v4”的编码版本,这是由MetaMask中的JSON-RPC方法ethu signTypedDataV4实现的

转发器契约-用于以太坊eth上可扩展元事务转发的智能契约

smart contract Forwarder.sol扩展了EIP-2770并包含以下核心功能:

  • 验证:根据输入的结构化数据验证签名
    function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {         address signer = _hashTypedDataV4(keccak256(abi.encode(             _TYPEHASH,             req.from,             req.to,             req.value,             req.gas,             req.nonce,             keccak256(req.data)         ))).recover(signature);         return _nonces[req.from] == req.nonce && signer == req.from;     }
  • 执行:通过低级调用执行元事务
    function execute(ForwardRequest calldata req, bytes calldata signature) public payable whenNotPaused() returns (bool, bytes memory) {         require(_senderWhitelist[msg.sender], "AwlForwarder: sender of meta-transaction is not whitelisted");         require(verify(req, signature), "AwlForwarder: signature does not match request");         _nonces[req.from] = req.nonce + 1;          (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(abi.encodePacked(req.data, req.from));                  if (!success) {             assembly {             returndatacopy(0, 0, returndatasize())             revert(0, returndatasize())             }         }          assert(gasleft() > req.gas / 63);          emit MetaTransactionExecuted(req.from, req.to, req.data);          return (success, returndata);     }

UML图转发器.sol Smart契约

Ethereum ERC-20 Meta-Transaction - <a href=以太坊ethERC-20元事务”>

单元测试

作为项目主干,我们使用Truffle开发环境。但是,由于Hardhat为Solidity调试实现了强大的功能,如Solidity stack traces、console.log和事务失败时的显式错误消息,因此我们利用Hardhat进行测试:

npx hardhat test

测试覆盖率

此存储库实现了一个测试覆盖率插件。只需运行:

npx hardhat coverage --testfiles "test/Forwarder.test.js"

文件Forwarder.test.js中提供的书面测试可实现100%的测试覆盖率:

----------------|----------|----------|----------|----------|----------------| File            |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines | ----------------|----------|----------|----------|----------|----------------|  contracts     |      100 |      100 |      100 |      100 |                |   Forwarder.sol |      100 |      100 |      100 |      100 |                | ----------------|----------|----------|----------|----------|----------------| All files       |      100 |      100 |      100 |      100 |                | ----------------|----------|----------|----------|----------|----------------|

重要提示:100%的测试覆盖率并不意味着没有漏洞。真正重要的是测试本身的质量和范围

安全考虑

为了保证重放保护,我们在链上跟踪nonce映射。此外,为了防止任何人广播具有潜在恶意意图的事务,转发器智能合约实现了execute函数的白名单。此外,智能合约是可拥有的,它提供了一个基本的访问控制机制,其中有一个EOA(所有者)被授予对特定功能的独占访问权(即addSenderToWhitelist、removeSenderFromWhitelist、killForwarder、pause、unpause)。此外,智能合约功能execute是可暂停的,即实现可由所有者触发的紧急停止机制。最后,作为紧急备份,通过函数killForwarder执行自毁操作

注1:在发送事务之前,白名单上的eoa必须仔细检查编码(用户签名)的calldata,这一点非常重要

注2:calldata是存储外部函数调用数据的地方。函数可以在内部调用,例如从合同内部调用,也可以从外部调用。当函数的可见性是外部的时,只有外部契约才能调用该函数。当发生这样的外部调用时,该调用的数据存储在calldata中

注3:对于addSenderToWhitelist和killForwarder函数,我们没有实现一个专用的严格策略,即永远不允许零地址0x0000000000000000。这样做的原因是,首先,函数是通过可拥有来保护的,其次,可以说像0x00000000000000000001这样的地址同样危险,但我们对此却无所作为

请记住,ETH可以强制发送到帐户

小心编码一个严格检查契约平衡的不变量。攻击者可以强制将ETH发送到任何帐户,这是无法阻止的(即使使用执行revert()的回退函数也不行)。攻击者可以通过创建一个契约,用1wei提供资金,并调用selfdestruct(victimAddress)来实现这一点。在victimAddress中没有调用任何代码,因此无法阻止。对于发送到矿工地址的块奖励也是如此,可以是任意地址。此外,由于契约地址可以预先计算,因此ETH可以在契约部署之前发送到一个地址

测试部署

smart contract Forwarder.sol已经部署在所有主要的测试网络中:

  • Rinkeby:0xDA9F0524bDbc92443797feA702eDBD10A51cD3Fd
  • Ropsten:0xeD1d5e84F1d2947509923Ac55AEb538684015cb2
  • Kovan:0xeb8647302b2F97653452Ce1582E046e205D515bc
  • Goerli:0x20ec414d11c2c9c332083284c1f99c1365a645

签名的用户数据(输入参数),以允许并执行

对于permit函数,每个令牌契约存储库都有一个JS脚本:例如Säntis Gulden。在运行这个脚本之前,确保用例的正确配置(例如所有者、花费者、金额、截止日期)

对于execute函数,首先确保用例的正确配置(例如toAddress、toContract、networku id),然后运行JS脚本sign-data.JS(假设安装了Node.JS):

node scripts/sign-data.js

示例输出:

payableAmount (ether): 0   req (tuple): ["0x3854Ca47Abc62A3771fE06ab45622A42C4A438Cf", "0x0f64069aC10c5Bcc3396b26C892A36D22CdCf5A6", "0", "210000", "0", "0x23b872dd0000000000000000000000003854ca47abc62a3771fe06ab45622a42c4a438cf000000000000000000000000a971eadc6dac94991d3ef3c00bc2a20894cd74f10000000000000000000000000000000000000000000000000000000000000001"]  signature (bytes): 0x3ac63b6929bc4ecde0391551bad4babda3b471dbaadf9994478da2af749021097bd135f5ed41df8119a59357662a38069e1c8c7e66dcefabd46d0f7da7a250681c

函数调用的calldata的前四个字节指定要调用的函数。它是函数签名的keccak256散列的第一个(左,高位,big endian)四字节。因此,由于1个半字节(4位)可以由一个十六进制数字表示,因此我们有4个字节=8个十六进制数字

示例事务(Rinkeby Testnet)

  • 1.交易(许可证):EOA 0x3854ca47abc62a3771fe06ab4562a42a438cf货代合同花费1个Saentis Gulden代币(SGD)。此交易的付款人和广播者是0x9f3f11d72d96910df008cfe3aba40f361d2eed03
  • 2. Transaction (execute): The EOA 0x3854Ca47Abc62A3771fE06ab45622A42C4A438Cf transfers the arbitrary amount (maximum possible amount would be 1 SGD) of 0.000000000000000001 SGD to another EOA 0xA971eADc6dac94991d3Ef3c00BC2A20894CD74F1. The payer and broadcaster of this transaction is 0x9f3f11d72d96910df008cfe3aba40f361d2eed03.

引用

[1]https://medium.com/coinmonks/ethereum-meta-transactions-101-de7f91884a06

[2]https://soliditydeveloper.com/meta-transactions

[3]https://docs.openzeppelin.com/contracts/4.x/api/metatx

[4]https://docs.opengsn.org

[5]https://eips.ethereum.org/EIPS/eip-2612

[6]https://eips.ethereum.org/EIPS/eip-712

部分转自网络,侵权联系删除区块链源码网

www.interchains.cc

https://www.interchains.cc/23046.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » Ethereum ERC-20 Meta-Transaction – 以太坊ERC-20元事务区块链毕设代写

提供最优质的资源集合

立即查看 了解详情